diff options
Diffstat (limited to 'src')
9 files changed, 121 insertions, 11 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 03a5793aa..181eac9f2 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -3,6 +3,7 @@ add_library(shader_recompiler STATIC | |||
| 3 | backend/spirv/emit_context.h | 3 | backend/spirv/emit_context.h |
| 4 | backend/spirv/emit_spirv.cpp | 4 | backend/spirv/emit_spirv.cpp |
| 5 | backend/spirv/emit_spirv.h | 5 | backend/spirv/emit_spirv.h |
| 6 | backend/spirv/emit_spirv_barriers.cpp | ||
| 6 | backend/spirv/emit_spirv_bitwise_conversion.cpp | 7 | backend/spirv/emit_spirv_bitwise_conversion.cpp |
| 7 | backend/spirv/emit_spirv_composite.cpp | 8 | backend/spirv/emit_spirv_composite.cpp |
| 8 | backend/spirv/emit_spirv_context_get_set.cpp | 9 | backend/spirv/emit_spirv_context_get_set.cpp |
| @@ -63,6 +64,7 @@ add_library(shader_recompiler STATIC | |||
| 63 | frontend/maxwell/program.h | 64 | frontend/maxwell/program.h |
| 64 | frontend/maxwell/structured_control_flow.cpp | 65 | frontend/maxwell/structured_control_flow.cpp |
| 65 | frontend/maxwell/structured_control_flow.h | 66 | frontend/maxwell/structured_control_flow.h |
| 67 | frontend/maxwell/translate/impl/barrier_operations.cpp | ||
| 66 | frontend/maxwell/translate/impl/bitfield_extract.cpp | 68 | frontend/maxwell/translate/impl/bitfield_extract.cpp |
| 67 | frontend/maxwell/translate/impl/bitfield_insert.cpp | 69 | frontend/maxwell/translate/impl/bitfield_insert.cpp |
| 68 | frontend/maxwell/translate/impl/branch_indirect.cpp | 70 | frontend/maxwell/translate/impl/branch_indirect.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index d2eda1f8e..749ad1240 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -28,6 +28,7 @@ void EmitSelectionMerge(EmitContext& ctx, Id merge_label); | |||
| 28 | void EmitReturn(EmitContext& ctx); | 28 | void EmitReturn(EmitContext& ctx); |
| 29 | void EmitUnreachable(EmitContext& ctx); | 29 | void EmitUnreachable(EmitContext& ctx); |
| 30 | void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); | 30 | void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); |
| 31 | void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst); | ||
| 31 | void EmitPrologue(EmitContext& ctx); | 32 | void EmitPrologue(EmitContext& ctx); |
| 32 | void EmitEpilogue(EmitContext& ctx); | 33 | void EmitEpilogue(EmitContext& ctx); |
| 33 | void EmitGetRegister(EmitContext& ctx); | 34 | void EmitGetRegister(EmitContext& ctx); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp new file mode 100644 index 000000000..413ac25a0 --- /dev/null +++ b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "shader_recompiler/backend/spirv/emit_spirv.h" | ||
| 6 | #include "shader_recompiler/frontend/ir/modifiers.h" | ||
| 7 | |||
| 8 | namespace Shader::Backend::SPIRV { | ||
| 9 | namespace { | ||
| 10 | spv::Scope MemoryScopeToSpirVScope(IR::MemoryScope scope) { | ||
| 11 | switch (scope) { | ||
| 12 | case IR::MemoryScope::Warp: | ||
| 13 | return spv::Scope::Subgroup; | ||
| 14 | case IR::MemoryScope::Workgroup: | ||
| 15 | return spv::Scope::Workgroup; | ||
| 16 | case IR::MemoryScope::Device: | ||
| 17 | return spv::Scope::Device; | ||
| 18 | case IR::MemoryScope::System: | ||
| 19 | return spv::Scope::CrossDevice; | ||
| 20 | case IR::MemoryScope::DontCare: | ||
| 21 | return spv::Scope::Invocation; | ||
| 22 | default: | ||
| 23 | throw NotImplementedException("Unknown memory scope!"); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | } // namespace | ||
| 28 | |||
| 29 | void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst) { | ||
| 30 | const auto info{inst->Flags<IR::BarrierInstInfo>()}; | ||
| 31 | const auto semantics = | ||
| 32 | spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory | | ||
| 33 | spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory | | ||
| 34 | spv::MemorySemanticsMask::ImageMemory; | ||
| 35 | const auto scope = MemoryScopeToSpirVScope(info.scope); | ||
| 36 | ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)), | ||
| 37 | ctx.Constant(ctx.U32[1], static_cast<u32>(semantics))); | ||
| 38 | } | ||
| 39 | |||
| 40 | } // namespace Shader::Backend::SPIRV | ||
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index ddaa873f2..2fd90303f 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -82,6 +82,10 @@ void IREmitter::SelectionMerge(Block* merge_block) { | |||
| 82 | Inst(Opcode::SelectionMerge, merge_block); | 82 | Inst(Opcode::SelectionMerge, merge_block); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void IREmitter::MemoryBarrier(BarrierInstInfo info) { | ||
| 86 | Inst(Opcode::MemoryBarrier, Flags{info}); | ||
| 87 | } | ||
| 88 | |||
| 85 | void IREmitter::Return() { | 89 | void IREmitter::Return() { |
| 86 | block->SetReturn(); | 90 | block->SetReturn(); |
| 87 | Inst(Opcode::Return); | 91 | Inst(Opcode::Return); |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 6e04eec7f..5bebf66e3 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -136,6 +136,8 @@ public: | |||
| 136 | [[nodiscard]] Value Select(const U1& condition, const Value& true_value, | 136 | [[nodiscard]] Value Select(const U1& condition, const Value& true_value, |
| 137 | const Value& false_value); | 137 | const Value& false_value); |
| 138 | 138 | ||
| 139 | [[nodiscard]] void MemoryBarrier(BarrierInstInfo info); | ||
| 140 | |||
| 139 | template <typename Dest, typename Source> | 141 | template <typename Dest, typename Source> |
| 140 | [[nodiscard]] Dest BitCast(const Source& value); | 142 | [[nodiscard]] Dest BitCast(const Source& value); |
| 141 | 143 | ||
diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h index 90078f535..7730c25a9 100644 --- a/src/shader_recompiler/frontend/ir/modifiers.h +++ b/src/shader_recompiler/frontend/ir/modifiers.h | |||
| @@ -25,6 +25,14 @@ enum class FpRounding : u8 { | |||
| 25 | RZ, // Round towards zero | 25 | RZ, // Round towards zero |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | enum class MemoryScope : u32 { | ||
| 29 | DontCare, | ||
| 30 | Warp, | ||
| 31 | Workgroup, | ||
| 32 | Device, | ||
| 33 | System | ||
| 34 | }; | ||
| 35 | |||
| 28 | struct FpControl { | 36 | struct FpControl { |
| 29 | bool no_contraction{false}; | 37 | bool no_contraction{false}; |
| 30 | FpRounding rounding{FpRounding::DontCare}; | 38 | FpRounding rounding{FpRounding::DontCare}; |
| @@ -32,6 +40,11 @@ struct FpControl { | |||
| 32 | }; | 40 | }; |
| 33 | static_assert(sizeof(FpControl) <= sizeof(u32)); | 41 | static_assert(sizeof(FpControl) <= sizeof(u32)); |
| 34 | 42 | ||
| 43 | union BarrierInstInfo { | ||
| 44 | u32 raw; | ||
| 45 | BitField<0, 3, MemoryScope> scope; | ||
| 46 | }; | ||
| 47 | |||
| 35 | union TextureInstInfo { | 48 | union TextureInstInfo { |
| 36 | u32 raw; | 49 | u32 raw; |
| 37 | BitField<0, 8, TextureType> type; | 50 | BitField<0, 8, TextureType> type; |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 702372775..d9e0d5471 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -16,6 +16,9 @@ OPCODE(Return, Void, | |||
| 16 | OPCODE(Unreachable, Void, ) | 16 | OPCODE(Unreachable, Void, ) |
| 17 | OPCODE(DemoteToHelperInvocation, Void, Label, ) | 17 | OPCODE(DemoteToHelperInvocation, Void, Label, ) |
| 18 | 18 | ||
| 19 | // Barriers | ||
| 20 | OPCODE(MemoryBarrier, Void, ) | ||
| 21 | |||
| 19 | // Special operations | 22 | // Special operations |
| 20 | OPCODE(Prologue, Void, ) | 23 | OPCODE(Prologue, Void, ) |
| 21 | OPCODE(Epilogue, Void, ) | 24 | OPCODE(Epilogue, Void, ) |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp new file mode 100644 index 000000000..933af572c --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/bit_field.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "shader_recompiler/frontend/ir/modifiers.h" | ||
| 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 9 | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||
| 10 | |||
| 11 | namespace Shader::Maxwell { | ||
| 12 | namespace { | ||
| 13 | // Seems to be in CUDA terminology. | ||
| 14 | enum class LocalScope : u64 { | ||
| 15 | CTG = 0, | ||
| 16 | GL = 1, | ||
| 17 | SYS = 2, | ||
| 18 | VC = 3, | ||
| 19 | }; | ||
| 20 | |||
| 21 | IR::MemoryScope LocalScopeToMemoryScope(LocalScope scope) { | ||
| 22 | switch (scope) { | ||
| 23 | case LocalScope::CTG: | ||
| 24 | return IR::MemoryScope::Warp; | ||
| 25 | case LocalScope::GL: | ||
| 26 | return IR::MemoryScope::Device; | ||
| 27 | case LocalScope::SYS: | ||
| 28 | return IR::MemoryScope::System; | ||
| 29 | case LocalScope::VC: | ||
| 30 | return IR::MemoryScope::Workgroup; // or should be device? | ||
| 31 | default: | ||
| 32 | throw NotImplementedException("Unimplemented Local Scope {}", scope); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | } // namespace | ||
| 37 | |||
| 38 | void TranslatorVisitor::MEMBAR(u64 inst) { | ||
| 39 | union { | ||
| 40 | u64 raw; | ||
| 41 | BitField<8, 2, LocalScope> scope; | ||
| 42 | } membar{inst}; | ||
| 43 | IR::BarrierInstInfo info{}; | ||
| 44 | info.scope.Assign(LocalScopeToMemoryScope(membar.scope)); | ||
| 45 | ir.MemoryBarrier(info); | ||
| 46 | } | ||
| 47 | |||
| 48 | void TranslatorVisitor::DEPBAR() { | ||
| 49 | // DEPBAR is a no-op | ||
| 50 | } | ||
| 51 | |||
| 52 | void TranslatorVisitor::BAR(u64) { | ||
| 53 | throw NotImplementedException("Instruction {} is not implemented", Opcode::BAR); | ||
| 54 | } | ||
| 55 | |||
| 56 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 83ed0c0fd..80a6ed578 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -37,10 +37,6 @@ void TranslatorVisitor::B2R(u64) { | |||
| 37 | ThrowNotImplemented(Opcode::B2R); | 37 | ThrowNotImplemented(Opcode::B2R); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | void TranslatorVisitor::BAR(u64) { | ||
| 41 | ThrowNotImplemented(Opcode::BAR); | ||
| 42 | } | ||
| 43 | |||
| 44 | void TranslatorVisitor::BPT(u64) { | 40 | void TranslatorVisitor::BPT(u64) { |
| 45 | ThrowNotImplemented(Opcode::BPT); | 41 | ThrowNotImplemented(Opcode::BPT); |
| 46 | } | 42 | } |
| @@ -73,9 +69,6 @@ void TranslatorVisitor::CS2R(u64) { | |||
| 73 | ThrowNotImplemented(Opcode::CS2R); | 69 | ThrowNotImplemented(Opcode::CS2R); |
| 74 | } | 70 | } |
| 75 | 71 | ||
| 76 | void TranslatorVisitor::DEPBAR() { | ||
| 77 | // DEPBAR is a no-op | ||
| 78 | } | ||
| 79 | 72 | ||
| 80 | void TranslatorVisitor::FCHK_reg(u64) { | 73 | void TranslatorVisitor::FCHK_reg(u64) { |
| 81 | ThrowNotImplemented(Opcode::FCHK_reg); | 74 | ThrowNotImplemented(Opcode::FCHK_reg); |
| @@ -189,10 +182,6 @@ void TranslatorVisitor::LONGJMP(u64) { | |||
| 189 | ThrowNotImplemented(Opcode::LONGJMP); | 182 | ThrowNotImplemented(Opcode::LONGJMP); |
| 190 | } | 183 | } |
| 191 | 184 | ||
| 192 | void TranslatorVisitor::MEMBAR(u64) { | ||
| 193 | ThrowNotImplemented(Opcode::MEMBAR); | ||
| 194 | } | ||
| 195 | |||
| 196 | void TranslatorVisitor::NOP(u64) { | 185 | void TranslatorVisitor::NOP(u64) { |
| 197 | ThrowNotImplemented(Opcode::NOP); | 186 | ThrowNotImplemented(Opcode::NOP); |
| 198 | } | 187 | } |