Quellcode durchsuchen

shader: Move Node declarations out of the shader IR header

Analysis passes do not have a good reason to depend on shader_ir.h to
work on top of nodes. This splits node-related declarations to their own
file and leaves the IR in shader_ir.h
ReinUsesLisp vor 7 Jahren
Ursprung
Commit
e1b3be7ced

+ 1 - 0
src/video_core/CMakeLists.txt

@@ -104,6 +104,7 @@ add_library(video_core STATIC
     shader/decode.cpp
     shader/node_helper.cpp
     shader/node_helper.h
+    shader/node.h
     shader/shader_ir.cpp
     shader/shader_ir.h
     shader/track.cpp

+ 510 - 0
src/video_core/shader/node.h

@@ -0,0 +1,510 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <variant>
+#include <vector>
+
+#include "common/common_types.h"
+#include "video_core/engines/shader_bytecode.h"
+
+namespace VideoCommon::Shader {
+
+class OperationNode;
+class ConditionalNode;
+class GprNode;
+class ImmediateNode;
+class InternalFlagNode;
+class PredicateNode;
+class AbufNode; ///< Attribute buffer
+class CbufNode; ///< Constant buffer
+class LmemNode; ///< Local memory
+class GmemNode; ///< Global memory
+class CommentNode;
+
+using NodeData =
+    std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
+                 PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>;
+using Node = std::shared_ptr<NodeData>;
+using Node4 = std::array<Node, 4>;
+using NodeBlock = std::vector<Node>;
+
+enum class OperationCode {
+    Assign, /// (float& dest, float src) -> void
+
+    Select, /// (MetaArithmetic, bool pred, float a, float b) -> float
+
+    FAdd,          /// (MetaArithmetic, float a, float b) -> float
+    FMul,          /// (MetaArithmetic, float a, float b) -> float
+    FDiv,          /// (MetaArithmetic, float a, float b) -> float
+    FFma,          /// (MetaArithmetic, float a, float b, float c) -> float
+    FNegate,       /// (MetaArithmetic, float a) -> float
+    FAbsolute,     /// (MetaArithmetic, float a) -> float
+    FClamp,        /// (MetaArithmetic, float value, float min, float max) -> float
+    FMin,          /// (MetaArithmetic, float a, float b) -> float
+    FMax,          /// (MetaArithmetic, float a, float b) -> float
+    FCos,          /// (MetaArithmetic, float a) -> float
+    FSin,          /// (MetaArithmetic, float a) -> float
+    FExp2,         /// (MetaArithmetic, float a) -> float
+    FLog2,         /// (MetaArithmetic, float a) -> float
+    FInverseSqrt,  /// (MetaArithmetic, float a) -> float
+    FSqrt,         /// (MetaArithmetic, float a) -> float
+    FRoundEven,    /// (MetaArithmetic, float a) -> float
+    FFloor,        /// (MetaArithmetic, float a) -> float
+    FCeil,         /// (MetaArithmetic, float a) -> float
+    FTrunc,        /// (MetaArithmetic, float a) -> float
+    FCastInteger,  /// (MetaArithmetic, int a) -> float
+    FCastUInteger, /// (MetaArithmetic, uint a) -> float
+
+    IAdd,                  /// (MetaArithmetic, int a, int b) -> int
+    IMul,                  /// (MetaArithmetic, int a, int b) -> int
+    IDiv,                  /// (MetaArithmetic, int a, int b) -> int
+    INegate,               /// (MetaArithmetic, int a) -> int
+    IAbsolute,             /// (MetaArithmetic, int a) -> int
+    IMin,                  /// (MetaArithmetic, int a, int b) -> int
+    IMax,                  /// (MetaArithmetic, int a, int b) -> int
+    ICastFloat,            /// (MetaArithmetic, float a) -> int
+    ICastUnsigned,         /// (MetaArithmetic, uint a) -> int
+    ILogicalShiftLeft,     /// (MetaArithmetic, int a, uint b) -> int
+    ILogicalShiftRight,    /// (MetaArithmetic, int a, uint b) -> int
+    IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int
+    IBitwiseAnd,           /// (MetaArithmetic, int a, int b) -> int
+    IBitwiseOr,            /// (MetaArithmetic, int a, int b) -> int
+    IBitwiseXor,           /// (MetaArithmetic, int a, int b) -> int
+    IBitwiseNot,           /// (MetaArithmetic, int a) -> int
+    IBitfieldInsert,       /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
+    IBitfieldExtract,      /// (MetaArithmetic, int value, int offset, int offset) -> int
+    IBitCount,             /// (MetaArithmetic, int) -> int
+
+    UAdd,                  /// (MetaArithmetic, uint a, uint b) -> uint
+    UMul,                  /// (MetaArithmetic, uint a, uint b) -> uint
+    UDiv,                  /// (MetaArithmetic, uint a, uint b) -> uint
+    UMin,                  /// (MetaArithmetic, uint a, uint b) -> uint
+    UMax,                  /// (MetaArithmetic, uint a, uint b) -> uint
+    UCastFloat,            /// (MetaArithmetic, float a) -> uint
+    UCastSigned,           /// (MetaArithmetic, int a) -> uint
+    ULogicalShiftLeft,     /// (MetaArithmetic, uint a, uint b) -> uint
+    ULogicalShiftRight,    /// (MetaArithmetic, uint a, uint b) -> uint
+    UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
+    UBitwiseAnd,           /// (MetaArithmetic, uint a, uint b) -> uint
+    UBitwiseOr,            /// (MetaArithmetic, uint a, uint b) -> uint
+    UBitwiseXor,           /// (MetaArithmetic, uint a, uint b) -> uint
+    UBitwiseNot,           /// (MetaArithmetic, uint a) -> uint
+    UBitfieldInsert,  /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
+    UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
+    UBitCount,        /// (MetaArithmetic, uint) -> uint
+
+    HAdd,      /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
+    HMul,      /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
+    HFma,      /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
+    HAbsolute, /// (f16vec2 a) -> f16vec2
+    HNegate,   /// (f16vec2 a, bool first, bool second) -> f16vec2
+    HClamp,    /// (f16vec2 src, float min, float max) -> f16vec2
+    HUnpack,   /// (Tegra::Shader::HalfType, T value) -> f16vec2
+    HMergeF32, /// (f16vec2 src) -> float
+    HMergeH0,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
+    HMergeH1,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
+    HPack2,    /// (float a, float b) -> f16vec2
+
+    LogicalAssign, /// (bool& dst, bool src) -> void
+    LogicalAnd,    /// (bool a, bool b) -> bool
+    LogicalOr,     /// (bool a, bool b) -> bool
+    LogicalXor,    /// (bool a, bool b) -> bool
+    LogicalNegate, /// (bool a) -> bool
+    LogicalPick2,  /// (bool2 pair, uint index) -> bool
+    LogicalAll2,   /// (bool2 a) -> bool
+    LogicalAny2,   /// (bool2 a) -> bool
+
+    LogicalFLessThan,     /// (float a, float b) -> bool
+    LogicalFEqual,        /// (float a, float b) -> bool
+    LogicalFLessEqual,    /// (float a, float b) -> bool
+    LogicalFGreaterThan,  /// (float a, float b) -> bool
+    LogicalFNotEqual,     /// (float a, float b) -> bool
+    LogicalFGreaterEqual, /// (float a, float b) -> bool
+    LogicalFIsNan,        /// (float a) -> bool
+
+    LogicalILessThan,     /// (int a, int b) -> bool
+    LogicalIEqual,        /// (int a, int b) -> bool
+    LogicalILessEqual,    /// (int a, int b) -> bool
+    LogicalIGreaterThan,  /// (int a, int b) -> bool
+    LogicalINotEqual,     /// (int a, int b) -> bool
+    LogicalIGreaterEqual, /// (int a, int b) -> bool
+
+    LogicalULessThan,     /// (uint a, uint b) -> bool
+    LogicalUEqual,        /// (uint a, uint b) -> bool
+    LogicalULessEqual,    /// (uint a, uint b) -> bool
+    LogicalUGreaterThan,  /// (uint a, uint b) -> bool
+    LogicalUNotEqual,     /// (uint a, uint b) -> bool
+    LogicalUGreaterEqual, /// (uint a, uint b) -> bool
+
+    Logical2HLessThan,            /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HEqual,               /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HLessEqual,           /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HGreaterThan,         /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HNotEqual,            /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HGreaterEqual,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HLessThanWithNan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HEqualWithNan,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HLessEqualWithNan,    /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HGreaterThanWithNan,  /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HNotEqualWithNan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+
+    Texture,                /// (MetaTexture, float[N] coords) -> float4
+    TextureLod,             /// (MetaTexture, float[N] coords) -> float4
+    TextureGather,          /// (MetaTexture, float[N] coords) -> float4
+    TextureQueryDimensions, /// (MetaTexture, float a) -> float4
+    TextureQueryLod,        /// (MetaTexture, float[N] coords) -> float4
+    TexelFetch,             /// (MetaTexture, int[N], int) -> float4
+
+    Branch,        /// (uint branch_target) -> void
+    PushFlowStack, /// (uint branch_target) -> void
+    PopFlowStack,  /// () -> void
+    Exit,          /// () -> void
+    Discard,       /// () -> void
+
+    EmitVertex,   /// () -> void
+    EndPrimitive, /// () -> void
+
+    YNegate,            /// () -> float
+    LocalInvocationIdX, /// () -> uint
+    LocalInvocationIdY, /// () -> uint
+    LocalInvocationIdZ, /// () -> uint
+    WorkGroupIdX,       /// () -> uint
+    WorkGroupIdY,       /// () -> uint
+    WorkGroupIdZ,       /// () -> uint
+
+    Amount,
+};
+
+enum class InternalFlag {
+    Zero = 0,
+    Sign = 1,
+    Carry = 2,
+    Overflow = 3,
+    Amount = 4,
+};
+
+class Sampler {
+public:
+    // Use this constructor for bounded Samplers
+    explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type,
+                     bool is_array, bool is_shadow)
+        : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow},
+          is_bindless{false} {}
+
+    // Use this constructor for bindless Samplers
+    explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index,
+                     Tegra::Shader::TextureType type, bool is_array, bool is_shadow)
+        : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type},
+          is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {}
+
+    // Use this only for serialization/deserialization
+    explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type,
+                     bool is_array, bool is_shadow, bool is_bindless)
+        : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow},
+          is_bindless{is_bindless} {}
+
+    std::size_t GetOffset() const {
+        return offset;
+    }
+
+    std::size_t GetIndex() const {
+        return index;
+    }
+
+    Tegra::Shader::TextureType GetType() const {
+        return type;
+    }
+
+    bool IsArray() const {
+        return is_array;
+    }
+
+    bool IsShadow() const {
+        return is_shadow;
+    }
+
+    bool IsBindless() const {
+        return is_bindless;
+    }
+
+    std::pair<u32, u32> GetBindlessCBuf() const {
+        return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)};
+    }
+
+    bool operator<(const Sampler& rhs) const {
+        return std::tie(index, offset, type, is_array, is_shadow, is_bindless) <
+               std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow,
+                        rhs.is_bindless);
+    }
+
+private:
+    /// Offset in TSC memory from which to read the sampler object, as specified by the sampling
+    /// instruction.
+    std::size_t offset{};
+    std::size_t index{}; ///< Value used to index into the generated GLSL sampler array.
+    Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
+    bool is_array{};    ///< Whether the texture is being sampled as an array texture or not.
+    bool is_shadow{};   ///< Whether the texture is being sampled as a depth texture or not.
+    bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
+};
+
+struct GlobalMemoryBase {
+    u32 cbuf_index{};
+    u32 cbuf_offset{};
+
+    bool operator<(const GlobalMemoryBase& rhs) const {
+        return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset);
+    }
+};
+
+struct MetaArithmetic {
+    bool precise{};
+};
+
+struct MetaTexture {
+    const Sampler& sampler;
+    Node array{};
+    Node depth_compare{};
+    std::vector<Node> aoffi;
+    Node bias{};
+    Node lod{};
+    Node component{};
+    u32 element{};
+};
+
+using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
+
+/// Holds any kind of operation that can be done in the IR
+class OperationNode final {
+public:
+    explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
+
+    explicit OperationNode(OperationCode code, Meta meta)
+        : OperationNode(code, meta, std::vector<Node>{}) {}
+
+    explicit OperationNode(OperationCode code, std::vector<Node> operands)
+        : OperationNode(code, Meta{}, std::move(operands)) {}
+
+    explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands)
+        : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {}
+
+    template <typename... Args>
+    explicit OperationNode(OperationCode code, Meta meta, Args&&... operands)
+        : code{code}, meta{std::move(meta)}, operands{operands...} {}
+
+    OperationCode GetCode() const {
+        return code;
+    }
+
+    const Meta& GetMeta() const {
+        return meta;
+    }
+
+    std::size_t GetOperandsCount() const {
+        return operands.size();
+    }
+
+    const Node& operator[](std::size_t operand_index) const {
+        return operands.at(operand_index);
+    }
+
+private:
+    OperationCode code{};
+    Meta meta{};
+    std::vector<Node> operands;
+};
+
+/// Encloses inside any kind of node that returns a boolean conditionally-executed code
+class ConditionalNode final {
+public:
+    explicit ConditionalNode(Node condition, std::vector<Node>&& code)
+        : condition{condition}, code{std::move(code)} {}
+
+    Node GetCondition() const {
+        return condition;
+    }
+
+    const std::vector<Node>& GetCode() const {
+        return code;
+    }
+
+private:
+    const Node condition;   ///< Condition to be satisfied
+    std::vector<Node> code; ///< Code to execute
+};
+
+/// A general purpose register
+class GprNode final {
+public:
+    explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {}
+
+    u32 GetIndex() const {
+        return static_cast<u32>(index);
+    }
+
+private:
+    const Tegra::Shader::Register index;
+};
+
+/// A 32-bits value that represents an immediate value
+class ImmediateNode final {
+public:
+    explicit constexpr ImmediateNode(u32 value) : value{value} {}
+
+    u32 GetValue() const {
+        return value;
+    }
+
+private:
+    const u32 value;
+};
+
+/// One of Maxwell's internal flags
+class InternalFlagNode final {
+public:
+    explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {}
+
+    InternalFlag GetFlag() const {
+        return flag;
+    }
+
+private:
+    const InternalFlag flag;
+};
+
+/// A predicate register, it can be negated without additional nodes
+class PredicateNode final {
+public:
+    explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated)
+        : index{index}, negated{negated} {}
+
+    Tegra::Shader::Pred GetIndex() const {
+        return index;
+    }
+
+    bool IsNegated() const {
+        return negated;
+    }
+
+private:
+    const Tegra::Shader::Pred index;
+    const bool negated;
+};
+
+/// Attribute buffer memory (known as attributes or varyings in GLSL terms)
+class AbufNode final {
+public:
+    // Initialize for standard attributes (index is explicit).
+    explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {})
+        : buffer{std::move(buffer)}, index{index}, element{element} {}
+
+    // Initialize for physical attributes (index is a variable value).
+    explicit AbufNode(Node physical_address, Node buffer = {})
+        : physical_address{physical_address}, buffer{std::move(buffer)} {}
+
+    Tegra::Shader::Attribute::Index GetIndex() const {
+        return index;
+    }
+
+    u32 GetElement() const {
+        return element;
+    }
+
+    Node GetBuffer() const {
+        return buffer;
+    }
+
+    bool IsPhysicalBuffer() const {
+        return static_cast<bool>(physical_address);
+    }
+
+    const Node& GetPhysicalAddress() const {
+        return physical_address;
+    }
+
+private:
+    Node physical_address;
+    Node buffer;
+    Tegra::Shader::Attribute::Index index{};
+    u32 element{};
+};
+
+/// Constant buffer node, usually mapped to uniform buffers in GLSL
+class CbufNode final {
+public:
+    explicit CbufNode(u32 index, Node offset) : index{index}, offset{offset} {}
+
+    u32 GetIndex() const {
+        return index;
+    }
+
+    Node GetOffset() const {
+        return offset;
+    }
+
+private:
+    const u32 index;
+    const Node offset;
+};
+
+/// Local memory node
+class LmemNode final {
+public:
+    explicit LmemNode(Node address) : address{address} {}
+
+    Node GetAddress() const {
+        return address;
+    }
+
+private:
+    const Node address;
+};
+
+/// Global memory node
+class GmemNode final {
+public:
+    explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor)
+        : real_address{real_address}, base_address{base_address}, descriptor{descriptor} {}
+
+    Node GetRealAddress() const {
+        return real_address;
+    }
+
+    Node GetBaseAddress() const {
+        return base_address;
+    }
+
+    const GlobalMemoryBase& GetDescriptor() const {
+        return descriptor;
+    }
+
+private:
+    const Node real_address;
+    const Node base_address;
+    const GlobalMemoryBase descriptor;
+};
+
+/// Commentary, can be dropped
+class CommentNode final {
+public:
+    explicit CommentNode(std::string text) : text{std::move(text)} {}
+
+    const std::string& GetText() const {
+        return text;
+    }
+
+private:
+    std::string text;
+};
+
+} // namespace VideoCommon::Shader

