diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 52 |
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 | ||