Shader_IR: add the ability to amend code in the shader ir.

This commit introduces a mechanism by which shader IR code can be
amended and extended. This useful for track algorithms where certain
information can derived from before the track such as indexes to array
samplers.
This commit is contained in:
Fernando Sahmkow 2019-12-30 13:54:53 -04:00 committed by FernandoS27
parent f846e3d6d0
commit b3371ed09e
5 changed files with 72 additions and 3 deletions

View File

@ -751,6 +751,11 @@ private:
Expression Visit(const Node& node) { Expression Visit(const Node& node) {
if (const auto operation = std::get_if<OperationNode>(&*node)) { if (const auto operation = std::get_if<OperationNode>(&*node)) {
auto amend_index = operation->GetAmendIndex();
if (amend_index) {
const Node& amend_node = ir.GetAmendNode(*amend_index);
Visit(amend_node).CheckVoid();
}
const auto operation_index = static_cast<std::size_t>(operation->GetCode()); const auto operation_index = static_cast<std::size_t>(operation->GetCode());
if (operation_index >= operation_decompilers.size()) { if (operation_index >= operation_decompilers.size()) {
UNREACHABLE_MSG("Out of bounds operation: {}", operation_index); UNREACHABLE_MSG("Out of bounds operation: {}", operation_index);
@ -872,6 +877,11 @@ private:
} }
if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
auto amend_index = conditional->GetAmendIndex();
if (amend_index) {
const Node& amend_node = ir.GetAmendNode(*amend_index);
Visit(amend_node).CheckVoid();
}
// It's invalid to call conditional on nested nodes, use an operation instead // It's invalid to call conditional on nested nodes, use an operation instead
code.AddLine("if ({}) {{", Visit(conditional->GetCondition()).AsBool()); code.AddLine("if ({}) {{", Visit(conditional->GetCondition()).AsBool());
++code.scope; ++code.scope;
@ -884,6 +894,11 @@ private:
} }
if (const auto comment = std::get_if<CommentNode>(&*node)) { if (const auto comment = std::get_if<CommentNode>(&*node)) {
auto amend_index = comment->GetAmendIndex();
if (amend_index) {
const Node& amend_node = ir.GetAmendNode(*amend_index);
Visit(amend_node).CheckVoid();
}
code.AddLine("// " + comment->GetText()); code.AddLine("// " + comment->GetText());
return {}; return {};
} }

View File

@ -954,6 +954,12 @@ private:
Expression Visit(const Node& node) { Expression Visit(const Node& node) {
if (const auto operation = std::get_if<OperationNode>(&*node)) { if (const auto operation = std::get_if<OperationNode>(&*node)) {
auto amend_index = operation->GetAmendIndex();
if (amend_index) {
const Node& amend_node = ir.GetAmendNode(*amend_index);
[[maybe_unused]] const Type type = Visit(amend_node).type;
ASSERT(type == Type::Void);
}
const auto operation_index = static_cast<std::size_t>(operation->GetCode()); const auto operation_index = static_cast<std::size_t>(operation->GetCode());
const auto decompiler = operation_decompilers[operation_index]; const auto decompiler = operation_decompilers[operation_index];
if (decompiler == nullptr) { if (decompiler == nullptr) {
@ -1142,6 +1148,12 @@ private:
} }
if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
auto amend_index = conditional->GetAmendIndex();
if (amend_index) {
const Node& amend_node = ir.GetAmendNode(*amend_index);
[[maybe_unused]] const Type type = Visit(amend_node).type;
ASSERT(type == Type::Void);
}
// It's invalid to call conditional on nested nodes, use an operation instead // It's invalid to call conditional on nested nodes, use an operation instead
const Id true_label = OpLabel(); const Id true_label = OpLabel();
const Id skip_label = OpLabel(); const Id skip_label = OpLabel();
@ -1164,6 +1176,12 @@ private:
} }
if (const auto comment = std::get_if<CommentNode>(&*node)) { if (const auto comment = std::get_if<CommentNode>(&*node)) {
auto amend_index = comment->GetAmendIndex();
if (amend_index) {
const Node& amend_node = ir.GetAmendNode(*amend_index);
[[maybe_unused]] const Type type = Visit(amend_node).type;
ASSERT(type == Type::Void);
}
Name(OpUndef(t_void), comment->GetText()); Name(OpUndef(t_void), comment->GetText());
return {}; return {};
} }

View File

@ -392,8 +392,30 @@ struct MetaImage {
using Meta = using Meta =
std::variant<MetaArithmetic, MetaTexture, MetaImage, MetaStackClass, Tegra::Shader::HalfType>; std::variant<MetaArithmetic, MetaTexture, MetaImage, MetaStackClass, Tegra::Shader::HalfType>;
class AmendNode {
public:
std::optional<u32> GetAmendIndex() const {
if (amend_index == amend_null_index) {
return std::nullopt;
}
return {amend_index};
}
void SetAmendIndex(u32 index) {
amend_index = index;
}
void ClearAmend() {
amend_index = amend_null_index;
}
private:
static constexpr u32 amend_null_index = 0xFFFFFFFF;
u32 amend_index{amend_null_index};
};
/// Holds any kind of operation that can be done in the IR /// Holds any kind of operation that can be done in the IR
class OperationNode final { class OperationNode final : public AmendNode {
public: public:
explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {} explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
@ -433,7 +455,7 @@ private:
}; };
/// Encloses inside any kind of node that returns a boolean conditionally-executed code /// Encloses inside any kind of node that returns a boolean conditionally-executed code
class ConditionalNode final { class ConditionalNode final : public AmendNode {
public: public:
explicit ConditionalNode(Node condition, std::vector<Node>&& code) explicit ConditionalNode(Node condition, std::vector<Node>&& code)
: condition{std::move(condition)}, code{std::move(code)} {} : condition{std::move(condition)}, code{std::move(code)} {}
@ -630,7 +652,7 @@ private:
}; };
/// Commentary, can be dropped /// Commentary, can be dropped
class CommentNode final { class CommentNode final : public AmendNode {
public: public:
explicit CommentNode(std::string text) : text{std::move(text)} {} explicit CommentNode(std::string text) : text{std::move(text)} {}

View File

@ -446,4 +446,10 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) {
Immediate(bits)); Immediate(bits));
} }
u32 ShaderIR::DeclareAmend(Node new_amend) {
const u32 id = static_cast<u32>(amend_code.size());
amend_code.push_back(new_amend);
return id;
}
} // namespace VideoCommon::Shader } // namespace VideoCommon::Shader

View File

@ -176,6 +176,10 @@ public:
/// Returns a condition code evaluated from internal flags /// Returns a condition code evaluated from internal flags
Node GetConditionCode(Tegra::Shader::ConditionCode cc) const; Node GetConditionCode(Tegra::Shader::ConditionCode cc) const;
const Node& GetAmendNode(u32 index) const {
return amend_code[index];
}
private: private:
friend class ASTDecoder; friend class ASTDecoder;
@ -392,6 +396,9 @@ private:
Tegra::Shader::Instruction instr, Tegra::Shader::Instruction instr,
bool is_write); bool is_write);
/// Amends
u32 DeclareAmend(Node new_amend);
const ProgramCode& program_code; const ProgramCode& program_code;
const u32 main_offset; const u32 main_offset;
const CompilerSettings settings; const CompilerSettings settings;
@ -406,6 +413,7 @@ private:
std::map<u32, NodeBlock> basic_blocks; std::map<u32, NodeBlock> basic_blocks;
NodeBlock global_code; NodeBlock global_code;
ASTManager program_manager{true, true}; ASTManager program_manager{true, true};
NodeBlock amend_code;
std::set<u32> used_registers; std::set<u32> used_registers;
std::set<Tegra::Shader::Pred> used_predicates; std::set<Tegra::Shader::Pred> used_predicates;