diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 37 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 19 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 2 |
5 files changed, 74 insertions, 3 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 57b57c647..6f98bd827 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -215,6 +215,18 @@ enum class F2fRoundingOp : u64 { | |||
| 215 | Trunc = 11, | 215 | Trunc = 11, |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | enum class AtomicOp : u64 { | ||
| 219 | Add = 0, | ||
| 220 | Min = 1, | ||
| 221 | Max = 2, | ||
| 222 | Inc = 3, | ||
| 223 | Dec = 4, | ||
| 224 | And = 5, | ||
| 225 | Or = 6, | ||
| 226 | Xor = 7, | ||
| 227 | Exch = 8, | ||
| 228 | }; | ||
| 229 | |||
| 218 | enum class UniformType : u64 { | 230 | enum class UniformType : u64 { |
| 219 | UnsignedByte = 0, | 231 | UnsignedByte = 0, |
| 220 | SignedByte = 1, | 232 | SignedByte = 1, |
| @@ -236,6 +248,13 @@ enum class StoreType : u64 { | |||
| 236 | Bits128 = 6, | 248 | Bits128 = 6, |
| 237 | }; | 249 | }; |
| 238 | 250 | ||
| 251 | enum class AtomicType : u64 { | ||
| 252 | U32 = 0, | ||
| 253 | S32 = 1, | ||
| 254 | U64 = 2, | ||
| 255 | S64 = 3, | ||
| 256 | }; | ||
| 257 | |||
| 239 | enum class IMinMaxExchange : u64 { | 258 | enum class IMinMaxExchange : u64 { |
| 240 | None = 0, | 259 | None = 0, |
| 241 | XLo = 1, | 260 | XLo = 1, |
| @@ -939,6 +958,16 @@ union Instruction { | |||
| 939 | } stg; | 958 | } stg; |
| 940 | 959 | ||
| 941 | union { | 960 | union { |
| 961 | BitField<52, 4, AtomicOp> operation; | ||
| 962 | BitField<28, 2, AtomicType> type; | ||
| 963 | BitField<30, 22, s64> offset; | ||
| 964 | |||
| 965 | s32 GetImmediateOffset() const { | ||
| 966 | return static_cast<s32>(offset << 2); | ||
| 967 | } | ||
| 968 | } atoms; | ||
| 969 | |||
| 970 | union { | ||
| 942 | BitField<32, 1, PhysicalAttributeDirection> direction; | 971 | BitField<32, 1, PhysicalAttributeDirection> direction; |
| 943 | BitField<47, 3, AttributeSize> size; | 972 | BitField<47, 3, AttributeSize> size; |
| 944 | BitField<20, 11, u64> address; | 973 | BitField<20, 11, u64> address; |
| @@ -1659,9 +1688,10 @@ public: | |||
| 1659 | ST_A, | 1688 | ST_A, |
| 1660 | ST_L, | 1689 | ST_L, |
| 1661 | ST_S, | 1690 | ST_S, |
| 1662 | ST, // Store in generic memory | 1691 | ST, // Store in generic memory |
| 1663 | STG, // Store in global memory | 1692 | STG, // Store in global memory |
| 1664 | AL2P, // Transforms attribute memory into physical memory | 1693 | ATOMS, // Atomic operation on shared memory |
| 1694 | AL2P, // Transforms attribute memory into physical memory | ||
| 1665 | TEX, | 1695 | TEX, |
| 1666 | TEX_B, // Texture Load Bindless | 1696 | TEX_B, // Texture Load Bindless |
| 1667 | TXQ, // Texture Query | 1697 | TXQ, // Texture Query |
| @@ -1964,6 +1994,7 @@ private: | |||
| 1964 | INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"), | 1994 | INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"), |
| 1965 | INST("101-------------", Id::ST, Type::Memory, "ST"), | 1995 | INST("101-------------", Id::ST, Type::Memory, "ST"), |
| 1966 | INST("1110111011011---", Id::STG, Type::Memory, "STG"), | 1996 | INST("1110111011011---", Id::STG, Type::Memory, "STG"), |
| 1997 | INST("11101100--------", Id::ATOMS, Type::Memory, "ATOMS"), | ||
| 1967 | INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"), | 1998 | INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"), |
| 1968 | INST("110000----111---", Id::TEX, Type::Texture, "TEX"), | 1999 | INST("110000----111---", Id::TEX, Type::Texture, "TEX"), |
| 1969 | INST("1101111010111---", Id::TEX_B, Type::Texture, "TEX_B"), | 2000 | INST("1101111010111---", Id::TEX_B, Type::Texture, "TEX_B"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index f9f7a97b5..19751939a 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1856,6 +1856,16 @@ private: | |||
| 1856 | Type::Uint}; | 1856 | Type::Uint}; |
| 1857 | } | 1857 | } |
| 1858 | 1858 | ||
| 1859 | template <const std::string_view& opname, Type type> | ||
| 1860 | Expression Atomic(Operation operation) { | ||
| 1861 | ASSERT(stage == ShaderType::Compute); | ||
| 1862 | auto& smem = std::get<SmemNode>(*operation[0]); | ||
| 1863 | |||
| 1864 | return {fmt::format("atomic{}(smem[{} >> 2], {})", opname, Visit(smem.GetAddress()).AsInt(), | ||
| 1865 | Visit(operation[1]).As(type)), | ||
| 1866 | type}; | ||
| 1867 | } | ||
| 1868 | |||
| 1859 | Expression Branch(Operation operation) { | 1869 | Expression Branch(Operation operation) { |
| 1860 | const auto target = std::get_if<ImmediateNode>(&*operation[0]); | 1870 | const auto target = std::get_if<ImmediateNode>(&*operation[0]); |
| 1861 | UNIMPLEMENTED_IF(!target); | 1871 | UNIMPLEMENTED_IF(!target); |
| @@ -2194,6 +2204,8 @@ private: | |||
| 2194 | &GLSLDecompiler::AtomicImage<Func::Xor>, | 2204 | &GLSLDecompiler::AtomicImage<Func::Xor>, |
| 2195 | &GLSLDecompiler::AtomicImage<Func::Exchange>, | 2205 | &GLSLDecompiler::AtomicImage<Func::Exchange>, |
| 2196 | 2206 | ||
| 2207 | &GLSLDecompiler::Atomic<Func::Add, Type::Uint>, | ||
| 2208 | |||
| 2197 | &GLSLDecompiler::Branch, | 2209 | &GLSLDecompiler::Branch, |
| 2198 | &GLSLDecompiler::BranchIndirect, | 2210 | &GLSLDecompiler::BranchIndirect, |
| 2199 | &GLSLDecompiler::PushFlowStack, | 2211 | &GLSLDecompiler::PushFlowStack, |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 8fe852ce8..0cf97cafa 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -1796,6 +1796,11 @@ private: | |||
| 1796 | return {}; | 1796 | return {}; |
| 1797 | } | 1797 | } |
| 1798 | 1798 | ||
| 1799 | Expression UAtomicAdd(Operation) { | ||
| 1800 | UNIMPLEMENTED(); | ||
| 1801 | return {}; | ||
| 1802 | } | ||
| 1803 | |||
| 1799 | Expression Branch(Operation operation) { | 1804 | Expression Branch(Operation operation) { |
| 1800 | const auto& target = std::get<ImmediateNode>(*operation[0]); | 1805 | const auto& target = std::get<ImmediateNode>(*operation[0]); |
| 1801 | OpStore(jmp_to, Constant(t_uint, target.GetValue())); | 1806 | OpStore(jmp_to, Constant(t_uint, target.GetValue())); |
| @@ -2373,6 +2378,8 @@ private: | |||
| 2373 | &SPIRVDecompiler::AtomicImageXor, | 2378 | &SPIRVDecompiler::AtomicImageXor, |
| 2374 | &SPIRVDecompiler::AtomicImageExchange, | 2379 | &SPIRVDecompiler::AtomicImageExchange, |
| 2375 | 2380 | ||
| 2381 | &SPIRVDecompiler::UAtomicAdd, | ||
| 2382 | |||
| 2376 | &SPIRVDecompiler::Branch, | 2383 | &SPIRVDecompiler::Branch, |
| 2377 | &SPIRVDecompiler::BranchIndirect, | 2384 | &SPIRVDecompiler::BranchIndirect, |
| 2378 | &SPIRVDecompiler::PushFlowStack, | 2385 | &SPIRVDecompiler::PushFlowStack, |
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 8cc84e935..7591a715f 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | 16 | ||
| 17 | namespace VideoCommon::Shader { | 17 | namespace VideoCommon::Shader { |
| 18 | 18 | ||
| 19 | using Tegra::Shader::AtomicOp; | ||
| 20 | using Tegra::Shader::AtomicType; | ||
| 19 | using Tegra::Shader::Attribute; | 21 | using Tegra::Shader::Attribute; |
| 20 | using Tegra::Shader::Instruction; | 22 | using Tegra::Shader::Instruction; |
| 21 | using Tegra::Shader::OpCode; | 23 | using Tegra::Shader::OpCode; |
| @@ -333,6 +335,23 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 333 | } | 335 | } |
| 334 | break; | 336 | break; |
| 335 | } | 337 | } |
| 338 | case OpCode::Id::ATOMS: { | ||
| 339 | UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}", | ||
| 340 | static_cast<int>(instr.atoms.operation.Value())); | ||
| 341 | UNIMPLEMENTED_IF_MSG(instr.atoms.type != AtomicType::U32, "type={}", | ||
| 342 | static_cast<int>(instr.atoms.type.Value())); | ||
| 343 | |||
| 344 | const s32 offset = instr.atoms.GetImmediateOffset(); | ||
| 345 | Node address = GetRegister(instr.gpr8); | ||
| 346 | address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); | ||
| 347 | |||
| 348 | Node memory = GetSharedMemory(std::move(address)); | ||
| 349 | Node data = GetRegister(instr.gpr20); | ||
| 350 | |||
| 351 | Node value = Operation(OperationCode::UAtomicAdd, std::move(memory), std::move(data)); | ||
| 352 | SetRegister(bb, instr.gpr0, std::move(value)); | ||
| 353 | break; | ||
| 354 | } | ||
| 336 | case OpCode::Id::AL2P: { | 355 | case OpCode::Id::AL2P: { |
| 337 | // Ignore al2p.direction since we don't care about it. | 356 | // Ignore al2p.direction since we don't care about it. |
| 338 | 357 | ||
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 4e155542a..075c7d07c 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -162,6 +162,8 @@ enum class OperationCode { | |||
| 162 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void | 162 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void |
| 163 | AtomicImageExchange, /// (MetaImage, int[N] coords) -> void | 163 | AtomicImageExchange, /// (MetaImage, int[N] coords) -> void |
| 164 | 164 | ||
| 165 | UAtomicAdd, /// (smem, uint) -> uint | ||
| 166 | |||
| 165 | Branch, /// (uint branch_target) -> void | 167 | Branch, /// (uint branch_target) -> void |
| 166 | BranchIndirect, /// (uint branch_target) -> void | 168 | BranchIndirect, /// (uint branch_target) -> void |
| 167 | PushFlowStack, /// (uint branch_target) -> void | 169 | PushFlowStack, /// (uint branch_target) -> void |