summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp23
-rw-r--r--src/video_core/shader/decode/memory.cpp48
-rw-r--r--src/video_core/shader/node.h16
-rw-r--r--src/video_core/shader/shader_ir.cpp9
-rw-r--r--src/video_core/shader/shader_ir.h6
5 files changed, 81 insertions, 21 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 137b23740..14834d86a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -325,6 +325,7 @@ public:
325 DeclareRegisters(); 325 DeclareRegisters();
326 DeclarePredicates(); 326 DeclarePredicates();
327 DeclareLocalMemory(); 327 DeclareLocalMemory();
328 DeclareSharedMemory();
328 DeclareInternalFlags(); 329 DeclareInternalFlags();
329 DeclareInputAttributes(); 330 DeclareInputAttributes();
330 DeclareOutputAttributes(); 331 DeclareOutputAttributes();
@@ -499,6 +500,13 @@ private:
499 code.AddNewLine(); 500 code.AddNewLine();
500 } 501 }
501 502
503 void DeclareSharedMemory() {
504 if (stage != ProgramType::Compute) {
505 return;
506 }
507 code.AddLine("shared uint {}[];", GetSharedMemory());
508 }
509
502 void DeclareInternalFlags() { 510 void DeclareInternalFlags() {
503 for (u32 flag = 0; flag < static_cast<u32>(InternalFlag::Amount); flag++) { 511 for (u32 flag = 0; flag < static_cast<u32>(InternalFlag::Amount); flag++) {
504 const auto flag_code = static_cast<InternalFlag>(flag); 512 const auto flag_code = static_cast<InternalFlag>(flag);
@@ -881,6 +889,12 @@ private:
881 Type::Uint}; 889 Type::Uint};
882 } 890 }
883 891
892 if (const auto smem = std::get_if<SmemNode>(&*node)) {
893 return {
894 fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()),
895 Type::Uint};
896 }
897
884 if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) { 898 if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) {
885 return {GetInternalFlag(internal_flag->GetFlag()), Type::Bool}; 899 return {GetInternalFlag(internal_flag->GetFlag()), Type::Bool};
886 } 900 }
@@ -1286,6 +1300,11 @@ private:
1286 target = { 1300 target = {
1287 fmt::format("{}[{} >> 2]", GetLocalMemory(), Visit(lmem->GetAddress()).AsUint()), 1301 fmt::format("{}[{} >> 2]", GetLocalMemory(), Visit(lmem->GetAddress()).AsUint()),
1288 Type::Uint}; 1302 Type::Uint};
1303 } else if (const auto smem = std::get_if<SmemNode>(&*dest)) {
1304 ASSERT(stage == ProgramType::Compute);
1305 target = {
1306 fmt::format("{}[{} >> 2]", GetSharedMemory(), Visit(smem->GetAddress()).AsUint()),
1307 Type::Uint};
1289 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { 1308 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
1290 const std::string real = Visit(gmem->GetRealAddress()).AsUint(); 1309 const std::string real = Visit(gmem->GetRealAddress()).AsUint();
1291 const std::string base = Visit(gmem->GetBaseAddress()).AsUint(); 1310 const std::string base = Visit(gmem->GetBaseAddress()).AsUint();
@@ -2175,6 +2194,10 @@ private:
2175 return "lmem_" + suffix; 2194 return "lmem_" + suffix;
2176 } 2195 }
2177 2196
2197 std::string GetSharedMemory() const {
2198 return fmt::format("smem_{}", suffix);
2199 }
2200
2178 std::string GetInternalFlag(InternalFlag flag) const { 2201 std::string GetInternalFlag(InternalFlag flag) const {
2179 constexpr std::array InternalFlagNames = {"zero_flag", "sign_flag", "carry_flag", 2202 constexpr std::array InternalFlagNames = {"zero_flag", "sign_flag", "carry_flag",
2180 "overflow_flag"}; 2203 "overflow_flag"};
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index ed108bea8..7923d4d69 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -35,7 +35,7 @@ u32 GetUniformTypeElementsCount(Tegra::Shader::UniformType uniform_type) {
35 return 1; 35 return 1;
36 } 36 }
37} 37}
38} // namespace 38} // Anonymous namespace
39 39
40u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { 40u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
41 const Instruction instr = {program_code[pc]}; 41 const Instruction instr = {program_code[pc]};
@@ -106,16 +106,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
106 } 106 }
107 break; 107 break;
108 } 108 }
109 case OpCode::Id::LD_L: { 109 case OpCode::Id::LD_L:
110 LOG_DEBUG(HW_GPU, "LD_L cache management mode: {}", 110 LOG_DEBUG(HW_GPU, "LD_L cache management mode: {}", static_cast<u64>(instr.ld_l.unknown));
111 static_cast<u64>(instr.ld_l.unknown.Value())); 111 [[fallthrough]];
112 112 case OpCode::Id::LD_S: {
113 const auto GetLmem = [&](s32 offset) { 113 const auto GetMemory = [&](s32 offset) {
114 ASSERT(offset % 4 == 0); 114 ASSERT(offset % 4 == 0);
115 const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset); 115 const Node immediate_offset = Immediate(static_cast<s32>(instr.smem_imm) + offset);
116 const Node address = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), 116 const Node address = Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8),
117 immediate_offset); 117 immediate_offset);
118 return GetLocalMemory(address); 118 return opcode->get().GetId() == OpCode::Id::LD_S ? GetSharedMemory(address)
119 : GetLocalMemory(address);
119 }; 120 };
120 121
121 switch (instr.ldst_sl.type.Value()) { 122 switch (instr.ldst_sl.type.Value()) {
@@ -135,14 +136,16 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
135 return 0; 136 return 0;
136 } 137 }
137 }(); 138 }();
138 for (u32 i = 0; i < count; ++i) 139 for (u32 i = 0; i < count; ++i) {
139 SetTemporary(bb, i, GetLmem(i * 4)); 140 SetTemporary(bb, i, GetMemory(i * 4));
140 for (u32 i = 0; i < count; ++i) 141 }
142 for (u32 i = 0; i < count; ++i) {
141 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); 143 SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i));
144 }
142 break; 145 break;
143 } 146 }
144 default: 147 default:
145 UNIMPLEMENTED_MSG("LD_L Unhandled type: {}", 148 UNIMPLEMENTED_MSG("{} Unhandled type: {}", opcode->get().GetName(),
146 static_cast<u32>(instr.ldst_sl.type.Value())); 149 static_cast<u32>(instr.ldst_sl.type.Value()));
147 } 150 }
148 break; 151 break;
@@ -209,27 +212,34 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
209 212
210 break; 213 break;
211 } 214 }
212 case OpCode::Id::ST_L: { 215 case OpCode::Id::ST_L:
213 LOG_DEBUG(HW_GPU, "ST_L cache management mode: {}", 216 LOG_DEBUG(HW_GPU, "ST_L cache management mode: {}",
214 static_cast<u64>(instr.st_l.cache_management.Value())); 217 static_cast<u64>(instr.st_l.cache_management.Value()));
215 218 [[fallthrough]];
216 const auto GetLmemAddr = [&](s32 offset) { 219 case OpCode::Id::ST_S: {
220 const auto GetAddress = [&](s32 offset) {
217 ASSERT(offset % 4 == 0); 221 ASSERT(offset % 4 == 0);
218 const Node immediate = Immediate(static_cast<s32>(instr.smem_imm) + offset); 222 const Node immediate = Immediate(static_cast<s32>(instr.smem_imm) + offset);
219 return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate); 223 return Operation(OperationCode::IAdd, NO_PRECISE, GetRegister(instr.gpr8), immediate);
220 }; 224 };
221 225
226 const auto set_memory = opcode->get().GetId() == OpCode::Id::ST_L
227 ? &ShaderIR::SetLocalMemory
228 : &ShaderIR::SetSharedMemory;
229
222 switch (instr.ldst_sl.type.Value()) { 230 switch (instr.ldst_sl.type.Value()) {
223 case Tegra::Shader::StoreType::Bits128: 231 case Tegra::Shader::StoreType::Bits128:
224 SetLocalMemory(bb, GetLmemAddr(12), GetRegister(instr.gpr0.Value() + 3)); 232 (this->*set_memory)(bb, GetAddress(12), GetRegister(instr.gpr0.Value() + 3));
225 SetLocalMemory(bb, GetLmemAddr(8), GetRegister(instr.gpr0.Value() + 2)); 233 (this->*set_memory)(bb, GetAddress(8), GetRegister(instr.gpr0.Value() + 2));
234 [[fallthrough]];
226 case Tegra::Shader::StoreType::Bits64: 235 case Tegra::Shader::StoreType::Bits64:
227 SetLocalMemory(bb, GetLmemAddr(4), GetRegister(instr.gpr0.Value() + 1)); 236 (this->*set_memory)(bb, GetAddress(4), GetRegister(instr.gpr0.Value() + 1));
237 [[fallthrough]];
228 case Tegra::Shader::StoreType::Bits32: 238 case Tegra::Shader::StoreType::Bits32:
229 SetLocalMemory(bb, GetLmemAddr(0), GetRegister(instr.gpr0)); 239 (this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0));
230 break; 240 break;
231 default: 241 default:
232 UNIMPLEMENTED_MSG("ST_L Unhandled type: {}", 242 UNIMPLEMENTED_MSG("{} unhandled type: {}", opcode->get().GetName(),
233 static_cast<u32>(instr.ldst_sl.type.Value())); 243 static_cast<u32>(instr.ldst_sl.type.Value()));
234 } 244 }
235 break; 245 break;
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index b47b201cf..425111cc4 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -206,12 +206,13 @@ class PredicateNode;
206class AbufNode; 206class AbufNode;
207class CbufNode; 207class CbufNode;
208class LmemNode; 208class LmemNode;
209class SmemNode;
209class GmemNode; 210class GmemNode;
210class CommentNode; 211class CommentNode;
211 212
212using NodeData = 213using NodeData =
213 std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, 214 std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
214 PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>; 215 PredicateNode, AbufNode, CbufNode, LmemNode, SmemNode, GmemNode, CommentNode>;
215using Node = std::shared_ptr<NodeData>; 216using Node = std::shared_ptr<NodeData>;
216using Node4 = std::array<Node, 4>; 217using Node4 = std::array<Node, 4>;
217using NodeBlock = std::vector<Node>; 218using NodeBlock = std::vector<Node>;
@@ -583,6 +584,19 @@ private:
583 Node address; 584 Node address;
584}; 585};
585 586
587/// Shared memory node
588class SmemNode final {
589public:
590 explicit SmemNode(Node address) : address{std::move(address)} {}
591
592 const Node& GetAddress() const {
593 return address;
594 }
595
596private:
597 Node address;
598};
599
586/// Global memory node 600/// Global memory node
587class GmemNode final { 601class GmemNode final {
588public: 602public:
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 1e5c7f660..bbbab0bca 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -137,6 +137,10 @@ Node ShaderIR::GetLocalMemory(Node address) {
137 return MakeNode<LmemNode>(std::move(address)); 137 return MakeNode<LmemNode>(std::move(address));
138} 138}
139 139
140Node ShaderIR::GetSharedMemory(Node address) {
141 return MakeNode<SmemNode>(std::move(address));
142}
143
140Node ShaderIR::GetTemporary(u32 id) { 144Node ShaderIR::GetTemporary(u32 id) {
141 return GetRegister(Register::ZeroIndex + 1 + id); 145 return GetRegister(Register::ZeroIndex + 1 + id);
142} 146}
@@ -378,6 +382,11 @@ void ShaderIR::SetLocalMemory(NodeBlock& bb, Node address, Node value) {
378 Operation(OperationCode::Assign, GetLocalMemory(std::move(address)), std::move(value))); 382 Operation(OperationCode::Assign, GetLocalMemory(std::move(address)), std::move(value)));
379} 383}
380 384
385void ShaderIR::SetSharedMemory(NodeBlock& bb, Node address, Node value) {
386 bb.push_back(
387 Operation(OperationCode::Assign, GetSharedMemory(std::move(address)), std::move(value)));
388}
389
381void ShaderIR::SetTemporary(NodeBlock& bb, u32 id, Node value) { 390void ShaderIR::SetTemporary(NodeBlock& bb, u32 id, Node value) {
382 SetRegister(bb, Register::ZeroIndex + 1 + id, std::move(value)); 391 SetRegister(bb, Register::ZeroIndex + 1 + id, std::move(value));
383} 392}
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 62816bd56..6aed9bb84 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -208,6 +208,8 @@ private:
208 Node GetInternalFlag(InternalFlag flag, bool negated = false); 208 Node GetInternalFlag(InternalFlag flag, bool negated = false);
209 /// Generates a node representing a local memory address 209 /// Generates a node representing a local memory address
210 Node GetLocalMemory(Node address); 210 Node GetLocalMemory(Node address);
211 /// Generates a node representing a shared memory address
212 Node GetSharedMemory(Node address);
211 /// Generates a temporary, internally it uses a post-RZ register 213 /// Generates a temporary, internally it uses a post-RZ register
212 Node GetTemporary(u32 id); 214 Node GetTemporary(u32 id);
213 215
@@ -217,8 +219,10 @@ private:
217 void SetPredicate(NodeBlock& bb, u64 dest, Node src); 219 void SetPredicate(NodeBlock& bb, u64 dest, Node src);
218 /// Sets an internal flag. src value must be a bool-evaluated node 220 /// Sets an internal flag. src value must be a bool-evaluated node
219 void SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value); 221 void SetInternalFlag(NodeBlock& bb, InternalFlag flag, Node value);
220 /// Sets a local memory address. address and value must be a number-evaluated node 222 /// Sets a local memory address with a value.
221 void SetLocalMemory(NodeBlock& bb, Node address, Node value); 223 void SetLocalMemory(NodeBlock& bb, Node address, Node value);
224 /// Sets a shared memory address with a value.
225 void SetSharedMemory(NodeBlock& bb, Node address, Node value);
222 /// Sets a temporary. Internally it uses a post-RZ register 226 /// Sets a temporary. Internally it uses a post-RZ register
223 void SetTemporary(NodeBlock& bb, u32 id, Node value); 227 void SetTemporary(NodeBlock& bb, u32 id, Node value);
224 228