Merge pull request #3258 from FernandoS27/shader-amend

Shader_IR: add the ability to amend code in the shader ir.
This commit is contained in:
bunnei 2020-01-04 14:05:17 -05:00 committed by GitHub
commit cd0a7dfdbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 2 deletions

View File

@ -751,6 +751,9 @@ 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)) {
if (const auto amend_index = operation->GetAmendIndex()) {
Visit(ir.GetAmendNode(*amend_index)).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 +875,9 @@ private:
} }
if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
if (const auto amend_index = conditional->GetAmendIndex()) {
Visit(ir.GetAmendNode(*amend_index)).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;

View File

@ -954,6 +954,10 @@ 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)) {
if (const auto amend_index = operation->GetAmendIndex()) {
[[maybe_unused]] const Type type = Visit(ir.GetAmendNode(*amend_index)).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 +1146,10 @@ private:
} }
if (const auto conditional = std::get_if<ConditionalNode>(&*node)) { if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
if (const auto amend_index = conditional->GetAmendIndex()) {
[[maybe_unused]] const Type type = Visit(ir.GetAmendNode(*amend_index)).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();

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<std::size_t> GetAmendIndex() const {
if (amend_index == amend_null_index) {
return std::nullopt;
}
return {amend_index};
}
void SetAmendIndex(std::size_t index) {
amend_index = index;
}
void ClearAmend() {
amend_index = amend_null_index;
}
private:
static constexpr std::size_t amend_null_index = 0xFFFFFFFFFFFFFFFFULL;
std::size_t 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)} {}

View File

@ -446,4 +446,10 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) {
Immediate(bits)); Immediate(bits));
} }
std::size_t ShaderIR::DeclareAmend(Node new_amend) {
const std::size_t id = 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(std::size_t 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);
/// Register new amending code and obtain the reference id.
std::size_t 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};
std::vector<Node> 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;