diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 39 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 5 |
2 files changed, 26 insertions, 18 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 7923d4d69..335d78146 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -166,9 +166,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 166 | }(); | 166 | }(); |
| 167 | 167 | ||
| 168 | const auto [real_address_base, base_address, descriptor] = | 168 | const auto [real_address_base, base_address, descriptor] = |
| 169 | TrackAndGetGlobalMemory(bb, instr, false); | 169 | TrackGlobalMemory(bb, instr, false); |
| 170 | 170 | ||
| 171 | const u32 count = GetUniformTypeElementsCount(type); | 171 | const u32 count = GetUniformTypeElementsCount(type); |
| 172 | if (!real_address_base || !base_address) { | ||
| 173 | // Tracking failed, load zeroes. | ||
| 174 | for (u32 i = 0; i < count; ++i) { | ||
| 175 | SetRegister(bb, instr.gpr0.Value() + i, Immediate(0.0f)); | ||
| 176 | } | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | |||
| 172 | for (u32 i = 0; i < count; ++i) { | 180 | for (u32 i = 0; i < count; ++i) { |
| 173 | const Node it_offset = Immediate(i * 4); | 181 | const Node it_offset = Immediate(i * 4); |
| 174 | const Node real_address = | 182 | const Node real_address = |
| @@ -260,22 +268,19 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 260 | }(); | 268 | }(); |
| 261 | 269 | ||
| 262 | const auto [real_address_base, base_address, descriptor] = | 270 | const auto [real_address_base, base_address, descriptor] = |
| 263 | TrackAndGetGlobalMemory(bb, instr, true); | 271 | TrackGlobalMemory(bb, instr, true); |
| 264 | 272 | if (!real_address_base || !base_address) { | |
| 265 | // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} | 273 | // Tracking failed, skip the store. |
| 266 | SetTemporary(bb, 0, real_address_base); | 274 | break; |
| 275 | } | ||
| 267 | 276 | ||
| 268 | const u32 count = GetUniformTypeElementsCount(type); | 277 | const u32 count = GetUniformTypeElementsCount(type); |
| 269 | for (u32 i = 0; i < count; ++i) { | 278 | for (u32 i = 0; i < count; ++i) { |
| 270 | SetTemporary(bb, i + 1, GetRegister(instr.gpr0.Value() + i)); | ||
| 271 | } | ||
| 272 | for (u32 i = 0; i < count; ++i) { | ||
| 273 | const Node it_offset = Immediate(i * 4); | 279 | const Node it_offset = Immediate(i * 4); |
| 274 | const Node real_address = | 280 | const Node real_address = Operation(OperationCode::UAdd, real_address_base, it_offset); |
| 275 | Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); | ||
| 276 | const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); | 281 | const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); |
| 277 | 282 | const Node value = GetRegister(instr.gpr0.Value() + i); | |
| 278 | bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporary(i + 1))); | 283 | bb.push_back(Operation(OperationCode::Assign, gmem, value)); |
| 279 | } | 284 | } |
| 280 | break; | 285 | break; |
| 281 | } | 286 | } |
| @@ -301,15 +306,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 301 | return pc; | 306 | return pc; |
| 302 | } | 307 | } |
| 303 | 308 | ||
| 304 | std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, | 309 | std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock& bb, |
| 305 | Instruction instr, | 310 | Instruction instr, |
| 306 | bool is_write) { | 311 | bool is_write) { |
| 307 | const auto addr_register{GetRegister(instr.gmem.gpr)}; | 312 | const auto addr_register{GetRegister(instr.gmem.gpr)}; |
| 308 | const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; | 313 | const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; |
| 309 | 314 | ||
| 310 | const auto [base_address, index, offset] = | 315 | const auto [base_address, index, offset] = |
| 311 | TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); | 316 | TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); |
| 312 | ASSERT(base_address != nullptr); | 317 | ASSERT_OR_EXECUTE_MSG(base_address != nullptr, |
| 318 | { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, | ||
| 319 | "Global memory tracking failed"); | ||
| 313 | 320 | ||
| 314 | bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); | 321 | bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); |
| 315 | 322 | ||
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 105981d67..91cd0a534 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -371,8 +371,9 @@ private: | |||
| 371 | std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, | 371 | std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, |
| 372 | s64 cursor) const; | 372 | s64 cursor) const; |
| 373 | 373 | ||
| 374 | std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory( | 374 | std::tuple<Node, Node, GlobalMemoryBase> TrackGlobalMemory(NodeBlock& bb, |
| 375 | NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write); | 375 | Tegra::Shader::Instruction instr, |
| 376 | bool is_write); | ||
| 376 | 377 | ||
| 377 | const ProgramCode& program_code; | 378 | const ProgramCode& program_code; |
| 378 | const u32 main_offset; | 379 | const u32 main_offset; |