mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-18 20:08:00 -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:
@ -11,6 +11,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/engines/shader_header.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
@ -169,7 +170,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
const Node it_offset = Immediate(i * 4);
|
||||
const Node real_address =
|
||||
Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
|
||||
const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor));
|
||||
const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
|
||||
|
||||
SetTemporal(bb, i, gmem);
|
||||
}
|
||||
@ -262,7 +263,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
|
||||
const Node it_offset = Immediate(i * 4);
|
||||
const Node real_address =
|
||||
Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
|
||||
const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor));
|
||||
const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
|
||||
|
||||
bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1)));
|
||||
}
|
||||
@ -298,9 +299,9 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeB
|
||||
|
||||
const Node base_address{
|
||||
TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))};
|
||||
const auto cbuf = std::get_if<CbufNode>(base_address);
|
||||
const auto cbuf = std::get_if<CbufNode>(&*base_address);
|
||||
ASSERT(cbuf != nullptr);
|
||||
const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset());
|
||||
const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset());
|
||||
ASSERT(cbuf_offset_imm != nullptr);
|
||||
const auto cbuf_offset = cbuf_offset_imm->GetValue();
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
@ -291,8 +292,8 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
|
||||
const Node sampler_register = GetRegister(reg);
|
||||
const Node base_sampler =
|
||||
TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
|
||||
const auto cbuf = std::get_if<CbufNode>(base_sampler);
|
||||
const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset());
|
||||
const auto cbuf = std::get_if<CbufNode>(&*base_sampler);
|
||||
const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset());
|
||||
ASSERT(cbuf_offset_imm != nullptr);
|
||||
const auto cbuf_offset = cbuf_offset_imm->GetValue();
|
||||
const auto cbuf_index = cbuf->GetIndex();
|
||||
@ -388,8 +389,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
|
||||
Node array, Node depth_compare, u32 bias_offset,
|
||||
std::vector<Node> aoffi,
|
||||
std::optional<Tegra::Shader::Register> bindless_reg) {
|
||||
const bool is_array = array;
|
||||
const bool is_shadow = depth_compare;
|
||||
const auto is_array = static_cast<bool>(array);
|
||||
const auto is_shadow = static_cast<bool>(depth_compare);
|
||||
const bool is_bindless = bindless_reg.has_value();
|
||||
|
||||
UNIMPLEMENTED_IF_MSG((texture_type == TextureType::Texture3D && (is_array || is_shadow)) ||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
99
src/video_core/shader/node_helper.cpp
Normal file
99
src/video_core/shader/node_helper.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
||||
Node Conditional(Node condition, std::vector<Node> code) {
|
||||
return MakeNode<ConditionalNode>(condition, std::move(code));
|
||||
}
|
||||
|
||||
Node Comment(std::string text) {
|
||||
return MakeNode<CommentNode>(std::move(text));
|
||||
}
|
||||
|
||||
Node Immediate(u32 value) {
|
||||
return MakeNode<ImmediateNode>(value);
|
||||
}
|
||||
|
||||
Node Immediate(s32 value) {
|
||||
return Immediate(static_cast<u32>(value));
|
||||
}
|
||||
|
||||
Node Immediate(f32 value) {
|
||||
u32 integral;
|
||||
std::memcpy(&integral, &value, sizeof(u32));
|
||||
return Immediate(integral);
|
||||
}
|
||||
|
||||
OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed) {
|
||||
if (is_signed) {
|
||||
return operation_code;
|
||||
}
|
||||
switch (operation_code) {
|
||||
case OperationCode::FCastInteger:
|
||||
return OperationCode::FCastUInteger;
|
||||
case OperationCode::IAdd:
|
||||
return OperationCode::UAdd;
|
||||
case OperationCode::IMul:
|
||||
return OperationCode::UMul;
|
||||
case OperationCode::IDiv:
|
||||
return OperationCode::UDiv;
|
||||
case OperationCode::IMin:
|
||||
return OperationCode::UMin;
|
||||
case OperationCode::IMax:
|
||||
return OperationCode::UMax;
|
||||
case OperationCode::ICastFloat:
|
||||
return OperationCode::UCastFloat;
|
||||
case OperationCode::ICastUnsigned:
|
||||
return OperationCode::UCastSigned;
|
||||
case OperationCode::ILogicalShiftLeft:
|
||||
return OperationCode::ULogicalShiftLeft;
|
||||
case OperationCode::ILogicalShiftRight:
|
||||
return OperationCode::ULogicalShiftRight;
|
||||
case OperationCode::IArithmeticShiftRight:
|
||||
return OperationCode::UArithmeticShiftRight;
|
||||
case OperationCode::IBitwiseAnd:
|
||||
return OperationCode::UBitwiseAnd;
|
||||
case OperationCode::IBitwiseOr:
|
||||
return OperationCode::UBitwiseOr;
|
||||
case OperationCode::IBitwiseXor:
|
||||
return OperationCode::UBitwiseXor;
|
||||
case OperationCode::IBitwiseNot:
|
||||
return OperationCode::UBitwiseNot;
|
||||
case OperationCode::IBitfieldInsert:
|
||||
return OperationCode::UBitfieldInsert;
|
||||
case OperationCode::IBitCount:
|
||||
return OperationCode::UBitCount;
|
||||
case OperationCode::LogicalILessThan:
|
||||
return OperationCode::LogicalULessThan;
|
||||
case OperationCode::LogicalIEqual:
|
||||
return OperationCode::LogicalUEqual;
|
||||
case OperationCode::LogicalILessEqual:
|
||||
return OperationCode::LogicalULessEqual;
|
||||
case OperationCode::LogicalIGreaterThan:
|
||||
return OperationCode::LogicalUGreaterThan;
|
||||
case OperationCode::LogicalINotEqual:
|
||||
return OperationCode::LogicalUNotEqual;
|
||||
case OperationCode::LogicalIGreaterEqual:
|
||||
return OperationCode::LogicalUGreaterEqual;
|
||||
case OperationCode::INegate:
|
||||
UNREACHABLE_MSG("Can't negate an unsigned integer");
|
||||
return {};
|
||||
case OperationCode::IAbsolute:
|
||||
UNREACHABLE_MSG("Can't apply absolute to an unsigned integer");
|
||||
return {};
|
||||
default:
|
||||
UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast<u32>(operation_code));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace VideoCommon::Shader
|
60
src/video_core/shader/node_helper.h
Normal file
60
src/video_core/shader/node_helper.h
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
|
||||
/// Creates a conditional node
|
||||
Node Conditional(Node condition, std::vector<Node> code);
|
||||
|
||||
/// Creates a commentary node
|
||||
Node Comment(std::string text);
|
||||
|
||||
/// Creates an u32 immediate
|
||||
Node Immediate(u32 value);
|
||||
|
||||
/// Creates a s32 immediate
|
||||
Node Immediate(s32 value);
|
||||
|
||||
/// Creates a f32 immediate
|
||||
Node Immediate(f32 value);
|
||||
|
||||
/// Converts an signed operation code to an unsigned operation code
|
||||
OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed);
|
||||
|
||||
template <typename T, typename... Args>
|
||||
Node MakeNode(Args&&... args) {
|
||||
static_assert(std::is_convertible_v<T, NodeData>);
|
||||
return std::make_shared<NodeData>(T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
Node Operation(OperationCode code, Args&&... args) {
|
||||
if constexpr (sizeof...(args) == 0) {
|
||||
return MakeNode<OperationNode>(code);
|
||||
} else if constexpr (std::is_convertible_v<std::tuple_element_t<0, std::tuple<Args...>>,
|
||||
Meta>) {
|
||||
return MakeNode<OperationNode>(code, std::forward<Args>(args)...);
|
||||
} else {
|
||||
return MakeNode<OperationNode>(code, Meta{}, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
Node SignedOperation(OperationCode code, bool is_signed, Args&&... args) {
|
||||
return Operation(SignedToUnsignedCode(code, is_signed), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace VideoCommon::Shader
|
@ -9,6 +9,7 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "video_core/engines/shader_bytecode.h"
|
||||
#include "video_core/shader/node_helper.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace VideoCommon::Shader {
|
||||
@ -28,30 +29,11 @@ ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset)
|
||||
|
||||
ShaderIR::~ShaderIR() = default;
|
||||
|
||||
Node ShaderIR::StoreNode(NodeData&& node_data) {
|
||||
auto store = std::make_unique<NodeData>(node_data);
|
||||
const Node node = store.get();
|
||||
stored_nodes.push_back(std::move(store));
|
||||
return node;
|
||||
}
|
||||
|
||||
Node ShaderIR::Conditional(Node condition, std::vector<Node>&& code) {
|
||||
return StoreNode(ConditionalNode(condition, std::move(code)));
|
||||
}
|
||||
|
||||
Node ShaderIR::Comment(std::string text) {
|
||||
return StoreNode(CommentNode(std::move(text)));
|
||||
}
|
||||
|
||||
Node ShaderIR::Immediate(u32 value) {
|
||||
return StoreNode(ImmediateNode(value));
|
||||
}
|
||||
|
||||
Node ShaderIR::GetRegister(Register reg) {
|
||||
if (reg != Register::ZeroIndex) {
|
||||
used_registers.insert(static_cast<u32>(reg));
|
||||
}
|
||||
return StoreNode(GprNode(reg));
|
||||
return MakeNode<GprNode>(reg);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetImmediate19(Instruction instr) {
|
||||
@ -69,7 +51,7 @@ Node ShaderIR::GetConstBuffer(u64 index_, u64 offset_) {
|
||||
const auto [entry, is_new] = used_cbufs.try_emplace(index);
|
||||
entry->second.MarkAsUsed(offset);
|
||||
|
||||
return StoreNode(CbufNode(index, Immediate(offset)));
|
||||
return MakeNode<CbufNode>(index, Immediate(offset));
|
||||
}
|
||||
|
||||
Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) {
|
||||
@ -80,7 +62,7 @@ Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) {
|
||||
entry->second.MarkAsUsedIndirect();
|
||||
|
||||
const Node final_offset = Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset));
|
||||
return StoreNode(CbufNode(index, final_offset));
|
||||
return MakeNode<CbufNode>(index, final_offset);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetPredicate(u64 pred_, bool negated) {
|
||||
@ -89,7 +71,7 @@ Node ShaderIR::GetPredicate(u64 pred_, bool negated) {
|
||||
used_predicates.insert(pred);
|
||||
}
|
||||
|
||||
return StoreNode(PredicateNode(pred, negated));
|
||||
return MakeNode<PredicateNode>(pred, negated);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetPredicate(bool immediate) {
|
||||
@ -98,12 +80,12 @@ Node ShaderIR::GetPredicate(bool immediate) {
|
||||
|
||||
Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) {
|
||||
used_input_attributes.emplace(index);
|
||||
return StoreNode(AbufNode(index, static_cast<u32>(element), buffer));
|
||||
return MakeNode<AbufNode>(index, static_cast<u32>(element), buffer);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) {
|
||||
uses_physical_attributes = true;
|
||||
return StoreNode(AbufNode(GetRegister(physical_address), buffer));
|
||||
return MakeNode<AbufNode>(GetRegister(physical_address), buffer);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) {
|
||||
@ -115,11 +97,11 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff
|
||||
}
|
||||
used_output_attributes.insert(index);
|
||||
|
||||
return StoreNode(AbufNode(index, static_cast<u32>(element), buffer));
|
||||
return MakeNode<AbufNode>(index, static_cast<u32>(element), buffer);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) {
|
||||
const Node node = StoreNode(InternalFlagNode(flag));
|
||||
const Node node = MakeNode<InternalFlagNode>(flag);
|
||||
if (negated) {
|
||||
return Operation(OperationCode::LogicalNegate, node);
|
||||
}
|
||||
@ -127,7 +109,7 @@ Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) {
|
||||
}
|
||||
|
||||
Node ShaderIR::GetLocalMemory(Node address) {
|
||||
return StoreNode(LmemNode(address));
|
||||
return MakeNode<LmemNode>(address);
|
||||
}
|
||||
|
||||
Node ShaderIR::GetTemporal(u32 id) {
|
||||
@ -393,68 +375,4 @@ Node ShaderIR::BitfieldExtract(Node value, u32 offset, u32 bits) {
|
||||
Immediate(bits));
|
||||
}
|
||||
|
||||
/*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code,
|
||||
bool is_signed) {
|
||||
if (is_signed) {
|
||||
return operation_code;
|
||||
}
|
||||
switch (operation_code) {
|
||||
case OperationCode::FCastInteger:
|
||||
return OperationCode::FCastUInteger;
|
||||
case OperationCode::IAdd:
|
||||
return OperationCode::UAdd;
|
||||
case OperationCode::IMul:
|
||||
return OperationCode::UMul;
|
||||
case OperationCode::IDiv:
|
||||
return OperationCode::UDiv;
|
||||
case OperationCode::IMin:
|
||||
return OperationCode::UMin;
|
||||
case OperationCode::IMax:
|
||||
return OperationCode::UMax;
|
||||
case OperationCode::ICastFloat:
|
||||
return OperationCode::UCastFloat;
|
||||
case OperationCode::ICastUnsigned:
|
||||
return OperationCode::UCastSigned;
|
||||
case OperationCode::ILogicalShiftLeft:
|
||||
return OperationCode::ULogicalShiftLeft;
|
||||
case OperationCode::ILogicalShiftRight:
|
||||
return OperationCode::ULogicalShiftRight;
|
||||
case OperationCode::IArithmeticShiftRight:
|
||||
return OperationCode::UArithmeticShiftRight;
|
||||
case OperationCode::IBitwiseAnd:
|
||||
return OperationCode::UBitwiseAnd;
|
||||
case OperationCode::IBitwiseOr:
|
||||
return OperationCode::UBitwiseOr;
|
||||
case OperationCode::IBitwiseXor:
|
||||
return OperationCode::UBitwiseXor;
|
||||
case OperationCode::IBitwiseNot:
|
||||
return OperationCode::UBitwiseNot;
|
||||
case OperationCode::IBitfieldInsert:
|
||||
return OperationCode::UBitfieldInsert;
|
||||
case OperationCode::IBitCount:
|
||||
return OperationCode::UBitCount;
|
||||
case OperationCode::LogicalILessThan:
|
||||
return OperationCode::LogicalULessThan;
|
||||
case OperationCode::LogicalIEqual:
|
||||
return OperationCode::LogicalUEqual;
|
||||
case OperationCode::LogicalILessEqual:
|
||||
return OperationCode::LogicalULessEqual;
|
||||
case OperationCode::LogicalIGreaterThan:
|
||||
return OperationCode::LogicalUGreaterThan;
|
||||
case OperationCode::LogicalINotEqual:
|
||||
return OperationCode::LogicalUNotEqual;
|
||||
case OperationCode::LogicalIGreaterEqual:
|
||||
return OperationCode::LogicalUGreaterEqual;
|
||||
case OperationCode::INegate:
|
||||
UNREACHABLE_MSG("Can't negate an unsigned integer");
|
||||
return {};
|
||||
case OperationCode::IAbsolute:
|
||||
UNREACHABLE_MSG("Can't apply absolute to an unsigned integer");
|
||||
return {};
|
||||
default:
|
||||
UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast<u32>(operation_code));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace VideoCommon::Shader
|
||||
|
@ -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;
|
||||
|
@ -16,12 +16,12 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
|
||||
OperationCode operation_code) {
|
||||
for (; cursor >= 0; --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) {
|
||||
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 [found, internal_cursor] = FindOperation(
|
||||
conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code);
|
||||
@ -35,11 +35,11 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
|
||||
} // namespace
|
||||
|
||||
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
|
||||
return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
|
||||
}
|
||||
if (const auto gpr = std::get_if<GprNode>(tracked)) {
|
||||
if (const auto gpr = std::get_if<GprNode>(&*tracked)) {
|
||||
if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -51,7 +51,7 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const
|
||||
}
|
||||
return TrackCbuf(source, code, new_cursor);
|
||||
}
|
||||
if (const auto operation = std::get_if<OperationNode>(tracked)) {
|
||||
if (const auto operation = std::get_if<OperationNode>(&*tracked)) {
|
||||
for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) {
|
||||
if (const auto found = TrackCbuf((*operation)[i], code, cursor)) {
|
||||
// Cbuf found in operand
|
||||
@ -60,7 +60,7 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
if (const auto conditional = std::get_if<ConditionalNode>(tracked)) {
|
||||
if (const auto conditional = std::get_if<ConditionalNode>(&*tracked)) {
|
||||
const auto& conditional_code = conditional->GetCode();
|
||||
return TrackCbuf(tracked, conditional_code, static_cast<s64>(conditional_code.size()));
|
||||
}
|
||||
@ -75,7 +75,7 @@ std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code,
|
||||
if (!found) {
|
||||
return {};
|
||||
}
|
||||
if (const auto immediate = std::get_if<ImmediateNode>(found)) {
|
||||
if (const auto immediate = std::get_if<ImmediateNode>(&*found)) {
|
||||
return immediate->GetValue();
|
||||
}
|
||||
return {};
|
||||
@ -88,11 +88,11 @@ std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeB
|
||||
if (!found_node) {
|
||||
return {};
|
||||
}
|
||||
const auto operation = std::get_if<OperationNode>(found_node);
|
||||
const auto operation = std::get_if<OperationNode>(&*found_node);
|
||||
ASSERT(operation);
|
||||
|
||||
const auto& target = (*operation)[0];
|
||||
if (const auto gpr_target = std::get_if<GprNode>(target)) {
|
||||
if (const auto gpr_target = std::get_if<GprNode>(&*target)) {
|
||||
if (gpr_target->GetIndex() == tracked->GetIndex()) {
|
||||
return {(*operation)[1], new_cursor};
|
||||
}
|
||||
|
Reference in New Issue
Block a user