summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_shader_decompiler.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp142
1 files changed, 74 insertions, 68 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 6a610a3bc..030550c53 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -415,27 +415,6 @@ public:
return code.GetResult();
}
- ShaderEntries GetShaderEntries() const {
- ShaderEntries entries;
- for (const auto& cbuf : ir.GetConstantBuffers()) {
- entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(),
- cbuf.first);
- }
- for (const auto& sampler : ir.GetSamplers()) {
- entries.samplers.emplace_back(sampler);
- }
- for (const auto& [offset, image] : ir.GetImages()) {
- entries.images.emplace_back(image);
- }
- for (const auto& [base, usage] : ir.GetGlobalMemory()) {
- entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset,
- usage.is_read, usage.is_written);
- }
- entries.clip_distances = ir.GetClipDistances();
- entries.shader_length = ir.GetLength();
- return entries;
- }
-
private:
friend class ASTDecompiler;
friend class ExprDecompiler;
@@ -1148,7 +1127,7 @@ private:
for (const auto& variant : extras) {
if (const auto argument = std::get_if<TextureArgument>(&variant)) {
expr += GenerateTextureArgument(*argument);
- } else if (std::get_if<TextureAoffi>(&variant)) {
+ } else if (std::holds_alternative<TextureAoffi>(variant)) {
expr += GenerateTextureAoffi(meta->aoffi);
} else {
UNREACHABLE();
@@ -1158,8 +1137,8 @@ private:
return expr + ')';
}
- std::string GenerateTextureArgument(TextureArgument argument) {
- const auto [type, operand] = argument;
+ std::string GenerateTextureArgument(const TextureArgument& argument) {
+ const auto& [type, operand] = argument;
if (operand == nullptr) {
return {};
}
@@ -1235,7 +1214,7 @@ private:
std::string BuildImageValues(Operation operation) {
constexpr std::array constructors{"uint", "uvec2", "uvec3", "uvec4"};
- const auto meta{std::get<MetaImage>(operation.GetMeta())};
+ const auto& meta{std::get<MetaImage>(operation.GetMeta())};
const std::size_t values_count{meta.values.size()};
std::string expr = fmt::format("{}(", constructors.at(values_count - 1));
@@ -1780,14 +1759,14 @@ private:
return {"0", Type::Int};
}
- const auto meta{std::get<MetaImage>(operation.GetMeta())};
+ const auto& meta{std::get<MetaImage>(operation.GetMeta())};
return {fmt::format("imageLoad({}, {}){}", GetImage(meta.image),
BuildIntegerCoordinates(operation), GetSwizzle(meta.element)),
Type::Uint};
}
Expression ImageStore(Operation operation) {
- const auto meta{std::get<MetaImage>(operation.GetMeta())};
+ const auto& meta{std::get<MetaImage>(operation.GetMeta())};
code.AddLine("imageStore({}, {}, {});", GetImage(meta.image),
BuildIntegerCoordinates(operation), BuildImageValues(operation));
return {};
@@ -1795,7 +1774,7 @@ private:
template <const std::string_view& opname>
Expression AtomicImage(Operation operation) {
- const auto meta{std::get<MetaImage>(operation.GetMeta())};
+ const auto& meta{std::get<MetaImage>(operation.GetMeta())};
ASSERT(meta.values.size() == 1);
return {fmt::format("imageAtomic{}({}, {}, {})", opname, GetImage(meta.image),
@@ -2246,7 +2225,7 @@ private:
code.AddLine("#ifdef SAMPLER_{}_IS_BUFFER", sampler.GetIndex());
}
- std::string GetDeclarationWithSuffix(u32 index, const std::string& name) const {
+ std::string GetDeclarationWithSuffix(u32 index, std::string_view name) const {
return fmt::format("{}_{}_{}", name, index, suffix);
}
@@ -2271,17 +2250,15 @@ private:
ShaderWriter code;
};
-static constexpr std::string_view flow_var = "flow_var_";
-
std::string GetFlowVariable(u32 i) {
- return fmt::format("{}{}", flow_var, i);
+ return fmt::format("flow_var_{}", i);
}
class ExprDecompiler {
public:
explicit ExprDecompiler(GLSLDecompiler& decomp) : decomp{decomp} {}
- void operator()(VideoCommon::Shader::ExprAnd& expr) {
+ void operator()(const ExprAnd& expr) {
inner += "( ";
std::visit(*this, *expr.operand1);
inner += " && ";
@@ -2289,7 +2266,7 @@ public:
inner += ')';
}
- void operator()(VideoCommon::Shader::ExprOr& expr) {
+ void operator()(const ExprOr& expr) {
inner += "( ";
std::visit(*this, *expr.operand1);
inner += " || ";
@@ -2297,17 +2274,17 @@ public:
inner += ')';
}
- void operator()(VideoCommon::Shader::ExprNot& expr) {
+ void operator()(const ExprNot& expr) {
inner += '!';
std::visit(*this, *expr.operand1);
}
- void operator()(VideoCommon::Shader::ExprPredicate& expr) {
+ void operator()(const ExprPredicate& expr) {
const auto pred = static_cast<Tegra::Shader::Pred>(expr.predicate);
inner += decomp.GetPredicate(pred);
}
- void operator()(VideoCommon::Shader::ExprCondCode& expr) {
+ void operator()(const ExprCondCode& expr) {
const Node cc = decomp.ir.GetConditionCode(expr.cc);
std::string target;
@@ -2316,10 +2293,13 @@ public:
switch (index) {
case Tegra::Shader::Pred::NeverExecute:
target = "false";
+ break;
case Tegra::Shader::Pred::UnusedIndex:
target = "true";
+ break;
default:
target = decomp.GetPredicate(index);
+ break;
}
} else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) {
target = decomp.GetInternalFlag(flag->GetFlag());
@@ -2329,15 +2309,20 @@ public:
inner += target;
}
- void operator()(VideoCommon::Shader::ExprVar& expr) {
+ void operator()(const ExprVar& expr) {
inner += GetFlowVariable(expr.var_index);
}
- void operator()(VideoCommon::Shader::ExprBoolean& expr) {
+ void operator()(const ExprBoolean& expr) {
inner += expr.value ? "true" : "false";
}
- std::string& GetResult() {
+ void operator()(VideoCommon::Shader::ExprGprEqual& expr) {
+ inner +=
+ "( ftou(" + decomp.GetRegister(expr.gpr) + ") == " + std::to_string(expr.value) + ')';
+ }
+
+ const std::string& GetResult() const {
return inner;
}
@@ -2350,7 +2335,7 @@ class ASTDecompiler {
public:
explicit ASTDecompiler(GLSLDecompiler& decomp) : decomp{decomp} {}
- void operator()(VideoCommon::Shader::ASTProgram& ast) {
+ void operator()(const ASTProgram& ast) {
ASTNode current = ast.nodes.GetFirst();
while (current) {
Visit(current);
@@ -2358,7 +2343,7 @@ public:
}
}
- void operator()(VideoCommon::Shader::ASTIfThen& ast) {
+ void operator()(const ASTIfThen& ast) {
ExprDecompiler expr_parser{decomp};
std::visit(expr_parser, *ast.condition);
decomp.code.AddLine("if ({}) {{", expr_parser.GetResult());
@@ -2372,7 +2357,7 @@ public:
decomp.code.AddLine("}}");
}
- void operator()(VideoCommon::Shader::ASTIfElse& ast) {
+ void operator()(const ASTIfElse& ast) {
decomp.code.AddLine("else {{");
decomp.code.scope++;
ASTNode current = ast.nodes.GetFirst();
@@ -2384,29 +2369,29 @@ public:
decomp.code.AddLine("}}");
}
- void operator()(VideoCommon::Shader::ASTBlockEncoded& ast) {
+ void operator()([[maybe_unused]] const ASTBlockEncoded& ast) {
UNREACHABLE();
}
- void operator()(VideoCommon::Shader::ASTBlockDecoded& ast) {
+ void operator()(const ASTBlockDecoded& ast) {
decomp.VisitBlock(ast.nodes);
}
- void operator()(VideoCommon::Shader::ASTVarSet& ast) {
+ void operator()(const ASTVarSet& ast) {
ExprDecompiler expr_parser{decomp};
std::visit(expr_parser, *ast.condition);
decomp.code.AddLine("{} = {};", GetFlowVariable(ast.index), expr_parser.GetResult());
}
- void operator()(VideoCommon::Shader::ASTLabel& ast) {
+ void operator()(const ASTLabel& ast) {
decomp.code.AddLine("// Label_{}:", ast.index);
}
- void operator()(VideoCommon::Shader::ASTGoto& ast) {
+ void operator()([[maybe_unused]] const ASTGoto& ast) {
UNREACHABLE();
}
- void operator()(VideoCommon::Shader::ASTDoWhile& ast) {
+ void operator()(const ASTDoWhile& ast) {
ExprDecompiler expr_parser{decomp};
std::visit(expr_parser, *ast.condition);
decomp.code.AddLine("do {{");
@@ -2420,7 +2405,7 @@ public:
decomp.code.AddLine("}} while({});", expr_parser.GetResult());
}
- void operator()(VideoCommon::Shader::ASTReturn& ast) {
+ void operator()(const ASTReturn& ast) {
const bool is_true = VideoCommon::Shader::ExprIsTrue(ast.condition);
if (!is_true) {
ExprDecompiler expr_parser{decomp};
@@ -2440,7 +2425,7 @@ public:
}
}
- void operator()(VideoCommon::Shader::ASTBreak& ast) {
+ void operator()(const ASTBreak& ast) {
const bool is_true = VideoCommon::Shader::ExprIsTrue(ast.condition);
if (!is_true) {
ExprDecompiler expr_parser{decomp};
@@ -2455,7 +2440,7 @@ public:
}
}
- void Visit(VideoCommon::Shader::ASTNode& node) {
+ void Visit(const ASTNode& node) {
std::visit(*this, *node->GetInnerData());
}
@@ -2468,32 +2453,53 @@ void GLSLDecompiler::DecompileAST() {
for (u32 i = 0; i < num_flow_variables; i++) {
code.AddLine("bool {} = false;", GetFlowVariable(i));
}
+
ASTDecompiler decompiler{*this};
- VideoCommon::Shader::ASTNode program = ir.GetASTProgram();
- decompiler.Visit(program);
+ decompiler.Visit(ir.GetASTProgram());
}
} // Anonymous namespace
+ShaderEntries GetEntries(const VideoCommon::Shader::ShaderIR& ir) {
+ ShaderEntries entries;
+ for (const auto& cbuf : ir.GetConstantBuffers()) {
+ entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(),
+ cbuf.first);
+ }
+ for (const auto& sampler : ir.GetSamplers()) {
+ entries.samplers.emplace_back(sampler);
+ }
+ for (const auto& [offset, image] : ir.GetImages()) {
+ entries.images.emplace_back(image);
+ }
+ for (const auto& [base, usage] : ir.GetGlobalMemory()) {
+ entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read,
+ usage.is_written);
+ }
+ entries.clip_distances = ir.GetClipDistances();
+ entries.shader_length = ir.GetLength();
+ return entries;
+}
+
std::string GetCommonDeclarations() {
- return fmt::format(
- "#define ftoi floatBitsToInt\n"
- "#define ftou floatBitsToUint\n"
- "#define itof intBitsToFloat\n"
- "#define utof uintBitsToFloat\n\n"
- "bvec2 HalfFloatNanComparison(bvec2 comparison, vec2 pair1, vec2 pair2) {{\n"
- " bvec2 is_nan1 = isnan(pair1);\n"
- " bvec2 is_nan2 = isnan(pair2);\n"
- " return bvec2(comparison.x || is_nan1.x || is_nan2.x, comparison.y || is_nan1.y || "
- "is_nan2.y);\n"
- "}}\n\n");
+ return R"(#define ftoi floatBitsToInt
+#define ftou floatBitsToUint
+#define itof intBitsToFloat
+#define utof uintBitsToFloat
+
+bvec2 HalfFloatNanComparison(bvec2 comparison, vec2 pair1, vec2 pair2) {
+ bvec2 is_nan1 = isnan(pair1);
+ bvec2 is_nan2 = isnan(pair2);
+ return bvec2(comparison.x || is_nan1.x || is_nan2.x, comparison.y || is_nan1.y || is_nan2.y);
+}
+)";
}
-ProgramResult Decompile(const Device& device, const ShaderIR& ir, ProgramType stage,
- const std::string& suffix) {
+std::string Decompile(const Device& device, const ShaderIR& ir, ProgramType stage,
+ const std::string& suffix) {
GLSLDecompiler decompiler(device, ir, stage, suffix);
decompiler.Decompile();
- return {decompiler.GetResult(), decompiler.GetShaderEntries()};
+ return decompiler.GetResult();
}
} // namespace OpenGL::GLShader