diff options
| author | 2020-03-31 00:56:28 -0300 | |
|---|---|---|
| committer | 2020-03-31 00:56:28 -0300 | |
| commit | c19425ed69589dc4577b660cfb50c2f25a42582e (patch) | |
| tree | f5888dc8ce3e6e65a5c7c061d099ea8473b71a38 /src/video_core/shader/decode | |
| parent | Merge pull request #3566 from ReinUsesLisp/vk-wrapper-part1 (diff) | |
| parent | clang-format (diff) | |
| download | yuzu-c19425ed69589dc4577b660cfb50c2f25a42582e.tar.gz yuzu-c19425ed69589dc4577b660cfb50c2f25a42582e.tar.xz yuzu-c19425ed69589dc4577b660cfb50c2f25a42582e.zip | |
Merge pull request #3506 from namkazt/patch-9
shader_decode: Implement partial ATOM/ATOMS instr
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index b5fbc4d58..28a49addd 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -19,7 +19,6 @@ namespace VideoCommon::Shader { | |||
| 19 | using Tegra::Shader::AtomicOp; | 19 | using Tegra::Shader::AtomicOp; |
| 20 | using Tegra::Shader::AtomicType; | 20 | using Tegra::Shader::AtomicType; |
| 21 | using Tegra::Shader::Attribute; | 21 | using Tegra::Shader::Attribute; |
| 22 | using Tegra::Shader::GlobalAtomicOp; | ||
| 23 | using Tegra::Shader::GlobalAtomicType; | 22 | using Tegra::Shader::GlobalAtomicType; |
| 24 | using Tegra::Shader::Instruction; | 23 | using Tegra::Shader::Instruction; |
| 25 | using Tegra::Shader::OpCode; | 24 | using Tegra::Shader::OpCode; |
| @@ -28,6 +27,28 @@ using Tegra::Shader::StoreType; | |||
| 28 | 27 | ||
| 29 | namespace { | 28 | namespace { |
| 30 | 29 | ||
| 30 | Node GetAtomOperation(AtomicOp op, bool is_signed, Node memory, Node data) { | ||
| 31 | const OperationCode operation_code = [op] { | ||
| 32 | switch (op) { | ||
| 33 | case AtomicOp::Add: | ||
| 34 | return OperationCode::AtomicIAdd; | ||
| 35 | case AtomicOp::Min: | ||
| 36 | return OperationCode::AtomicIMin; | ||
| 37 | case AtomicOp::Max: | ||
| 38 | return OperationCode::AtomicIMax; | ||
| 39 | case AtomicOp::And: | ||
| 40 | return OperationCode::AtomicIAnd; | ||
| 41 | case AtomicOp::Or: | ||
| 42 | return OperationCode::AtomicIOr; | ||
| 43 | case AtomicOp::Xor: | ||
| 44 | return OperationCode::AtomicIXor; | ||
| 45 | case AtomicOp::Exch: | ||
| 46 | return OperationCode::AtomicIExchange; | ||
| 47 | } | ||
| 48 | }(); | ||
| 49 | return SignedOperation(operation_code, is_signed, std::move(memory), std::move(data)); | ||
| 50 | } | ||
| 51 | |||
| 31 | bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { | 52 | bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { |
| 32 | return uniform_type == Tegra::Shader::UniformType::UnsignedByte || | 53 | return uniform_type == Tegra::Shader::UniformType::UnsignedByte || |
| 33 | uniform_type == Tegra::Shader::UniformType::UnsignedShort; | 54 | uniform_type == Tegra::Shader::UniformType::UnsignedShort; |
| @@ -363,10 +384,13 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 363 | break; | 384 | break; |
| 364 | } | 385 | } |
| 365 | case OpCode::Id::ATOM: { | 386 | case OpCode::Id::ATOM: { |
| 366 | UNIMPLEMENTED_IF_MSG(instr.atom.operation != GlobalAtomicOp::Add, "operation={}", | 387 | UNIMPLEMENTED_IF_MSG(instr.atom.operation == AtomicOp::Inc || |
| 367 | static_cast<int>(instr.atom.operation.Value())); | 388 | instr.atom.operation == AtomicOp::Dec || |
| 368 | UNIMPLEMENTED_IF_MSG(instr.atom.type != GlobalAtomicType::S32, "type={}", | 389 | instr.atom.operation == AtomicOp::SafeAdd, |
| 369 | static_cast<int>(instr.atom.type.Value())); | 390 | "operation={}", static_cast<int>(instr.atom.operation.Value())); |
| 391 | UNIMPLEMENTED_IF_MSG(instr.atom.type == GlobalAtomicType::S64 || | ||
| 392 | instr.atom.type == GlobalAtomicType::U64, | ||
| 393 | "type={}", static_cast<int>(instr.atom.type.Value())); | ||
| 370 | 394 | ||
| 371 | const auto [real_address, base_address, descriptor] = | 395 | const auto [real_address, base_address, descriptor] = |
| 372 | TrackGlobalMemory(bb, instr, true, true); | 396 | TrackGlobalMemory(bb, instr, true, true); |
| @@ -375,25 +399,29 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 375 | break; | 399 | break; |
| 376 | } | 400 | } |
| 377 | 401 | ||
| 402 | const bool is_signed = | ||
| 403 | instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; | ||
| 378 | Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); | 404 | Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); |
| 379 | Node value = Operation(OperationCode::AtomicAdd, std::move(gmem), GetRegister(instr.gpr20)); | 405 | Node value = GetAtomOperation(static_cast<AtomicOp>(instr.atom.operation), is_signed, gmem, |
| 406 | GetRegister(instr.gpr20)); | ||
| 380 | SetRegister(bb, instr.gpr0, std::move(value)); | 407 | SetRegister(bb, instr.gpr0, std::move(value)); |
| 381 | break; | 408 | break; |
| 382 | } | 409 | } |
| 383 | case OpCode::Id::ATOMS: { | 410 | case OpCode::Id::ATOMS: { |
| 384 | UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}", | 411 | UNIMPLEMENTED_IF_MSG(instr.atoms.operation == AtomicOp::Inc || |
| 385 | static_cast<int>(instr.atoms.operation.Value())); | 412 | instr.atoms.operation == AtomicOp::Dec, |
| 386 | UNIMPLEMENTED_IF_MSG(instr.atoms.type != AtomicType::U32, "type={}", | 413 | "operation={}", static_cast<int>(instr.atoms.operation.Value())); |
| 387 | static_cast<int>(instr.atoms.type.Value())); | 414 | UNIMPLEMENTED_IF_MSG(instr.atoms.type == AtomicType::S64 || |
| 388 | 415 | instr.atoms.type == AtomicType::U64, | |
| 416 | "type={}", static_cast<int>(instr.atoms.type.Value())); | ||
| 417 | const bool is_signed = | ||
| 418 | instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; | ||
| 389 | const s32 offset = instr.atoms.GetImmediateOffset(); | 419 | const s32 offset = instr.atoms.GetImmediateOffset(); |
| 390 | Node address = GetRegister(instr.gpr8); | 420 | Node address = GetRegister(instr.gpr8); |
| 391 | address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); | 421 | address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); |
| 392 | 422 | Node value = | |
| 393 | Node memory = GetSharedMemory(std::move(address)); | 423 | GetAtomOperation(static_cast<AtomicOp>(instr.atoms.operation), is_signed, |
| 394 | Node data = GetRegister(instr.gpr20); | 424 | GetSharedMemory(std::move(address)), GetRegister(instr.gpr20)); |
| 395 | |||
| 396 | Node value = Operation(OperationCode::AtomicAdd, std::move(memory), std::move(data)); | ||
| 397 | SetRegister(bb, instr.gpr0, std::move(value)); | 425 | SetRegister(bb, instr.gpr0, std::move(value)); |
| 398 | break; | 426 | break; |
| 399 | } | 427 | } |