summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-10-23 10:21:30 -0400
committerGravatar GitHub2018-10-23 10:21:30 -0400
commit75d807788ccaf64a478fdc48aecdb841baecc34e (patch)
tree4fc8a09dcc0f1ad915ba7d65154fafd43ae684a2
parentMerge pull request #1512 from ReinUsesLisp/brk (diff)
parentAssert that multiple render targets are not set while alpha testing (diff)
downloadyuzu-75d807788ccaf64a478fdc48aecdb841baecc34e.tar.gz
yuzu-75d807788ccaf64a478fdc48aecdb841baecc34e.tar.xz
yuzu-75d807788ccaf64a478fdc48aecdb841baecc34e.zip
Merge pull request #1470 from FernandoS27/alpha_testing
Implemented Alpha Test using Shader Emulation
-rw-r--r--src/video_core/engines/maxwell_3d.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp25
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp24
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp29
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h8
7 files changed, 87 insertions, 20 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index c8af1c6b6..0e09a7ee5 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -643,8 +643,10 @@ public:
643 u32 d3d_cull_mode; 643 u32 d3d_cull_mode;
644 644
645 ComparisonOp depth_test_func; 645 ComparisonOp depth_test_func;
646 float alpha_test_ref;
647 ComparisonOp alpha_test_func;
646 648
647 INSERT_PADDING_WORDS(0xB); 649 INSERT_PADDING_WORDS(0x9);
648 650
649 struct { 651 struct {
650 u32 separate_alpha; 652 u32 separate_alpha;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 3daccf82f..be51c5215 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -570,10 +570,11 @@ void RasterizerOpenGL::DrawArrays() {
570 SyncBlendState(); 570 SyncBlendState();
571 SyncLogicOpState(); 571 SyncLogicOpState();
572 SyncCullMode(); 572 SyncCullMode();
573 SyncAlphaTest();
574 SyncScissorTest(); 573 SyncScissorTest();
574 // Alpha Testing is synced on shaders.
575 SyncTransformFeedback(); 575 SyncTransformFeedback();
576 SyncPointState(); 576 SyncPointState();
577 CheckAlphaTests();
577 578
578 // TODO(bunnei): Sync framebuffer_scale uniform here 579 // TODO(bunnei): Sync framebuffer_scale uniform here
579 // TODO(bunnei): Sync scissorbox uniform(s) here 580 // TODO(bunnei): Sync scissorbox uniform(s) here
@@ -1007,17 +1008,6 @@ void RasterizerOpenGL::SyncLogicOpState() {
1007 state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation); 1008 state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation);
1008} 1009}
1009 1010
1010void RasterizerOpenGL::SyncAlphaTest() {
1011 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1012
1013 // TODO(Rodrigo): Alpha testing is a legacy OpenGL feature, but it can be
1014 // implemented with a test+discard in fragment shaders.
1015 if (regs.alpha_test_enabled != 0) {
1016 LOG_CRITICAL(Render_OpenGL, "Alpha testing is not implemented");
1017 UNREACHABLE();
1018 }
1019}
1020
1021void RasterizerOpenGL::SyncScissorTest() { 1011void RasterizerOpenGL::SyncScissorTest() {
1022 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 1012 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1023 1013
@@ -1052,4 +1042,15 @@ void RasterizerOpenGL::SyncPointState() {
1052 state.point.size = regs.point_size == 0 ? 1 : regs.point_size; 1042 state.point.size = regs.point_size == 0 ? 1 : regs.point_size;
1053} 1043}
1054 1044
1045void RasterizerOpenGL::CheckAlphaTests() {
1046 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1047
1048 if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) {
1049 LOG_CRITICAL(
1050 Render_OpenGL,
1051 "Alpha Testing is enabled with Multiple Render Targets, this behavior is undefined.");
1052 UNREACHABLE();
1053 }
1054}
1055
1055} // namespace OpenGL 1056} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index b1f7ccc7e..0e90a31f5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -162,9 +162,6 @@ private:
162 /// Syncs the LogicOp state to match the guest state 162 /// Syncs the LogicOp state to match the guest state
163 void SyncLogicOpState(); 163 void SyncLogicOpState();
164 164
165 /// Syncs the alpha test state to match the guest state
166 void SyncAlphaTest();
167
168 /// Syncs the scissor test state to match the guest state 165 /// Syncs the scissor test state to match the guest state
169 void SyncScissorTest(); 166 void SyncScissorTest();
170 167
@@ -174,6 +171,9 @@ private:
174 /// Syncs the point state to match the guest state 171 /// Syncs the point state to match the guest state
175 void SyncPointState(); 172 void SyncPointState();
176 173
174 /// Check asserts for alpha testing.
175 void CheckAlphaTests();
176
177 bool has_ARB_direct_state_access = false; 177 bool has_ARB_direct_state_access = false;
178 bool has_ARB_multi_bind = false; 178 bool has_ARB_multi_bind = false;
179 bool has_ARB_separate_shader_objects = false; 179 bool has_ARB_separate_shader_objects = false;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index d36f190b7..7a019fc86 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1266,9 +1266,29 @@ private:
1266 1266
1267 ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented"); 1267 ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented");
1268 1268
1269 shader.AddLine("if (alpha_test[0] != 0) {");
1270 ++shader.scope;
1271 // We start on the register containing the alpha value in the first RT.
1272 u32 current_reg = 3;
1273 for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets;
1274 ++render_target) {
1275 // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when
1276 // multiple render targets are used.
1277 if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
1278 header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
1279 header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
1280 header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
1281 shader.AddLine(fmt::format("if (!AlphaFunc({})) discard;",
1282 regs.GetRegisterAsFloat(current_reg)));
1283 current_reg += 4;
1284 }
1285 }
1286 --shader.scope;
1287 shader.AddLine('}');
1288
1269 // Write the color outputs using the data in the shader registers, disabled 1289 // Write the color outputs using the data in the shader registers, disabled
1270 // rendertargets/components are skipped in the register assignment. 1290 // rendertargets/components are skipped in the register assignment.
1271 u32 current_reg = 0; 1291 current_reg = 0;
1272 for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets; 1292 for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets;
1273 ++render_target) { 1293 ++render_target) {
1274 // TODO(Subv): Figure out how dual-source blending is configured in the Switch. 1294 // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
@@ -3516,7 +3536,7 @@ private:
3516 3536
3517 // Declarations 3537 // Declarations
3518 std::set<std::string> declr_predicates; 3538 std::set<std::string> declr_predicates;
3519}; // namespace Decompiler 3539}; // namespace OpenGL::GLShader::Decompiler
3520 3540
3521std::string GetCommonDeclarations() { 3541std::string GetCommonDeclarations() {
3522 return fmt::format("#define MAX_CONSTBUFFER_ELEMENTS {}\n", 3542 return fmt::format("#define MAX_CONSTBUFFER_ELEMENTS {}\n",
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index ecbc9d8ed..e883ffb1d 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -29,6 +29,7 @@ layout(std140) uniform vs_config {
29 vec4 viewport_flip; 29 vec4 viewport_flip;
30 uvec4 instance_id; 30 uvec4 instance_id;
31 uvec4 flip_stage; 31 uvec4 flip_stage;
32 uvec4 alpha_test;
32}; 33};
33)"; 34)";
34 35
@@ -105,6 +106,7 @@ layout (std140) uniform gs_config {
105 vec4 viewport_flip; 106 vec4 viewport_flip;
106 uvec4 instance_id; 107 uvec4 instance_id;
107 uvec4 flip_stage; 108 uvec4 flip_stage;
109 uvec4 alpha_test;
108}; 110};
109 111
110void main() { 112void main() {
@@ -142,8 +144,33 @@ layout (std140) uniform fs_config {
142 vec4 viewport_flip; 144 vec4 viewport_flip;
143 uvec4 instance_id; 145 uvec4 instance_id;
144 uvec4 flip_stage; 146 uvec4 flip_stage;
147 uvec4 alpha_test;
145}; 148};
146 149
150bool AlphaFunc(in float value) {
151 float ref = uintBitsToFloat(alpha_test[2]);
152 switch (alpha_test[1]) {
153 case 1:
154 return false;
155 case 2:
156 return value < ref;
157 case 3:
158 return value == ref;
159 case 4:
160 return value <= ref;
161 case 5:
162 return value > ref;
163 case 6:
164 return value != ref;
165 case 7:
166 return value >= ref;
167 case 8:
168 return true;
169 default:
170 return false;
171 }
172}
173
147void main() { 174void main() {
148 exec_fragment(); 175 exec_fragment();
149} 176}
@@ -152,4 +179,4 @@ void main() {
152 out += program.first; 179 out += program.first;
153 return {out, program.second}; 180 return {out, program.second};
154} 181}
155} // namespace OpenGL::GLShader \ No newline at end of file 182} // namespace OpenGL::GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 010857ec6..8b8869ecb 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -16,6 +16,17 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& sh
16 viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; 16 viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
17 viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; 17 viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
18 18
19 u32 func = static_cast<u32>(regs.alpha_test_func);
20 // Normalize the gl variants of opCompare to be the same as the normal variants
21 u32 op_gl_variant_base = static_cast<u32>(Tegra::Engines::Maxwell3D::Regs::ComparisonOp::Never);
22 if (func >= op_gl_variant_base) {
23 func = func - op_gl_variant_base + 1U;
24 }
25
26 alpha_test.enabled = regs.alpha_test_enabled;
27 alpha_test.func = func;
28 alpha_test.ref = regs.alpha_test_ref;
29
19 // We only assign the instance to the first component of the vector, the rest is just padding. 30 // We only assign the instance to the first component of the vector, the rest is just padding.
20 instance_id[0] = state.current_instance; 31 instance_id[0] = state.current_instance;
21 32
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index b3a191cf2..36fe1f04c 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -22,8 +22,14 @@ struct MaxwellUniformData {
22 alignas(16) GLvec4 viewport_flip; 22 alignas(16) GLvec4 viewport_flip;
23 alignas(16) GLuvec4 instance_id; 23 alignas(16) GLuvec4 instance_id;
24 alignas(16) GLuvec4 flip_stage; 24 alignas(16) GLuvec4 flip_stage;
25 struct alignas(16) {
26 GLuint enabled;
27 GLuint func;
28 GLfloat ref;
29 GLuint padding;
30 } alpha_test;
25}; 31};
26static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect"); 32static_assert(sizeof(MaxwellUniformData) == 64, "MaxwellUniformData structure size is incorrect");
27static_assert(sizeof(MaxwellUniformData) < 16384, 33static_assert(sizeof(MaxwellUniformData) < 16384,
28 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); 34 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
29 35