shader: Implement MEMBAR
This commit is contained in:
		| @@ -3,6 +3,7 @@ add_library(shader_recompiler STATIC | |||||||
|     backend/spirv/emit_context.h |     backend/spirv/emit_context.h | ||||||
|     backend/spirv/emit_spirv.cpp |     backend/spirv/emit_spirv.cpp | ||||||
|     backend/spirv/emit_spirv.h |     backend/spirv/emit_spirv.h | ||||||
|  |     backend/spirv/emit_spirv_barriers.cpp | ||||||
|     backend/spirv/emit_spirv_bitwise_conversion.cpp |     backend/spirv/emit_spirv_bitwise_conversion.cpp | ||||||
|     backend/spirv/emit_spirv_composite.cpp |     backend/spirv/emit_spirv_composite.cpp | ||||||
|     backend/spirv/emit_spirv_context_get_set.cpp |     backend/spirv/emit_spirv_context_get_set.cpp | ||||||
| @@ -63,6 +64,7 @@ add_library(shader_recompiler STATIC | |||||||
|     frontend/maxwell/program.h |     frontend/maxwell/program.h | ||||||
|     frontend/maxwell/structured_control_flow.cpp |     frontend/maxwell/structured_control_flow.cpp | ||||||
|     frontend/maxwell/structured_control_flow.h |     frontend/maxwell/structured_control_flow.h | ||||||
|  |     frontend/maxwell/translate/impl/barrier_operations.cpp | ||||||
|     frontend/maxwell/translate/impl/bitfield_extract.cpp |     frontend/maxwell/translate/impl/bitfield_extract.cpp | ||||||
|     frontend/maxwell/translate/impl/bitfield_insert.cpp |     frontend/maxwell/translate/impl/bitfield_insert.cpp | ||||||
|     frontend/maxwell/translate/impl/branch_indirect.cpp |     frontend/maxwell/translate/impl/branch_indirect.cpp | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ void EmitSelectionMerge(EmitContext& ctx, Id merge_label); | |||||||
| void EmitReturn(EmitContext& ctx); | void EmitReturn(EmitContext& ctx); | ||||||
| void EmitUnreachable(EmitContext& ctx); | void EmitUnreachable(EmitContext& ctx); | ||||||
| void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); | void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); | ||||||
|  | void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst); | ||||||
| void EmitPrologue(EmitContext& ctx); | void EmitPrologue(EmitContext& ctx); | ||||||
| void EmitEpilogue(EmitContext& ctx); | void EmitEpilogue(EmitContext& ctx); | ||||||
| void EmitGetRegister(EmitContext& ctx); | void EmitGetRegister(EmitContext& ctx); | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include "shader_recompiler/backend/spirv/emit_spirv.h" | ||||||
|  | #include "shader_recompiler/frontend/ir/modifiers.h" | ||||||
|  |  | ||||||
|  | namespace Shader::Backend::SPIRV { | ||||||
|  | namespace { | ||||||
|  | spv::Scope MemoryScopeToSpirVScope(IR::MemoryScope scope) { | ||||||
|  |     switch (scope) { | ||||||
|  |     case IR::MemoryScope::Warp: | ||||||
|  |         return spv::Scope::Subgroup; | ||||||
|  |     case IR::MemoryScope::Workgroup: | ||||||
|  |         return spv::Scope::Workgroup; | ||||||
|  |     case IR::MemoryScope::Device: | ||||||
|  |         return spv::Scope::Device; | ||||||
|  |     case IR::MemoryScope::System: | ||||||
|  |         return spv::Scope::CrossDevice; | ||||||
|  |     case IR::MemoryScope::DontCare: | ||||||
|  |         return spv::Scope::Invocation; | ||||||
|  |     default: | ||||||
|  |         throw NotImplementedException("Unknown memory scope!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
|  | void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst) { | ||||||
|  |     const auto info{inst->Flags<IR::BarrierInstInfo>()}; | ||||||
|  |     const auto semantics = | ||||||
|  |         spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory | | ||||||
|  |         spv::MemorySemanticsMask::WorkgroupMemory | spv::MemorySemanticsMask::AtomicCounterMemory | | ||||||
|  |         spv::MemorySemanticsMask::ImageMemory; | ||||||
|  |     const auto scope = MemoryScopeToSpirVScope(info.scope); | ||||||
|  |     ctx.OpMemoryBarrier(ctx.Constant(ctx.U32[1], static_cast<u32>(scope)), | ||||||
|  |                         ctx.Constant(ctx.U32[1], static_cast<u32>(semantics))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace Shader::Backend::SPIRV | ||||||
| @@ -82,6 +82,10 @@ void IREmitter::SelectionMerge(Block* merge_block) { | |||||||
|     Inst(Opcode::SelectionMerge, merge_block); |     Inst(Opcode::SelectionMerge, merge_block); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void IREmitter::MemoryBarrier(BarrierInstInfo info) { | ||||||
|  |     Inst(Opcode::MemoryBarrier, Flags{info}); | ||||||
|  | } | ||||||
|  |  | ||||||
| void IREmitter::Return() { | void IREmitter::Return() { | ||||||
|     block->SetReturn(); |     block->SetReturn(); | ||||||
|     Inst(Opcode::Return); |     Inst(Opcode::Return); | ||||||
|   | |||||||
| @@ -136,6 +136,8 @@ public: | |||||||
|     [[nodiscard]] Value Select(const U1& condition, const Value& true_value, |     [[nodiscard]] Value Select(const U1& condition, const Value& true_value, | ||||||
|                                const Value& false_value); |                                const Value& false_value); | ||||||
|  |  | ||||||
|  |     [[nodiscard]] void MemoryBarrier(BarrierInstInfo info); | ||||||
|  |  | ||||||
|     template <typename Dest, typename Source> |     template <typename Dest, typename Source> | ||||||
|     [[nodiscard]] Dest BitCast(const Source& value); |     [[nodiscard]] Dest BitCast(const Source& value); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,6 +25,14 @@ enum class FpRounding : u8 { | |||||||
|     RZ,       // Round towards zero |     RZ,       // Round towards zero | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | enum class MemoryScope : u32 { | ||||||
|  |   DontCare, | ||||||
|  |   Warp, | ||||||
|  |   Workgroup, | ||||||
|  |   Device, | ||||||
|  |   System | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct FpControl { | struct FpControl { | ||||||
|     bool no_contraction{false}; |     bool no_contraction{false}; | ||||||
|     FpRounding rounding{FpRounding::DontCare}; |     FpRounding rounding{FpRounding::DontCare}; | ||||||
| @@ -32,6 +40,11 @@ struct FpControl { | |||||||
| }; | }; | ||||||
| static_assert(sizeof(FpControl) <= sizeof(u32)); | static_assert(sizeof(FpControl) <= sizeof(u32)); | ||||||
|  |  | ||||||
|  | union BarrierInstInfo { | ||||||
|  |     u32 raw; | ||||||
|  |     BitField<0, 3, MemoryScope> scope; | ||||||
|  | }; | ||||||
|  |  | ||||||
| union TextureInstInfo { | union TextureInstInfo { | ||||||
|     u32 raw; |     u32 raw; | ||||||
|     BitField<0, 8, TextureType> type; |     BitField<0, 8, TextureType> type; | ||||||
|   | |||||||
| @@ -16,6 +16,9 @@ OPCODE(Return,                                              Void, | |||||||
| OPCODE(Unreachable,                                         Void,                                                                                           ) | OPCODE(Unreachable,                                         Void,                                                                                           ) | ||||||
| OPCODE(DemoteToHelperInvocation,                            Void,           Label,                                                                          ) | OPCODE(DemoteToHelperInvocation,                            Void,           Label,                                                                          ) | ||||||
|  |  | ||||||
|  | // Barriers | ||||||
|  | OPCODE(MemoryBarrier,                                       Void,                                                                                           ) | ||||||
|  |  | ||||||
| // Special operations | // Special operations | ||||||
| OPCODE(Prologue,                                            Void,                                                                                           ) | OPCODE(Prologue,                                            Void,                                                                                           ) | ||||||
| OPCODE(Epilogue,                                            Void,                                                                                           ) | OPCODE(Epilogue,                                            Void,                                                                                           ) | ||||||
|   | |||||||
| @@ -0,0 +1,56 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include "common/bit_field.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "shader_recompiler/frontend/ir/modifiers.h" | ||||||
|  | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
|  |  | ||||||
|  | namespace Shader::Maxwell { | ||||||
|  | namespace { | ||||||
|  | // Seems to be in CUDA terminology. | ||||||
|  | enum class LocalScope : u64 { | ||||||
|  |     CTG = 0, | ||||||
|  |     GL = 1, | ||||||
|  |     SYS = 2, | ||||||
|  |     VC = 3, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | IR::MemoryScope LocalScopeToMemoryScope(LocalScope scope) { | ||||||
|  |     switch (scope) { | ||||||
|  |     case LocalScope::CTG: | ||||||
|  |         return IR::MemoryScope::Warp; | ||||||
|  |     case LocalScope::GL: | ||||||
|  |         return IR::MemoryScope::Device; | ||||||
|  |     case LocalScope::SYS: | ||||||
|  |         return IR::MemoryScope::System; | ||||||
|  |     case LocalScope::VC: | ||||||
|  |         return IR::MemoryScope::Workgroup; // or should be device? | ||||||
|  |     default: | ||||||
|  |         throw NotImplementedException("Unimplemented Local Scope {}", scope); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
|  | void TranslatorVisitor::MEMBAR(u64 inst) { | ||||||
|  |     union { | ||||||
|  |         u64 raw; | ||||||
|  |         BitField<8, 2, LocalScope> scope; | ||||||
|  |     } membar{inst}; | ||||||
|  |     IR::BarrierInstInfo info{}; | ||||||
|  |     info.scope.Assign(LocalScopeToMemoryScope(membar.scope)); | ||||||
|  |     ir.MemoryBarrier(info); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void TranslatorVisitor::DEPBAR() { | ||||||
|  |     // DEPBAR is a no-op | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void TranslatorVisitor::BAR(u64) { | ||||||
|  |     throw NotImplementedException("Instruction {} is not implemented", Opcode::BAR); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace Shader::Maxwell | ||||||
| @@ -37,10 +37,6 @@ void TranslatorVisitor::B2R(u64) { | |||||||
|     ThrowNotImplemented(Opcode::B2R); |     ThrowNotImplemented(Opcode::B2R); | ||||||
| } | } | ||||||
|  |  | ||||||
| void TranslatorVisitor::BAR(u64) { |  | ||||||
|     ThrowNotImplemented(Opcode::BAR); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void TranslatorVisitor::BPT(u64) { | void TranslatorVisitor::BPT(u64) { | ||||||
|     ThrowNotImplemented(Opcode::BPT); |     ThrowNotImplemented(Opcode::BPT); | ||||||
| } | } | ||||||
| @@ -73,9 +69,6 @@ void TranslatorVisitor::CS2R(u64) { | |||||||
|     ThrowNotImplemented(Opcode::CS2R); |     ThrowNotImplemented(Opcode::CS2R); | ||||||
| } | } | ||||||
|  |  | ||||||
| void TranslatorVisitor::DEPBAR() { |  | ||||||
|     // DEPBAR is a no-op |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void TranslatorVisitor::FCHK_reg(u64) { | void TranslatorVisitor::FCHK_reg(u64) { | ||||||
|     ThrowNotImplemented(Opcode::FCHK_reg); |     ThrowNotImplemented(Opcode::FCHK_reg); | ||||||
| @@ -189,10 +182,6 @@ void TranslatorVisitor::LONGJMP(u64) { | |||||||
|     ThrowNotImplemented(Opcode::LONGJMP); |     ThrowNotImplemented(Opcode::LONGJMP); | ||||||
| } | } | ||||||
|  |  | ||||||
| void TranslatorVisitor::MEMBAR(u64) { |  | ||||||
|     ThrowNotImplemented(Opcode::MEMBAR); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void TranslatorVisitor::NOP(u64) { | void TranslatorVisitor::NOP(u64) { | ||||||
|     ThrowNotImplemented(Opcode::NOP); |     ThrowNotImplemented(Opcode::NOP); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user