gl_rasterizer: Implement polygon modes and fill rectangles
This commit is contained in:
		| @@ -524,6 +524,12 @@ public: | |||||||
|             FractionalEven = 2, |             FractionalEven = 2, | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |         enum class PolygonMode : u32 { | ||||||
|  |             Point = 0x1b00, | ||||||
|  |             Line = 0x1b01, | ||||||
|  |             Fill = 0x1b02, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|         struct RenderTargetConfig { |         struct RenderTargetConfig { | ||||||
|             u32 address_high; |             u32 address_high; | ||||||
|             u32 address_low; |             u32 address_low; | ||||||
| @@ -705,7 +711,12 @@ public: | |||||||
|  |  | ||||||
|                 s32 clear_stencil; |                 s32 clear_stencil; | ||||||
|  |  | ||||||
|                 INSERT_UNION_PADDING_WORDS(0x7); |                 INSERT_UNION_PADDING_WORDS(0x2); | ||||||
|  |  | ||||||
|  |                 PolygonMode polygon_mode_front; | ||||||
|  |                 PolygonMode polygon_mode_back; | ||||||
|  |  | ||||||
|  |                 INSERT_UNION_PADDING_WORDS(0x3); | ||||||
|  |  | ||||||
|                 u32 polygon_offset_point_enable; |                 u32 polygon_offset_point_enable; | ||||||
|                 u32 polygon_offset_line_enable; |                 u32 polygon_offset_line_enable; | ||||||
| @@ -764,7 +775,11 @@ public: | |||||||
|                     BitField<12, 4, u32> viewport; |                     BitField<12, 4, u32> viewport; | ||||||
|                 } clear_flags; |                 } clear_flags; | ||||||
|  |  | ||||||
|                 INSERT_UNION_PADDING_WORDS(0x19); |                 INSERT_UNION_PADDING_WORDS(0x10); | ||||||
|  |  | ||||||
|  |                 u32 fill_rectangle; | ||||||
|  |  | ||||||
|  |                 INSERT_UNION_PADDING_WORDS(0x8); | ||||||
|  |  | ||||||
|                 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; |                 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; | ||||||
|  |  | ||||||
| @@ -1422,6 +1437,8 @@ ASSERT_REG_POSITION(depth_mode, 0x35F); | |||||||
| ASSERT_REG_POSITION(clear_color[0], 0x360); | ASSERT_REG_POSITION(clear_color[0], 0x360); | ||||||
| ASSERT_REG_POSITION(clear_depth, 0x364); | ASSERT_REG_POSITION(clear_depth, 0x364); | ||||||
| ASSERT_REG_POSITION(clear_stencil, 0x368); | ASSERT_REG_POSITION(clear_stencil, 0x368); | ||||||
|  | ASSERT_REG_POSITION(polygon_mode_front, 0x36B); | ||||||
|  | ASSERT_REG_POSITION(polygon_mode_back, 0x36C); | ||||||
| ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370); | ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370); | ||||||
| ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371); | ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371); | ||||||
| ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372); | ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372); | ||||||
| @@ -1435,6 +1452,7 @@ ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); | |||||||
| ASSERT_REG_POSITION(depth_bounds, 0x3E7); | ASSERT_REG_POSITION(depth_bounds, 0x3E7); | ||||||
| ASSERT_REG_POSITION(zeta, 0x3F8); | ASSERT_REG_POSITION(zeta, 0x3F8); | ||||||
| ASSERT_REG_POSITION(clear_flags, 0x43E); | ASSERT_REG_POSITION(clear_flags, 0x43E); | ||||||
|  | ASSERT_REG_POSITION(fill_rectangle, 0x44F); | ||||||
| ASSERT_REG_POSITION(vertex_attrib_format, 0x458); | ASSERT_REG_POSITION(vertex_attrib_format, 0x458); | ||||||
| ASSERT_REG_POSITION(rt_control, 0x487); | ASSERT_REG_POSITION(rt_control, 0x487); | ||||||
| ASSERT_REG_POSITION(zeta_width, 0x48a); | ASSERT_REG_POSITION(zeta_width, 0x48a); | ||||||
|   | |||||||
| @@ -487,6 +487,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||||||
|  |  | ||||||
|     SyncViewport(); |     SyncViewport(); | ||||||
|     SyncRasterizeEnable(); |     SyncRasterizeEnable(); | ||||||
|  |     SyncPolygonModes(); | ||||||
|     SyncColorMask(); |     SyncColorMask(); | ||||||
|     SyncFragmentColorClampState(); |     SyncFragmentColorClampState(); | ||||||
|     SyncMultiSampleState(); |     SyncMultiSampleState(); | ||||||
| @@ -1097,6 +1098,45 @@ void RasterizerOpenGL::SyncRasterizeEnable() { | |||||||
|     oglEnable(GL_RASTERIZER_DISCARD, gpu.regs.rasterize_enable == 0); |     oglEnable(GL_RASTERIZER_DISCARD, gpu.regs.rasterize_enable == 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void RasterizerOpenGL::SyncPolygonModes() { | ||||||
|  |     auto& gpu = system.GPU().Maxwell3D(); | ||||||
|  |     auto& flags = gpu.dirty.flags; | ||||||
|  |     if (!flags[Dirty::PolygonModes]) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     flags[Dirty::PolygonModes] = false; | ||||||
|  |  | ||||||
|  |     if (gpu.regs.fill_rectangle) { | ||||||
|  |         if (!GLAD_GL_NV_fill_rectangle) { | ||||||
|  |             LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported"); | ||||||
|  |             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         flags[Dirty::PolygonModeFront] = true; | ||||||
|  |         flags[Dirty::PolygonModeBack] = true; | ||||||
|  |         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (gpu.regs.polygon_mode_front == gpu.regs.polygon_mode_back) { | ||||||
|  |         flags[Dirty::PolygonModeFront] = false; | ||||||
|  |         flags[Dirty::PolygonModeBack] = false; | ||||||
|  |         glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front)); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (flags[Dirty::PolygonModeFront]) { | ||||||
|  |         flags[Dirty::PolygonModeFront] = false; | ||||||
|  |         glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (flags[Dirty::PolygonModeBack]) { | ||||||
|  |         flags[Dirty::PolygonModeBack] = false; | ||||||
|  |         glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_back)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| void RasterizerOpenGL::SyncColorMask() { | void RasterizerOpenGL::SyncColorMask() { | ||||||
|     auto& gpu = system.GPU().Maxwell3D(); |     auto& gpu = system.GPU().Maxwell3D(); | ||||||
|     auto& flags = gpu.dirty.flags; |     auto& flags = gpu.dirty.flags; | ||||||
|   | |||||||
| @@ -178,6 +178,9 @@ private: | |||||||
|     /// Syncs the rasterizer enable state to match the guest state |     /// Syncs the rasterizer enable state to match the guest state | ||||||
|     void SyncRasterizeEnable(); |     void SyncRasterizeEnable(); | ||||||
|  |  | ||||||
|  |     /// Syncs polygon modes to match the guest state | ||||||
|  |     void SyncPolygonModes(); | ||||||
|  |  | ||||||
|     /// Syncs Color Mask |     /// Syncs Color Mask | ||||||
|     void SyncColorMask(); |     void SyncColorMask(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -94,6 +94,15 @@ void SetupDirtyShaders(Tables& tables) { | |||||||
|               Shaders); |               Shaders); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void SetupDirtyPolygonModes(Tables& tables) { | ||||||
|  |     tables[0][OFF(polygon_mode_front)] = PolygonModeFront; | ||||||
|  |     tables[0][OFF(polygon_mode_back)] = PolygonModeBack; | ||||||
|  |  | ||||||
|  |     tables[1][OFF(polygon_mode_front)] = PolygonModes; | ||||||
|  |     tables[1][OFF(polygon_mode_back)] = PolygonModes; | ||||||
|  |     tables[0][OFF(fill_rectangle)] = PolygonModes; | ||||||
|  | } | ||||||
|  |  | ||||||
| void SetupDirtyDepthTest(Tables& tables) { | void SetupDirtyDepthTest(Tables& tables) { | ||||||
|     auto& table = tables[0]; |     auto& table = tables[0]; | ||||||
|     table[OFF(depth_test_enable)] = DepthTest; |     table[OFF(depth_test_enable)] = DepthTest; | ||||||
| @@ -211,6 +220,7 @@ void StateTracker::Initialize() { | |||||||
|     SetupDirtyVertexArrays(tables); |     SetupDirtyVertexArrays(tables); | ||||||
|     SetupDirtyVertexFormat(tables); |     SetupDirtyVertexFormat(tables); | ||||||
|     SetupDirtyShaders(tables); |     SetupDirtyShaders(tables); | ||||||
|  |     SetupDirtyPolygonModes(tables); | ||||||
|     SetupDirtyDepthTest(tables); |     SetupDirtyDepthTest(tables); | ||||||
|     SetupDirtyStencilTest(tables); |     SetupDirtyStencilTest(tables); | ||||||
|     SetupDirtyAlphaTest(tables); |     SetupDirtyAlphaTest(tables); | ||||||
|   | |||||||
| @@ -59,6 +59,10 @@ enum : u8 { | |||||||
|     Shaders, |     Shaders, | ||||||
|     ClipDistances, |     ClipDistances, | ||||||
|  |  | ||||||
|  |     PolygonModes, | ||||||
|  |     PolygonModeFront, | ||||||
|  |     PolygonModeBack, | ||||||
|  |  | ||||||
|     ColorMask, |     ColorMask, | ||||||
|     FrontFace, |     FrontFace, | ||||||
|     CullTest, |     CullTest, | ||||||
| @@ -111,6 +115,13 @@ public: | |||||||
|         flags[OpenGL::Dirty::VertexInstance0 + 1] = true; |         flags[OpenGL::Dirty::VertexInstance0 + 1] = true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void NotifyPolygonModes() { | ||||||
|  |         auto& flags = system.GPU().Maxwell3D().dirty.flags; | ||||||
|  |         flags[OpenGL::Dirty::PolygonModes] = true; | ||||||
|  |         flags[OpenGL::Dirty::PolygonModeFront] = true; | ||||||
|  |         flags[OpenGL::Dirty::PolygonModeBack] = true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void NotifyViewport0() { |     void NotifyViewport0() { | ||||||
|         auto& flags = system.GPU().Maxwell3D().dirty.flags; |         auto& flags = system.GPU().Maxwell3D().dirty.flags; | ||||||
|         flags[OpenGL::Dirty::Viewports] = true; |         flags[OpenGL::Dirty::Viewports] = true; | ||||||
|   | |||||||
| @@ -488,5 +488,18 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) { | |||||||
|     return GL_COPY; |     return GL_COPY; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline GLenum PolygonMode(Maxwell::PolygonMode polygon_mode) { | ||||||
|  |     switch (polygon_mode) { | ||||||
|  |     case Maxwell::PolygonMode::Point: | ||||||
|  |         return GL_POINT; | ||||||
|  |     case Maxwell::PolygonMode::Line: | ||||||
|  |         return GL_LINE; | ||||||
|  |     case Maxwell::PolygonMode::Fill: | ||||||
|  |         return GL_FILL; | ||||||
|  |     } | ||||||
|  |     UNREACHABLE_MSG("Invalid polygon mode={}", static_cast<int>(polygon_mode)); | ||||||
|  |     return GL_FILL; | ||||||
|  | } | ||||||
|  |  | ||||||
| } // namespace MaxwellToGL | } // namespace MaxwellToGL | ||||||
| } // namespace OpenGL | } // namespace OpenGL | ||||||
|   | |||||||
| @@ -577,6 +577,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||||||
|  |  | ||||||
|     // TODO: Signal state tracker about these changes |     // TODO: Signal state tracker about these changes | ||||||
|     state_tracker.NotifyScreenDrawVertexArray(); |     state_tracker.NotifyScreenDrawVertexArray(); | ||||||
|  |     state_tracker.NotifyPolygonModes(); | ||||||
|     state_tracker.NotifyViewport0(); |     state_tracker.NotifyViewport0(); | ||||||
|     state_tracker.NotifyScissor0(); |     state_tracker.NotifyScissor0(); | ||||||
|     state_tracker.NotifyColorMask0(); |     state_tracker.NotifyColorMask0(); | ||||||
| @@ -612,6 +613,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||||||
|     glDisable(GL_ALPHA_TEST); |     glDisable(GL_ALPHA_TEST); | ||||||
|     glDisablei(GL_BLEND, 0); |     glDisablei(GL_BLEND, 0); | ||||||
|     glDisablei(GL_SCISSOR_TEST, 0); |     glDisablei(GL_SCISSOR_TEST, 0); | ||||||
|  |     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||||
|     glCullFace(GL_BACK); |     glCullFace(GL_BACK); | ||||||
|     glFrontFace(GL_CW); |     glFrontFace(GL_CW); | ||||||
|     glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |     glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user