GPU: Fix VRAM palette changes not being detected in hw renderer

Fixes wall texture animation in Mega Man Legends.
This commit is contained in:
Connor McLaughlin 2020-11-22 13:22:20 +10:00
parent b49067d165
commit e06f85a328
3 changed files with 38 additions and 39 deletions

View File

@ -358,30 +358,30 @@ protected:
BitField<u32, DMADirection, 29, 2> dma_direction; BitField<u32, DMADirection, 29, 2> dma_direction;
BitField<u32, bool, 31, 1> display_line_lsb; BitField<u32, bool, 31, 1> display_line_lsb;
bool IsMaskingEnabled() const ALWAYS_INLINE bool IsMaskingEnabled() const
{ {
static constexpr u32 MASK = ((1 << 11) | (1 << 12)); static constexpr u32 MASK = ((1 << 11) | (1 << 12));
return ((bits & MASK) != 0); return ((bits & MASK) != 0);
} }
bool SkipDrawingToActiveField() const ALWAYS_INLINE bool SkipDrawingToActiveField() const
{ {
static constexpr u32 MASK = (1 << 19) | (1 << 22) | (1 << 10); static constexpr u32 MASK = (1 << 19) | (1 << 22) | (1 << 10);
static constexpr u32 ACTIVE = (1 << 19) | (1 << 22); static constexpr u32 ACTIVE = (1 << 19) | (1 << 22);
return ((bits & MASK) == ACTIVE); return ((bits & MASK) == ACTIVE);
} }
bool InInterleaved480iMode() const ALWAYS_INLINE bool InInterleaved480iMode() const
{ {
static constexpr u32 ACTIVE = (1 << 19) | (1 << 22); static constexpr u32 ACTIVE = (1 << 19) | (1 << 22);
return ((bits & ACTIVE) == ACTIVE); return ((bits & ACTIVE) == ACTIVE);
} }
// During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or } // During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or }
u16 GetMaskAND() const ALWAYS_INLINE u16 GetMaskAND() const
{ {
// return check_mask_before_draw ? 0x8000 : 0x0000; // return check_mask_before_draw ? 0x8000 : 0x0000;
return Truncate16((bits << 3) & 0x8000); return Truncate16((bits << 3) & 0x8000);
} }
u16 GetMaskOR() const ALWAYS_INLINE u16 GetMaskOR() const
{ {
// return set_mask_while_drawing ? 0x8000 : 0x0000; // return set_mask_while_drawing ? 0x8000 : 0x0000;
return Truncate16((bits << 4) & 0x8000); return Truncate16((bits << 4) & 0x8000);
@ -409,13 +409,21 @@ protected:
bool texture_page_changed; bool texture_page_changed;
bool texture_window_changed; bool texture_window_changed;
bool IsTexturePageChanged() const { return texture_page_changed; } /// Returns a rectangle comprising the texture palette area.
void SetTexturePageChanged() { texture_page_changed = true; } ALWAYS_INLINE_RELEASE Common::Rectangle<u32> GetTexturePaletteRectangle() const
void ClearTexturePageChangedFlag() { texture_page_changed = false; } {
static constexpr std::array<u32, 4> palette_widths = {{16, 256, 0, 0}};
return Common::Rectangle<u32>::FromExtents(texture_palette_x, texture_palette_y,
palette_widths[static_cast<u8>(mode_reg.texture_mode.GetValue())], 1);
}
bool IsTextureWindowChanged() const { return texture_window_changed; } ALWAYS_INLINE bool IsTexturePageChanged() const { return texture_page_changed; }
void SetTextureWindowChanged() { texture_window_changed = true; } ALWAYS_INLINE void SetTexturePageChanged() { texture_page_changed = true; }
void ClearTextureWindowChangedFlag() { texture_window_changed = false; } ALWAYS_INLINE void ClearTexturePageChangedFlag() { texture_page_changed = false; }
ALWAYS_INLINE bool IsTextureWindowChanged() const { return texture_window_changed; }
ALWAYS_INLINE void SetTextureWindowChanged() { texture_window_changed = true; }
ALWAYS_INLINE void ClearTextureWindowChangedFlag() { texture_window_changed = false; }
} m_draw_mode = {}; } m_draw_mode = {};
Common::Rectangle<u32> m_drawing_area{0, 0, VRAM_WIDTH, VRAM_HEIGHT}; Common::Rectangle<u32> m_drawing_area{0, 0, VRAM_WIDTH, VRAM_HEIGHT};

