GPU: Fix batching regression (draws split on texture page)

This commit is contained in:
Connor McLaughlin 2019-11-03 00:36:47 +10:00
parent 5abbdef065
commit ba1a5a5ca9
5 changed files with 42 additions and 36 deletions

View file

@ -67,7 +67,7 @@ bool GPU::DoState(StateWrapper& sw)
sw.Do(&m_render_state.texture_page_y);
sw.Do(&m_render_state.texture_palette_x);
sw.Do(&m_render_state.texture_palette_y);
sw.Do(&m_render_state.texture_color_mode);
sw.Do(&m_render_state.texture_mode);
sw.Do(&m_render_state.transparency_mode);
sw.Do(&m_render_state.texture_window_mask_x);
sw.Do(&m_render_state.texture_window_mask_y);
@ -701,7 +701,7 @@ void GPU::RenderState::SetFromPageAttribute(u16 value)
texture_page_changed |=
(old_page_attribute & PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK) != (value & PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK);
texture_color_mode = (static_cast<TextureMode>((value >> 7) & UINT16_C(0x03)));
texture_mode = (static_cast<TextureMode>((value >> 7) & UINT16_C(0x03)));
transparency_mode = (static_cast<TransparencyMode>((value >> 5) & UINT16_C(0x03)));
}

View file

@ -337,7 +337,7 @@ protected:
u32 texture_page_y;
u32 texture_palette_x;
u32 texture_palette_y;
TextureMode texture_color_mode;
TextureMode texture_mode;
TransparencyMode transparency_mode;
u8 texture_window_mask_x; // in 8 pixel steps
u8 texture_window_mask_y; // in 8 pixel steps
@ -354,6 +354,13 @@ protected:
bool texture_page_changed = false;
bool texture_window_changed = false;
/// Returns true if the texture mode requires a palette.
bool IsUsingPalette() const
{
return (static_cast<u8>(texture_mode) &
(static_cast<u8>(TextureMode::Palette4Bit) | static_cast<u8>(TextureMode::Palette8Bit))) != 0;
}
bool IsTexturePageChanged() const { return texture_page_changed; }
void ClearTexturePageChangedFlag() { texture_page_changed = false; }

View file

@ -620,7 +620,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
break;
}
texture_mode = m_render_state.texture_color_mode;
texture_mode = m_render_state.texture_mode;
if (rc.raw_texture_enable)
{
texture_mode =
@ -633,6 +633,35 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
texture_mode = TextureMode::Disabled;
}
// texture page changed - check that the new page doesn't intersect the drawing area
if (m_render_state.IsTexturePageChanged())
{
m_render_state.ClearTexturePageChangedFlag();
const u32 texture_page_left = m_render_state.texture_page_x;
const u32 texture_page_right = m_render_state.texture_page_y + TEXTURE_PAGE_WIDTH;
const u32 texture_page_top = m_render_state.texture_page_y;
const u32 texture_page_bottom = texture_page_top + TEXTURE_PAGE_HEIGHT;
const bool texture_page_overlaps =
(texture_page_left < m_drawing_area.right && texture_page_right > m_drawing_area.left &&
texture_page_top > m_drawing_area.bottom && texture_page_bottom < m_drawing_area.top);
const u32 texture_palette_left = m_render_state.texture_palette_x;
const u32 texture_palette_right = m_render_state.texture_palette_x + 256;
const bool texture_palette_overlaps =
m_render_state.IsUsingPalette() && texture_palette_left < m_drawing_area.right &&
texture_palette_right > m_drawing_area.left && m_render_state.texture_palette_y < m_drawing_area.bottom &&
m_render_state.texture_palette_y >= m_drawing_area.top;
// we only need to update the copy texture if the render area intersects with the texture page
if (texture_page_overlaps || texture_palette_overlaps)
{
Log_WarningPrintf("Invalidating VRAM read cache due to drawing area overlap");
if (!IsFlushed())
FlushRender();
InvalidateVRAMReadCache();
}
}
// has any state changed which requires a new batch?
const TransparencyMode transparency_mode =
rc.transparency_enable ? m_render_state.transparency_mode : TransparencyMode::Disabled;
@ -644,8 +673,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
const bool buffer_overflow = GetBatchVertexSpace() < max_added_vertices;
if (buffer_overflow || rc_primitive == HWPrimitive::LineStrip || m_batch.texture_mode != texture_mode ||
m_batch.transparency_mode != transparency_mode || m_batch.primitive != rc_primitive ||
dithering_enable != m_batch.dithering || m_render_state.IsTexturePageChanged() ||
m_render_state.IsTextureWindowChanged())
dithering_enable != m_batch.dithering || m_render_state.IsTextureWindowChanged())
{
FlushRender();
}
@ -661,31 +689,6 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
m_batch.transparency_mode = transparency_mode;
m_batch.dithering = dithering_enable;
if (m_render_state.IsTexturePageChanged())
{
// we only need to update the copy texture if the render area intersects with the texture page
const u32 texture_page_left = m_render_state.texture_page_x;
const u32 texture_page_right = m_render_state.texture_page_y + TEXTURE_PAGE_WIDTH;
const u32 texture_page_top = m_render_state.texture_page_y;
const u32 texture_page_bottom = texture_page_top + TEXTURE_PAGE_HEIGHT;
const bool texture_page_overlaps =
(texture_page_left < m_drawing_area.right && texture_page_right > m_drawing_area.left &&
texture_page_top > m_drawing_area.bottom && texture_page_bottom < m_drawing_area.top);
// TODO: Check palette too.
if (texture_page_overlaps)
{
Log_DebugPrintf("Invalidating VRAM read cache due to drawing area overlap");
InvalidateVRAMReadCache();
}
m_batch.texture_page_x = m_render_state.texture_page_x;
m_batch.texture_page_y = m_render_state.texture_page_y;
m_batch.texture_palette_x = m_render_state.texture_palette_x;
m_batch.texture_palette_y = m_render_state.texture_palette_y;
m_render_state.ClearTexturePageChangedFlag();
}
if (m_render_state.IsTextureWindowChanged())
{
m_batch.texture_window_values[0] = m_render_state.texture_window_mask_x;

View file

@ -57,10 +57,6 @@ protected:
struct HWBatchConfig
{
u32 texture_page_x;
u32 texture_page_y;
u32 texture_palette_x;
u32 texture_palette_y;
HWPrimitive primitive;
TextureMode texture_mode;
TransparencyMode transparency_mode;

View file

@ -416,7 +416,7 @@ void GPU_SW::ShadePixel(RenderCommand rc, u32 x, u32 y, u8 color_r, u8 color_g,
((m_render_state.texture_window_offset_y & m_render_state.texture_window_mask_y) * 8u);
VRAMPixel texture_color;
switch (m_render_state.texture_color_mode)
switch (m_render_state.texture_mode)
{
case GPU::TextureMode::Palette4Bit:
{