forked from suyu/suyu
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:
commit
cd0a7dfdbc
5 changed files with 52 additions and 2 deletions
|
@ -751,6 +751,9 @@ private:
|
|||
|
||||
Expression Visit(const Node& 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());
|
||||
if (operation_index >= operation_decompilers.size()) {
|
||||
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 amend_index = conditional->GetAmendIndex()) {
|
||||
Visit(ir.GetAmendNode(*amend_index)).CheckVoid();
|
||||
}
|
||||
// It's invalid to call conditional on nested nodes, use an operation instead
|
||||
code.AddLine("if ({}) {{", Visit(conditional->GetCondition()).AsBool());
|
||||
++code.scope;
|
||||
|
|
|
@ -954,6 +954,10 @@ private:
|
|||
|
||||
Expression Visit(const Node& 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 decompiler = operation_decompilers[operation_index];
|
||||
if (decompiler == nullptr) {
|
||||
|
@ -1142,6 +1146,10 @@ private:
|
|||
}
|
||||
|
||||
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
|
||||
const Id true_label = OpLabel();
|
||||
const Id skip_label = OpLabel();
|
||||
|
|
|
@ -392,8 +392,30 @@ struct MetaImage {
|
|||
using Meta =
|
||||
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
|
||||
class OperationNode final {
|
||||
class OperationNode final : public AmendNode {
|
||||
public:
|
||||
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
|
||||
class ConditionalNode final {
|
||||
class ConditionalNode final : public AmendNode {
|
||||
public:
|
||||
explicit ConditionalNode(Node condition, std::vector<Node>&& code)
|
||||
: condition{std::move(condition)}, code{std::move(code)} {}
|
||||
|
|
|
@ -446,4 +446,10 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 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
|
||||
|
|
|
@ -176,6 +176,10 @@ public:
|
|||
/// Returns a condition code evaluated from internal flags
|
||||
Node GetConditionCode(Tegra::Shader::ConditionCode cc) const;
|
||||
|
||||
const Node& GetAmendNode(std::size_t index) const {
|
||||
return amend_code[index];
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ASTDecoder;
|
||||
|
||||
|
@ -392,6 +396,9 @@ private:
|
|||
Tegra::Shader::Instruction instr,
|
||||
bool is_write);
|
||||
|
||||
/// Register new amending code and obtain the reference id.
|
||||
std::size_t DeclareAmend(Node new_amend);
|
||||
|
||||
const ProgramCode& program_code;
|
||||
const u32 main_offset;
|
||||
const CompilerSettings settings;
|
||||
|
@ -406,6 +413,7 @@ private:
|
|||
std::map<u32, NodeBlock> basic_blocks;
|
||||
NodeBlock global_code;
|
||||
ASTManager program_manager{true, true};
|
||||
std::vector<Node> amend_code;
|
||||
|
||||
std::set<u32> used_registers;
|
||||
std::set<Tegra::Shader::Pred> used_predicates;
|
||||
|
|
Loading…
Reference in a new issue