diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 23 | ||||
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 48 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 16 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 6 |
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 | ||
| 40 | u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | 40 | u32 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; | |||
| 206 | class AbufNode; | 206 | class AbufNode; |
| 207 | class CbufNode; | 207 | class CbufNode; |
| 208 | class LmemNode; | 208 | class LmemNode; |
| 209 | class SmemNode; | ||
| 209 | class GmemNode; | 210 | class GmemNode; |
| 210 | class CommentNode; | 211 | class CommentNode; |
| 211 | 212 | ||
| 212 | using NodeData = | 213 | using 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>; |
| 215 | using Node = std::shared_ptr<NodeData>; | 216 | using Node = std::shared_ptr<NodeData>; |
| 216 | using Node4 = std::array<Node, 4>; | 217 | using Node4 = std::array<Node, 4>; |
| 217 | using NodeBlock = std::vector<Node>; | 218 | using NodeBlock = std::vector<Node>; |
| @@ -583,6 +584,19 @@ private: | |||
| 583 | Node address; | 584 | Node address; |
| 584 | }; | 585 | }; |
| 585 | 586 | ||
| 587 | /// Shared memory node | ||
| 588 | class SmemNode final { | ||
| 589 | public: | ||
| 590 | explicit SmemNode(Node address) : address{std::move(address)} {} | ||
| 591 | |||
| 592 | const Node& GetAddress() const { | ||
| 593 | return address; | ||
| 594 | } | ||
| 595 | |||
| 596 | private: | ||
| 597 | Node address; | ||
| 598 | }; | ||
| 599 | |||
| 586 | /// Global memory node | 600 | /// Global memory node |
| 587 | class GmemNode final { | 601 | class GmemNode final { |
| 588 | public: | 602 | public: |
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 | ||
| 140 | Node ShaderIR::GetSharedMemory(Node address) { | ||
| 141 | return MakeNode<SmemNode>(std::move(address)); | ||
| 142 | } | ||
| 143 | |||
| 140 | Node ShaderIR::GetTemporary(u32 id) { | 144 | Node 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 | ||
| 385 | void 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 | |||
| 381 | void ShaderIR::SetTemporary(NodeBlock& bb, u32 id, Node value) { | 390 | void 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 | ||