Use standard UBO and fix/stylize the code
This commit is contained in:
parent
17315cee16
commit
59a004f915
8 changed files with 51 additions and 91 deletions
|
@ -323,8 +323,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
|
||||||
current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
|
current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
|
||||||
primitive_mode, current_texture_bindpoint);
|
primitive_mode, current_texture_bindpoint);
|
||||||
|
|
||||||
SetupAlphaTesting(shader);
|
|
||||||
|
|
||||||
// When VertexA is enabled, we have dual vertex shaders
|
// When VertexA is enabled, we have dual vertex shaders
|
||||||
if (program == Maxwell::ShaderProgram::VertexA) {
|
if (program == Maxwell::ShaderProgram::VertexA) {
|
||||||
// VertexB was combined with VertexA, so we skip the VertexB iteration
|
// 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());
|
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() {
|
void RasterizerOpenGL::SyncViewport() {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
|
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
|
||||||
|
|
|
@ -132,9 +132,6 @@ private:
|
||||||
u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
|
u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
|
||||||
GLenum primitive_mode, u32 current_unit);
|
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
|
/// Syncs the viewport to match the guest state
|
||||||
void SyncViewport();
|
void SyncViewport();
|
||||||
|
|
||||||
|
|
|
@ -94,10 +94,6 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
|
||||||
// Store shader's code to lazily build it on draw
|
// Store shader's code to lazily build it on draw
|
||||||
geometry_programs.code = program_result.first;
|
geometry_programs.code = program_result.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program_type == Maxwell::ShaderProgram::Fragment) {
|
|
||||||
SaveAlphaTestingLocations();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
|
GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
|
||||||
|
@ -138,22 +134,6 @@ GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program,
|
||||||
return target_program.handle;
|
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) {
|
Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
||||||
const VAddr program_addr{GetShaderAddress(program)};
|
const VAddr program_addr{GetShaderAddress(program)};
|
||||||
|
|
||||||
|
|
|
@ -73,15 +73,11 @@ public:
|
||||||
/// Gets the GL uniform location for the specified resource, caching as needed
|
/// Gets the GL uniform location for the specified resource, caching as needed
|
||||||
GLint GetUniformLocation(const GLShader::SamplerEntry& sampler);
|
GLint GetUniformLocation(const GLShader::SamplerEntry& sampler);
|
||||||
|
|
||||||
void SetAlphaTesting(const bool enable, const float ref, const u32 func);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Generates a geometry shader or returns one that already exists.
|
/// Generates a geometry shader or returns one that already exists.
|
||||||
GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology,
|
GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology,
|
||||||
const std::string& debug_name);
|
const std::string& debug_name);
|
||||||
|
|
||||||
void SaveAlphaTestingLocations();
|
|
||||||
|
|
||||||
VAddr addr;
|
VAddr addr;
|
||||||
Maxwell::ShaderProgram program_type;
|
Maxwell::ShaderProgram program_type;
|
||||||
GLShader::ShaderSetup setup;
|
GLShader::ShaderSetup setup;
|
||||||
|
@ -102,12 +98,6 @@ private:
|
||||||
OGLProgram triangles_adjacency;
|
OGLProgram triangles_adjacency;
|
||||||
} geometry_programs;
|
} geometry_programs;
|
||||||
|
|
||||||
struct {
|
|
||||||
GLint enable_loc;
|
|
||||||
GLint ref_loc;
|
|
||||||
GLint func_loc;
|
|
||||||
} alpha_test;
|
|
||||||
|
|
||||||
std::map<u32, GLuint> resource_cache;
|
std::map<u32, GLuint> resource_cache;
|
||||||
std::map<u32, GLint> uniform_cache;
|
std::map<u32, GLint> uniform_cache;
|
||||||
};
|
};
|
||||||
|
|
|
@ -643,13 +643,6 @@ private:
|
||||||
';');
|
';');
|
||||||
}
|
}
|
||||||
declarations.AddNewLine();
|
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.
|
/// Generates declarations used for geometry shaders.
|
||||||
|
@ -1271,17 +1264,20 @@ private:
|
||||||
|
|
||||||
ASSERT_MSG(header.ps.omap.sample_mask == 0, "Samplemask write is unimplemented");
|
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;
|
++shader.scope;
|
||||||
|
// We start on the register containing the alpha value in the first RT.
|
||||||
u32 current_reg = 3;
|
u32 current_reg = 3;
|
||||||
for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets;
|
for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets;
|
||||||
++render_target) {
|
++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) ||
|
if (header.ps.IsColorComponentOutputEnabled(render_target, 0) ||
|
||||||
header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
|
header.ps.IsColorComponentOutputEnabled(render_target, 1) ||
|
||||||
header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
|
header.ps.IsColorComponentOutputEnabled(render_target, 2) ||
|
||||||
header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
|
header.ps.IsColorComponentOutputEnabled(render_target, 3)) {
|
||||||
shader.AddLine(fmt::format(
|
shader.AddLine(fmt::format(
|
||||||
"if (AlphaFunc({}, alpha_testing_ref, alpha_testing_func)) discard;",
|
"if (AlphaFunc({})) discard;",
|
||||||
regs.GetRegisterAsFloat(current_reg)));
|
regs.GetRegisterAsFloat(current_reg)));
|
||||||
current_reg += 4;
|
current_reg += 4;
|
||||||
}
|
}
|
||||||
|
@ -3506,38 +3502,6 @@ private:
|
||||||
declarations.AddLine("bool " + pred + " = false;");
|
declarations.AddLine("bool " + pred + " = false;");
|
||||||
}
|
}
|
||||||
declarations.AddNewLine();
|
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:
|
private:
|
||||||
|
|
|
@ -29,6 +29,7 @@ layout(std140) uniform vs_config {
|
||||||
vec4 viewport_flip;
|
vec4 viewport_flip;
|
||||||
uvec4 instance_id;
|
uvec4 instance_id;
|
||||||
uvec4 flip_stage;
|
uvec4 flip_stage;
|
||||||
|
uvec4 alpha_test;
|
||||||
};
|
};
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
@ -105,6 +106,7 @@ layout (std140) uniform gs_config {
|
||||||
vec4 viewport_flip;
|
vec4 viewport_flip;
|
||||||
uvec4 instance_id;
|
uvec4 instance_id;
|
||||||
uvec4 flip_stage;
|
uvec4 flip_stage;
|
||||||
|
uvec4 alpha_test;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -142,8 +144,33 @@ layout (std140) uniform fs_config {
|
||||||
vec4 viewport_flip;
|
vec4 viewport_flip;
|
||||||
uvec4 instance_id;
|
uvec4 instance_id;
|
||||||
uvec4 flip_stage;
|
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() {
|
void main() {
|
||||||
exec_fragment();
|
exec_fragment();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[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;
|
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.
|
// We only assign the instance to the first component of the vector, the rest is just padding.
|
||||||
instance_id[0] = state.current_instance;
|
instance_id[0] = state.current_instance;
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,14 @@ struct MaxwellUniformData {
|
||||||
alignas(16) GLvec4 viewport_flip;
|
alignas(16) GLvec4 viewport_flip;
|
||||||
alignas(16) GLuvec4 instance_id;
|
alignas(16) GLuvec4 instance_id;
|
||||||
alignas(16) GLuvec4 flip_stage;
|
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,
|
static_assert(sizeof(MaxwellUniformData) < 16384,
|
||||||
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
|
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue