diff options
Diffstat (limited to 'src/video_core')
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 4 | ||||
-rw-r--r-- | src/video_core/shader/decode/memory.cpp | 9 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.cpp | 5 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.h | 20 |
4 files changed, 32 insertions, 6 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 766bb4f79..e4a9471b8 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -98,6 +98,10 @@ union Attribute { BitField<22, 2, u64> element; BitField<24, 6, Index> index; BitField<47, 3, AttributeSize> size; + + bool IsPhysical() const { + return element == 0 && static_cast<u64>(index.Value()) == 0; + } } fmt20; union { diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 84db4d4dc..339692295 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp @@ -50,13 +50,16 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, "Unaligned attribute loads are not supported"); + const Node buffer{GetRegister(instr.gpr39)}; + u64 next_element = instr.attribute.fmt20.element; auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); const auto LoadNextElement = [&](u32 reg_offset) { - const Node buffer = GetRegister(instr.gpr39); - const Node attribute = - GetInputAttribute(static_cast<Attribute::Index>(next_index), next_element, buffer); + const Node attribute{instr.attribute.fmt20.IsPhysical() + ? GetPhysicalInputAttribute(instr.gpr8, buffer) + : GetInputAttribute(static_cast<Attribute::Index>(next_index), + next_element, buffer)}; SetRegister(bb, instr.gpr0.Value() + reg_offset, attribute); diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 0307ae5b0..947a372a2 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -94,6 +94,11 @@ Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffe return StoreNode(AbufNode(index, static_cast<u32>(element), buffer)); } +Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) { + use_physical_attributes = true; + return StoreNode(AbufNode(GetRegister(physical_address), buffer)); +} + Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { if (index == Attribute::Index::ClipDistances0123 || index == Attribute::Index::ClipDistances4567) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 6aff64394..3a1164d4f 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -469,6 +469,9 @@ public: Node buffer = {}) : buffer{buffer}, index{index}, element{element} {} + explicit constexpr AbufNode(Node physical_address, Node buffer = {}) + : physical_address{physical_address}, buffer{buffer} {} + Tegra::Shader::Attribute::Index GetIndex() const { return index; } @@ -481,10 +484,19 @@ public: return buffer; } + bool IsPhysicalBuffer() const { + return physical_address != nullptr; + } + + Node GetPhysicalAddress() const { + return physical_address; + } + private: - const Node buffer; - const Tegra::Shader::Attribute::Index index; - const u32 element; + Node physical_address{}; + Node buffer{}; + Tegra::Shader::Attribute::Index index{}; + u32 element{}; }; /// Constant buffer node, usually mapped to uniform buffers in GLSL @@ -691,6 +703,8 @@ private: Node GetPredicate(bool immediate); /// Generates a node representing an input attribute. Keeps track of used attributes. Node GetInputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer = {}); + /// Generates a node representing a physical input attribute. + Node GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer = {}); /// Generates a node representing an output attribute. Keeps track of used attributes. Node GetOutputAttribute(Tegra::Shader::Attribute::Index index, u64 element, Node buffer); /// Generates a node representing an internal flag |