summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h10
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp46
-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
8 files changed, 51 insertions, 91 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 0f8227f7b..d93681813 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -323,8 +323,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
323 current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader, 323 current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
324 primitive_mode, current_texture_bindpoint); 324 primitive_mode, current_texture_bindpoint);
325 325
326 SetupAlphaTesting(shader);
327
328 // When VertexA is enabled, we have dual vertex shaders 326 // When VertexA is enabled, we have dual vertex shaders
329 if (program == Maxwell::ShaderProgram::VertexA) { 327 if (program == Maxwell::ShaderProgram::VertexA) {
330 // VertexB was combined with VertexA, so we skip the VertexB iteration 328 // VertexB was combined with VertexA, so we skip the VertexB iteration
@@ -882,19 +880,6 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
882 return current_unit + static_cast<u32>(entries.size()); 880 return current_unit + static_cast<u32>(entries.size());
883} 881}
884 882
885void RasterizerOpenGL::SetupAlphaTesting(Shader& shader) {
886 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
887
888 u32 func = static_cast<u32>(regs.alpha_test_func);
889 // Normalize the gl variants of opCompare to be the same as the normal variants
890 u32 op = static_cast<u32>(Tegra::Engines::Maxwell3D::Regs::ComparisonOp::Never);
891 if (func >= op) {
892 func = func - op + 1U;
893 }
894
895 shader->SetAlphaTesting(regs.alpha_test_enabled == 1, regs.alpha_test_ref, func);
896}
897
898void RasterizerOpenGL::SyncViewport() { 883void RasterizerOpenGL::SyncViewport() {
899 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 884 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
900 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; 885 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 32a30e1b6..ece5cb2c4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -132,9 +132,6 @@ private:
132 u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, 132 u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
133 GLenum primitive_mode, u32 current_unit); 133 GLenum primitive_mode, u32 current_unit);
134 134
135 /// Syncs the alpha test state to match the guest state
136 void SetupAlphaTesting(Shader& shader);
137
138 /// Syncs the viewport to match the guest state 135 /// Syncs the viewport to match the guest state
139 void SyncViewport(); 136 void SyncViewport();
140 137
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index ccb8b4805..1a03a677f 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -94,10 +94,6 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
94 // Store shader's code to lazily build it on draw 94 // Store shader's code to lazily build it on draw
95 geometry_programs.code = program_result.first; 95 geometry_programs.code = program_result.first;
96 } 96 }
97
98 if (program_type == Maxwell::ShaderProgram::Fragment) {
99 SaveAlphaTestingLocations();
100 }
101} 97}
102 98
103GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { 99GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
@@ -138,22 +134,6 @@ GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program,
138 return target_program.handle; 134 return target_program.handle;
139}; 135};
140 136
141void CachedShader::SetAlphaTesting(const bool enable, const float ref, const u32 func) {
142 if (program_type == Maxwell::ShaderProgram::Fragment) {
143 glProgramUniform1ui(program.handle, alpha_test.enable_loc,
144 (enable ? 1 : 0));
145 glProgramUniform1f(program.handle, alpha_test.ref_loc,
146 ref);
147 glProgramUniform1ui(program.handle, alpha_test.func_loc, func);
148 }
149}
150
151void CachedShader::SaveAlphaTestingLocations() {
152 alpha_test.enable_loc = glGetUniformLocation(program.handle, "alpha_testing_enable");
153 alpha_test.ref_loc = glGetUniformLocation(program.handle, "alpha_testing_ref");
154 alpha_test.func_loc = glGetUniformLocation(program.handle, "alpha_testing_func");
155}
156
157Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { 137Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
158 const VAddr program_addr{GetShaderAddress(program)}; 138 const VAddr program_addr{GetShaderAddress(program)};
159 139
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 7c80ee86b..a210f1731 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -73,15 +73,11 @@ public:
73 /// Gets the GL uniform location for the specified resource, caching as needed 73 /// Gets the GL uniform location for the specified resource, caching as needed
74 GLint GetUniformLocation(const GLShader::SamplerEntry& sampler); 74 GLint GetUniformLocation(const GLShader::SamplerEntry& sampler);
75 75
76 void SetAlphaTesting(const bool enable, const float ref, const u32 func);
77
78private: 76private:
79 /// Generates a geometry shader or returns one that already exists. 77 /// Generates a geometry shader or returns one that already exists.
80 GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology, 78 GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology,
81 const std::string& debug_name); 79 const std::string& debug_name);
82 80
83 void SaveAlphaTestingLocations();
84
85 VAddr addr; 81 VAddr addr;
86 Maxwell::ShaderProgram program_type; 82 Maxwell::ShaderProgram program_type;
87 GLShader::ShaderSetup setup; 83 GLShader::ShaderSetup setup;
@@ -102,12 +98,6 @@ private:
102 OGLProgram triangles_adjacency; 98 OGLProgram triangles_adjacency;
103 } geometry_programs; 99 } geometry_programs;
104 100
105 struct {
106 GLint enable_loc;
107 GLint ref_loc;
108 GLint func_loc;
109 } alpha_test;
110
111 std::map<u32, GLuint> resource_cache; 101 std::map<u32, GLuint> resource_cache;
112 std::map<u32, GLint> uniform_cache; 102 std::map<u32, GLint> uniform_cache;
113}; 103};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 7bd4d2d95..6fdfc742b 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -643,13 +643,6 @@ private:
643 ';'); 643 ';');
644 } 644 }
645 declarations.AddNewLine(); 645 declarations.AddNewLine();
646
647 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
648 declarations.AddLine("uniform bool alpha_testing_active;");
649 declarations.AddLine("uniform float alpha_testing_ref;");
650 declarations.AddLine("uniform uint alpha_testing_func;");
651 }
652 declarations.AddNewLine();
653 } 646 }
654 647
655 /// Generates declarations used for geometry shaders. 648 /// Generates declarations used for geometry shaders.
@@ -1271,17 +1264,20 @@ private:
1271 1264
1272 ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented"); 1265 ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented");
1273 1266
1274 shader.AddLine("if (alpha_testing_active) {"); 1267 shader.AddLine("if (alpha_test[0] != 0) {");
1275 ++shader.scope; 1268 ++shader.scope;
1269 // We start on the register containing the alpha value in the first RT.
1276 u32 current_reg = 3; 1270 u32 current_reg = 3;
1277 for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets; 1271 for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets;
1278 ++render_target) { 1272 ++render_target) {
1273 // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when
1274 // multiple render targets are used.
1279 if (header.ps.IsColorComponentOutputEnabled(render_target, 0) || 1275 if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
1280 header.ps.IsColorComponentOutputEnabled(render_target, 1) || 1276 header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
1281 header.ps.IsColorComponentOutputEnabled(render_target, 2) || 1277 header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
1282 header.ps.IsColorComponentOutputEnabled(render_target, 3)) { 1278 header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
1283 shader.AddLine(fmt::format( 1279 shader.AddLine(fmt::format(
1284 "if (AlphaFunc({}, alpha_testing_ref, alpha_testing_func)) discard;", 1280 "if (AlphaFunc({})) discard;",
1285 regs.GetRegisterAsFloat(current_reg))); 1281 regs.GetRegisterAsFloat(current_reg)));
1286 current_reg += 4; 1282 current_reg += 4;
1287 } 1283 }
@@ -3506,38 +3502,6 @@ private:
3506 declarations.AddLine("bool " + pred + " = false;"); 3502 declarations.AddLine("bool " + pred + " = false;");
3507 } 3503 }
3508 declarations.AddNewLine(); 3504 declarations.AddNewLine();
3509 GenerateFunctionDeclarations();
3510 }
3511
3512 void GenerateFunctionDeclarations() {
3513 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
3514 declarations.AddLine("bool AlphaFunc(in float value, in float ref, in uint func) {");
3515 declarations.scope++;
3516 declarations.AddLine("switch (func) {");
3517 declarations.scope++;
3518 declarations.AddLine("case 1:");
3519 declarations.AddLine("return false;");
3520 declarations.AddLine("case 2:");
3521 declarations.AddLine("return value < ref;");
3522 declarations.AddLine("case 3:");
3523 declarations.AddLine("return value == ref;");
3524 declarations.AddLine("case 4:");
3525 declarations.AddLine("return value <= ref;");
3526 declarations.AddLine("case 5:");
3527 declarations.AddLine("return value > ref;");
3528 declarations.AddLine("case 6:");
3529 declarations.AddLine("return value != ref;");
3530 declarations.AddLine("case 7:");
3531 declarations.AddLine("return value >= ref;");
3532 declarations.AddLine("case 8:");
3533 declarations.AddLine("return true;");
3534 declarations.AddLine("default:");
3535 declarations.AddLine("return false;");
3536 declarations.scope--;
3537 declarations.AddLine('}');
3538 declarations.scope--;
3539 declarations.AddLine('}');
3540 }
3541 } 3505 }
3542 3506
3543private: 3507private:
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