summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h4
-rw-r--r--src/video_core/shader/decode/memory.cpp9
-rw-r--r--src/video_core/shader/shader_ir.cpp5
-rw-r--r--src/video_core/shader/shader_ir.h20
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