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_spirv.cpp | ||||
|     backend/spirv/emit_spirv.h | ||||
|     backend/spirv/emit_spirv_barriers.cpp | ||||
|     backend/spirv/emit_spirv_bitwise_conversion.cpp | ||||
|     backend/spirv/emit_spirv_composite.cpp | ||||
|     backend/spirv/emit_spirv_context_get_set.cpp | ||||
| @@ -63,6 +64,7 @@ add_library(shader_recompiler STATIC | ||||
|     frontend/maxwell/program.h | ||||
|     frontend/maxwell/structured_control_flow.cpp | ||||
|     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_insert.cpp | ||||
|     frontend/maxwell/translate/impl/branch_indirect.cpp | ||||
|   | ||||
| @@ -28,6 +28,7 @@ void EmitSelectionMerge(EmitContext& ctx, Id merge_label); | ||||
| void EmitReturn(EmitContext& ctx); | ||||
| void EmitUnreachable(EmitContext& ctx); | ||||
| void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); | ||||
| void EmitMemoryBarrier(EmitContext& ctx, IR::Inst* inst); | ||||
| void EmitPrologue(EmitContext& ctx); | ||||
| void EmitEpilogue(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); | ||||
| } | ||||
|  | ||||
| void IREmitter::MemoryBarrier(BarrierInstInfo info) { | ||||
|     Inst(Opcode::MemoryBarrier, Flags{info}); | ||||
| } | ||||
|  | ||||
| void IREmitter::Return() { | ||||
|     block->SetReturn(); | ||||
|     Inst(Opcode::Return); | ||||
|   | ||||
| @@ -136,6 +136,8 @@ public: | ||||
|     [[nodiscard]] Value Select(const U1& condition, const Value& true_value, | ||||
|                                const Value& false_value); | ||||
|  | ||||
|     [[nodiscard]] void MemoryBarrier(BarrierInstInfo info); | ||||
|  | ||||
|     template <typename Dest, typename Source> | ||||
|     [[nodiscard]] Dest BitCast(const Source& value); | ||||
|  | ||||
|   | ||||
| @@ -25,6 +25,14 @@ enum class FpRounding : u8 { | ||||
|     RZ,       // Round towards zero | ||||
| }; | ||||
|  | ||||
| enum class MemoryScope : u32 { | ||||
|   DontCare, | ||||
|   Warp, | ||||
|   Workgroup, | ||||
|   Device, | ||||
|   System | ||||
| }; | ||||
|  | ||||
| struct FpControl { | ||||
|     bool no_contraction{false}; | ||||
|     FpRounding rounding{FpRounding::DontCare}; | ||||
| @@ -32,6 +40,11 @@ struct FpControl { | ||||
| }; | ||||
| static_assert(sizeof(FpControl) <= sizeof(u32)); | ||||
|  | ||||
| union BarrierInstInfo { | ||||
|     u32 raw; | ||||
|     BitField<0, 3, MemoryScope> scope; | ||||
| }; | ||||
|  | ||||
| union TextureInstInfo { | ||||
|     u32 raw; | ||||
|     BitField<0, 8, TextureType> type; | ||||
|   | ||||
| @@ -16,6 +16,9 @@ OPCODE(Return,                                              Void, | ||||
| OPCODE(Unreachable,                                         Void,                                                                                           ) | ||||
| OPCODE(DemoteToHelperInvocation,                            Void,           Label,                                                                          ) | ||||
|  | ||||
| // Barriers | ||||
| OPCODE(MemoryBarrier,                                       Void,                                                                                           ) | ||||
|  | ||||
| // Special operations | ||||
| OPCODE(Prologue,                                            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); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::BAR(u64) { | ||||
|     ThrowNotImplemented(Opcode::BAR); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::BPT(u64) { | ||||
|     ThrowNotImplemented(Opcode::BPT); | ||||
| } | ||||
| @@ -73,9 +69,6 @@ void TranslatorVisitor::CS2R(u64) { | ||||
|     ThrowNotImplemented(Opcode::CS2R); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::DEPBAR() { | ||||
|     // DEPBAR is a no-op | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::FCHK_reg(u64) { | ||||
|     ThrowNotImplemented(Opcode::FCHK_reg); | ||||
| @@ -189,10 +182,6 @@ void TranslatorVisitor::LONGJMP(u64) { | ||||
|     ThrowNotImplemented(Opcode::LONGJMP); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::MEMBAR(u64) { | ||||
|     ThrowNotImplemented(Opcode::MEMBAR); | ||||
| } | ||||
|  | ||||
| void TranslatorVisitor::NOP(u64) { | ||||
|     ThrowNotImplemented(Opcode::NOP); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user