GPU: Truncate sprite/rectangle positions to 12 bits before rendering

Fixes disappearing objects in Skullmonkeys.
This commit is contained in:
Connor McLaughlin 2020-04-27 12:51:17 +10:00
parent 63692a012f
commit 304391bd00
3 changed files with 16 additions and 14 deletions

View file

@ -166,7 +166,7 @@ public:
bool ConvertScreenCoordinatesToBeamTicksAndLines(s32 window_x, s32 window_y, u32* out_tick, u32* out_line) const; bool ConvertScreenCoordinatesToBeamTicksAndLines(s32 window_x, s32 window_y, u32* out_tick, u32* out_line) const;
protected: protected:
static TickCount GPUTicksToSystemTicks(TickCount gpu_ticks) static constexpr TickCount GPUTicksToSystemTicks(TickCount gpu_ticks)
{ {
// convert to master clock, rounding up as we want to overshoot not undershoot // convert to master clock, rounding up as we want to overshoot not undershoot
return static_cast<TickCount>((static_cast<u32>(gpu_ticks) * 7u + 10u) / 11u); return static_cast<TickCount>((static_cast<u32>(gpu_ticks) * 7u + 10u) / 11u);
@ -254,7 +254,6 @@ protected:
} }
}; };
// TODO: Use BitField to do sign extending instead
union VertexPosition union VertexPosition
{ {
u32 bits; u32 bits;
@ -263,6 +262,9 @@ protected:
BitField<u32, s32, 16, 12> y; BitField<u32, s32, 16, 12> y;
}; };
// Sprites/rectangles should be clipped to 12 bits before drawing.
static constexpr s32 TruncateVertexPosition(s32 x) { return SignExtendN<11, s32>(x); }
union VRAMPixel union VRAMPixel
{ {
u16 bits; u16 bits;

View file

@ -270,8 +270,8 @@ void GPU_HW::LoadVertices()
{ {
const u32 color = rc.color_for_first_vertex; const u32 color = rc.color_for_first_vertex;
const VertexPosition vp{m_fifo.Pop()}; const VertexPosition vp{m_fifo.Pop()};
const s32 pos_x = m_drawing_offset.x + vp.x; const s32 pos_x = TruncateVertexPosition(m_drawing_offset.x + vp.x);
const s32 pos_y = m_drawing_offset.y + vp.y; const s32 pos_y = TruncateVertexPosition(m_drawing_offset.y + vp.y);
const auto [texcoord_x, texcoord_y] = UnpackTexcoord(rc.texture_enable ? Truncate16(m_fifo.Pop()) : 0); const auto [texcoord_x, texcoord_y] = UnpackTexcoord(rc.texture_enable ? Truncate16(m_fifo.Pop()) : 0);
u16 orig_tex_left = ZeroExtend16(texcoord_x); u16 orig_tex_left = ZeroExtend16(texcoord_x);

View file

@ -514,24 +514,24 @@ template<bool texture_enable, bool raw_texture_enable, bool transparency_enable>
void GPU_SW::DrawRectangle(s32 origin_x, s32 origin_y, u32 width, u32 height, u8 r, u8 g, u8 b, u8 origin_texcoord_x, void GPU_SW::DrawRectangle(s32 origin_x, s32 origin_y, u32 width, u32 height, u8 r, u8 g, u8 b, u8 origin_texcoord_x,
u8 origin_texcoord_y) u8 origin_texcoord_y)
{ {
origin_x += m_drawing_offset.x; const s32 start_x = TruncateVertexPosition(m_drawing_offset.x + origin_x);
origin_y += m_drawing_offset.y; const s32 start_y = TruncateVertexPosition(m_drawing_offset.y + origin_y);
{ {
const u32 clip_left = static_cast<u32>(std::clamp<s32>(origin_x, m_drawing_area.left, m_drawing_area.right)); const u32 clip_left = static_cast<u32>(std::clamp<s32>(start_x, m_drawing_area.left, m_drawing_area.right));
const u32 clip_right = const u32 clip_right =
static_cast<u32>(std::clamp<s32>(origin_x + static_cast<s32>(width), m_drawing_area.left, m_drawing_area.right)) + static_cast<u32>(std::clamp<s32>(start_x + static_cast<s32>(width), m_drawing_area.left, m_drawing_area.right)) +
1u;
const u32 clip_top = static_cast<u32>(std::clamp<s32>(start_y, m_drawing_area.top, m_drawing_area.bottom));
const u32 clip_bottom =
static_cast<u32>(std::clamp<s32>(start_y + static_cast<s32>(height), m_drawing_area.top, m_drawing_area.bottom)) +
1u; 1u;
const u32 clip_top = static_cast<u32>(std::clamp<s32>(origin_y, m_drawing_area.top, m_drawing_area.bottom));
const u32 clip_bottom = static_cast<u32>(std::clamp<s32>(origin_y + static_cast<s32>(height), m_drawing_area.top,
m_drawing_area.bottom)) +
1u;
AddDrawRectangleTicks(clip_right - clip_left, clip_bottom - clip_top, texture_enable); AddDrawRectangleTicks(clip_right - clip_left, clip_bottom - clip_top, texture_enable);
} }
for (u32 offset_y = 0; offset_y < height; offset_y++) for (u32 offset_y = 0; offset_y < height; offset_y++)
{ {
const s32 y = origin_y + static_cast<s32>(offset_y); const s32 y = start_y + static_cast<s32>(offset_y);
if (y < static_cast<s32>(m_drawing_area.top) || y > static_cast<s32>(m_drawing_area.bottom)) if (y < static_cast<s32>(m_drawing_area.top) || y > static_cast<s32>(m_drawing_area.bottom))
continue; continue;
@ -539,7 +539,7 @@ void GPU_SW::DrawRectangle(s32 origin_x, s32 origin_y, u32 width, u32 height, u8
for (u32 offset_x = 0; offset_x < width; offset_x++) for (u32 offset_x = 0; offset_x < width; offset_x++)
{ {
const s32 x = origin_x + static_cast<s32>(offset_x); const s32 x = start_x + static_cast<s32>(offset_x);
if (x < static_cast<s32>(m_drawing_area.left) || x > static_cast<s32>(m_drawing_area.right)) if (x < static_cast<s32>(m_drawing_area.left) || x > static_cast<s32>(m_drawing_area.right))
continue; continue;