Merge pull request #2497 from lioncash/shader-ir
shader/shader_ir: Minor changes
This commit is contained in:
commit
2aebbe9bf9
|
@ -21,6 +21,13 @@ using Tegra::Shader::PredCondition;
|
||||||
using Tegra::Shader::PredOperation;
|
using Tegra::Shader::PredOperation;
|
||||||
using Tegra::Shader::Register;
|
using Tegra::Shader::Register;
|
||||||
|
|
||||||
|
ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset)
|
||||||
|
: program_code{program_code}, main_offset{main_offset} {
|
||||||
|
Decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderIR::~ShaderIR() = default;
|
||||||
|
|
||||||
Node ShaderIR::StoreNode(NodeData&& node_data) {
|
Node ShaderIR::StoreNode(NodeData&& node_data) {
|
||||||
auto store = std::make_unique<NodeData>(node_data);
|
auto store = std::make_unique<NodeData>(node_data);
|
||||||
const Node node = store.get();
|
const Node node = store.get();
|
||||||
|
|
|
@ -328,40 +328,31 @@ struct MetaTexture {
|
||||||
u32 element{};
|
u32 element{};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr MetaArithmetic PRECISE = {true};
|
constexpr MetaArithmetic PRECISE = {true};
|
||||||
inline constexpr MetaArithmetic NO_PRECISE = {false};
|
constexpr MetaArithmetic NO_PRECISE = {false};
|
||||||
|
|
||||||
using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
|
using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
|
||||||
|
|
||||||
/// 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:
|
public:
|
||||||
template <typename... T>
|
explicit OperationNode(OperationCode code) : code{code} {}
|
||||||
explicit constexpr OperationNode(OperationCode code) : code{code}, meta{} {}
|
|
||||||
|
explicit OperationNode(OperationCode code, Meta&& meta) : code{code}, meta{std::move(meta)} {}
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
explicit constexpr OperationNode(OperationCode code, Meta&& meta)
|
explicit OperationNode(OperationCode code, const T*... operands)
|
||||||
: code{code}, meta{std::move(meta)} {}
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
explicit constexpr OperationNode(OperationCode code, const T*... operands)
|
|
||||||
: OperationNode(code, {}, operands...) {}
|
: OperationNode(code, {}, operands...) {}
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
explicit constexpr OperationNode(OperationCode code, Meta&& meta, const T*... operands_)
|
explicit OperationNode(OperationCode code, Meta&& meta, const T*... operands_)
|
||||||
: code{code}, meta{std::move(meta)} {
|
: code{code}, meta{std::move(meta)}, operands{operands_...} {}
|
||||||
|
|
||||||
auto operands_list = {operands_...};
|
|
||||||
for (auto& operand : operands_list) {
|
|
||||||
operands.push_back(operand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands)
|
explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands)
|
||||||
: code{code}, meta{meta}, operands{std::move(operands)} {}
|
: code{code}, meta{meta}, operands{std::move(operands)} {}
|
||||||
|
|
||||||
explicit OperationNode(OperationCode code, std::vector<Node>&& operands)
|
explicit OperationNode(OperationCode code, std::vector<Node>&& operands)
|
||||||
: code{code}, meta{}, operands{std::move(operands)} {}
|
: code{code}, operands{std::move(operands)} {}
|
||||||
|
|
||||||
OperationCode GetCode() const {
|
OperationCode GetCode() const {
|
||||||
return code;
|
return code;
|
||||||
|
@ -567,11 +558,8 @@ private:
|
||||||
|
|
||||||
class ShaderIR final {
|
class ShaderIR final {
|
||||||
public:
|
public:
|
||||||
explicit ShaderIR(const ProgramCode& program_code, u32 main_offset)
|
explicit ShaderIR(const ProgramCode& program_code, u32 main_offset);
|
||||||
: program_code{program_code}, main_offset{main_offset} {
|
~ShaderIR();
|
||||||
|
|
||||||
Decode();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<u32, NodeBlock>& GetBasicBlocks() const {
|
const std::map<u32, NodeBlock>& GetBasicBlocks() const {
|
||||||
return basic_blocks;
|
return basic_blocks;
|
||||||
|
@ -814,11 +802,12 @@ private:
|
||||||
void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
|
void WriteLop3Instruction(NodeBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
|
||||||
Node op_c, Node imm_lut, bool sets_cc);
|
Node op_c, Node imm_lut, bool sets_cc);
|
||||||
|
|
||||||
Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor);
|
Node TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const;
|
||||||
|
|
||||||
std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor);
|
std::optional<u32> TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const;
|
||||||
|
|
||||||
std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, s64 cursor);
|
std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code,
|
||||||
|
s64 cursor) const;
|
||||||
|
|
||||||
std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(NodeBlock& bb,
|
std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(NodeBlock& bb,
|
||||||
Node addr_register,
|
Node addr_register,
|
||||||
|
@ -835,12 +824,10 @@ private:
|
||||||
return StoreNode(OperationNode(code, std::move(meta), operands...));
|
return StoreNode(OperationNode(code, std::move(meta), operands...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
Node Operation(OperationCode code, std::vector<Node>&& operands) {
|
Node Operation(OperationCode code, std::vector<Node>&& operands) {
|
||||||
return StoreNode(OperationNode(code, std::move(operands)));
|
return StoreNode(OperationNode(code, std::move(operands)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) {
|
Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) {
|
||||||
return StoreNode(OperationNode(code, std::move(meta), std::move(operands)));
|
return StoreNode(OperationNode(code, std::move(meta), std::move(operands)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,22 +17,24 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
|
||||||
for (; cursor >= 0; --cursor) {
|
for (; cursor >= 0; --cursor) {
|
||||||
const Node node = code.at(cursor);
|
const Node node = code.at(cursor);
|
||||||
if (const auto operation = std::get_if<OperationNode>(node)) {
|
if (const auto operation = std::get_if<OperationNode>(node)) {
|
||||||
if (operation->GetCode() == operation_code)
|
if (operation->GetCode() == operation_code) {
|
||||||
return {node, cursor};
|
return {node, cursor};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (const auto conditional = std::get_if<ConditionalNode>(node)) {
|
if (const auto conditional = std::get_if<ConditionalNode>(node)) {
|
||||||
const auto& conditional_code = conditional->GetCode();
|
const auto& conditional_code = conditional->GetCode();
|
||||||
const auto [found, internal_cursor] = FindOperation(
|
const auto [found, internal_cursor] = FindOperation(
|
||||||
conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code);
|
conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code);
|
||||||
if (found)
|
if (found) {
|
||||||
return {found, cursor};
|
return {found, cursor};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) {
|
Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const {
|
||||||
if (const auto cbuf = std::get_if<CbufNode>(tracked)) {
|
if (const auto cbuf = std::get_if<CbufNode>(tracked)) {
|
||||||
// Cbuf found, but it has to be immediate
|
// Cbuf found, but it has to be immediate
|
||||||
return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
|
return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
|
||||||
|
@ -65,7 +67,7 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) {
|
std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const {
|
||||||
// Reduce the cursor in one to avoid infinite loops when the instruction sets the same register
|
// Reduce the cursor in one to avoid infinite loops when the instruction sets the same register
|
||||||
// that it uses as operand
|
// that it uses as operand
|
||||||
const auto [found, found_cursor] =
|
const auto [found, found_cursor] =
|
||||||
|
@ -80,7 +82,7 @@ std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeBlock& code,
|
std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeBlock& code,
|
||||||
s64 cursor) {
|
s64 cursor) const {
|
||||||
for (; cursor >= 0; --cursor) {
|
for (; cursor >= 0; --cursor) {
|
||||||
const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign);
|
const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign);
|
||||||
if (!found_node) {
|
if (!found_node) {
|
||||||
|
|
Reference in New Issue