VideoCore: Split rasterizer regs from Regs struct
This commit is contained in:
		| @@ -359,7 +359,7 @@ void GraphicsVertexShaderWidget::DumpShader() { | ||||
|     auto& config = Pica::g_state.regs.vs; | ||||
|  | ||||
|     Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, | ||||
|                                  Pica::g_state.regs.vs_output_attributes); | ||||
|                                  Pica::g_state.regs.rasterizer.vs_output_attributes); | ||||
| } | ||||
|  | ||||
| GraphicsVertexShaderWidget::GraphicsVertexShaderWidget( | ||||
|   | ||||
| @@ -32,6 +32,7 @@ set(HEADERS | ||||
|             primitive_assembly.h | ||||
|             rasterizer.h | ||||
|             rasterizer_interface.h | ||||
|             regs_rasterizer.h | ||||
|             renderer_base.h | ||||
|             renderer_opengl/gl_rasterizer.h | ||||
|             renderer_opengl/gl_rasterizer_cache.h | ||||
|   | ||||
| @@ -64,10 +64,10 @@ static void InitScreenCoordinates(Vertex& vtx) { | ||||
|     } viewport; | ||||
|  | ||||
|     const auto& regs = g_state.regs; | ||||
|     viewport.halfsize_x = float24::FromRaw(regs.viewport_size_x); | ||||
|     viewport.halfsize_y = float24::FromRaw(regs.viewport_size_y); | ||||
|     viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.viewport_corner.x)); | ||||
|     viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.viewport_corner.y)); | ||||
|     viewport.halfsize_x = float24::FromRaw(regs.rasterizer.viewport_size_x); | ||||
|     viewport.halfsize_y = float24::FromRaw(regs.rasterizer.viewport_size_y); | ||||
|     viewport.offset_x = float24::FromFloat32(static_cast<float>(regs.rasterizer.viewport_corner.x)); | ||||
|     viewport.offset_y = float24::FromFloat32(static_cast<float>(regs.rasterizer.viewport_corner.y)); | ||||
|  | ||||
|     float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; | ||||
|     vtx.color *= inv_w; | ||||
|   | ||||
| @@ -165,7 +165,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||
|                     }; | ||||
|  | ||||
|                     g_state.primitive_assembler.SubmitVertex( | ||||
|                         Shader::OutputVertex::FromAttributeBuffer(regs, output), AddTriangle); | ||||
|                         Shader::OutputVertex::FromAttributeBuffer(regs.rasterizer, output), | ||||
|                         AddTriangle); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -295,7 +296,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||
|                 shader_unit.WriteOutput(regs.vs, output); | ||||
|  | ||||
|                 // Retrieve vertex from register data | ||||
|                 output_vertex = Shader::OutputVertex::FromAttributeBuffer(regs, output); | ||||
|                 output_vertex = Shader::OutputVertex::FromAttributeBuffer(regs.rasterizer, output); | ||||
|  | ||||
|                 if (is_indexed) { | ||||
|                     vertex_cache[vertex_cache_pos] = output_vertex; | ||||
|   | ||||
| @@ -90,7 +90,7 @@ namespace DebugUtils { | ||||
|  | ||||
| void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, | ||||
|                 const Shader::ShaderSetup& setup, | ||||
|                 const Regs::VSOutputAttributes* output_attributes) { | ||||
|                 const RasterizerRegs::VSOutputAttributes* output_attributes) { | ||||
|     struct StuffToWrite { | ||||
|         const u8* pointer; | ||||
|         u32 size; | ||||
| @@ -129,7 +129,7 @@ void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, | ||||
|     // This is put into a try-catch block to make sure we notice unknown configurations. | ||||
|     std::vector<OutputRegisterInfo> output_info_table; | ||||
|     for (unsigned i = 0; i < 7; ++i) { | ||||
|         using OutputAttributes = Pica::Regs::VSOutputAttributes; | ||||
|         using OutputAttributes = Pica::RasterizerRegs::VSOutputAttributes; | ||||
|  | ||||
|         // TODO: It's still unclear how the attribute components map to the register! | ||||
|         //       Once we know that, this code probably will not make much sense anymore. | ||||
|   | ||||
| @@ -184,7 +184,7 @@ namespace DebugUtils { | ||||
|  | ||||
| void DumpShader(const std::string& filename, const Regs::ShaderConfig& config, | ||||
|                 const Shader::ShaderSetup& setup, | ||||
|                 const Regs::VSOutputAttributes* output_attributes); | ||||
|                 const RasterizerRegs::VSOutputAttributes* output_attributes); | ||||
|  | ||||
| // Utility class to log Pica commands. | ||||
| struct PicaTrace { | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/vector_math.h" | ||||
| #include "video_core/regs_rasterizer.h" | ||||
|  | ||||
| namespace Pica { | ||||
|  | ||||
| @@ -44,121 +45,10 @@ namespace Pica { | ||||
| #endif // _MSC_VER | ||||
|  | ||||
| struct Regs { | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x10); | ||||
|  | ||||
|     u32 trigger_irq; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x2f); | ||||
|  | ||||
|     enum class CullMode : u32 { | ||||
|         // Select which polygons are considered to be "frontfacing". | ||||
|         KeepAll = 0, | ||||
|         KeepClockWise = 1, | ||||
|         KeepCounterClockWise = 2, | ||||
|         // TODO: What does the third value imply? | ||||
|     }; | ||||
|  | ||||
|     union { | ||||
|         BitField<0, 2, CullMode> cull_mode; | ||||
|     }; | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_size_x; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_size_y; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x9); | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_depth_range;      // float24 | ||||
|     BitField<0, 24, u32> viewport_depth_near_plane; // float24 | ||||
|  | ||||
|     BitField<0, 3, u32> vs_output_total; | ||||
|  | ||||
|     union VSOutputAttributes { | ||||
|         // Maps components of output vertex attributes to semantics | ||||
|         enum Semantic : u32 { | ||||
|             POSITION_X = 0, | ||||
|             POSITION_Y = 1, | ||||
|             POSITION_Z = 2, | ||||
|             POSITION_W = 3, | ||||
|  | ||||
|             QUATERNION_X = 4, | ||||
|             QUATERNION_Y = 5, | ||||
|             QUATERNION_Z = 6, | ||||
|             QUATERNION_W = 7, | ||||
|  | ||||
|             COLOR_R = 8, | ||||
|             COLOR_G = 9, | ||||
|             COLOR_B = 10, | ||||
|             COLOR_A = 11, | ||||
|  | ||||
|             TEXCOORD0_U = 12, | ||||
|             TEXCOORD0_V = 13, | ||||
|             TEXCOORD1_U = 14, | ||||
|             TEXCOORD1_V = 15, | ||||
|  | ||||
|             TEXCOORD0_W = 16, | ||||
|  | ||||
|             VIEW_X = 18, | ||||
|             VIEW_Y = 19, | ||||
|             VIEW_Z = 20, | ||||
|  | ||||
|             TEXCOORD2_U = 22, | ||||
|             TEXCOORD2_V = 23, | ||||
|  | ||||
|             INVALID = 31, | ||||
|         }; | ||||
|  | ||||
|         BitField<0, 5, Semantic> map_x; | ||||
|         BitField<8, 5, Semantic> map_y; | ||||
|         BitField<16, 5, Semantic> map_z; | ||||
|         BitField<24, 5, Semantic> map_w; | ||||
|     } vs_output_attributes[7]; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0xe); | ||||
|  | ||||
|     enum class ScissorMode : u32 { | ||||
|         Disabled = 0, | ||||
|         Exclude = 1, // Exclude pixels inside the scissor box | ||||
|  | ||||
|         Include = 3 // Exclude pixels outside the scissor box | ||||
|     }; | ||||
|  | ||||
|     struct { | ||||
|         BitField<0, 2, ScissorMode> mode; | ||||
|  | ||||
|         union { | ||||
|             BitField<0, 16, u32> x1; | ||||
|             BitField<16, 16, u32> y1; | ||||
|         }; | ||||
|  | ||||
|         union { | ||||
|             BitField<0, 16, u32> x2; | ||||
|             BitField<16, 16, u32> y2; | ||||
|         }; | ||||
|     } scissor_test; | ||||
|  | ||||
|     union { | ||||
|         BitField<0, 10, s32> x; | ||||
|         BitField<16, 10, s32> y; | ||||
|     } viewport_corner; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     // TODO: early depth | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x2); | ||||
|  | ||||
|     enum DepthBuffering : u32 { | ||||
|         WBuffering = 0, | ||||
|         ZBuffering = 1, | ||||
|     }; | ||||
|     BitField<0, 1, DepthBuffering> depthmap_enable; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x12); | ||||
|     RasterizerRegs rasterizer; | ||||
|  | ||||
|     struct TextureConfig { | ||||
|         enum TextureType : u32 { | ||||
| @@ -1338,16 +1228,19 @@ private: | ||||
|                   "Field " #field_name " has invalid position") | ||||
|  | ||||
| ASSERT_REG_POSITION(trigger_irq, 0x10); | ||||
| ASSERT_REG_POSITION(cull_mode, 0x40); | ||||
| ASSERT_REG_POSITION(viewport_size_x, 0x41); | ||||
| ASSERT_REG_POSITION(viewport_size_y, 0x43); | ||||
| ASSERT_REG_POSITION(viewport_depth_range, 0x4d); | ||||
| ASSERT_REG_POSITION(viewport_depth_near_plane, 0x4e); | ||||
| ASSERT_REG_POSITION(vs_output_attributes[0], 0x50); | ||||
| ASSERT_REG_POSITION(vs_output_attributes[1], 0x51); | ||||
| ASSERT_REG_POSITION(scissor_test, 0x65); | ||||
| ASSERT_REG_POSITION(viewport_corner, 0x68); | ||||
| ASSERT_REG_POSITION(depthmap_enable, 0x6D); | ||||
|  | ||||
| ASSERT_REG_POSITION(rasterizer, 0x40); | ||||
| ASSERT_REG_POSITION(rasterizer.cull_mode, 0x40); | ||||
| ASSERT_REG_POSITION(rasterizer.viewport_size_x, 0x41); | ||||
| ASSERT_REG_POSITION(rasterizer.viewport_size_y, 0x43); | ||||
| ASSERT_REG_POSITION(rasterizer.viewport_depth_range, 0x4d); | ||||
| ASSERT_REG_POSITION(rasterizer.viewport_depth_near_plane, 0x4e); | ||||
| ASSERT_REG_POSITION(rasterizer.vs_output_attributes[0], 0x50); | ||||
| ASSERT_REG_POSITION(rasterizer.vs_output_attributes[1], 0x51); | ||||
| ASSERT_REG_POSITION(rasterizer.scissor_test, 0x65); | ||||
| ASSERT_REG_POSITION(rasterizer.viewport_corner, 0x68); | ||||
| ASSERT_REG_POSITION(rasterizer.depthmap_enable, 0x6D); | ||||
|  | ||||
| ASSERT_REG_POSITION(texture0_enable, 0x80); | ||||
| ASSERT_REG_POSITION(texture0, 0x81); | ||||
| ASSERT_REG_POSITION(texture0_format, 0x8e); | ||||
|   | ||||
| @@ -327,14 +327,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | ||||
|                                   ScreenToRasterizerCoordinates(v1.screenpos), | ||||
|                                   ScreenToRasterizerCoordinates(v2.screenpos)}; | ||||
|  | ||||
|     if (regs.cull_mode == Regs::CullMode::KeepAll) { | ||||
|     if (regs.rasterizer.cull_mode == RasterizerRegs::CullMode::KeepAll) { | ||||
|         // Make sure we always end up with a triangle wound counter-clockwise | ||||
|         if (!reversed && SignedArea(vtxpos[0].xy(), vtxpos[1].xy(), vtxpos[2].xy()) <= 0) { | ||||
|             ProcessTriangleInternal(v0, v2, v1, true); | ||||
|             return; | ||||
|         } | ||||
|     } else { | ||||
|         if (!reversed && regs.cull_mode == Regs::CullMode::KeepClockWise) { | ||||
|         if (!reversed && regs.rasterizer.cull_mode == RasterizerRegs::CullMode::KeepClockWise) { | ||||
|             // Reverse vertex order and use the CCW code path. | ||||
|             ProcessTriangleInternal(v0, v2, v1, true); | ||||
|             return; | ||||
| @@ -351,13 +351,13 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | ||||
|     u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); | ||||
|  | ||||
|     // Convert the scissor box coordinates to 12.4 fixed point | ||||
|     u16 scissor_x1 = (u16)(regs.scissor_test.x1 << 4); | ||||
|     u16 scissor_y1 = (u16)(regs.scissor_test.y1 << 4); | ||||
|     u16 scissor_x1 = (u16)(regs.rasterizer.scissor_test.x1 << 4); | ||||
|     u16 scissor_y1 = (u16)(regs.rasterizer.scissor_test.y1 << 4); | ||||
|     // x2,y2 have +1 added to cover the entire sub-pixel area | ||||
|     u16 scissor_x2 = (u16)((regs.scissor_test.x2 + 1) << 4); | ||||
|     u16 scissor_y2 = (u16)((regs.scissor_test.y2 + 1) << 4); | ||||
|     u16 scissor_x2 = (u16)((regs.rasterizer.scissor_test.x2 + 1) << 4); | ||||
|     u16 scissor_y2 = (u16)((regs.rasterizer.scissor_test.y2 + 1) << 4); | ||||
|  | ||||
|     if (regs.scissor_test.mode == Regs::ScissorMode::Include) { | ||||
|     if (regs.rasterizer.scissor_test.mode == RasterizerRegs::ScissorMode::Include) { | ||||
|         // Calculate the new bounds | ||||
|         min_x = std::max(min_x, scissor_x1); | ||||
|         min_y = std::max(min_y, scissor_y1); | ||||
| @@ -411,7 +411,7 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | ||||
|  | ||||
|             // Do not process the pixel if it's inside the scissor box and the scissor mode is set | ||||
|             // to Exclude | ||||
|             if (regs.scissor_test.mode == Regs::ScissorMode::Exclude) { | ||||
|             if (regs.rasterizer.scissor_test.mode == RasterizerRegs::ScissorMode::Exclude) { | ||||
|                 if (x >= scissor_x1 && x < scissor_x2 && y >= scissor_y1 && y < scissor_y2) | ||||
|                     continue; | ||||
|             } | ||||
| @@ -441,12 +441,14 @@ static void ProcessTriangleInternal(const Vertex& v0, const Vertex& v1, const Ve | ||||
|  | ||||
|             // Not fully accurate. About 3 bits in precision are missing. | ||||
|             // Z-Buffer (z / w * scale + offset) | ||||
|             float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32(); | ||||
|             float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32(); | ||||
|             float depth_scale = float24::FromRaw(regs.rasterizer.viewport_depth_range).ToFloat32(); | ||||
|             float depth_offset = | ||||
|                 float24::FromRaw(regs.rasterizer.viewport_depth_near_plane).ToFloat32(); | ||||
|             float depth = interpolated_z_over_w * depth_scale + depth_offset; | ||||
|  | ||||
|             // Potentially switch to W-Buffer | ||||
|             if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) { | ||||
|             if (regs.rasterizer.depthmap_enable == | ||||
|                 Pica::RasterizerRegs::DepthBuffering::WBuffering) { | ||||
|                 // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w) | ||||
|                 depth *= interpolated_w_inverse.ToFloat32() * wsum; | ||||
|             } | ||||
|   | ||||
							
								
								
									
										129
									
								
								src/video_core/regs_rasterizer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/video_core/regs_rasterizer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| // Copyright 2017 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
|  | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| namespace Pica { | ||||
|  | ||||
| struct RasterizerRegs { | ||||
|     enum class CullMode : u32 { | ||||
|         // Select which polygons are considered to be "frontfacing". | ||||
|         KeepAll = 0, | ||||
|         KeepClockWise = 1, | ||||
|         KeepCounterClockWise = 2, | ||||
|         // TODO: What does the third value imply? | ||||
|     }; | ||||
|  | ||||
|     union { | ||||
|         BitField<0, 2, CullMode> cull_mode; | ||||
|     }; | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_size_x; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_size_y; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x9); | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_depth_range;      // float24 | ||||
|     BitField<0, 24, u32> viewport_depth_near_plane; // float24 | ||||
|  | ||||
|     BitField<0, 3, u32> vs_output_total; | ||||
|  | ||||
|     union VSOutputAttributes { | ||||
|         // Maps components of output vertex attributes to semantics | ||||
|         enum Semantic : u32 { | ||||
|             POSITION_X = 0, | ||||
|             POSITION_Y = 1, | ||||
|             POSITION_Z = 2, | ||||
|             POSITION_W = 3, | ||||
|  | ||||
|             QUATERNION_X = 4, | ||||
|             QUATERNION_Y = 5, | ||||
|             QUATERNION_Z = 6, | ||||
|             QUATERNION_W = 7, | ||||
|  | ||||
|             COLOR_R = 8, | ||||
|             COLOR_G = 9, | ||||
|             COLOR_B = 10, | ||||
|             COLOR_A = 11, | ||||
|  | ||||
|             TEXCOORD0_U = 12, | ||||
|             TEXCOORD0_V = 13, | ||||
|             TEXCOORD1_U = 14, | ||||
|             TEXCOORD1_V = 15, | ||||
|  | ||||
|             TEXCOORD0_W = 16, | ||||
|  | ||||
|             VIEW_X = 18, | ||||
|             VIEW_Y = 19, | ||||
|             VIEW_Z = 20, | ||||
|  | ||||
|             TEXCOORD2_U = 22, | ||||
|             TEXCOORD2_V = 23, | ||||
|  | ||||
|             INVALID = 31, | ||||
|         }; | ||||
|  | ||||
|         BitField<0, 5, Semantic> map_x; | ||||
|         BitField<8, 5, Semantic> map_y; | ||||
|         BitField<16, 5, Semantic> map_z; | ||||
|         BitField<24, 5, Semantic> map_w; | ||||
|     } vs_output_attributes[7]; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0xe); | ||||
|  | ||||
|     enum class ScissorMode : u32 { | ||||
|         Disabled = 0, | ||||
|         Exclude = 1, // Exclude pixels inside the scissor box | ||||
|  | ||||
|         Include = 3 // Exclude pixels outside the scissor box | ||||
|     }; | ||||
|  | ||||
|     struct { | ||||
|         BitField<0, 2, ScissorMode> mode; | ||||
|  | ||||
|         union { | ||||
|             BitField<0, 16, u32> x1; | ||||
|             BitField<16, 16, u32> y1; | ||||
|         }; | ||||
|  | ||||
|         union { | ||||
|             BitField<0, 16, u32> x2; | ||||
|             BitField<16, 16, u32> y2; | ||||
|         }; | ||||
|     } scissor_test; | ||||
|  | ||||
|     union { | ||||
|         BitField<0, 10, s32> x; | ||||
|         BitField<16, 10, s32> y; | ||||
|     } viewport_corner; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     // TODO: early depth | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x2); | ||||
|  | ||||
|     enum DepthBuffering : u32 { | ||||
|         WBuffering = 0, | ||||
|         ZBuffering = 1, | ||||
|     }; | ||||
|     BitField<0, 1, DepthBuffering> depthmap_enable; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x12); | ||||
| }; | ||||
|  | ||||
| static_assert(sizeof(RasterizerRegs) == 0x40 * sizeof(u32), | ||||
|               "RasterizerRegs struct has incorrect size"); | ||||
|  | ||||
| } // namespace Pica | ||||
| @@ -197,13 +197,16 @@ void RasterizerOpenGL::DrawTriangles() { | ||||
|  | ||||
|     // Sync the viewport | ||||
|     // These registers hold half-width and half-height, so must be multiplied by 2 | ||||
|     GLsizei viewport_width = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_x).ToFloat32() * 2; | ||||
|     GLsizei viewport_height = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_y).ToFloat32() * 2; | ||||
|     GLsizei viewport_width = | ||||
|         (GLsizei)Pica::float24::FromRaw(regs.rasterizer.viewport_size_x).ToFloat32() * 2; | ||||
|     GLsizei viewport_height = | ||||
|         (GLsizei)Pica::float24::FromRaw(regs.rasterizer.viewport_size_y).ToFloat32() * 2; | ||||
|  | ||||
|     glViewport((GLint)(rect.left + regs.viewport_corner.x * color_surface->res_scale_width), | ||||
|                (GLint)(rect.bottom + regs.viewport_corner.y * color_surface->res_scale_height), | ||||
|                (GLsizei)(viewport_width * color_surface->res_scale_width), | ||||
|                (GLsizei)(viewport_height * color_surface->res_scale_height)); | ||||
|     glViewport( | ||||
|         (GLint)(rect.left + regs.rasterizer.viewport_corner.x * color_surface->res_scale_width), | ||||
|         (GLint)(rect.bottom + regs.rasterizer.viewport_corner.y * color_surface->res_scale_height), | ||||
|         (GLsizei)(viewport_width * color_surface->res_scale_width), | ||||
|         (GLsizei)(viewport_height * color_surface->res_scale_height)); | ||||
|  | ||||
|     if (uniform_block_data.data.framebuffer_scale[0] != color_surface->res_scale_width || | ||||
|         uniform_block_data.data.framebuffer_scale[1] != color_surface->res_scale_height) { | ||||
| @@ -215,16 +218,16 @@ void RasterizerOpenGL::DrawTriangles() { | ||||
|  | ||||
|     // Scissor checks are window-, not viewport-relative, which means that if the cached texture | ||||
|     // sub-rect changes, the scissor bounds also need to be updated. | ||||
|     GLint scissor_x1 = | ||||
|         static_cast<GLint>(rect.left + regs.scissor_test.x1 * color_surface->res_scale_width); | ||||
|     GLint scissor_y1 = | ||||
|         static_cast<GLint>(rect.bottom + regs.scissor_test.y1 * color_surface->res_scale_height); | ||||
|     GLint scissor_x1 = static_cast<GLint>( | ||||
|         rect.left + regs.rasterizer.scissor_test.x1 * color_surface->res_scale_width); | ||||
|     GLint scissor_y1 = static_cast<GLint>( | ||||
|         rect.bottom + regs.rasterizer.scissor_test.y1 * color_surface->res_scale_height); | ||||
|     // x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when | ||||
|     // scaling or doing multisampling. | ||||
|     GLint scissor_x2 = | ||||
|         static_cast<GLint>(rect.left + (regs.scissor_test.x2 + 1) * color_surface->res_scale_width); | ||||
|     GLint scissor_x2 = static_cast<GLint>( | ||||
|         rect.left + (regs.rasterizer.scissor_test.x2 + 1) * color_surface->res_scale_width); | ||||
|     GLint scissor_y2 = static_cast<GLint>( | ||||
|         rect.bottom + (regs.scissor_test.y2 + 1) * color_surface->res_scale_height); | ||||
|         rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * color_surface->res_scale_height); | ||||
|  | ||||
|     if (uniform_block_data.data.scissor_x1 != scissor_x1 || | ||||
|         uniform_block_data.data.scissor_x2 != scissor_x2 || | ||||
| @@ -316,20 +319,20 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | ||||
|  | ||||
|     switch (id) { | ||||
|     // Culling | ||||
|     case PICA_REG_INDEX(cull_mode): | ||||
|     case PICA_REG_INDEX(rasterizer.cull_mode): | ||||
|         SyncCullMode(); | ||||
|         break; | ||||
|  | ||||
|     // Depth modifiers | ||||
|     case PICA_REG_INDEX(viewport_depth_range): | ||||
|     case PICA_REG_INDEX(rasterizer.viewport_depth_range): | ||||
|         SyncDepthScale(); | ||||
|         break; | ||||
|     case PICA_REG_INDEX(viewport_depth_near_plane): | ||||
|     case PICA_REG_INDEX(rasterizer.viewport_depth_near_plane): | ||||
|         SyncDepthOffset(); | ||||
|         break; | ||||
|  | ||||
|     // Depth buffering | ||||
|     case PICA_REG_INDEX(depthmap_enable): | ||||
|     case PICA_REG_INDEX(rasterizer.depthmap_enable): | ||||
|         shader_dirty = true; | ||||
|         break; | ||||
|  | ||||
| @@ -398,7 +401,7 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | ||||
|         break; | ||||
|  | ||||
|     // Scissor test | ||||
|     case PICA_REG_INDEX(scissor_test.mode): | ||||
|     case PICA_REG_INDEX(rasterizer.scissor_test.mode): | ||||
|         shader_dirty = true; | ||||
|         break; | ||||
|  | ||||
| @@ -1110,30 +1113,31 @@ void RasterizerOpenGL::SetShader() { | ||||
| void RasterizerOpenGL::SyncCullMode() { | ||||
|     const auto& regs = Pica::g_state.regs; | ||||
|  | ||||
|     switch (regs.cull_mode) { | ||||
|     case Pica::Regs::CullMode::KeepAll: | ||||
|     switch (regs.rasterizer.cull_mode) { | ||||
|     case Pica::RasterizerRegs::CullMode::KeepAll: | ||||
|         state.cull.enabled = false; | ||||
|         break; | ||||
|  | ||||
|     case Pica::Regs::CullMode::KeepClockWise: | ||||
|     case Pica::RasterizerRegs::CullMode::KeepClockWise: | ||||
|         state.cull.enabled = true; | ||||
|         state.cull.front_face = GL_CW; | ||||
|         break; | ||||
|  | ||||
|     case Pica::Regs::CullMode::KeepCounterClockWise: | ||||
|     case Pica::RasterizerRegs::CullMode::KeepCounterClockWise: | ||||
|         state.cull.enabled = true; | ||||
|         state.cull.front_face = GL_CCW; | ||||
|         break; | ||||
|  | ||||
|     default: | ||||
|         LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", regs.cull_mode.Value()); | ||||
|         LOG_CRITICAL(Render_OpenGL, "Unknown cull mode %d", regs.rasterizer.cull_mode.Value()); | ||||
|         UNIMPLEMENTED(); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void RasterizerOpenGL::SyncDepthScale() { | ||||
|     float depth_scale = Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_range).ToFloat32(); | ||||
|     float depth_scale = | ||||
|         Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_range).ToFloat32(); | ||||
|     if (depth_scale != uniform_block_data.data.depth_scale) { | ||||
|         uniform_block_data.data.depth_scale = depth_scale; | ||||
|         uniform_block_data.dirty = true; | ||||
| @@ -1142,7 +1146,7 @@ void RasterizerOpenGL::SyncDepthScale() { | ||||
|  | ||||
| void RasterizerOpenGL::SyncDepthOffset() { | ||||
|     float depth_offset = | ||||
|         Pica::float24::FromRaw(Pica::g_state.regs.viewport_depth_near_plane).ToFloat32(); | ||||
|         Pica::float24::FromRaw(Pica::g_state.regs.rasterizer.viewport_depth_near_plane).ToFloat32(); | ||||
|     if (depth_offset != uniform_block_data.data.depth_offset) { | ||||
|         uniform_block_data.data.depth_offset = depth_offset; | ||||
|         uniform_block_data.dirty = true; | ||||
|   | ||||
| @@ -52,9 +52,9 @@ union PicaShaderConfig { | ||||
|  | ||||
|         const auto& regs = Pica::g_state.regs; | ||||
|  | ||||
|         state.scissor_test_mode = regs.scissor_test.mode; | ||||
|         state.scissor_test_mode = regs.rasterizer.scissor_test.mode; | ||||
|  | ||||
|         state.depthmap_enable = regs.depthmap_enable; | ||||
|         state.depthmap_enable = regs.rasterizer.depthmap_enable; | ||||
|  | ||||
|         state.alpha_test_func = regs.output_merger.alpha_test.enable | ||||
|                                     ? regs.output_merger.alpha_test.func.Value() | ||||
| @@ -172,12 +172,12 @@ union PicaShaderConfig { | ||||
|  | ||||
|     struct State { | ||||
|         Pica::Regs::CompareFunc alpha_test_func; | ||||
|         Pica::Regs::ScissorMode scissor_test_mode; | ||||
|         Pica::RasterizerRegs::ScissorMode scissor_test_mode; | ||||
|         Pica::Regs::TextureConfig::TextureType texture0_type; | ||||
|         std::array<TevStageConfigRaw, 6> tev_stages; | ||||
|         u8 combiner_buffer_input; | ||||
|  | ||||
|         Pica::Regs::DepthBuffering depthmap_enable; | ||||
|         Pica::RasterizerRegs::DepthBuffering depthmap_enable; | ||||
|         Pica::Regs::FogMode fog_mode; | ||||
|         bool fog_flip; | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include "video_core/renderer_opengl/gl_shader_util.h" | ||||
|  | ||||
| using Pica::Regs; | ||||
| using Pica::RasterizerRegs; | ||||
| using TevStageConfig = Regs::TevStageConfig; | ||||
|  | ||||
| namespace GLShader { | ||||
| @@ -639,10 +640,10 @@ vec4 secondary_fragment_color = vec4(0.0); | ||||
|     } | ||||
|  | ||||
|     // Append the scissor test | ||||
|     if (state.scissor_test_mode != Regs::ScissorMode::Disabled) { | ||||
|     if (state.scissor_test_mode != RasterizerRegs::ScissorMode::Disabled) { | ||||
|         out += "if ("; | ||||
|         // Negate the condition if we have to keep only the pixels outside the scissor box | ||||
|         if (state.scissor_test_mode == Regs::ScissorMode::Include) | ||||
|         if (state.scissor_test_mode == RasterizerRegs::ScissorMode::Include) | ||||
|             out += "!"; | ||||
|         out += "(gl_FragCoord.x >= scissor_x1 && " | ||||
|                "gl_FragCoord.y >= scissor_y1 && " | ||||
| @@ -652,7 +653,7 @@ vec4 secondary_fragment_color = vec4(0.0); | ||||
|  | ||||
|     out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n"; | ||||
|     out += "float depth = z_over_w * depth_scale + depth_offset;\n"; | ||||
|     if (state.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) { | ||||
|     if (state.depthmap_enable == Pica::RasterizerRegs::DepthBuffering::WBuffering) { | ||||
|         out += "depth /= gl_FragCoord.w;\n"; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,7 @@ namespace Pica { | ||||
|  | ||||
| namespace Shader { | ||||
|  | ||||
| OutputVertex OutputVertex::FromAttributeBuffer(const Regs& regs, AttributeBuffer& input) { | ||||
| OutputVertex OutputVertex::FromAttributeBuffer(const RasterizerRegs& regs, AttributeBuffer& input) { | ||||
|     // Setup output data | ||||
|     union { | ||||
|         OutputVertex ret{}; | ||||
| @@ -33,16 +33,16 @@ OutputVertex OutputVertex::FromAttributeBuffer(const Regs& regs, AttributeBuffer | ||||
|     for (unsigned int i = 0; i < num_attributes; ++i) { | ||||
|         const auto& output_register_map = regs.vs_output_attributes[i]; | ||||
|  | ||||
|         Regs::VSOutputAttributes::Semantic semantics[4] = { | ||||
|         RasterizerRegs::VSOutputAttributes::Semantic semantics[4] = { | ||||
|             output_register_map.map_x, output_register_map.map_y, output_register_map.map_z, | ||||
|             output_register_map.map_w}; | ||||
|  | ||||
|         for (unsigned comp = 0; comp < 4; ++comp) { | ||||
|             Regs::VSOutputAttributes::Semantic semantic = semantics[comp]; | ||||
|             RasterizerRegs::VSOutputAttributes::Semantic semantic = semantics[comp]; | ||||
|             float24* out = &vertex_slots[semantic]; | ||||
|             if (semantic < vertex_slots.size()) { | ||||
|                 *out = input.attr[i][comp]; | ||||
|             } else if (semantic != Regs::VSOutputAttributes::INVALID) { | ||||
|             } else if (semantic != RasterizerRegs::VSOutputAttributes::INVALID) { | ||||
|                 LOG_ERROR(HW_GPU, "Invalid/unknown semantic id: %u", (unsigned int)semantic); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -39,19 +39,19 @@ struct OutputVertex { | ||||
|     INSERT_PADDING_WORDS(1); | ||||
|     Math::Vec2<float24> tc2; | ||||
|  | ||||
|     static OutputVertex FromAttributeBuffer(const Regs& regs, AttributeBuffer& output); | ||||
|     static OutputVertex FromAttributeBuffer(const RasterizerRegs& regs, AttributeBuffer& output); | ||||
| }; | ||||
| #define ASSERT_POS(var, pos)                                                                       \ | ||||
|     static_assert(offsetof(OutputVertex, var) == pos * sizeof(float24), "Semantic at wrong "       \ | ||||
|                                                                         "offset.") | ||||
| ASSERT_POS(pos, Regs::VSOutputAttributes::POSITION_X); | ||||
| ASSERT_POS(quat, Regs::VSOutputAttributes::QUATERNION_X); | ||||
| ASSERT_POS(color, Regs::VSOutputAttributes::COLOR_R); | ||||
| ASSERT_POS(tc0, Regs::VSOutputAttributes::TEXCOORD0_U); | ||||
| ASSERT_POS(tc1, Regs::VSOutputAttributes::TEXCOORD1_U); | ||||
| ASSERT_POS(tc0_w, Regs::VSOutputAttributes::TEXCOORD0_W); | ||||
| ASSERT_POS(view, Regs::VSOutputAttributes::VIEW_X); | ||||
| ASSERT_POS(tc2, Regs::VSOutputAttributes::TEXCOORD2_U); | ||||
| ASSERT_POS(pos, RasterizerRegs::VSOutputAttributes::POSITION_X); | ||||
| ASSERT_POS(quat, RasterizerRegs::VSOutputAttributes::QUATERNION_X); | ||||
| ASSERT_POS(color, RasterizerRegs::VSOutputAttributes::COLOR_R); | ||||
| ASSERT_POS(tc0, RasterizerRegs::VSOutputAttributes::TEXCOORD0_U); | ||||
| ASSERT_POS(tc1, RasterizerRegs::VSOutputAttributes::TEXCOORD1_U); | ||||
| ASSERT_POS(tc0_w, RasterizerRegs::VSOutputAttributes::TEXCOORD0_W); | ||||
| ASSERT_POS(view, RasterizerRegs::VSOutputAttributes::VIEW_X); | ||||
| ASSERT_POS(tc2, RasterizerRegs::VSOutputAttributes::TEXCOORD2_U); | ||||
| #undef ASSERT_POS | ||||
| static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); | ||||
| static_assert(sizeof(OutputVertex) == 24 * sizeof(float), "OutputVertex has invalid size"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Yuri Kunde Schlesner
					Yuri Kunde Schlesner