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_page_y);
sw.Do(&m_render_state.texture_palette_x); sw.Do(&m_render_state.texture_palette_x);
sw.Do(&m_render_state.texture_palette_y); 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.transparency_mode);
sw.Do(&m_render_state.texture_window_mask_x); sw.Do(&m_render_state.texture_window_mask_x);
sw.Do(&m_render_state.texture_window_mask_y); sw.Do(&m_render_state.texture_window_mask_y);
@ -701,7 +701,7 @@ void GPU::RenderState::SetFromPageAttribute(u16 value)
texture_page_changed |= texture_page_changed |=
(old_page_attribute & PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK) != (value & PAGE_ATTRIBUTE_TEXTURE_PAGE_MASK); (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))); transparency_mode = (static_cast<TransparencyMode>((value >> 5) & UINT16_C(0x03)));
} }

View file

@ -337,7 +337,7 @@ protected:
u32 texture_page_y; u32 texture_page_y;
u32 texture_palette_x; u32 texture_palette_x;
u32 texture_palette_y; u32 texture_palette_y;
TextureMode texture_color_mode; TextureMode texture_mode;
TransparencyMode transparency_mode; TransparencyMode transparency_mode;
u8 texture_window_mask_x; // in 8 pixel steps u8 texture_window_mask_x; // in 8 pixel steps
u8 texture_window_mask_y; // 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_page_changed = false;
bool texture_window_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; } bool IsTexturePageChanged() const { return texture_page_changed; }
void ClearTexturePageChangedFlag() { texture_page_changed = false; } void ClearTexturePageChangedFlag() { texture_page_changed = false; }

View file

@ -620,7 +620,7 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
break; break;
} }
texture_mode = m_render_state.texture_color_mode; texture_mode = m_render_state.texture_mode;
if (rc.raw_texture_enable) if (rc.raw_texture_enable)
{ {
texture_mode = texture_mode =
@ -633,6 +633,35 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
texture_mode = TextureMode::Disabled; 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? // has any state changed which requires a new batch?
const TransparencyMode transparency_mode = const TransparencyMode transparency_mode =
rc.transparency_enable ? m_render_state.transparency_mode : TransparencyMode::Disabled; 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; const bool buffer_overflow = GetBatchVertexSpace() < max_added_vertices;
if (buffer_overflow || rc_primitive == HWPrimitive::LineStrip || m_batch.texture_mode != texture_mode || if (buffer_overflow || rc_primitive == HWPrimitive::LineStrip || m_batch.texture_mode != texture_mode ||
m_batch.transparency_mode != transparency_mode || m_batch.primitive != rc_primitive || m_batch.transparency_mode != transparency_mode || m_batch.primitive != rc_primitive ||
dithering_enable != m_batch.dithering || m_render_state.IsTexturePageChanged() || dithering_enable != m_batch.dithering || m_render_state.IsTextureWindowChanged())
m_render_state.IsTextureWindowChanged())
{ {
FlushRender(); FlushRender();
} }
@ -661,31 +689,6 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
m_batch.transparency_mode = transparency_mode; m_batch.transparency_mode = transparency_mode;
m_batch.dithering = dithering_enable; 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()) if (m_render_state.IsTextureWindowChanged())
{ {
m_batch.texture_window_values[0] = m_render_state.texture_window_mask_x; m_batch.texture_window_values[0] = m_render_state.texture_window_mask_x;

View file

@ -57,10 +57,6 @@ protected:
struct HWBatchConfig struct HWBatchConfig
{ {
u32 texture_page_x;
u32 texture_page_y;
u32 texture_palette_x;
u32 texture_palette_y;
HWPrimitive primitive; HWPrimitive primitive;
TextureMode texture_mode; TextureMode texture_mode;
TransparencyMode transparency_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); ((m_render_state.texture_window_offset_y & m_render_state.texture_window_mask_y) * 8u);
VRAMPixel texture_color; VRAMPixel texture_color;
switch (m_render_state.texture_color_mode) switch (m_render_state.texture_mode)
{ {
case GPU::TextureMode::Palette4Bit: case GPU::TextureMode::Palette4Bit:
{ {