mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2025-06-12 04:27:55 -05:00
shader: Use shared_ptr to store nodes and move initialization to file
Instead of having a vector of unique_ptr stored in a vector and returning star pointers to this, use shared_ptr. While changing initialization code, move it to a separate file when possible. This is a first step to allow code analysis and node generation beyond the ShaderIR class.
This commit is contained in:
@ -38,7 +38,7 @@ using ProgramCode = std::vector<u64>;
|
||||
using NodeData =
|
||||
std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
|
||||
PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>;
|
||||
using Node = const NodeData*;
|
||||
using Node = std::shared_ptr<NodeData>;
|
||||
using Node4 = std::array<Node, 4>;
|
||||
using NodeBlock = std::vector<Node>;
|
||||
|
||||
@ -342,23 +342,20 @@ 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) : code{code} {}
|
||||
explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
|
||||
|
||||
explicit OperationNode(OperationCode code, Meta&& meta) : code{code}, meta{std::move(meta)} {}
|
||||
explicit OperationNode(OperationCode code, Meta meta)
|
||||
: OperationNode(code, meta, std::vector<Node>{}) {}
|
||||
|
||||
template <typename... T>
|
||||
explicit OperationNode(OperationCode code, const T*... operands)
|
||||
: OperationNode(code, {}, operands...) {}
|
||||
explicit OperationNode(OperationCode code, std::vector<Node> operands)
|
||||
: OperationNode(code, Meta{}, std::move(operands)) {}
|
||||
|
||||
template <typename... T>
|
||||
explicit OperationNode(OperationCode code, Meta&& meta, const T*... operands_)
|
||||
: code{code}, meta{std::move(meta)}, operands{operands_...} {}
|
||||
explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands)
|
||||
: code{code}, meta{std::move(meta)}, operands{std::move(operands)} {}
|
||||
|
||||
explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands)
|
||||
: code{code}, meta{meta}, operands{std::move(operands)} {}
|
||||
|
||||
explicit OperationNode(OperationCode code, std::vector<Node>&& operands)
|
||||
: code{code}, 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;
|
||||
@ -372,13 +369,13 @@ public:
|
||||
return operands.size();
|
||||
}
|
||||
|
||||
Node operator[](std::size_t operand_index) const {
|
||||
const Node& operator[](std::size_t operand_index) const {
|
||||
return operands.at(operand_index);
|
||||
}
|
||||
|
||||
private:
|
||||
const OperationCode code;
|
||||
const Meta meta;
|
||||
OperationCode code{};
|
||||
Meta meta{};
|
||||
std::vector<Node> operands;
|
||||
};
|
||||
|
||||
@ -463,13 +460,12 @@ private:
|
||||
class AbufNode final {
|
||||
public:
|
||||
// Initialize for standard attributes (index is explicit).
|
||||
explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element,
|
||||
Node buffer = {})
|
||||
: buffer{buffer}, index{index}, element{element} {}
|
||||
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 constexpr AbufNode(Node physical_address, Node buffer = {})
|
||||
: physical_address{physical_address}, buffer{buffer} {}
|
||||
explicit AbufNode(Node physical_address, Node buffer = {})
|
||||
: physical_address{physical_address}, buffer{std::move(buffer)} {}
|
||||
|
||||
Tegra::Shader::Attribute::Index GetIndex() const {
|
||||
return index;
|
||||
@ -484,16 +480,16 @@ public:
|
||||
}
|
||||
|
||||
bool IsPhysicalBuffer() const {
|
||||
return physical_address != nullptr;
|
||||
return static_cast<bool>(physical_address);
|
||||
}
|
||||
|
||||
Node GetPhysicalAddress() const {
|
||||
const Node& GetPhysicalAddress() const {
|
||||
return physical_address;
|
||||
}
|
||||
|
||||
private:
|
||||
Node physical_address{};
|
||||
Node buffer{};
|
||||
Node physical_address;
|
||||
Node buffer;
|
||||
Tegra::Shader::Attribute::Index index{};
|
||||
u32 element{};
|
||||
};
|
||||
@ -501,7 +497,7 @@ private:
|
||||
/// Constant buffer node, usually mapped to uniform buffers in GLSL
|
||||
class CbufNode final {
|
||||
public:
|
||||
explicit constexpr CbufNode(u32 index, Node offset) : index{index}, offset{offset} {}
|
||||
explicit CbufNode(u32 index, Node offset) : index{index}, offset{offset} {}
|
||||
|
||||
u32 GetIndex() const {
|
||||
return index;
|
||||
@ -519,7 +515,7 @@ private:
|
||||
/// Local memory node
|
||||
class LmemNode final {
|
||||
public:
|
||||
explicit constexpr LmemNode(Node address) : address{address} {}
|
||||
explicit LmemNode(Node address) : address{address} {}
|
||||
|
||||
Node GetAddress() const {
|
||||
return address;
|
||||
@ -532,8 +528,7 @@ private:
|
||||
/// Global memory node
|
||||
class GmemNode final {
|
||||
public:
|
||||
explicit constexpr GmemNode(Node real_address, Node base_address,
|
||||
const GlobalMemoryBase& descriptor)
|
||||
explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor)
|
||||
: real_address{real_address}, base_address{base_address}, descriptor{descriptor} {}
|
||||
|
||||
Node GetRealAddress() const {
|
||||
@ -663,26 +658,6 @@ private:
|
||||
u32 DecodeXmad(NodeBlock& bb, u32 pc);
|
||||
u32 DecodeOther(NodeBlock& bb, u32 pc);
|
||||
|
||||
/// Internalizes node's data and returns a managed pointer to a clone of that node
|
||||
Node StoreNode(NodeData&& node_data);
|
||||
|
||||
/// Creates a conditional node
|
||||
Node Conditional(Node condition, std::vector<Node>&& code);
|
||||
/// Creates a commentary
|
||||
Node Comment(std::string text);
|
||||
/// Creates an u32 immediate
|
||||
Node Immediate(u32 value);
|
||||
/// Creates a s32 immediate
|
||||
Node Immediate(s32 value) {
|
||||
return Immediate(static_cast<u32>(value));
|
||||
}
|
||||
/// Creates a f32 immediate
|
||||
Node Immediate(f32 value) {
|
||||
u32 integral;
|
||||
std::memcpy(&integral, &value, sizeof(u32));
|
||||
return Immediate(integral);
|
||||
}
|
||||
|
||||
/// Generates a node for a passed register.
|
||||
Node GetRegister(Tegra::Shader::Register reg);
|
||||
/// Generates a node representing a 19-bit immediate value
|
||||
@ -827,37 +802,6 @@ private:
|
||||
std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(
|
||||
NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write);
|
||||
|
||||
template <typename... T>
|
||||
Node Operation(OperationCode code, const T*... operands) {
|
||||
return StoreNode(OperationNode(code, operands...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
Node Operation(OperationCode code, Meta&& meta, const T*... operands) {
|
||||
return StoreNode(OperationNode(code, std::move(meta), operands...));
|
||||
}
|
||||
|
||||
Node Operation(OperationCode code, std::vector<Node>&& operands) {
|
||||
return StoreNode(OperationNode(code, std::move(operands)));
|
||||
}
|
||||
|
||||
Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) {
|
||||
return StoreNode(OperationNode(code, std::move(meta), std::move(operands)));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
Node SignedOperation(OperationCode code, bool is_signed, const T*... operands) {
|
||||
return StoreNode(OperationNode(SignedToUnsignedCode(code, is_signed), operands...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
Node SignedOperation(OperationCode code, bool is_signed, Meta&& meta, const T*... operands) {
|
||||
return StoreNode(
|
||||
OperationNode(SignedToUnsignedCode(code, is_signed), std::move(meta), operands...));
|
||||
}
|
||||
|
||||
static OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed);
|
||||
|
||||
const ProgramCode& program_code;
|
||||
const u32 main_offset;
|
||||
|
||||
@ -868,8 +812,6 @@ private:
|
||||
std::map<u32, NodeBlock> basic_blocks;
|
||||
NodeBlock global_code;
|
||||
|
||||
std::vector<std::unique_ptr<NodeData>> stored_nodes;
|
||||
|
||||
std::set<u32> used_registers;
|
||||
std::set<Tegra::Shader::Pred> used_predicates;
|
||||
std::set<Tegra::Shader::Attribute::Index> used_input_attributes;
|
||||
|
Reference in New Issue
Block a user