From 390639e7956557fdb7defc5f427a813ed09c8e92 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 27 Sep 2019 22:45:57 +1000 Subject: [PATCH] GPU: Implement line rendering --- src/pse/gpu.cpp | 3 ++- src/pse/gpu.h | 4 ++-- src/pse/gpu_hw.cpp | 31 ++++++++++++++++++++++++++----- src/pse/gpu_hw.h | 5 +++-- src/pse/gpu_hw_opengl.cpp | 2 +- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/pse/gpu.cpp b/src/pse/gpu.cpp index 11ea2520a..182b86dc7 100644 --- a/src/pse/gpu.cpp +++ b/src/pse/gpu.cpp @@ -580,7 +580,8 @@ bool GPU::HandleRenderCommand() // polyline goes until we hit the termination code num_vertices = 0; bool found_terminator = false; - for (size_t pos = 0; pos < m_GP0_command.size(); pos += words_per_vertex) + for (u32 pos = BoolToUInt32(!rc.shading_enable); pos < static_cast(m_GP0_command.size()); + pos += words_per_vertex) { if (m_GP0_command[pos] == 0x55555555) { diff --git a/src/pse/gpu.h b/src/pse/gpu.h index ac9d46980..b82cf7812 100644 --- a/src/pse/gpu.h +++ b/src/pse/gpu.h @@ -151,8 +151,8 @@ protected: BitField x_s11; BitField y_s11; - u32 x() const { return S11ToS32(x_s11); } - u32 y() const { return S11ToS32(y_s11); } + s32 x() const { return S11ToS32(x_s11); } + s32 y() const { return S11ToS32(y_s11); } }; void SoftReset(); diff --git a/src/pse/gpu_hw.cpp b/src/pse/gpu_hw.cpp index c6b03116c..f25607dce 100644 --- a/src/pse/gpu_hw.cpp +++ b/src/pse/gpu_hw.cpp @@ -111,6 +111,26 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices) } break; + case Primitive::Line: + { + const u32 first_color = rc.color_for_first_vertex; + const bool shaded = rc.shading_enable; + + u32 buffer_pos = 1; + for (u32 i = 0; i < num_vertices; i++) + { + // x/y are encoded differently for lines - 16 bits each + const u32 color = (shaded && i > 0) ? (m_GP0_command[buffer_pos++] & UINT32_C(0x00FFFFFF)) : first_color; + const s32 x = Truncate16(m_GP0_command[buffer_pos]); + const s32 y = Truncate16(m_GP0_command[buffer_pos++] >> 16); + m_batch.vertices.push_back(HWVertex{x, y, color}); + } + + FlushRender(); + UpdateDisplay(); + } + break; + default: UnreachableCode(); break; @@ -357,7 +377,7 @@ void main() GPU_HW::HWRenderBatch::Primitive GPU_HW::GetPrimitiveForCommand(RenderCommand rc) { if (rc.primitive == Primitive::Line) - return HWRenderBatch::Primitive::Lines; + return rc.polyline ? HWRenderBatch::Primitive::LineStrip : HWRenderBatch::Primitive::Lines; else if ((rc.primitive == Primitive::Polygon && rc.quad_polygon) || rc.primitive == Primitive::Rectangle) return HWRenderBatch::Primitive::TriangleStrip; else @@ -395,9 +415,9 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) } // has any state changed which requires a new batch? - const bool rc_transparency_enable = rc.transparency_enable; - const bool rc_texture_enable = rc.texture_enable; - const bool rc_texture_blend_enable = !rc.texture_blend_disable; + const bool rc_transparency_enable = rc.IsTransparencyEnabled(); + const bool rc_texture_enable = rc.IsTextureEnabled(); + const bool rc_texture_blend_enable = rc.IsTextureBlendingEnabled(); const HWRenderBatch::Primitive rc_primitive = GetPrimitiveForCommand(rc); const u32 max_added_vertices = num_vertices + 2; const bool buffer_overflow = (m_batch.vertices.size() + max_added_vertices) >= MAX_BATCH_VERTEX_COUNT; @@ -405,9 +425,10 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices) m_batch.render_command_bits != rc.bits && m_batch.transparency_enable != rc_transparency_enable || m_batch.texture_enable != rc_texture_enable || m_batch.texture_blending_enable != rc_texture_blend_enable || m_batch.primitive != rc_primitive; + const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip); const bool needs_flush = !IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() || - buffer_overflow || rc_changed); + buffer_overflow || rc_changed || restart_line_strip); if (needs_flush) FlushRender(); diff --git a/src/pse/gpu_hw.h b/src/pse/gpu_hw.h index 4e859a906..8265fa216 100644 --- a/src/pse/gpu_hw.h +++ b/src/pse/gpu_hw.h @@ -32,8 +32,9 @@ protected: enum class Primitive : u8 { Lines = 0, - Triangles = 1, - TriangleStrip = 2 + LineStrip = 1, + Triangles = 2, + TriangleStrip = 3 }; u32 render_command_bits; diff --git a/src/pse/gpu_hw_opengl.cpp b/src/pse/gpu_hw_opengl.cpp index 3454ba998..6c180581d 100644 --- a/src/pse/gpu_hw_opengl.cpp +++ b/src/pse/gpu_hw_opengl.cpp @@ -441,7 +441,7 @@ void GPU_HW_OpenGL::FlushRender() glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast(sizeof(HWVertex) * m_batch.vertices.size()), m_batch.vertices.data()); - static constexpr std::array gl_primitives = {{GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP}}; + static constexpr std::array gl_primitives = {{GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP}}; glDrawArrays(gl_primitives[static_cast(m_batch.primitive)], 0, static_cast(m_batch.vertices.size())); m_batch.vertices.clear();