summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp15
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp4
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h1
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp4
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp58
7 files changed, 79 insertions, 5 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index e066ba87d..032b0b2f9 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);
28void EmitReturn(EmitContext& ctx); 28void EmitReturn(EmitContext& ctx);
29void EmitUnreachable(EmitContext& ctx); 29void EmitUnreachable(EmitContext& ctx);
30void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); 30void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label);
31void EmitBarrier(EmitContext& ctx);
31void EmitMemoryBarrierWorkgroupLevel(EmitContext& ctx); 32void EmitMemoryBarrierWorkgroupLevel(EmitContext& ctx);
32void EmitMemoryBarrierDeviceLevel(EmitContext& ctx); 33void EmitMemoryBarrierDeviceLevel(EmitContext& ctx);
33void EmitMemoryBarrierSystemLevel(EmitContext& ctx); 34void EmitMemoryBarrierSystemLevel(EmitContext& ctx);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
index 18f512319..74f523d0f 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
@@ -8,16 +8,25 @@
8namespace Shader::Backend::SPIRV { 8namespace Shader::Backend::SPIRV {
9namespace { 9namespace {
10void EmitMemoryBarrierImpl(EmitContext& ctx, spv::Scope scope) { 10void EmitMemoryBarrierImpl(EmitContext& ctx, spv::Scope scope) {
11 const auto semantics = 11 const auto semantics{
12 spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory | 12 spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory |
13 spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory | 13 spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory |
14 spv::MemorySemanticsMask::ImageMemory; 14 spv::MemorySemanticsMask::ImageMemory};
15 ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)), 15 ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)),
16 ctx.Constant(ctx.U32[1], static_cast<u32>(semantics))); 16 ctx.Constant(ctx.U32[1], static_cast<u32>(semantics)));
17} 17}
18
19} // Anonymous namespace 18} // Anonymous namespace
20 19
20void EmitBarrier(EmitContext& ctx) {
21 const auto execution{spv::Scope::Workgroup};
22 const auto memory{spv::Scope::Workgroup};
23 const auto memory_semantics{spv::MemorySemanticsMask::AcquireRelease |
24 spv::MemorySemanticsMask::WorkgroupMemory};
25 ctx.OpControlBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(execution)),
26 ctx.Constant(ctx.U32[1], static_cast<u32>(memory)),
27 ctx.Constant(ctx.U32[1], static_cast<u32>(memory_semantics)));
28}
29
21void EmitMemoryBarrierWorkgroupLevel(EmitContext& ctx) { 30void EmitMemoryBarrierWorkgroupLevel(EmitContext& ctx) {
22 EmitMemoryBarrierImpl(ctx, spv::Scope::Workgroup); 31 EmitMemoryBarrierImpl(ctx, spv::Scope::Workgroup);
23} 32}
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index dbd38a28b..246c3b9ef 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
85void IREmitter::Barrier() {
86 Inst(Opcode::Barrier);
87}
88
85void IREmitter::MemoryBarrier(MemoryScope scope) { 89void IREmitter::MemoryBarrier(MemoryScope scope) {
86 switch (scope) { 90 switch (scope) {
87 case MemoryScope::Workgroup: 91 case MemoryScope::Workgroup:
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 81a57fefe..1b00c548d 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -128,6 +128,7 @@ public:
128 [[nodiscard]] Value Select(const U1& condition, const Value& true_value, 128 [[nodiscard]] Value Select(const U1& condition, const Value& true_value,
129 const Value& false_value); 129 const Value& false_value);
130 130
131 [[nodiscard]] void Barrier();
131 [[nodiscard]] void MemoryBarrier(MemoryScope scope); 132 [[nodiscard]] void MemoryBarrier(MemoryScope scope);
132 133
133 template <typename Dest, typename Source> 134 template <typename Dest, typename Source>
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 074c71d53..481202d94 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -57,6 +57,10 @@ bool Inst::MayHaveSideEffects() const noexcept {
57 case Opcode::Return: 57 case Opcode::Return:
58 case Opcode::Unreachable: 58 case Opcode::Unreachable:
59 case Opcode::DemoteToHelperInvocation: 59 case Opcode::DemoteToHelperInvocation:
60 case Opcode::Barrier:
61 case Opcode::MemoryBarrierWorkgroupLevel:
62 case Opcode::MemoryBarrierDeviceLevel:
63 case Opcode::MemoryBarrierSystemLevel:
60 case Opcode::Prologue: 64 case Opcode::Prologue:
61 case Opcode::Epilogue: 65 case Opcode::Epilogue:
62 case Opcode::SetAttribute: 66 case Opcode::SetAttribute:
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 734f5328b..dcd54bcf7 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -17,6 +17,7 @@ OPCODE(Unreachable, Void,
17OPCODE(DemoteToHelperInvocation, Void, Label, ) 17OPCODE(DemoteToHelperInvocation, Void, Label, )
18 18
19// Barriers 19// Barriers
20OPCODE(Barrier, Void, )
20OPCODE(MemoryBarrierWorkgroupLevel, Void, ) 21OPCODE(MemoryBarrierWorkgroupLevel, Void, )
21OPCODE(MemoryBarrierDeviceLevel, Void, ) 22OPCODE(MemoryBarrierDeviceLevel, Void, )
22OPCODE(MemoryBarrierSystemLevel, Void, ) 23OPCODE(MemoryBarrierSystemLevel, 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
index 26d5e276b..2a2a294df 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/barrier_operations.cpp
@@ -38,6 +38,7 @@ void TranslatorVisitor::MEMBAR(u64 inst) {
38 u64 raw; 38 u64 raw;
39 BitField<8, 2, LocalScope> scope; 39 BitField<8, 2, LocalScope> scope;
40 } membar{inst}; 40 } membar{inst};
41
41 ir.MemoryBarrier(LocalScopeToMemoryScope(membar.scope)); 42 ir.MemoryBarrier(LocalScopeToMemoryScope(membar.scope));
42} 43}
43 44
@@ -45,8 +46,61 @@ void TranslatorVisitor::DEPBAR() {
45 // DEPBAR is a no-op 46 // DEPBAR is a no-op
46} 47}
47 48
48void TranslatorVisitor::BAR(u64) { 49void TranslatorVisitor::BAR(u64 insn) {
49 throw NotImplementedException("Instruction {} is not implemented", Opcode::BAR); 50 enum class Mode {
51 RedPopc,
52 Scan,
53 RedAnd,
54 RedOr,
55 Sync,
56 Arrive,
57 };
58 union {
59 u64 raw;
60 BitField<43, 1, u64> is_a_imm;
61 BitField<44, 1, u64> is_b_imm;
62 BitField<8, 8, u64> imm_a;
63 BitField<20, 12, u64> imm_b;
64 BitField<42, 1, u64> neg_pred;
65 BitField<39, 3, IR::Pred> pred;
66 } const bar{insn};
67
68 const Mode mode{[insn] {
69 switch (insn & 0x0000009B00000000ULL) {
70 case 0x0000000200000000ULL:
71 return Mode::RedPopc;
72 case 0x0000000300000000ULL:
73 return Mode::Scan;
74 case 0x0000000A00000000ULL:
75 return Mode::RedAnd;
76 case 0x0000001200000000ULL:
77 return Mode::RedOr;
78 case 0x0000008000000000ULL:
79 return Mode::Sync;
80 case 0x0000008100000000ULL:
81 return Mode::Arrive;
82 }
83 throw NotImplementedException("Invalid encoding");
84 }()};
85 if (mode != Mode::Sync) {
86 throw NotImplementedException("BAR mode {}", mode);
87 }
88 if (bar.is_a_imm == 0) {
89 throw NotImplementedException("Non-immediate input A");
90 }
91 if (bar.imm_a != 0) {
92 throw NotImplementedException("Non-zero input A");
93 }
94 if (bar.is_b_imm == 0) {
95 throw NotImplementedException("Non-immediate input B");
96 }
97 if (bar.imm_b != 0) {
98 throw NotImplementedException("Non-zero input B");
99 }
100 if (bar.pred != IR::Pred::PT && bar.neg_pred != 0) {
101 throw NotImplementedException("Non-true input predicate");
102 }
103 ir.Barrier();
50} 104}
51 105
52} // namespace Shader::Maxwell 106} // namespace Shader::Maxwell