+ 6 - 1
src/video_core/shader/node_helper.h

@@ -12,10 +12,15 @@
 #include <vector>
 
 #include "common/common_types.h"
-#include "video_core/shader/shader_ir.h"
+#include "video_core/shader/node.h"
 
 namespace VideoCommon::Shader {
 
+/// This arithmetic operation cannot be constraint
+inline constexpr MetaArithmetic PRECISE = {true};
+/// This arithmetic operation can be optimized away
+inline constexpr MetaArithmetic NO_PRECISE = {false};
+
 /// Creates a conditional node
 Node Conditional(Node condition, std::vector<Node> code);
 

+ 1 - 492
src/video_core/shader/shader_ir.h

@@ -18,188 +18,14 @@
 #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"
 
 namespace VideoCommon::Shader {
 
-class OperationNode;
-class ConditionalNode;
-class GprNode;
-class ImmediateNode;
-class InternalFlagNode;
-class PredicateNode;
-class AbufNode; ///< Attribute buffer
-class CbufNode; ///< Constant buffer
-class LmemNode; ///< Local memory
-class GmemNode; ///< Global memory
-class CommentNode;
-
 using ProgramCode = std::vector<u64>;
 
-using NodeData =
-    std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
-                 PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>;
-using Node = std::shared_ptr<NodeData>;
-using Node4 = std::array<Node, 4>;
-using NodeBlock = std::vector<Node>;
-
 constexpr u32 MAX_PROGRAM_LENGTH = 0x1000;
 
-enum class OperationCode {
-    Assign, /// (float& dest, float src) -> void
-
-    Select, /// (MetaArithmetic, bool pred, float a, float b) -> float
-
-    FAdd,          /// (MetaArithmetic, float a, float b) -> float
-    FMul,          /// (MetaArithmetic, float a, float b) -> float
-    FDiv,          /// (MetaArithmetic, float a, float b) -> float
-    FFma,          /// (MetaArithmetic, float a, float b, float c) -> float
-    FNegate,       /// (MetaArithmetic, float a) -> float
-    FAbsolute,     /// (MetaArithmetic, float a) -> float
-    FClamp,        /// (MetaArithmetic, float value, float min, float max) -> float
-    FMin,          /// (MetaArithmetic, float a, float b) -> float
-    FMax,          /// (MetaArithmetic, float a, float b) -> float
-    FCos,          /// (MetaArithmetic, float a) -> float
-    FSin,          /// (MetaArithmetic, float a) -> float
-    FExp2,         /// (MetaArithmetic, float a) -> float
-    FLog2,         /// (MetaArithmetic, float a) -> float
-    FInverseSqrt,  /// (MetaArithmetic, float a) -> float
-    FSqrt,         /// (MetaArithmetic, float a) -> float
-    FRoundEven,    /// (MetaArithmetic, float a) -> float
-    FFloor,        /// (MetaArithmetic, float a) -> float
-    FCeil,         /// (MetaArithmetic, float a) -> float
-    FTrunc,        /// (MetaArithmetic, float a) -> float
-    FCastInteger,  /// (MetaArithmetic, int a) -> float
-    FCastUInteger, /// (MetaArithmetic, uint a) -> float
-
-    IAdd,                  /// (MetaArithmetic, int a, int b) -> int
-    IMul,                  /// (MetaArithmetic, int a, int b) -> int
-    IDiv,                  /// (MetaArithmetic, int a, int b) -> int
-    INegate,               /// (MetaArithmetic, int a) -> int
-    IAbsolute,             /// (MetaArithmetic, int a) -> int
-    IMin,                  /// (MetaArithmetic, int a, int b) -> int
-    IMax,                  /// (MetaArithmetic, int a, int b) -> int
-    ICastFloat,            /// (MetaArithmetic, float a) -> int
-    ICastUnsigned,         /// (MetaArithmetic, uint a) -> int
-    ILogicalShiftLeft,     /// (MetaArithmetic, int a, uint b) -> int
-    ILogicalShiftRight,    /// (MetaArithmetic, int a, uint b) -> int
-    IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int
-    IBitwiseAnd,           /// (MetaArithmetic, int a, int b) -> int
-    IBitwiseOr,            /// (MetaArithmetic, int a, int b) -> int
-    IBitwiseXor,           /// (MetaArithmetic, int a, int b) -> int
-    IBitwiseNot,           /// (MetaArithmetic, int a) -> int
-    IBitfieldInsert,       /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
-    IBitfieldExtract,      /// (MetaArithmetic, int value, int offset, int offset) -> int
-    IBitCount,             /// (MetaArithmetic, int) -> int
-
-    UAdd,                  /// (MetaArithmetic, uint a, uint b) -> uint
-    UMul,                  /// (MetaArithmetic, uint a, uint b) -> uint
-    UDiv,                  /// (MetaArithmetic, uint a, uint b) -> uint
-    UMin,                  /// (MetaArithmetic, uint a, uint b) -> uint
-    UMax,                  /// (MetaArithmetic, uint a, uint b) -> uint
-    UCastFloat,            /// (MetaArithmetic, float a) -> uint
-    UCastSigned,           /// (MetaArithmetic, int a) -> uint
-    ULogicalShiftLeft,     /// (MetaArithmetic, uint a, uint b) -> uint
-    ULogicalShiftRight,    /// (MetaArithmetic, uint a, uint b) -> uint
-    UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
-    UBitwiseAnd,           /// (MetaArithmetic, uint a, uint b) -> uint
-    UBitwiseOr,            /// (MetaArithmetic, uint a, uint b) -> uint
-    UBitwiseXor,           /// (MetaArithmetic, uint a, uint b) -> uint
-    UBitwiseNot,           /// (MetaArithmetic, uint a) -> uint
-    UBitfieldInsert,  /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
-    UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
-    UBitCount,        /// (MetaArithmetic, uint) -> uint
-
-    HAdd,      /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
-    HMul,      /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
-    HFma,      /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
-    HAbsolute, /// (f16vec2 a) -> f16vec2
-    HNegate,   /// (f16vec2 a, bool first, bool second) -> f16vec2
-    HClamp,    /// (f16vec2 src, float min, float max) -> f16vec2
-    HUnpack,   /// (Tegra::Shader::HalfType, T value) -> f16vec2
-    HMergeF32, /// (f16vec2 src) -> float
-    HMergeH0,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
-    HMergeH1,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
-    HPack2,    /// (float a, float b) -> f16vec2
-
-    LogicalAssign, /// (bool& dst, bool src) -> void
-    LogicalAnd,    /// (bool a, bool b) -> bool
-    LogicalOr,     /// (bool a, bool b) -> bool
-    LogicalXor,    /// (bool a, bool b) -> bool
-    LogicalNegate, /// (bool a) -> bool
-    LogicalPick2,  /// (bool2 pair, uint index) -> bool
-    LogicalAll2,   /// (bool2 a) -> bool
-    LogicalAny2,   /// (bool2 a) -> bool
-
-    LogicalFLessThan,     /// (float a, float b) -> bool
-    LogicalFEqual,        /// (float a, float b) -> bool
-    LogicalFLessEqual,    /// (float a, float b) -> bool
-    LogicalFGreaterThan,  /// (float a, float b) -> bool
-    LogicalFNotEqual,     /// (float a, float b) -> bool
-    LogicalFGreaterEqual, /// (float a, float b) -> bool
-    LogicalFIsNan,        /// (float a) -> bool
-
-    LogicalILessThan,     /// (int a, int b) -> bool
-    LogicalIEqual,        /// (int a, int b) -> bool
-    LogicalILessEqual,    /// (int a, int b) -> bool
-    LogicalIGreaterThan,  /// (int a, int b) -> bool
-    LogicalINotEqual,     /// (int a, int b) -> bool
-    LogicalIGreaterEqual, /// (int a, int b) -> bool
-
-    LogicalULessThan,     /// (uint a, uint b) -> bool
-    LogicalUEqual,        /// (uint a, uint b) -> bool
-    LogicalULessEqual,    /// (uint a, uint b) -> bool
-    LogicalUGreaterThan,  /// (uint a, uint b) -> bool
-    LogicalUNotEqual,     /// (uint a, uint b) -> bool
-    LogicalUGreaterEqual, /// (uint a, uint b) -> bool
-
-    Logical2HLessThan,            /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HEqual,               /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HLessEqual,           /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HGreaterThan,         /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HNotEqual,            /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HGreaterEqual,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HLessThanWithNan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HEqualWithNan,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HLessEqualWithNan,    /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HGreaterThanWithNan,  /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HNotEqualWithNan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-    Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
-
-    Texture,                /// (MetaTexture, float[N] coords) -> float4
-    TextureLod,             /// (MetaTexture, float[N] coords) -> float4
-    TextureGather,          /// (MetaTexture, float[N] coords) -> float4
-    TextureQueryDimensions, /// (MetaTexture, float a) -> float4
-    TextureQueryLod,        /// (MetaTexture, float[N] coords) -> float4
-    TexelFetch,             /// (MetaTexture, int[N], int) -> float4
-
-    Branch,        /// (uint branch_target) -> void
-    PushFlowStack, /// (uint branch_target) -> void
-    PopFlowStack,  /// () -> void
-    Exit,          /// () -> void
-    Discard,       /// () -> void
-
-    EmitVertex,   /// () -> void
-    EndPrimitive, /// () -> void
-
-    YNegate,            /// () -> float
-    LocalInvocationIdX, /// () -> uint
-    LocalInvocationIdY, /// () -> uint
-    LocalInvocationIdZ, /// () -> uint
-    WorkGroupIdX,       /// () -> uint
-    WorkGroupIdY,       /// () -> uint
-    WorkGroupIdZ,       /// () -> uint
-
-    Amount,
-};
-
-enum class InternalFlag {
-    Zero = 0,
-    Sign = 1,
-    Carry = 2,
-    Overflow = 3,
-    Amount = 4,
-};
-
 /// Describes the behaviour of code path of a given entry point and a return point.
 enum class ExitMethod {
     Undetermined, ///< Internal value. Only occur when analyzing JMP loop.
@@ -208,71 +34,6 @@ enum class ExitMethod {
     AlwaysEnd,    ///< All code paths reach a END instruction.
 };
 
-class Sampler {
-public:
-    // Use this constructor for bounded Samplers
-    explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type,
-                     bool is_array, bool is_shadow)
-        : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow},
-          is_bindless{false} {}
-
-    // Use this constructor for bindless Samplers
-    explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index,
-                     Tegra::Shader::TextureType type, bool is_array, bool is_shadow)
-        : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type},
-          is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {}
-
-    // Use this only for serialization/deserialization
-    explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type,
-                     bool is_array, bool is_shadow, bool is_bindless)
-        : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow},
-          is_bindless{is_bindless} {}
-
-    std::size_t GetOffset() const {
-        return offset;
-    }
-
-    std::size_t GetIndex() const {
-        return index;
-    }
-
-    Tegra::Shader::TextureType GetType() const {
-        return type;
-    }
-
-    bool IsArray() const {
-        return is_array;
-    }
-
-    bool IsShadow() const {
-        return is_shadow;
-    }
-
-    bool IsBindless() const {
-        return is_bindless;
-    }
-
-    std::pair<u32, u32> GetBindlessCBuf() const {
-        return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)};
-    }
-
-    bool operator<(const Sampler& rhs) const {
-        return std::tie(index, offset, type, is_array, is_shadow, is_bindless) <
-               std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow,
-                        rhs.is_bindless);
-    }
-
-private:
-    /// Offset in TSC memory from which to read the sampler object, as specified by the sampling
-    /// instruction.
-    std::size_t offset{};
-    std::size_t index{}; ///< Value used to index into the generated GLSL sampler array.
-    Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
-    bool is_array{};    ///< Whether the texture is being sampled as an array texture or not.
-    bool is_shadow{};   ///< Whether the texture is being sampled as a depth texture or not.
-    bool is_bindless{}; ///< Whether this sampler belongs to a bindless texture or not.
-};
-
 class ConstBuffer {
 public:
     explicit ConstBuffer(u32 max_offset, bool is_indirect)
@@ -305,263 +66,11 @@ private:
     bool is_indirect{};
 };
 
