GPU/HW: Fix potential crash in rectangle expansion

This commit is contained in:
Connor McLaughlin 2020-02-28 22:58:31 +10:00
parent a298e93004
commit 0690491883
2 changed files with 23 additions and 7 deletions

View file

@ -88,6 +88,7 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command
case Primitive::Polygon:
{
DebugAssert(num_vertices == 3 || num_vertices == 4);
EnsureVertexBufferSpace(rc.quad_polygon ? 6 : 3);
const u32 first_color = rc.color_for_first_vertex;
const bool shaded = rc.shading_enable;
@ -201,6 +202,11 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command
return;
}
// we can split the rectangle up into potentially 8 quads
const u32 required_vertices = 6 * ((rectangle_width + (TEXTURE_PAGE_WIDTH - 1)) / TEXTURE_PAGE_WIDTH) *
((rectangle_height + (TEXTURE_PAGE_HEIGHT - 1)) / TEXTURE_PAGE_HEIGHT);
EnsureVertexBufferSpace(required_vertices);
min_x = pos_x;
min_y = pos_y;
max_x = pos_x + rectangle_width;
@ -243,6 +249,8 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command
case Primitive::Line:
{
EnsureVertexBufferSpace(num_vertices * 2);
const u32 first_color = rc.color_for_first_vertex;
const bool shaded = rc.shading_enable;
@ -348,6 +356,19 @@ void GPU_HW::IncludeVRAMDityRectangle(const Common::Rectangle<u32>& rect)
}
}
void GPU_HW::EnsureVertexBufferSpace(u32 required_vertices)
{
if (m_batch_current_vertex_ptr)
{
if (GetBatchVertexSpace() >= required_vertices)
return;
FlushRender();
}
MapBatchVertexPointer(required_vertices);
}
void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
{
IncludeVRAMDityRectangle(
@ -406,11 +427,9 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
rc.transparency_enable ? m_draw_mode.GetTransparencyMode() : TransparencyMode::Disabled;
const BatchPrimitive rc_primitive = GetPrimitiveForCommand(rc);
const bool dithering_enable = (!m_true_color && rc.IsDitheringEnabled()) ? m_GPUSTAT.dither_enable : false;
const u32 max_added_vertices = num_vertices + 5;
if (!IsFlushed())
{
const bool buffer_overflow = GetBatchVertexSpace() < max_added_vertices;
if (buffer_overflow || m_batch.texture_mode != texture_mode || m_batch.transparency_mode != transparency_mode ||
if (m_batch.texture_mode != texture_mode || m_batch.transparency_mode != transparency_mode ||
m_batch.primitive != rc_primitive || dithering_enable != m_batch.dithering || m_drawing_area_changed ||
m_drawing_offset_changed || m_draw_mode.IsTextureWindowChanged())
{
@ -444,10 +463,6 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
m_batch_ubo_dirty = true;
}
// map buffer if it's not already done
if (!m_batch_current_vertex_ptr)
MapBatchVertexPointer(max_added_vertices);
// update state
m_batch.primitive = rc_primitive;
m_batch.texture_mode = texture_mode;

View file

@ -132,6 +132,7 @@ protected:
u32 GetBatchVertexSpace() const { return static_cast<u32>(m_batch_end_vertex_ptr - m_batch_current_vertex_ptr); }
u32 GetBatchVertexCount() const { return static_cast<u32>(m_batch_current_vertex_ptr - m_batch_start_vertex_ptr); }
void EnsureVertexBufferSpace(u32 required_vertices);
bool IsFlushed() const { return m_batch_current_vertex_ptr == m_batch_start_vertex_ptr; }