summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/shader/decode/memory.cpp52
1 files changed, 42 insertions, 10 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index b5fbc4d58..f5a6964bc 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -376,16 +376,20 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
376 } 376 }
377 377
378 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); 378 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
379 Node value = Operation(OperationCode::AtomicAdd, std::move(gmem), GetRegister(instr.gpr20)); 379 Node value =
380 Operation(OperationCode::AtomicIAdd, std::move(gmem), GetRegister(instr.gpr20));
380 SetRegister(bb, instr.gpr0, std::move(value)); 381 SetRegister(bb, instr.gpr0, std::move(value));
381 break; 382 break;
382 } 383 }
383 case OpCode::Id::ATOMS: { 384 case OpCode::Id::ATOMS: {
384 UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}", 385 UNIMPLEMENTED_IF_MSG(instr.atoms.operation == AtomicOp::Inc ||
385 static_cast<int>(instr.atoms.operation.Value())); 386 instr.atoms.operation == AtomicOp::Dec,
386 UNIMPLEMENTED_IF_MSG(instr.atoms.type != AtomicType::U32, "type={}", 387 "operation={}", static_cast<int>(instr.atoms.operation.Value()));
387 static_cast<int>(instr.atoms.type.Value())); 388 UNIMPLEMENTED_IF_MSG(instr.atoms.type == AtomicType::S64 ||
388 389 instr.atoms.type == AtomicType::U64,
390 "type={}", static_cast<int>(instr.atoms.type.Value()));
391 const bool is_signed =
392 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64;
389 const s32 offset = instr.atoms.GetImmediateOffset(); 393 const s32 offset = instr.atoms.GetImmediateOffset();
390 Node address = GetRegister(instr.gpr8); 394 Node address = GetRegister(instr.gpr8);
391 address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); 395 address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset));
@@ -393,7 +397,35 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
393 Node memory = GetSharedMemory(std::move(address)); 397 Node memory = GetSharedMemory(std::move(address));
394 Node data = GetRegister(instr.gpr20); 398 Node data = GetRegister(instr.gpr20);
395 399
396 Node value = Operation(OperationCode::AtomicAdd, std::move(memory), std::move(data)); 400 Node value = [&]() {
401 switch (instr.atoms.operation) {
402 case AtomicOp::Add:
403 return SignedOperation(OperationCode::AtomicIAdd, is_signed, std::move(memory),
404 std::move(data));
405 case AtomicOp::Min:
406 return SignedOperation(OperationCode::AtomicIMin, is_signed, std::move(memory),
407 std::move(data));
408 case AtomicOp::Max:
409 return SignedOperation(OperationCode::AtomicIMax, is_signed, std::move(memory),
410 std::move(data));
411 case AtomicOp::And:
412 return SignedOperation(OperationCode::AtomicIAnd, is_signed, std::move(memory),
413 std::move(data));
414 case AtomicOp::Or:
415 return SignedOperation(OperationCode::AtomicIOr, is_signed, std::move(memory),
416 std::move(data));
417 case AtomicOp::Xor:
418 return SignedOperation(OperationCode::AtomicIXor, is_signed, std::move(memory),
419 std::move(data));
420 case AtomicOp::Exch:
421 return SignedOperation(OperationCode::AtomicIExchange, is_signed, std::move(memory),
422 std::move(data));
423 default:
424 UNREACHABLE();
425 return Immediate(0);
426 }
427 }();
428
397 SetRegister(bb, instr.gpr0, std::move(value)); 429 SetRegister(bb, instr.gpr0, std::move(value));
398 break; 430 break;
399 } 431 }
@@ -427,9 +459,9 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock&
427 459
428 const auto [base_address, index, offset] = 460 const auto [base_address, index, offset] =
429 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); 461 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()));
430 ASSERT_OR_EXECUTE_MSG(base_address != nullptr, 462 ASSERT_OR_EXECUTE_MSG(
431 { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, 463 base_address != nullptr, { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); },
432 "Global memory tracking failed"); 464 "Global memory tracking failed");
433 465
434 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); 466 bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset)));
435 467