summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernandoS27 <fsahmkow27@gmail.com>2018-10-10 22:34:15 +0200
committerFernandoS27 <fsahmkow27@gmail.com>2018-10-22 21:07:33 +0200
commit59a004f915e84fec4a4fed125661eb486e1de198 (patch)
tree0503fc9161e632023e1deeb005b33ee028440bcc
parentCache uniform locations and restructure the implementation (diff)
downloadyuzu-59a004f915e84fec4a4fed125661eb486e1de198.tar
yuzu-59a004f915e84fec4a4fed125661eb486e1de198.tar.gz
yuzu-59a004f915e84fec4a4fed125661eb486e1de198.tar.bz2
yuzu-59a004f915e84fec4a4fed125661eb486e1de198.tar.lz
yuzu-59a004f915e84fec4a4fed125661eb486e1de198.tar.xz
yuzu-59a004f915e84fec4a4fed125661eb486e1de198.tar.zst
yuzu-59a004f915e84fec4a4fed125661eb486e1de198.zip
-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) {
current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(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<u32>(entries.size());
}
-void RasterizerOpenGL::SetupAlphaTesting(Shader& shader) {
- const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
-
- u32 func = static_cast<u32>(regs.alpha_test_func);
- // Normalize the gl variants of opCompare to be the same as the normal variants
- u32 op = static_cast<u32>(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<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:
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<u32, GLuint> resource_cache;
std::map<u32, GLint> 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<u32>(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<u32>(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");