summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/pica.h32
-rw-r--r--src/video_core/rasterizer.cpp22
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp26
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h12
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp16
5 files changed, 105 insertions, 3 deletions
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 09702d46a..065a3fd0c 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -115,7 +115,36 @@ struct Regs {
115 BitField<24, 5, Semantic> map_w; 115 BitField<24, 5, Semantic> map_w;
116 } vs_output_attributes[7]; 116 } vs_output_attributes[7];
117 117
118 INSERT_PADDING_WORDS(0x11); 118 INSERT_PADDING_WORDS(0xe);
119
120 enum class ScissorMode : u32 {
121 Disabled = 0,
122 Exclude = 1, // Exclude pixels inside the scissor box
123
124 Include = 3 // Exclude pixels outside the scissor box
125 };
126
127 struct {
128 BitField<0, 2, ScissorMode> mode;
129
130 union {
131 BitField< 0, 16, u32> right;
132 BitField<16, 16, u32> bottom;
133 };
134
135 union {
136 BitField< 0, 16, u32> left_minus_1;
137 BitField<16, 16, u32> top_minus_1;
138 };
139
140 u32 GetTop() const {
141 return top_minus_1 + 1;
142 }
143
144 u32 GetLeft() const {
145 return left_minus_1 + 1;
146 }
147 } scissor_test;
119 148
120 union { 149 union {
121 BitField< 0, 10, s32> x; 150 BitField< 0, 10, s32> x;
@@ -1328,6 +1357,7 @@ ASSERT_REG_POSITION(viewport_depth_range, 0x4d);
1328ASSERT_REG_POSITION(viewport_depth_near_plane, 0x4e); 1357ASSERT_REG_POSITION(viewport_depth_near_plane, 0x4e);
1329ASSERT_REG_POSITION(vs_output_attributes[0], 0x50); 1358ASSERT_REG_POSITION(vs_output_attributes[0], 0x50);
1330ASSERT_REG_POSITION(vs_output_attributes[1], 0x51); 1359ASSERT_REG_POSITION(vs_output_attributes[1], 0x51);
1360ASSERT_REG_POSITION(scissor_test, 0x65);
1331ASSERT_REG_POSITION(viewport_corner, 0x68); 1361ASSERT_REG_POSITION(viewport_corner, 0x68);
1332ASSERT_REG_POSITION(depthmap_enable, 0x6D); 1362ASSERT_REG_POSITION(depthmap_enable, 0x6D);
1333ASSERT_REG_POSITION(texture0_enable, 0x80); 1363ASSERT_REG_POSITION(texture0_enable, 0x80);
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index a84170094..514d64208 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -338,12 +338,25 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
338 return; 338 return;
339 } 339 }
340 340
341 // TODO: Proper scissor rect test!
342 u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); 341 u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
343 u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); 342 u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
344 u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); 343 u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
345 u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); 344 u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
346 345
346 // Convert the scissor box coordinates to 12.4 fixed point
347 u16 scissor_left = (u16)(regs.scissor_test.GetLeft() << 4);
348 u16 scissor_top = (u16)(regs.scissor_test.GetTop() << 4);
349 u16 scissor_right = (u16)(regs.scissor_test.right << 4);
350 u16 scissor_bottom = (u16)(regs.scissor_test.bottom << 4);
351
352 if (regs.scissor_test.mode == Regs::ScissorMode::Include) {
353 // Calculate the new bounds
354 min_x = std::max(min_x, scissor_right);
355 min_y = std::max(min_y, scissor_bottom);
356 max_x = std::min(max_x, scissor_left);
357 max_y = std::min(max_y, scissor_top);
358 }
359
347 min_x &= Fix12P4::IntMask(); 360 min_x &= Fix12P4::IntMask();
348 min_y &= Fix12P4::IntMask(); 361 min_y &= Fix12P4::IntMask();
349 max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask()); 362 max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask());
@@ -383,6 +396,13 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
383 for (u16 y = min_y + 8; y < max_y; y += 0x10) { 396 for (u16 y = min_y + 8; y < max_y; y += 0x10) {
384 for (u16 x = min_x + 8; x < max_x; x += 0x10) { 397 for (u16 x = min_x + 8; x < max_x; x += 0x10) {
385 398
399 // Do not process the pixel if it's inside the scissor box and the scissor mode is set to Exclude
400 if (regs.scissor_test.mode == Regs::ScissorMode::Exclude &&
401 x >= scissor_right && x <= scissor_left &&
402 y >= scissor_bottom && y <= scissor_top) {
403 continue;
404 }
405
386 // Calculate the barycentric coordinates w0, w1 and w2 406 // Calculate the barycentric coordinates w0, w1 and w2
387 int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); 407 int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y});
388 int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y}); 408 int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y});
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 328a4f66b..14ee97d57 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -353,6 +353,15 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
353 SyncColorWriteMask(); 353 SyncColorWriteMask();
354 break; 354 break;
355 355
356 // Scissor test
357 case PICA_REG_INDEX(scissor_test.mode):
358 shader_dirty = true;
359 break;
360 case PICA_REG_INDEX(scissor_test.right):
361 case PICA_REG_INDEX(scissor_test.left_minus_1):
362 SyncScissorTest();
363 break;
364
356 // Logic op 365 // Logic op
357 case PICA_REG_INDEX(output_merger.logic_op): 366 case PICA_REG_INDEX(output_merger.logic_op):
358 SyncLogicOp(); 367 SyncLogicOp();
@@ -1002,6 +1011,7 @@ void RasterizerOpenGL::SetShader() {
1002 SyncDepthOffset(); 1011 SyncDepthOffset();
1003 SyncAlphaTest(); 1012 SyncAlphaTest();
1004 SyncCombinerColor(); 1013 SyncCombinerColor();
1014 SyncScissorTest();
1005 auto& tev_stages = Pica::g_state.regs.GetTevStages(); 1015 auto& tev_stages = Pica::g_state.regs.GetTevStages();
1006 for (int index = 0; index < tev_stages.size(); ++index) 1016 for (int index = 0; index < tev_stages.size(); ++index)
1007 SyncTevConstColor(index, tev_stages[index]); 1017 SyncTevConstColor(index, tev_stages[index]);
@@ -1166,6 +1176,22 @@ void RasterizerOpenGL::SyncDepthTest() {
1166 PicaToGL::CompareFunc(regs.output_merger.depth_test_func) : GL_ALWAYS; 1176 PicaToGL::CompareFunc(regs.output_merger.depth_test_func) : GL_ALWAYS;
1167} 1177}
1168 1178
1179void RasterizerOpenGL::SyncScissorTest() {
1180 const auto& regs = Pica::g_state.regs;
1181
1182 if (uniform_block_data.data.scissor_right != regs.scissor_test.right ||
1183 uniform_block_data.data.scissor_bottom != regs.scissor_test.bottom ||
1184 uniform_block_data.data.scissor_left != regs.scissor_test.GetLeft() ||
1185 uniform_block_data.data.scissor_top != regs.scissor_test.GetTop()) {
1186
1187 uniform_block_data.data.scissor_right = regs.scissor_test.right;
1188 uniform_block_data.data.scissor_bottom = regs.scissor_test.bottom;
1189 uniform_block_data.data.scissor_left = regs.scissor_test.GetLeft();
1190 uniform_block_data.data.scissor_top = regs.scissor_test.GetTop();
1191 uniform_block_data.dirty = true;
1192 }
1193}
1194
1169void RasterizerOpenGL::SyncCombinerColor() { 1195void RasterizerOpenGL::SyncCombinerColor() {
1170 auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw); 1196 auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw);
1171 if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) { 1197 if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 42482df4b..193c10291 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -56,6 +56,8 @@ union PicaShaderConfig {
56 56
57 const auto& regs = Pica::g_state.regs; 57 const auto& regs = Pica::g_state.regs;
58 58
59 state.scissor_test_mode = regs.scissor_test.mode;
60
59 state.depthmap_enable = regs.depthmap_enable; 61 state.depthmap_enable = regs.depthmap_enable;
60 62
61 state.alpha_test_func = regs.output_merger.alpha_test.enable ? 63 state.alpha_test_func = regs.output_merger.alpha_test.enable ?
@@ -172,6 +174,7 @@ union PicaShaderConfig {
172 174
173 struct State { 175 struct State {
174 Pica::Regs::CompareFunc alpha_test_func; 176 Pica::Regs::CompareFunc alpha_test_func;
177 Pica::Regs::ScissorMode scissor_test_mode;
175 Pica::Regs::TextureConfig::TextureType texture0_type; 178 Pica::Regs::TextureConfig::TextureType texture0_type;
176 std::array<TevStageConfigRaw, 6> tev_stages; 179 std::array<TevStageConfigRaw, 6> tev_stages;
177 u8 combiner_buffer_input; 180 u8 combiner_buffer_input;
@@ -328,6 +331,10 @@ private:
328 GLint alphatest_ref; 331 GLint alphatest_ref;
329 GLfloat depth_scale; 332 GLfloat depth_scale;
330 GLfloat depth_offset; 333 GLfloat depth_offset;
334 GLint scissor_right;
335 GLint scissor_bottom;
336 GLint scissor_left;
337 GLint scissor_top;
331 alignas(16) GLvec3 fog_color; 338 alignas(16) GLvec3 fog_color;
332 alignas(16) GLvec3 lighting_global_ambient; 339 alignas(16) GLvec3 lighting_global_ambient;
333 LightSrc light_src[8]; 340 LightSrc light_src[8];
@@ -335,7 +342,7 @@ private:
335 alignas(16) GLvec4 tev_combiner_buffer_color; 342 alignas(16) GLvec4 tev_combiner_buffer_color;
336 }; 343 };
337 344
338 static_assert(sizeof(UniformData) == 0x3A0, "The size of the UniformData structure has changed, update the structure in the shader"); 345 static_assert(sizeof(UniformData) == 0x3B0, "The size of the UniformData structure has changed, update the structure in the shader");
339 static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec"); 346 static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec");
340 347
341 /// Sets the OpenGL shader in accordance with the current PICA register state 348 /// Sets the OpenGL shader in accordance with the current PICA register state
@@ -384,6 +391,9 @@ private:
384 /// Syncs the depth test states to match the PICA register 391 /// Syncs the depth test states to match the PICA register
385 void SyncDepthTest(); 392 void SyncDepthTest();
386 393
394 /// Syncs the scissor test state to match the PICA register
395 void SyncScissorTest();
396
387 /// Syncs the TEV combiner color buffer to match the PICA register 397 /// Syncs the TEV combiner color buffer to match the PICA register
388 void SyncCombinerColor(); 398 void SyncCombinerColor();
389 399
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 3bace7f01..10bb44210 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -539,6 +539,8 @@ in float texcoord0_w;
539in vec4 normquat; 539in vec4 normquat;
540in vec3 view; 540in vec3 view;
541 541
542in vec4 gl_FragCoord;
543
542out vec4 color; 544out vec4 color;
543 545
544struct LightSrc { 546struct LightSrc {
@@ -555,6 +557,10 @@ layout (std140) uniform shader_data {
555 int alphatest_ref; 557 int alphatest_ref;
556 float depth_scale; 558 float depth_scale;
557 float depth_offset; 559 float depth_offset;
560 int scissor_right;
561 int scissor_bottom;
562 int scissor_left;
563 int scissor_top;
558 vec3 fog_color; 564 vec3 fog_color;
559 vec3 lighting_global_ambient; 565 vec3 lighting_global_ambient;
560 LightSrc light_src[NUM_LIGHTS]; 566 LightSrc light_src[NUM_LIGHTS];
@@ -582,6 +588,16 @@ vec4 secondary_fragment_color = vec4(0.0);
582 return out; 588 return out;
583 } 589 }
584 590
591 // Append the scissor test
592 if (state.scissor_test_mode == Regs::ScissorMode::Include || state.scissor_test_mode == Regs::ScissorMode::Exclude) {
593 out += "if (scissor_left <= scissor_right || scissor_top <= scissor_bottom) discard;\n";
594 out += "if (";
595 // Negate the condition if we have to keep only the pixels outside the scissor box
596 if (state.scissor_test_mode == Regs::ScissorMode::Include)
597 out += "!";
598 out += "(gl_FragCoord.x >= scissor_right && gl_FragCoord.x <= scissor_left && gl_FragCoord.y >= scissor_bottom && gl_FragCoord.y <= scissor_top)) discard;\n";
599 }
600
585 out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n"; 601 out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n";
586 out += "float depth = z_over_w * depth_scale + depth_offset;\n"; 602 out += "float depth = z_over_w * depth_scale + depth_offset;\n";
587 if (state.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) { 603 if (state.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {