summaryrefslogtreecommitdiffstats
path: root/src/video_core/shader
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2019-06-29 07:44:07 +0200
committerFernandoS27 <fsahmkow27@gmail.com>2019-10-05 00:52:50 +0200
commit38fc995f6cc2c2af29abc976ddb45b72873b2cc4 (patch)
treea73839d510c79a5e296e54a6768868f788abd45d /src/video_core/shader
parentshader_ir: Declare Manager and pass it to appropiate programs. (diff)
downloadyuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.tar
yuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.tar.gz
yuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.tar.bz2
yuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.tar.lz
yuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.tar.xz
yuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.tar.zst
yuzu-38fc995f6cc2c2af29abc976ddb45b72873b2cc4.zip
Diffstat (limited to 'src/video_core/shader')
-rw-r--r--src/video_core/shader/ast.cpp10
-rw-r--r--src/video_core/shader/ast.h18
-rw-r--r--src/video_core/shader/control_flow.cpp2
-rw-r--r--src/video_core/shader/control_flow.h2
-rw-r--r--src/video_core/shader/decode.cpp70
-rw-r--r--src/video_core/shader/decode/other.cpp8
-rw-r--r--src/video_core/shader/expr.cpp7
-rw-r--r--src/video_core/shader/expr.h2
-rw-r--r--src/video_core/shader/shader_ir.cpp6
-rw-r--r--src/video_core/shader/shader_ir.h25
10 files changed, 116 insertions, 34 deletions
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp
index 0bf289f98..68a96cc79 100644
--- a/src/video_core/shader/ast.cpp
+++ b/src/video_core/shader/ast.cpp
@@ -372,13 +372,13 @@ ASTManager::~ASTManager() {
void ASTManager::Init() {
main_node = ASTBase::Make<ASTProgram>(ASTNode{});
program = std::get_if<ASTProgram>(main_node->GetInnerData());
- true_condition = MakeExpr<ExprBoolean>(true);
+ false_condition = MakeExpr<ExprBoolean>(false);
}
ASTManager::ASTManager(ASTManager&& other)
: labels_map(std::move(other.labels_map)), labels_count{other.labels_count},
gotos(std::move(other.gotos)), labels(std::move(other.labels)), variables{other.variables},
- program{other.program}, main_node{other.main_node}, true_condition{other.true_condition} {
+ program{other.program}, main_node{other.main_node}, false_condition{other.false_condition} {
other.main_node.reset();
}
@@ -390,7 +390,7 @@ ASTManager& ASTManager::operator=(ASTManager&& other) {
variables = other.variables;
program = other.program;
main_node = other.main_node;
- true_condition = other.true_condition;
+ false_condition = other.false_condition;
other.main_node.reset();
return *this;
@@ -594,7 +594,7 @@ void ASTManager::MoveOutward(ASTNode goto_node) {
u32 var_index = NewVariable();
Expr var_condition = MakeExpr<ExprVar>(var_index);
ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
- ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, true_condition);
+ ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, false_condition);
zipper2.InsertBefore(var_node_init, parent);
zipper.InsertAfter(var_node, prev);
goto_node->SetGotoCondition(var_condition);
@@ -605,7 +605,7 @@ void ASTManager::MoveOutward(ASTNode goto_node) {
u32 var_index = NewVariable();
Expr var_condition = MakeExpr<ExprVar>(var_index);
ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
- ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, true_condition);
+ ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, false_condition);
if (is_if) {
zipper2.InsertBefore(var_node_init, parent);
} else {
diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h
index 958989bcd..06ab20cc5 100644
--- a/src/video_core/shader/ast.h
+++ b/src/video_core/shader/ast.h
@@ -141,8 +141,6 @@ public:
Expr condition;
};
-using TransformCallback = std::function<NodeBlock(u32 start, u32 end)>;
-
class ASTBase {
public:
explicit ASTBase(ASTNode parent, ASTData data) : parent{parent}, data{data} {}
@@ -233,11 +231,7 @@ public:
return std::holds_alternative<ASTBlockEncoded>(data);
}
- void TransformBlockEncoded(TransformCallback& callback) {
- auto block = std::get_if<ASTBlockEncoded>(&data);
- const u32 start = block->start;
- const u32 end = block->end;
- NodeBlock nodes = callback(start, end);
+ void TransformBlockEncoded(NodeBlock& nodes) {
data = ASTBlockDecoded(nodes);
}
@@ -309,16 +303,20 @@ public:
void SanityCheck();
- bool IsFullyDecompiled() {
+ bool IsFullyDecompiled() const {
return gotos.size() == 0;
}
- ASTNode GetProgram() {
+ ASTNode GetProgram() const {
return main_node;
}
void Clear();
+ u32 GetVariables() const {
+ return variables;
+ }
+
private:
bool IndirectlyRelated(ASTNode first, ASTNode second);
@@ -343,7 +341,7 @@ private:
u32 variables{};
ASTProgram* program{};
ASTNode main_node{};
- Expr true_condition{};
+ Expr false_condition{};
};
} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index deb3d3ebd..a29922815 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -425,7 +425,7 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch) {
}
if (cond.predicate != Pred::UnusedIndex) {
u32 pred = static_cast<u32>(cond.predicate);
- bool negate;
+ bool negate = false;
if (pred > 7) {
negate = true;
pred -= 8;
diff --git a/src/video_core/shader/control_flow.h b/src/video_core/shader/control_flow.h
index 2805d975c..347a35dcf 100644
--- a/src/video_core/shader/control_flow.h
+++ b/src/video_core/shader/control_flow.h
@@ -74,6 +74,6 @@ struct ShaderCharacteristics {
};
std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
- u32 start_address, ASTManager& manager);
+ u32 start_address, ASTManager& manager);
} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 381e87415..e7e0903f6 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -35,10 +35,73 @@ constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) {
} // namespace
+class ASTDecoder {
+public:
+ ASTDecoder(ShaderIR& ir) : ir(ir) {}
+
+ void operator()(ASTProgram& ast) {
+ ASTNode current = ast.nodes.GetFirst();
+ while (current) {
+ Visit(current);
+ current = current->GetNext();
+ }
+ }
+
+ void operator()(ASTIfThen& ast) {
+ ASTNode current = ast.nodes.GetFirst();
+ while (current) {
+ Visit(current);
+ current = current->GetNext();
+ }
+ }
+
+ void operator()(ASTIfElse& ast) {
+ ASTNode current = ast.nodes.GetFirst();
+ while (current) {
+ Visit(current);
+ current = current->GetNext();
+ }
+ }
+
+ void operator()(ASTBlockEncoded& ast) {}
+
+ void operator()(ASTBlockDecoded& ast) {}
+
+ void operator()(ASTVarSet& ast) {}
+
+ void operator()(ASTLabel& ast) {}
+
+ void operator()(ASTGoto& ast) {}
+
+ void operator()(ASTDoWhile& ast) {
+ ASTNode current = ast.nodes.GetFirst();
+ while (current) {
+ Visit(current);
+ current = current->GetNext();
+ }
+ }
+
+ void operator()(ASTReturn& ast) {}
+
+ void operator()(ASTBreak& ast) {}
+
+ void Visit(ASTNode& node) {
+ std::visit(*this, *node->GetInnerData());
+ if (node->IsBlockEncoded()) {
+ auto block = std::get_if<ASTBlockEncoded>(node->GetInnerData());
+ NodeBlock bb = ir.DecodeRange(block->start, block->end);
+ node->TransformBlockEncoded(bb);
+ }
+ }
+
+private:
+ ShaderIR& ir;
+};
+
void ShaderIR::Decode() {
std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
- disable_flow_stack = false;
+ decompiled = false;
const auto info =
ScanFlow(program_code, program_size, main_offset, program_manager);
if (info) {
@@ -46,7 +109,10 @@ void ShaderIR::Decode() {
coverage_begin = shader_info.start;
coverage_end = shader_info.end;
if (shader_info.decompiled) {
- disable_flow_stack = true;
+ decompiled = true;
+ ASTDecoder decoder{*this};
+ ASTNode program = GetASTProgram();
+ decoder.Visit(program);
return;
}
LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method");
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index d46e0f823..6f678003c 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -157,7 +157,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
"Constant buffer flow is not supported");
- if (disable_flow_stack) {
+ if (decompiled) {
break;
}
@@ -171,7 +171,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0,
"Constant buffer PBK is not supported");
- if (disable_flow_stack) {
+ if (decompiled) {
break;
}
@@ -186,7 +186,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "SYNC condition code used: {}",
static_cast<u32>(cc));
- if (disable_flow_stack) {
+ if (decompiled) {
break;
}
@@ -198,7 +198,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
const Tegra::Shader::ConditionCode cc = instr.flow_condition_code;
UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "BRK condition code used: {}",
static_cast<u32>(cc));
- if (disable_flow_stack) {
+ if (decompiled) {
break;
}
diff --git a/src/video_core/shader/expr.cpp b/src/video_core/shader/expr.cpp
index ebce6339b..ca633ffb1 100644
--- a/src/video_core/shader/expr.cpp
+++ b/src/video_core/shader/expr.cpp
@@ -72,4 +72,11 @@ bool ExprAreOpposite(Expr first, Expr second) {
return false;
}
+bool ExprIsTrue(Expr first) {
+ if (ExprIsBoolean(first)) {
+ return ExprBooleanGet(first);
+ }
+ return false;
+}
+
} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/expr.h b/src/video_core/shader/expr.h
index f012f6fcf..b954cffb0 100644
--- a/src/video_core/shader/expr.h
+++ b/src/video_core/shader/expr.h
@@ -115,4 +115,6 @@ Expr MakeExprAnd(Expr first, Expr second);
Expr MakeExprOr(Expr first, Expr second);
+bool ExprIsTrue(Expr first);
+
} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index c79f80e04..004b1e16f 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -137,7 +137,7 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff
return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
}
-Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) {
+Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) const {
const Node node = MakeNode<InternalFlagNode>(flag);
if (negated) {
return Operation(OperationCode::LogicalNegate, node);
@@ -367,13 +367,13 @@ OperationCode ShaderIR::GetPredicateCombiner(PredOperation operation) {
return op->second;
}
-Node ShaderIR::GetConditionCode(Tegra::Shader::ConditionCode cc) {
+Node ShaderIR::GetConditionCode(Tegra::Shader::ConditionCode cc) const {
switch (cc) {
case Tegra::Shader::ConditionCode::NEU:
return GetInternalFlag(InternalFlag::Zero, true);
default:
UNIMPLEMENTED_MSG("Unimplemented condition code: {}", static_cast<u32>(cc));
- return GetPredicate(static_cast<u64>(Pred::NeverExecute));
+ return MakeNode<PredicateNode>(Pred::NeverExecute, false);
}
}
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index a91cd7d67..48c7b722e 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -15,8 +15,8 @@
#include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/engines/shader_header.h"
-#include "video_core/shader/node.h"
#include "video_core/shader/ast.h"
+#include "video_core/shader/node.h"
namespace VideoCommon::Shader {
@@ -141,15 +141,27 @@ public:
return header;
}
- bool IsFlowStackDisabled() const {
- return disable_flow_stack;
+ bool IsDecompiled() const {
+ return decompiled;
+ }
+
+ ASTNode GetASTProgram() const {
+ return program_manager.GetProgram();
+ }
+
+ u32 GetASTNumVariables() const {
+ return program_manager.GetVariables();
}
u32 ConvertAddressToNvidiaSpace(const u32 address) const {
return (address - main_offset) * sizeof(Tegra::Shader::Instruction);
}
+ /// Returns a condition code evaluated from internal flags
+ Node GetConditionCode(Tegra::Shader::ConditionCode cc) const;
+
private:
+ friend class ASTDecoder;
void Decode();
NodeBlock DecodeRange(u32 begin, u32 end);
@@ -214,7 +226,7 @@ private:
/// Generates a node representing an output attribute. Keeps track of used attributes.
Node GetOutputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer);
/// Generates a node representing an internal flag
- Node GetInternalFlag(InternalFlag flag, bool negated = false);
+ Node GetInternalFlag(InternalFlag flag, bool negated = false) const;
/// Generates a node representing a local memory address
Node GetLocalMemory(Node address);
/// Generates a node representing a shared memory address
@@ -272,9 +284,6 @@ private:
/// Returns a predicate combiner operation
OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);
- /// Returns a condition code evaluated from internal flags
- Node GetConditionCode(Tegra::Shader::ConditionCode cc);
-
/// Accesses a texture sampler
const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler,
Tegra::Shader::TextureType type, bool is_array, bool is_shadow);
@@ -358,7 +367,7 @@ private:
const ProgramCode& program_code;
const u32 main_offset;
const std::size_t program_size;
- bool disable_flow_stack{};
+ bool decompiled{};
u32 coverage_begin{};
u32 coverage_end{};