summaryrefslogtreecommitdiff
path: root/src/video_core/shader/decode
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-01-25 21:03:02 -0300
committerGravatar ReinUsesLisp2020-01-26 01:54:24 -0300
commitd95d4ac84396973d76985dc96249d4714f58b6a2 (patch)
tree63083efff309ea993e1de84e4b93fd6d348dfce2 /src/video_core/shader/decode
parentMerge pull request #3343 from FearlessTobi/ui-tab (diff)
downloadyuzu-d95d4ac84396973d76985dc96249d4714f58b6a2.tar.gz
yuzu-d95d4ac84396973d76985dc96249d4714f58b6a2.tar.xz
yuzu-d95d4ac84396973d76985dc96249d4714f58b6a2.zip
shader/memory: Implement ATOM.ADD
ATOM operates atomically on global memory. For now only add ATOM.ADD since that's what was found in commercial games. This asserts for ATOM.ADD.S32 (handling the others as unimplemented), although ATOM.ADD.U32 shouldn't be any different. This change forces us to change the default type on SPIR-V storage buffers from float to uint. We could also alias the buffers, but it's simpler for now to just use uint. While we are at it, abstract the code to avoid repetition.
Diffstat (limited to 'src/video_core/shader/decode')
-rw-r--r--src/video_core/shader/decode/memory.cpp22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 7591a715f..3da833e81 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -19,6 +19,8 @@ namespace VideoCommon::Shader {
19using Tegra::Shader::AtomicOp; 19using Tegra::Shader::AtomicOp;
20using Tegra::Shader::AtomicType; 20using Tegra::Shader::AtomicType;
21using Tegra::Shader::Attribute; 21using Tegra::Shader::Attribute;
22using Tegra::Shader::GlobalAtomicOp;
23using Tegra::Shader::GlobalAtomicType;
22using Tegra::Shader::Instruction; 24using Tegra::Shader::Instruction;
23using Tegra::Shader::OpCode; 25using Tegra::Shader::OpCode;
24using Tegra::Shader::Register; 26using Tegra::Shader::Register;
@@ -335,6 +337,24 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
335 } 337 }
336 break; 338 break;
337 } 339 }
340 case OpCode::Id::ATOM: {
341 UNIMPLEMENTED_IF_MSG(instr.atom.operation != GlobalAtomicOp::Add, "operation={}",
342 static_cast<int>(instr.atom.operation.Value()));
343 UNIMPLEMENTED_IF_MSG(instr.atom.type != GlobalAtomicType::S32, "type={}",
344 static_cast<int>(instr.atom.type.Value()));
345
346 const auto [real_address, base_address, descriptor] =
347 TrackGlobalMemory(bb, instr, true, true);
348 if (!real_address || !base_address) {
349 // Tracking failed, skip atomic.
350 break;
351 }
352
353 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
354 Node value = Operation(OperationCode::AtomicAdd, std::move(gmem), GetRegister(instr.gpr20));
355 SetRegister(bb, instr.gpr0, std::move(value));
356 break;
357 }
338 case OpCode::Id::ATOMS: { 358 case OpCode::Id::ATOMS: {
339 UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}", 359 UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}",
340 static_cast<int>(instr.atoms.operation.Value())); 360 static_cast<int>(instr.atoms.operation.Value()));
@@ -348,7 +368,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
348 Node memory = GetSharedMemory(std::move(address)); 368 Node memory = GetSharedMemory(std::move(address));
349 Node data = GetRegister(instr.gpr20); 369 Node data = GetRegister(instr.gpr20);
350 370
351 Node value = Operation(OperationCode::UAtomicAdd, std::move(memory), std::move(data)); 371 Node value = Operation(OperationCode::AtomicAdd, std::move(memory), std::move(data));
352 SetRegister(bb, instr.gpr0, std::move(value)); 372 SetRegister(bb, instr.gpr0, std::move(value));
353 break; 373 break;
354 } 374 }