summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-10-18 01:23:10 -0300
committerGravatar ReinUsesLisp2019-10-22 02:49:17 -0300
commit1ea07954fb71d3445aab4f11411ed7187e7c911f (patch)
treed85f194a4fbde8f620b2ab67ef69a1c886e72946 /src
parentMerge pull request #3001 from bunnei/fix-clang-error (diff)
downloadyuzu-1ea07954fb71d3445aab4f11411ed7187e7c911f.tar.gz
yuzu-1ea07954fb71d3445aab4f11411ed7187e7c911f.tar.xz
yuzu-1ea07954fb71d3445aab4f11411ed7187e7c911f.zip
shader_ir/memory: Ignore global memory when tracking fails
Ignore global memory operations instead of invoking undefined behaviour when constant buffer tracking fails and we are blasting through asserts, ignore the operation. In the case of LDG this means filling the destination registers with zeroes; for STG this means ignore the instruction as a whole. The default behaviour is still to abort execution on failure.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/decode/memory.cpp39
-rw-r--r--src/video_core/shader/shader_ir.h5
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
304std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, 309std::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;