diff options
| author | 2019-05-21 20:28:09 -0300 | |
|---|---|---|
| committer | 2019-05-30 13:21:01 -0300 | |
| commit | b76df62c00c28244f2fdd657b809853907f0070f (patch) | |
| tree | dfba6fc3c4fa662f9ee6825595597596811873ec /src | |
| parent | gl_rasterizer: Use GL_QUADS to emulate quads rendering (diff) | |
| download | yuzu-b76df62c00c28244f2fdd657b809853907f0070f.tar.gz yuzu-b76df62c00c28244f2fdd657b809853907f0070f.tar.xz yuzu-b76df62c00c28244f2fdd657b809853907f0070f.zip | |
gl_rasterizer: Move alpha testing to the OpenGL pipeline
Removes the alpha testing code from each fragment shader invocation.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 20 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 7 |
8 files changed, 33 insertions, 71 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 5087d9406..ca410287a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -663,13 +663,10 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 663 | SyncCullMode(); | 663 | SyncCullMode(); |
| 664 | SyncPrimitiveRestart(); | 664 | SyncPrimitiveRestart(); |
| 665 | SyncScissorTest(state); | 665 | SyncScissorTest(state); |
| 666 | // Alpha Testing is synced on shaders. | ||
| 667 | SyncTransformFeedback(); | 666 | SyncTransformFeedback(); |
| 668 | SyncPointState(); | 667 | SyncPointState(); |
| 669 | CheckAlphaTests(); | ||
| 670 | SyncPolygonOffset(); | 668 | SyncPolygonOffset(); |
| 671 | // TODO(bunnei): Sync framebuffer_scale uniform here | 669 | SyncAlphaTest(); |
| 672 | // TODO(bunnei): Sync scissorbox uniform(s) here | ||
| 673 | 670 | ||
| 674 | // Draw the vertex batch | 671 | // Draw the vertex batch |
| 675 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | 672 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; |
| @@ -1121,10 +1118,17 @@ void RasterizerOpenGL::SyncPolygonOffset() { | |||
| 1121 | state.polygon_offset.clamp = regs.polygon_offset_clamp; | 1118 | state.polygon_offset.clamp = regs.polygon_offset_clamp; |
| 1122 | } | 1119 | } |
| 1123 | 1120 | ||
| 1124 | void RasterizerOpenGL::CheckAlphaTests() { | 1121 | void RasterizerOpenGL::SyncAlphaTest() { |
| 1125 | const auto& regs = system.GPU().Maxwell3D().regs; | 1122 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 1126 | UNIMPLEMENTED_IF_MSG(regs.alpha_test_enabled != 0 && regs.rt_control.count > 1, | 1123 | UNIMPLEMENTED_IF_MSG(regs.alpha_test_enabled != 0 && regs.rt_control.count > 1, |
| 1127 | "Alpha Testing is enabled with more than one rendertarget"); | 1124 | "Alpha Testing is enabled with more than one rendertarget"); |
| 1125 | |||
| 1126 | state.alpha_test.enabled = regs.alpha_test_enabled; | ||
| 1127 | if (!state.alpha_test.enabled) { | ||
| 1128 | return; | ||
| 1129 | } | ||
| 1130 | state.alpha_test.func = MaxwellToGL::ComparisonOp(regs.alpha_test_func); | ||
| 1131 | state.alpha_test.ref = regs.alpha_test_ref; | ||
| 1128 | } | 1132 | } |
| 1129 | 1133 | ||
| 1130 | } // namespace OpenGL | 1134 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index f2643f26f..2817f65c9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -166,8 +166,8 @@ private: | |||
| 166 | /// Syncs the polygon offsets | 166 | /// Syncs the polygon offsets |
| 167 | void SyncPolygonOffset(); | 167 | void SyncPolygonOffset(); |
| 168 | 168 | ||
| 169 | /// Check asserts for alpha testing. | 169 | /// Syncs the alpha test state to match the guest state |
| 170 | void CheckAlphaTests(); | 170 | void SyncAlphaTest(); |
| 171 | 171 | ||
| 172 | /// Check for extension that are not strictly required | 172 | /// Check for extension that are not strictly required |
| 173 | /// but are needed for correct emulation | 173 | /// but are needed for correct emulation |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index e9f8d40db..ab75bb795 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1447,27 +1447,9 @@ private: | |||
| 1447 | 1447 | ||
| 1448 | UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented"); | 1448 | UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented"); |
| 1449 | 1449 | ||
| 1450 | code.AddLine("if (alpha_test[0] != 0) {{"); | ||
| 1451 | ++code.scope; | ||
| 1452 | // We start on the register containing the alpha value in the first RT. | ||
| 1453 | u32 current_reg = 3; | ||
| 1454 | for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) { | ||
| 1455 | // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when | ||
| 1456 | // multiple render targets are used. | ||
| 1457 | if (header.ps.IsColorComponentOutputEnabled(render_target, 0) || | ||
| 1458 | header.ps.IsColorComponentOutputEnabled(render_target, 1) || | ||
| 1459 | header.ps.IsColorComponentOutputEnabled(render_target, 2) || | ||
| 1460 | header.ps.IsColorComponentOutputEnabled(render_target, 3)) { | ||
| 1461 | code.AddLine("if (!AlphaFunc({})) discard;", SafeGetRegister(current_reg)); | ||
| 1462 | current_reg += 4; | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | --code.scope; | ||
| 1466 | code.AddLine("}}"); | ||
| 1467 | |||
| 1468 | // Write the color outputs using the data in the shader registers, disabled | 1450 | // Write the color outputs using the data in the shader registers, disabled |
| 1469 | // rendertargets/components are skipped in the register assignment. | 1451 | // rendertargets/components are skipped in the register assignment. |
| 1470 | current_reg = 0; | 1452 | u32 current_reg = 0; |
| 1471 | for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) { | 1453 | for (u32 render_target = 0; render_target < Maxwell::NumRenderTargets; ++render_target) { |
| 1472 | // TODO(Subv): Figure out how dual-source blending is configured in the Switch. | 1454 | // TODO(Subv): Figure out how dual-source blending is configured in the Switch. |
| 1473 | for (u32 component = 0; component < 4; ++component) { | 1455 | for (u32 component = 0; component < 4; ++component) { |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index d2bb705a9..269dda122 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -28,7 +28,6 @@ layout (location = 0) out vec4 position; | |||
| 28 | layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { | 28 | layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config { |
| 29 | vec4 viewport_flip; | 29 | vec4 viewport_flip; |
| 30 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding | 30 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding |
| 31 | uvec4 alpha_test; | ||
| 32 | }; | 31 | }; |
| 33 | 32 | ||
| 34 | )"; | 33 | )"; |
| @@ -91,7 +90,6 @@ layout (location = 0) out vec4 position; | |||
| 91 | layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { | 90 | layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config { |
| 92 | vec4 viewport_flip; | 91 | vec4 viewport_flip; |
| 93 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding | 92 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding |
| 94 | uvec4 alpha_test; | ||
| 95 | }; | 93 | }; |
| 96 | 94 | ||
| 97 | )"; | 95 | )"; |
| @@ -129,33 +127,8 @@ layout (location = 0) in noperspective vec4 position; | |||
| 129 | layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config { | 127 | layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config { |
| 130 | vec4 viewport_flip; | 128 | vec4 viewport_flip; |
| 131 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding | 129 | uvec4 config_pack; // instance_id, flip_stage, y_direction, padding |
| 132 | uvec4 alpha_test; | ||
| 133 | }; | 130 | }; |
| 134 | 131 | ||
| 135 | bool AlphaFunc(in float value) { | ||
| 136 | float ref = uintBitsToFloat(alpha_test[2]); | ||
| 137 | switch (alpha_test[1]) { | ||
| 138 | case 1: | ||
| 139 | return false; | ||
| 140 | case 2: | ||
| 141 | return value < ref; | ||
| 142 | case 3: | ||
| 143 | return value == ref; | ||
| 144 | case 4: | ||
| 145 | return value <= ref; | ||
| 146 | case 5: | ||
| 147 | return value > ref; | ||
| 148 | case 6: | ||
| 149 | return value != ref; | ||
| 150 | case 7: | ||
| 151 | return value >= ref; | ||
| 152 | case 8: | ||
| 153 | return true; | ||
| 154 | default: | ||
| 155 | return false; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | )"; | 132 | )"; |
| 160 | const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); | 133 | const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); |
| 161 | ProgramResult program = | 134 | ProgramResult program = |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 05ab01dcb..b05f90f20 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -48,17 +48,6 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shade | |||
| 48 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; | 48 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; |
| 49 | viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; | 49 | viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; |
| 50 | 50 | ||
| 51 | auto func{static_cast<u32>(regs.alpha_test_func)}; | ||
| 52 | // Normalize the gl variants of opCompare to be the same as the normal variants | ||
| 53 | const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never); | ||
| 54 | if (func >= op_gl_variant_base) { | ||
| 55 | func = func - op_gl_variant_base + 1U; | ||
| 56 | } | ||
| 57 | |||
| 58 | alpha_test.enabled = regs.alpha_test_enabled; | ||
| 59 | alpha_test.func = func; | ||
| 60 | alpha_test.ref = regs.alpha_test_ref; | ||
| 61 | |||
| 62 | instance_id = state.current_instance; | 51 | instance_id = state.current_instance; |
| 63 | 52 | ||
| 64 | // Assign in which stage the position has to be flipped | 53 | // Assign in which stage the position has to be flipped |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index cec18a832..6961e702a 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -27,14 +27,8 @@ struct MaxwellUniformData { | |||
| 27 | GLuint flip_stage; | 27 | GLuint flip_stage; |
| 28 | GLfloat y_direction; | 28 | GLfloat y_direction; |
| 29 | }; | 29 | }; |
| 30 | struct alignas(16) { | ||
| 31 | GLuint enabled; | ||
| 32 | GLuint func; | ||
| 33 | GLfloat ref; | ||
| 34 | GLuint padding; | ||
| 35 | } alpha_test; | ||
| 36 | }; | 30 | }; |
| 37 | static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect"); | 31 | static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect"); |
| 38 | static_assert(sizeof(MaxwellUniformData) < 16384, | 32 | static_assert(sizeof(MaxwellUniformData) < 16384, |
| 39 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); | 33 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); |
| 40 | 34 | ||
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 7425fbe5d..d86e137ac 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -156,6 +156,10 @@ OpenGLState::OpenGLState() { | |||
| 156 | polygon_offset.factor = 0.0f; | 156 | polygon_offset.factor = 0.0f; |
| 157 | polygon_offset.units = 0.0f; | 157 | polygon_offset.units = 0.0f; |
| 158 | polygon_offset.clamp = 0.0f; | 158 | polygon_offset.clamp = 0.0f; |
| 159 | |||
| 160 | alpha_test.enabled = false; | ||
| 161 | alpha_test.func = GL_ALWAYS; | ||
| 162 | alpha_test.ref = 0.0f; | ||
| 159 | } | 163 | } |
| 160 | 164 | ||
| 161 | void OpenGLState::ApplyDefaultState() { | 165 | void OpenGLState::ApplyDefaultState() { |
| @@ -461,6 +465,14 @@ void OpenGLState::ApplyPolygonOffset() const { | |||
| 461 | } | 465 | } |
| 462 | } | 466 | } |
| 463 | 467 | ||
| 468 | void OpenGLState::ApplyAlphaTest() const { | ||
| 469 | Enable(GL_ALPHA_TEST, cur_state.alpha_test.enabled, alpha_test.enabled); | ||
| 470 | if (UpdateTie(std::tie(cur_state.alpha_test.func, cur_state.alpha_test.ref), | ||
| 471 | std::tie(alpha_test.func, alpha_test.ref))) { | ||
| 472 | glAlphaFunc(alpha_test.func, alpha_test.ref); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | |||
| 464 | void OpenGLState::ApplyTextures() const { | 476 | void OpenGLState::ApplyTextures() const { |
| 465 | bool has_delta{}; | 477 | bool has_delta{}; |
| 466 | std::size_t first{}; | 478 | std::size_t first{}; |
| @@ -533,6 +545,7 @@ void OpenGLState::Apply() const { | |||
| 533 | ApplyTextures(); | 545 | ApplyTextures(); |
| 534 | ApplySamplers(); | 546 | ApplySamplers(); |
| 535 | ApplyPolygonOffset(); | 547 | ApplyPolygonOffset(); |
| 548 | ApplyAlphaTest(); | ||
| 536 | } | 549 | } |
| 537 | 550 | ||
| 538 | void OpenGLState::EmulateViewportWithScissor() { | 551 | void OpenGLState::EmulateViewportWithScissor() { |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 41418a7b8..b0140495d 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -172,6 +172,12 @@ public: | |||
| 172 | GLfloat clamp; | 172 | GLfloat clamp; |
| 173 | } polygon_offset; | 173 | } polygon_offset; |
| 174 | 174 | ||
| 175 | struct { | ||
| 176 | bool enabled; // GL_ALPHA_TEST | ||
| 177 | GLenum func; // GL_ALPHA_TEST_FUNC | ||
| 178 | GLfloat ref; // GL_ALPHA_TEST_REF | ||
| 179 | } alpha_test; | ||
| 180 | |||
| 175 | std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE | 181 | std::array<bool, 8> clip_distance; // GL_CLIP_DISTANCE |
| 176 | 182 | ||
| 177 | OpenGLState(); | 183 | OpenGLState(); |
| @@ -215,6 +221,7 @@ public: | |||
| 215 | void ApplySamplers() const; | 221 | void ApplySamplers() const; |
| 216 | void ApplyDepthClamp() const; | 222 | void ApplyDepthClamp() const; |
| 217 | void ApplyPolygonOffset() const; | 223 | void ApplyPolygonOffset() const; |
| 224 | void ApplyAlphaTest() const; | ||
| 218 | 225 | ||
| 219 | /// Set the initial OpenGL state | 226 | /// Set the initial OpenGL state |
| 220 | static void ApplyDefaultState(); | 227 | static void ApplyDefaultState(); |