From 59a004f915e84fec4a4fed125661eb486e1de198 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Wed, 10 Oct 2018 16:34:15 -0400 Subject: [PATCH] Use standard UBO and fix/stylize the code --- .../renderer_opengl/gl_rasterizer.cpp | 15 ------ .../renderer_opengl/gl_rasterizer.h | 3 -- .../renderer_opengl/gl_shader_cache.cpp | 20 -------- .../renderer_opengl/gl_shader_cache.h | 10 ---- .../renderer_opengl/gl_shader_decompiler.cpp | 46 ++----------------- .../renderer_opengl/gl_shader_gen.cpp | 29 +++++++++++- .../renderer_opengl/gl_shader_manager.cpp | 11 +++++ .../renderer_opengl/gl_shader_manager.h | 8 +++- 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) { current_texture_bindpoint = SetupTextures(static_cast(stage), shader, primitive_mode, current_texture_bindpoint); - SetupAlphaTesting(shader); - // When VertexA is enabled, we have dual vertex shaders if (program == Maxwell::ShaderProgram::VertexA) { // VertexB was combined with VertexA, so we skip the VertexB iteration @@ -882,19 +880,6 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, return current_unit + static_cast(entries.size()); } -void RasterizerOpenGL::SetupAlphaTesting(Shader& shader) { - const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; - - u32 func = static_cast(regs.alpha_test_func); - // Normalize the gl variants of opCompare to be the same as the normal variants - u32 op = static_cast(Tegra::Engines::Maxwell3D::Regs::ComparisonOp::Never); - if (func >= op) { - func = func - op + 1U; - } - - shader->SetAlphaTesting(regs.alpha_test_enabled == 1, regs.alpha_test_ref, func); -} - void RasterizerOpenGL::SyncViewport() { const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; const MathUtil::Rectangle 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: u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, GLenum primitive_mode, u32 current_unit); - /// Syncs the alpha test state to match the guest state - void SetupAlphaTesting(Shader& shader); - /// Syncs the viewport to match the guest state void SyncViewport(); 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) // Store shader's code to lazily build it on draw geometry_programs.code = program_result.first; } - - if (program_type == Maxwell::ShaderProgram::Fragment) { - SaveAlphaTestingLocations(); - } } GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { @@ -138,22 +134,6 @@ GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, return target_program.handle; }; -void CachedShader::SetAlphaTesting(const bool enable, const float ref, const u32 func) { - if (program_type == Maxwell::ShaderProgram::Fragment) { - glProgramUniform1ui(program.handle, alpha_test.enable_loc, - (enable ? 1 : 0)); - glProgramUniform1f(program.handle, alpha_test.ref_loc, - ref); - glProgramUniform1ui(program.handle, alpha_test.func_loc, func); - } -} - -void CachedShader::SaveAlphaTestingLocations() { - alpha_test.enable_loc = glGetUniformLocation(program.handle, "alpha_testing_enable"); - alpha_test.ref_loc = glGetUniformLocation(program.handle, "alpha_testing_ref"); - alpha_test.func_loc = glGetUniformLocation(program.handle, "alpha_testing_func"); -} - Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { const VAddr program_addr{GetShaderAddress(program)}; 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: /// Gets the GL uniform location for the specified resource, caching as needed GLint GetUniformLocation(const GLShader::SamplerEntry& sampler); - void SetAlphaTesting(const bool enable, const float ref, const u32 func); - private: /// Generates a geometry shader or returns one that already exists. GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology, const std::string& debug_name); - void SaveAlphaTestingLocations(); - VAddr addr; Maxwell::ShaderProgram program_type; GLShader::ShaderSetup setup; @@ -102,12 +98,6 @@ private: OGLProgram triangles_adjacency; } geometry_programs; - struct { - GLint enable_loc; - GLint ref_loc; - GLint func_loc; - } alpha_test; - std::map resource_cache; std::map uniform_cache; }; 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: ';'); } declarations.AddNewLine(); - - if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { - declarations.AddLine("uniform bool alpha_testing_active;"); - declarations.AddLine("uniform float alpha_testing_ref;"); - declarations.AddLine("uniform uint alpha_testing_func;"); - } - declarations.AddNewLine(); } /// Generates declarations used for geometry shaders. @@ -1271,17 +1264,20 @@ private: ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented"); - shader.AddLine("if (alpha_testing_active) {"); + shader.AddLine("if (alpha_test[0] != 0) {"); ++shader.scope; + // We start on the register containing the alpha value in the first RT. u32 current_reg = 3; for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets; ++render_target) { + // TODO(Blinkhawk): verify the behavior of alpha testing on hardware when + // multiple render targets are used. if (header.ps.IsColorComponentOutputEnabled(render_target, 0) || header.ps.IsColorComponentOutputEnabled(render_target, 1) || header.ps.IsColorComponentOutputEnabled(render_target, 2) || header.ps.IsColorComponentOutputEnabled(render_target, 3)) { shader.AddLine(fmt::format( - "if (AlphaFunc({}, alpha_testing_ref, alpha_testing_func)) discard;", + "if (AlphaFunc({})) discard;", regs.GetRegisterAsFloat(current_reg))); current_reg += 4; } @@ -3506,38 +3502,6 @@ private: declarations.AddLine("bool " + pred + " = false;"); } declarations.AddNewLine(); - GenerateFunctionDeclarations(); - } - - void GenerateFunctionDeclarations() { - if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { - declarations.AddLine("bool AlphaFunc(in float value, in float ref, in uint func) {"); - declarations.scope++; - declarations.AddLine("switch (func) {"); - declarations.scope++; - declarations.AddLine("case 1:"); - declarations.AddLine("return false;"); - declarations.AddLine("case 2:"); - declarations.AddLine("return value < ref;"); - declarations.AddLine("case 3:"); - declarations.AddLine("return value == ref;"); - declarations.AddLine("case 4:"); - declarations.AddLine("return value <= ref;"); - declarations.AddLine("case 5:"); - declarations.AddLine("return value > ref;"); - declarations.AddLine("case 6:"); - declarations.AddLine("return value != ref;"); - declarations.AddLine("case 7:"); - declarations.AddLine("return value >= ref;"); - declarations.AddLine("case 8:"); - declarations.AddLine("return true;"); - declarations.AddLine("default:"); - declarations.AddLine("return false;"); - declarations.scope--; - declarations.AddLine('}'); - declarations.scope--; - declarations.AddLine('}'); - } } private: 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 { vec4 viewport_flip; uvec4 instance_id; uvec4 flip_stage; + uvec4 alpha_test; }; )"; @@ -105,6 +106,7 @@ layout (std140) uniform gs_config { vec4 viewport_flip; uvec4 instance_id; uvec4 flip_stage; + uvec4 alpha_test; }; void main() { @@ -142,8 +144,33 @@ layout (std140) uniform fs_config { vec4 viewport_flip; uvec4 instance_id; uvec4 flip_stage; + uvec4 alpha_test; }; +bool AlphaFunc(in float value) { + float ref = uintBitsToFloat(alpha_test[2]); + switch (alpha_test[1]) { + case 1: + return false; + case 2: + return value < ref; + case 3: + return value == ref; + case 4: + return value <= ref; + case 5: + return value > ref; + case 6: + return value != ref; + case 7: + return value >= ref; + case 8: + return true; + default: + return false; + } +} + void main() { exec_fragment(); } @@ -152,4 +179,4 @@ void main() { out += program.first; return {out, program.second}; } -} // namespace OpenGL::GLShader \ No newline at end of file +} // 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 viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f; + u32 func = static_cast(regs.alpha_test_func); + // Normalize the gl variants of opCompare to be the same as the normal variants + u32 op_gl_variant_base = static_cast(Tegra::Engines::Maxwell3D::Regs::ComparisonOp::Never); + if (func >= op_gl_variant_base) { + func = func - op_gl_variant_base + 1U; + } + + alpha_test.enabled = regs.alpha_test_enabled; + alpha_test.func = func; + alpha_test.ref = regs.alpha_test_ref; + // We only assign the instance to the first component of the vector, the rest is just padding. instance_id[0] = state.current_instance; 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 { alignas(16) GLvec4 viewport_flip; alignas(16) GLuvec4 instance_id; alignas(16) GLuvec4 flip_stage; + struct alignas(16) { + GLuint enabled; + GLuint func; + GLfloat ref; + GLuint padding; + } alpha_test; }; -static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect"); +static_assert(sizeof(MaxwellUniformData) == 64, "MaxwellUniformData structure size is incorrect"); static_assert(sizeof(MaxwellUniformData) < 16384, "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");