-struct GlobalMemoryBase {
-    u32 cbuf_index{};
-    u32 cbuf_offset{};
-
-    bool operator<(const GlobalMemoryBase& rhs) const {
-        return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset);
-    }
-};
-
 struct GlobalMemoryUsage {
     bool is_read{};
     bool is_written{};
 };
 
-struct MetaArithmetic {
-    bool precise{};
-};
-
-struct MetaTexture {
-    const Sampler& sampler;
-    Node array{};
-    Node depth_compare{};
-    std::vector<Node> aoffi;
-    Node bias{};
-    Node lod{};
-    Node component{};
-    u32 element{};
-};
-
-constexpr MetaArithmetic PRECISE = {true};
-constexpr MetaArithmetic NO_PRECISE = {false};
-
-using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
-
-/// Holds any kind of operation that can be done in the IR
-class OperationNode final {
-public:
-    explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
-
-    explicit OperationNode(OperationCode code, Meta meta)
-        : OperationNode(code, meta, std::vector<Node>{}) {}
-
-    explicit OperationNode(OperationCode code, std::vector<Node> operands)
-        : OperationNode(code, Meta{}, std::move(operands)) {}
-
-    explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands)
-        : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {}
-
-    template <typename... Args>
-    explicit OperationNode(OperationCode code, Meta meta, Args&&... operands)
-        : code{code}, meta{std::move(meta)}, operands{operands...} {}
-
-    OperationCode GetCode() const {
-        return code;
-    }
-
-    const Meta& GetMeta() const {
-        return meta;
-    }
-
-    std::size_t GetOperandsCount() const {
-        return operands.size();
-    }
-
-    const Node& operator[](std::size_t operand_index) const {
-        return operands.at(operand_index);
-    }
-
-private:
-    OperationCode code{};
-    Meta meta{};
-    std::vector<Node> operands;
-};
-
-/// Encloses inside any kind of node that returns a boolean conditionally-executed code
-class ConditionalNode final {
-public:
-    explicit ConditionalNode(Node condition, std::vector<Node>&& code)
-        : condition{condition}, code{std::move(code)} {}
-
-    Node GetCondition() const {
-        return condition;
-    }
-
-    const std::vector<Node>& GetCode() const {
-        return code;
-    }
-
-private:
-    const Node condition;   ///< Condition to be satisfied
-    std::vector<Node> code; ///< Code to execute
-};
-
-/// A general purpose register
-class GprNode final {
-public:
-    explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {}
-
-    u32 GetIndex() const {
-        return static_cast<u32>(index);
-    }
-
-private:
-    const Tegra::Shader::Register index;
-};
-
-/// A 32-bits value that represents an immediate value
-class ImmediateNode final {
-public:
-    explicit constexpr ImmediateNode(u32 value) : value{value} {}
-
-    u32 GetValue() const {
-        return value;
-    }
-
-private:
-    const u32 value;
-};
-
-/// One of Maxwell's internal flags
-class InternalFlagNode final {
-public:
-    explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {}
-
-    InternalFlag GetFlag() const {
-        return flag;
-    }
-
-private:
-    const InternalFlag flag;
-};
-
-/// A predicate register, it can be negated without additional nodes
-class PredicateNode final {
-public:
-    explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated)
-        : index{index}, negated{negated} {}
-
-    Tegra::Shader::Pred GetIndex() const {
-        return index;
-    }
-
-    bool IsNegated() const {
-        return negated;
-    }
-
-private:
-    const Tegra::Shader::Pred index;
-    const bool negated;
-};
-
-/// Attribute buffer memory (known as attributes or varyings in GLSL terms)
-class AbufNode final {
-public:
-    // Initialize for standard attributes (index is explicit).
-    explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {})
-        : buffer{std::move(buffer)}, index{index}, element{element} {}
-
-    // Initialize for physical attributes (index is a variable value).
-    explicit AbufNode(Node physical_address, Node buffer = {})
-        : physical_address{physical_address}, buffer{std::move(buffer)} {}
-
-    Tegra::Shader::Attribute::Index GetIndex() const {
-        return index;
-    }
-
-    u32 GetElement() const {
-        return element;
-    }
-
-    Node GetBuffer() const {
-        return buffer;
-    }
-
-    bool IsPhysicalBuffer() const {
-        return static_cast<bool>(physical_address);
-    }
-
-    const Node& GetPhysicalAddress() const {
-        return physical_address;
-    }
-
-private:
-    Node physical_address;
-    Node buffer;
-    Tegra::Shader::Attribute::Index index{};
-    u32 element{};
-};
-
-/// Constant buffer node, usually mapped to uniform buffers in GLSL
-class CbufNode final {
-public:
-    explicit CbufNode(u32 index, Node offset) : index{index}, offset{offset} {}
-
-    u32 GetIndex() const {
-        return index;
-    }
-
-    Node GetOffset() const {
-        return offset;
-    }
-
-private:
-    const u32 index;
-    const Node offset;
-};
-
-/// Local memory node
-class LmemNode final {
-public:
-    explicit LmemNode(Node address) : address{address} {}
-
-    Node GetAddress() const {
-        return address;
-    }
-
-private:
-    const Node address;
-};
-
-/// Global memory node
-class GmemNode final {
-public:
-    explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor)
-        : real_address{real_address}, base_address{base_address}, descriptor{descriptor} {}
-
-    Node GetRealAddress() const {
-        return real_address;
-    }
-
-    Node GetBaseAddress() const {
-        return base_address;
-    }
-
-    const GlobalMemoryBase& GetDescriptor() const {
-        return descriptor;
-    }
-
-private:
-    const Node real_address;
-    const Node base_address;
-    const GlobalMemoryBase descriptor;
-};
-
-/// Commentary, can be dropped
-class CommentNode final {
-public:
-    explicit CommentNode(std::string text) : text{std::move(text)} {}
-
-    const std::string& GetText() const {
-        return text;
-    }
-
-private:
-    std::string text;
-};
-
 class ShaderIR final {
 public:
     explicit ShaderIR(const ProgramCode& program_code, u32 main_offset);