GPU: Implement line rendering

This commit is contained in:
Connor McLaughlin 2019-09-27 22:45:57 +10:00
parent f2a3629016
commit 390639e795
5 changed files with 34 additions and 11 deletions

View file

@ -580,7 +580,8 @@ bool GPU::HandleRenderCommand()
// polyline goes until we hit the termination code // polyline goes until we hit the termination code
num_vertices = 0; num_vertices = 0;
bool found_terminator = false; 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<u32>(m_GP0_command.size());
pos += words_per_vertex)
{ {
if (m_GP0_command[pos] == 0x55555555) if (m_GP0_command[pos] == 0x55555555)
{ {

View file

@ -151,8 +151,8 @@ protected:
BitField<u32, u32, 0, 11> x_s11; BitField<u32, u32, 0, 11> x_s11;
BitField<u32, u32, 16, 11> y_s11; BitField<u32, u32, 16, 11> y_s11;
u32 x() const { return S11ToS32(x_s11); } s32 x() const { return S11ToS32(x_s11); }
u32 y() const { return S11ToS32(y_s11); } s32 y() const { return S11ToS32(y_s11); }
}; };
void SoftReset(); void SoftReset();

View file

@ -111,6 +111,26 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices)
} }
break; 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: default:
UnreachableCode(); UnreachableCode();
break; break;
@ -357,7 +377,7 @@ void main()
GPU_HW::HWRenderBatch::Primitive GPU_HW::GetPrimitiveForCommand(RenderCommand rc) GPU_HW::HWRenderBatch::Primitive GPU_HW::GetPrimitiveForCommand(RenderCommand rc)
{ {
if (rc.primitive == Primitive::Line) 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) else if ((rc.primitive == Primitive::Polygon && rc.quad_polygon) || rc.primitive == Primitive::Rectangle)
return HWRenderBatch::Primitive::TriangleStrip; return HWRenderBatch::Primitive::TriangleStrip;
else else
@ -395,9 +415,9 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
} }
// has any state changed which requires a new batch? // has any state changed which requires a new batch?
const bool rc_transparency_enable = rc.transparency_enable; const bool rc_transparency_enable = rc.IsTransparencyEnabled();
const bool rc_texture_enable = rc.texture_enable; const bool rc_texture_enable = rc.IsTextureEnabled();
const bool rc_texture_blend_enable = !rc.texture_blend_disable; const bool rc_texture_blend_enable = rc.IsTextureBlendingEnabled();
const HWRenderBatch::Primitive rc_primitive = GetPrimitiveForCommand(rc); const HWRenderBatch::Primitive rc_primitive = GetPrimitiveForCommand(rc);
const u32 max_added_vertices = num_vertices + 2; const u32 max_added_vertices = num_vertices + 2;
const bool buffer_overflow = (m_batch.vertices.size() + max_added_vertices) >= MAX_BATCH_VERTEX_COUNT; 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.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.texture_enable != rc_texture_enable || m_batch.texture_blending_enable != rc_texture_blend_enable ||
m_batch.primitive != rc_primitive; m_batch.primitive != rc_primitive;
const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip);
const bool needs_flush = const bool needs_flush =
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() || !IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
buffer_overflow || rc_changed); buffer_overflow || rc_changed || restart_line_strip);
if (needs_flush) if (needs_flush)
FlushRender(); FlushRender();

View file

@ -32,8 +32,9 @@ protected:
enum class Primitive : u8 enum class Primitive : u8
{ {
Lines = 0, Lines = 0,
Triangles = 1, LineStrip = 1,
TriangleStrip = 2 Triangles = 2,
TriangleStrip = 3
}; };
u32 render_command_bits; u32 render_command_bits;

View file

@ -441,7 +441,7 @@ void GPU_HW_OpenGL::FlushRender()
glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizei>(sizeof(HWVertex) * m_batch.vertices.size()), glBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizei>(sizeof(HWVertex) * m_batch.vertices.size()),
m_batch.vertices.data()); m_batch.vertices.data());
static constexpr std::array<GLenum, 3> gl_primitives = {{GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP}}; static constexpr std::array<GLenum, 4> gl_primitives = {{GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP}};
glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], 0, static_cast<GLsizei>(m_batch.vertices.size())); glDrawArrays(gl_primitives[static_cast<u8>(m_batch.primitive)], 0, static_cast<GLsizei>(m_batch.vertices.size()));
m_batch.vertices.clear(); m_batch.vertices.clear();