summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-11-01 00:34:38 -0300
committerGravatar ReinUsesLisp2019-12-09 23:25:21 -0300
commit6233b1db089686e1ea0dde68278e9086981d6f76 (patch)
tree42199ac76ce7f34d543d77a5a70cc3e5f46e2576 /src/video_core
parentMerge pull request #3205 from ReinUsesLisp/vk-device (diff)
downloadyuzu-6233b1db089686e1ea0dde68278e9086981d6f76.tar.gz
yuzu-6233b1db089686e1ea0dde68278e9086981d6f76.tar.xz
yuzu-6233b1db089686e1ea0dde68278e9086981d6f76.zip
shader_ir/memory: Implement patch stores
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/shader_bytecode.h3
-rw-r--r--src/video_core/shader/decode/memory.cpp34
-rw-r--r--src/video_core/shader/node.h20
-rw-r--r--src/video_core/shader/track.cpp1
4 files changed, 38 insertions, 20 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 8b7dcbe9d..7703a76a3 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -98,10 +98,11 @@ union Attribute {
98 BitField<20, 10, u64> immediate; 98 BitField<20, 10, u64> immediate;
99 BitField<22, 2, u64> element; 99 BitField<22, 2, u64> element;
100 BitField<24, 6, Index> index; 100 BitField<24, 6, Index> index;
101 BitField<31, 1, u64> patch;
101 BitField<47, 3, AttributeSize> size; 102 BitField<47, 3, AttributeSize> size;
102 103
103 bool IsPhysical() const { 104 bool IsPhysical() const {
104 return element == 0 && static_cast<u64>(index.Value()) == 0; 105 return patch == 0 && element == 0 && static_cast<u64>(index.Value()) == 0;
105 } 106 }
106 } fmt20; 107 } fmt20;
107 108
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 335d78146..78e92f52e 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -21,6 +21,7 @@ using Tegra::Shader::OpCode;
21using Tegra::Shader::Register; 21using Tegra::Shader::Register;
22 22
23namespace { 23namespace {
24
24u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) { 25u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) {
25 switch (uniform_type) { 26 switch (uniform_type) {
26 case Tegra::Shader::UniformType::Single: 27 case Tegra::Shader::UniformType::Single:
@@ -35,6 +36,7 @@ u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) {
35 return 1; 36 return 1;
36 } 37 }
37} 38}
39
38} // Anonymous namespace 40} // Anonymous namespace
39 41
40u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { 42u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
@@ -196,28 +198,28 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
196 UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0, 198 UNIMPLEMENTED_IF_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) != 0,
197 "Unaligned attribute loads are not supported"); 199 "Unaligned attribute loads are not supported");
198 200
199 u64 next_element = instr.attribute.fmt20.element; 201 u64 element = instr.attribute.fmt20.element;
200 auto next_index = static_cast<u64>(instr.attribute.fmt20.index.Value()); 202 auto index = static_cast<u64>(instr.attribute.fmt20.index.Value());
201 203
202 const auto StoreNextElement = [&](u32 reg_offset) { 204 const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1;
203 const auto dest = GetOutputAttribute(static_cast<Attribute::Index>(next_index), 205 for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) {
204 next_element, GetRegister(instr.gpr39)); 206 Node dest;
207 if (instr.attribute.fmt20.patch) {
208 const u32 offset = static_cast<u32>(index) * 4 + static_cast<u32>(element);
209 dest = MakeNode<PatchNode>(offset);
210 } else {
211 dest = GetOutputAttribute(static_cast<Attribute::Index>(index), element,
212 GetRegister(instr.gpr39));
213 }
205 const auto src = GetRegister(instr.gpr0.Value() + reg_offset); 214 const auto src = GetRegister(instr.gpr0.Value() + reg_offset);
206 215
207 bb.push_back(Operation(OperationCode::Assign, dest, src)); 216 bb.push_back(Operation(OperationCode::Assign, dest, src));
208 217
209 // Load the next attribute element into the following register. If the element 218 // Load the next attribute element into the following register. If the element to load
210 // to load goes beyond the vec4 size, load the first element of the next 219 // goes beyond the vec4 size, load the first element of the next attribute.
211 // attribute. 220 element = (element + 1) % 4;
212 next_element = (next_element + 1) % 4; 221 index = index + (element == 0 ? 1 : 0);
213 next_index = next_index + (next_element == 0 ? 1 : 0);
214 };
215
216 const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1;
217 for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) {
218 StoreNextElement(reg_offset);
219 } 222 }
220
221 break; 223 break;
222 } 224 }
223 case OpCode::Id::ST_L: 225 case OpCode::Id::ST_L:
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index b2576bdd6..8f4811c88 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -213,13 +213,14 @@ class PredicateNode;
213class AbufNode; 213class AbufNode;
214class CbufNode; 214class CbufNode;
215class LmemNode; 215class LmemNode;
216class PatchNode;
216class SmemNode; 217class SmemNode;
217class GmemNode; 218class GmemNode;
218class CommentNode; 219class CommentNode;
219 220
220using NodeData = 221using NodeData = std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode,
221 std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, 222 InternalFlagNode, PredicateNode, AbufNode, PatchNode, CbufNode,
222 PredicateNode, AbufNode, CbufNode, LmemNode, SmemNode, GmemNode, CommentNode>; 223 LmemNode, SmemNode, GmemNode, CommentNode>;
223using Node = std::shared_ptr<NodeData>; 224using Node = std::shared_ptr<NodeData>;
224using Node4 = std::array<Node, 4>; 225using Node4 = std::array<Node, 4>;
225using NodeBlock = std::vector<Node>; 226using NodeBlock = std::vector<Node>;
@@ -542,6 +543,19 @@ private:
542 u32 element{}; 543 u32 element{};
543}; 544};
544 545
546/// Patch memory (used to communicate tessellation stages).
547class PatchNode final {
548public:
549 explicit PatchNode(u32 offset) : offset{offset} {}
550
551 u32 GetOffset() const {
552 return offset;
553 }
554
555private:
556 u32 offset{};
557};
558
545/// Constant buffer node, usually mapped to uniform buffers in GLSL 559/// Constant buffer node, usually mapped to uniform buffers in GLSL
546class CbufNode final { 560class CbufNode final {
547public: 561public:
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
index 55f5949e4..165c79330 100644
--- a/src/video_core/shader/track.cpp
+++ b/src/video_core/shader/track.cpp
@@ -7,6 +7,7 @@
7#include <variant> 7#include <variant>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/shader/node.h"
10#include "video_core/shader/shader_ir.h" 11#include "video_core/shader/shader_ir.h"
11 12
12namespace VideoCommon::Shader { 13namespace VideoCommon::Shader {