Browse Source
Merge pull request #3258 from FernandoS27/shader-amend
Shader_IR: add the ability to amend code in the shader ir.
pull/15/merge
bunnei
6 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with
52 additions and
2 deletions
-
src/video_core/renderer_opengl/gl_shader_decompiler.cpp
-
src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
-
src/video_core/shader/node.h
-
src/video_core/shader/shader_ir.cpp
-
src/video_core/shader/shader_ir.h
|
|
|
@ -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; |
|
|
|
|