diff --git a/src/core/gpu.h b/src/core/gpu.h index 880c903a7..c62f1e8db 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -88,6 +88,8 @@ public: VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16), TEXTURE_PAGE_WIDTH = 256, TEXTURE_PAGE_HEIGHT = 256, + MAX_PRIMITIVE_WIDTH = 1024, + MAX_PRIMITIVE_HEIGHT = 512, DOT_TIMER_INDEX = 0, HBLANK_TIMER_INDEX = 1 }; diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index d2b42ff79..2f42f21c8 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -79,14 +79,27 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command const bool shaded = rc.shading_enable; const bool textured = rc.texture_enable; + BatchVertex* old_vertex_ptr = m_batch_current_vertex_ptr; + s32 min_x = std::numeric_limits::max(); + s32 max_x = std::numeric_limits::min(); + s32 min_y = std::numeric_limits::max(); + s32 max_y = std::numeric_limits::min(); + u32 buffer_pos = 1; for (u32 i = 0; i < num_vertices; i++) { const u32 color = (shaded && i > 0) ? (command_ptr[buffer_pos++] & UINT32_C(0x00FFFFFF)) : first_color; const VertexPosition vp{command_ptr[buffer_pos++]}; const u16 packed_texcoord = textured ? Truncate16(command_ptr[buffer_pos++]) : 0; + const s32 x = vp.x; + const s32 y = vp.y; - (m_batch_current_vertex_ptr++)->Set(vp.x, vp.y, color, texpage, packed_texcoord); + min_x = std::min(min_x, x); + max_x = std::max(max_x, x); + min_y = std::min(min_y, y); + max_y = std::max(max_y, y); + + (m_batch_current_vertex_ptr++)->Set(x, y, color, texpage, packed_texcoord); if (restart_strip) { @@ -94,6 +107,10 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command restart_strip = false; } } + + // Cull polygons which are too large. + if ((max_x - min_x) > MAX_PRIMITIVE_WIDTH || (max_y - min_y) > MAX_PRIMITIVE_HEIGHT) + m_batch_current_vertex_ptr = old_vertex_ptr; } break; @@ -135,6 +152,9 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command break; } + if (rectangle_width >= MAX_PRIMITIVE_WIDTH || rectangle_height >= MAX_PRIMITIVE_HEIGHT) + return; + // TODO: This should repeat the texcoords instead of stretching const s32 pos_right = pos_left + static_cast(rectangle_width); const s32 pos_bottom = pos_top + static_cast(rectangle_height); @@ -156,13 +176,30 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command const u32 first_color = rc.color_for_first_vertex; const bool shaded = rc.shading_enable; + BatchVertex* old_vertex_ptr = m_batch_current_vertex_ptr; + s32 min_x = std::numeric_limits::max(); + s32 max_x = std::numeric_limits::min(); + s32 min_y = std::numeric_limits::max(); + s32 max_y = std::numeric_limits::min(); + u32 buffer_pos = 1; for (u32 i = 0; i < num_vertices; i++) { const u32 color = (shaded && i > 0) ? (command_ptr[buffer_pos++] & UINT32_C(0x00FFFFFF)) : first_color; const VertexPosition vp{command_ptr[buffer_pos++]}; - (m_batch_current_vertex_ptr++)->Set(vp.x, vp.y, color, 0, 0); + const s32 x = vp.x; + const s32 y = vp.y; + + min_x = std::min(min_x, x); + max_x = std::max(max_x, x); + min_y = std::min(min_y, y); + max_y = std::max(max_y, y); + + (m_batch_current_vertex_ptr++)->Set(x, y, color, 0, 0); } + + if ((max_x - min_x) > MAX_PRIMITIVE_WIDTH || (max_y - min_y) > MAX_PRIMITIVE_HEIGHT) + m_batch_current_vertex_ptr = old_vertex_ptr; } break; diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index 1db8234d4..e7692ca05 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -303,7 +303,7 @@ void GPU_SW::DrawTriangle(RenderCommand rc, const SWVertex* v0, const SWVertex* s32 max_y = std::max(py0, std::max(py1, py2)); // reject triangles which cover the whole vram area - if ((max_x - min_x) >= VRAM_WIDTH || (max_y - min_y) >= VRAM_HEIGHT) + if ((max_x - min_x) > MAX_PRIMITIVE_WIDTH || (max_y - min_y) > MAX_PRIMITIVE_HEIGHT) return; // clip to drawing area