View File

@ -829,7 +829,7 @@ void GPU_HW::IncludeVRAMDityRectangle(const Common::Rectangle<u32>& rect)
// shadow texture is updated // shadow texture is updated
if (!m_draw_mode.IsTexturePageChanged() && if (!m_draw_mode.IsTexturePageChanged() &&
(m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(rect) || (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(rect) ||
(m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(rect)))) (m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(rect))))
{ {
m_draw_mode.SetTexturePageChanged(); m_draw_mode.SetTexturePageChanged();
} }
@ -932,10 +932,9 @@ void GPU_HW::DispatchRenderCommand()
if (m_draw_mode.IsTexturePageChanged()) if (m_draw_mode.IsTexturePageChanged())
{ {
m_draw_mode.ClearTexturePageChangedFlag(); m_draw_mode.ClearTexturePageChangedFlag();
if (m_vram_dirty_rect.Valid() && if (m_vram_dirty_rect.Valid() && (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) ||
(m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) || (m_draw_mode.mode_reg.IsUsingPalette() &&
(m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect))))
{ {
// Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap"); // Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap");
if (!IsFlushed()) if (!IsFlushed())

View File

@ -93,15 +93,15 @@ union GPURenderCommand
{ {
switch (primitive) switch (primitive)
{ {
case GPUPrimitive::Polygon: case GPUPrimitive::Polygon:
return shading_enable || (texture_enable && !raw_texture_enable); return shading_enable || (texture_enable && !raw_texture_enable);
case GPUPrimitive::Line: case GPUPrimitive::Line:
return true; return true;
case GPUPrimitive::Rectangle: case GPUPrimitive::Rectangle:
default: default:
return false; return false;
} }
} }
}; };
@ -175,24 +175,16 @@ union GPUDrawModeReg
ALWAYS_INLINE u16 GetTexturePageBaseY() const { return ZeroExtend16(texture_page_y_base.GetValue()) * 256; } ALWAYS_INLINE u16 GetTexturePageBaseY() const { return ZeroExtend16(texture_page_y_base.GetValue()) * 256; }
/// Returns true if the texture mode requires a palette. /// Returns true if the texture mode requires a palette.
bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; } ALWAYS_INLINE bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; }
/// Returns a rectangle comprising the texture page area. /// Returns a rectangle comprising the texture page area.
Common::Rectangle<u32> GetTexturePageRectangle() const ALWAYS_INLINE_RELEASE Common::Rectangle<u32> GetTexturePageRectangle() const
{ {
static constexpr std::array<u32, 4> texture_page_widths = { static constexpr std::array<u32, 4> texture_page_widths = {
{TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH} }; {TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH}};
return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(), return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
texture_page_widths[static_cast<u8>(texture_mode.GetValue())], texture_page_widths[static_cast<u8>(texture_mode.GetValue())],
TEXTURE_PAGE_HEIGHT); TEXTURE_PAGE_HEIGHT);
}
/// Returns a rectangle comprising the texture palette area.
Common::Rectangle<u32> GetTexturePaletteRectangle() const
{
static constexpr std::array<u32, 4> palette_widths = { {16, 256, 0, 0} };
return Common::Rectangle<u32>::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(),
palette_widths[static_cast<u8>(texture_mode.GetValue())], 1);
} }
}; };
@ -218,14 +210,14 @@ struct GPUTextureWindow
}; };
// 4x4 dither matrix. // 4x4 dither matrix.
static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = { {-4, +0, -3, +1}, // row 0 static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = {{-4, +0, -3, +1}, // row 0
{+2, -2, +3, -1}, // row 1 {+2, -2, +3, -1}, // row 1
{-3, +1, -4, +0}, // row 2 {-3, +1, -4, +0}, // row 2
{+4, -1, +2, -2} }; // row 3 {+4, -1, +2, -2}}; // row 3
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union #pragma warning(disable : 4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union
#endif #endif
enum class GPUBackendCommandType : u8 enum class GPUBackendCommandType : u8