forked from eden-emu/eden
		
	shader: Primitive Vulkan integration
This commit is contained in:
		
							parent
							
								
									65069df8aa
								
							
						
					
					
						commit
						a5f87011d3
					
				
					 43 changed files with 1003 additions and 3036 deletions
				
			
		|  | @ -1,4 +1,4 @@ | ||||||
| add_executable(shader_recompiler | add_library(shader_recompiler STATIC | ||||||
|     backend/spirv/emit_context.cpp |     backend/spirv/emit_context.cpp | ||||||
|     backend/spirv/emit_context.h |     backend/spirv/emit_context.h | ||||||
|     backend/spirv/emit_spirv.cpp |     backend/spirv/emit_spirv.cpp | ||||||
|  | @ -85,13 +85,19 @@ add_executable(shader_recompiler | ||||||
|     ir_opt/passes.h |     ir_opt/passes.h | ||||||
|     ir_opt/ssa_rewrite_pass.cpp |     ir_opt/ssa_rewrite_pass.cpp | ||||||
|     ir_opt/verification_pass.cpp |     ir_opt/verification_pass.cpp | ||||||
|     main.cpp |  | ||||||
|     object_pool.h |     object_pool.h | ||||||
|  |     profile.h | ||||||
|  |     recompiler.cpp | ||||||
|  |     recompiler.h | ||||||
|     shader_info.h |     shader_info.h | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_include_directories(video_core PRIVATE sirit) | target_include_directories(shader_recompiler PRIVATE sirit) | ||||||
| target_link_libraries(shader_recompiler PRIVATE fmt::fmt sirit) | target_link_libraries(shader_recompiler PRIVATE fmt::fmt sirit) | ||||||
|  | target_link_libraries(shader_recompiler INTERFACE fmt::fmt sirit) | ||||||
|  | 
 | ||||||
|  | add_executable(shader_util main.cpp) | ||||||
|  | target_link_libraries(shader_util PRIVATE shader_recompiler) | ||||||
| 
 | 
 | ||||||
| if (MSVC) | if (MSVC) | ||||||
|     target_compile_options(shader_recompiler PRIVATE |     target_compile_options(shader_recompiler PRIVATE | ||||||
|  | @ -121,3 +127,4 @@ else() | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| create_target_directory_groups(shader_recompiler) | create_target_directory_groups(shader_recompiler) | ||||||
|  | create_target_directory_groups(shader_util) | ||||||
|  |  | ||||||
|  | @ -115,6 +115,7 @@ void EmitContext::DefineConstantBuffers(const Info& info) { | ||||||
|     for (const Info::ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) { |     for (const Info::ConstantBufferDescriptor& desc : info.constant_buffer_descriptors) { | ||||||
|         const Id id{AddGlobalVariable(uniform_type, spv::StorageClass::Uniform)}; |         const Id id{AddGlobalVariable(uniform_type, spv::StorageClass::Uniform)}; | ||||||
|         Decorate(id, spv::Decoration::Binding, binding); |         Decorate(id, spv::Decoration::Binding, binding); | ||||||
|  |         Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||||||
|         Name(id, fmt::format("c{}", desc.index)); |         Name(id, fmt::format("c{}", desc.index)); | ||||||
|         std::fill_n(cbufs.data() + desc.index, desc.count, id); |         std::fill_n(cbufs.data() + desc.index, desc.count, id); | ||||||
|         binding += desc.count; |         binding += desc.count; | ||||||
|  | @ -143,6 +144,7 @@ void EmitContext::DefineStorageBuffers(const Info& info) { | ||||||
|     for (const Info::StorageBufferDescriptor& desc : info.storage_buffers_descriptors) { |     for (const Info::StorageBufferDescriptor& desc : info.storage_buffers_descriptors) { | ||||||
|         const Id id{AddGlobalVariable(storage_type, spv::StorageClass::StorageBuffer)}; |         const Id id{AddGlobalVariable(storage_type, spv::StorageClass::StorageBuffer)}; | ||||||
|         Decorate(id, spv::Decoration::Binding, binding); |         Decorate(id, spv::Decoration::Binding, binding); | ||||||
|  |         Decorate(id, spv::Decoration::DescriptorSet, 0U); | ||||||
|         Name(id, fmt::format("ssbo{}", binding)); |         Name(id, fmt::format("ssbo{}", binding)); | ||||||
|         std::fill_n(ssbos.data() + binding, desc.count, id); |         std::fill_n(ssbos.data() + binding, desc.count, id); | ||||||
|         binding += desc.count; |         binding += desc.count; | ||||||
|  |  | ||||||
|  | @ -2,8 +2,11 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <numeric> | #include <span> | ||||||
|  | #include <tuple> | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
|  | #include <utility> | ||||||
|  | #include <vector> | ||||||
| 
 | 
 | ||||||
| #include "shader_recompiler/backend/spirv/emit_spirv.h" | #include "shader_recompiler/backend/spirv/emit_spirv.h" | ||||||
| #include "shader_recompiler/frontend/ir/basic_block.h" | #include "shader_recompiler/frontend/ir/basic_block.h" | ||||||
|  | @ -14,10 +17,10 @@ | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| namespace { | namespace { | ||||||
| template <class Func> | template <class Func> | ||||||
| struct FuncTraits : FuncTraits<decltype(&Func::operator())> {}; | struct FuncTraits : FuncTraits<Func> {}; | ||||||
| 
 | 
 | ||||||
| template <class ClassType, class ReturnType_, class... Args> | template <class ReturnType_, class... Args> | ||||||
| struct FuncTraits<ReturnType_ (ClassType::*)(Args...)> { | struct FuncTraits<ReturnType_ (*)(Args...)> { | ||||||
|     using ReturnType = ReturnType_; |     using ReturnType = ReturnType_; | ||||||
| 
 | 
 | ||||||
|     static constexpr size_t NUM_ARGS = sizeof...(Args); |     static constexpr size_t NUM_ARGS = sizeof...(Args); | ||||||
|  | @ -26,15 +29,15 @@ struct FuncTraits<ReturnType_ (ClassType::*)(Args...)> { | ||||||
|     using ArgType = std::tuple_element_t<I, std::tuple<Args...>>; |     using ArgType = std::tuple_element_t<I, std::tuple<Args...>>; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <auto method, typename... Args> | template <auto func, typename... Args> | ||||||
| void SetDefinition(EmitSPIRV& emit, EmitContext& ctx, IR::Inst* inst, Args... args) { | void SetDefinition(EmitContext& ctx, IR::Inst* inst, Args... args) { | ||||||
|     const Id forward_id{inst->Definition<Id>()}; |     const Id forward_id{inst->Definition<Id>()}; | ||||||
|     const bool has_forward_id{Sirit::ValidId(forward_id)}; |     const bool has_forward_id{Sirit::ValidId(forward_id)}; | ||||||
|     Id current_id{}; |     Id current_id{}; | ||||||
|     if (has_forward_id) { |     if (has_forward_id) { | ||||||
|         current_id = ctx.ExchangeCurrentId(forward_id); |         current_id = ctx.ExchangeCurrentId(forward_id); | ||||||
|     } |     } | ||||||
|     const Id new_id{(emit.*method)(ctx, std::forward<Args>(args)...)}; |     const Id new_id{func(ctx, std::forward<Args>(args)...)}; | ||||||
|     if (has_forward_id) { |     if (has_forward_id) { | ||||||
|         ctx.ExchangeCurrentId(current_id); |         ctx.ExchangeCurrentId(current_id); | ||||||
|     } else { |     } else { | ||||||
|  | @ -55,42 +58,62 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <auto method, bool is_first_arg_inst, size_t... I> | template <auto func, bool is_first_arg_inst, size_t... I> | ||||||
| void Invoke(EmitSPIRV& emit, EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) { | void Invoke(EmitContext& ctx, IR::Inst* inst, std::index_sequence<I...>) { | ||||||
|     using Traits = FuncTraits<decltype(method)>; |     using Traits = FuncTraits<decltype(func)>; | ||||||
|     if constexpr (std::is_same_v<Traits::ReturnType, Id>) { |     if constexpr (std::is_same_v<Traits::ReturnType, Id>) { | ||||||
|         if constexpr (is_first_arg_inst) { |         if constexpr (is_first_arg_inst) { | ||||||
|             SetDefinition<method>(emit, ctx, inst, inst, |             SetDefinition<func>(ctx, inst, inst, Arg<Traits::ArgType<I + 2>>(ctx, inst->Arg(I))...); | ||||||
|                                   Arg<Traits::ArgType<I + 2>>(ctx, inst->Arg(I))...); |  | ||||||
|         } else { |         } else { | ||||||
|             SetDefinition<method>(emit, ctx, inst, |             SetDefinition<func>(ctx, inst, Arg<Traits::ArgType<I + 1>>(ctx, inst->Arg(I))...); | ||||||
|                                   Arg<Traits::ArgType<I + 1>>(ctx, inst->Arg(I))...); |  | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         if constexpr (is_first_arg_inst) { |         if constexpr (is_first_arg_inst) { | ||||||
|             (emit.*method)(ctx, inst, Arg<Traits::ArgType<I + 2>>(ctx, inst->Arg(I))...); |             func(ctx, inst, Arg<Traits::ArgType<I + 2>>(ctx, inst->Arg(I))...); | ||||||
|         } else { |         } else { | ||||||
|             (emit.*method)(ctx, Arg<Traits::ArgType<I + 1>>(ctx, inst->Arg(I))...); |             func(ctx, Arg<Traits::ArgType<I + 1>>(ctx, inst->Arg(I))...); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <auto method> | template <auto func> | ||||||
| void Invoke(EmitSPIRV& emit, EmitContext& ctx, IR::Inst* inst) { | void Invoke(EmitContext& ctx, IR::Inst* inst) { | ||||||
|     using Traits = FuncTraits<decltype(method)>; |     using Traits = FuncTraits<decltype(func)>; | ||||||
|     static_assert(Traits::NUM_ARGS >= 1, "Insufficient arguments"); |     static_assert(Traits::NUM_ARGS >= 1, "Insufficient arguments"); | ||||||
|     if constexpr (Traits::NUM_ARGS == 1) { |     if constexpr (Traits::NUM_ARGS == 1) { | ||||||
|         Invoke<method, false>(emit, ctx, inst, std::make_index_sequence<0>{}); |         Invoke<func, false>(ctx, inst, std::make_index_sequence<0>{}); | ||||||
|     } else { |     } else { | ||||||
|         using FirstArgType = typename Traits::template ArgType<1>; |         using FirstArgType = typename Traits::template ArgType<1>; | ||||||
|         static constexpr bool is_first_arg_inst = std::is_same_v<FirstArgType, IR::Inst*>; |         static constexpr bool is_first_arg_inst = std::is_same_v<FirstArgType, IR::Inst*>; | ||||||
|         using Indices = std::make_index_sequence<Traits::NUM_ARGS - (is_first_arg_inst ? 2 : 1)>; |         using Indices = std::make_index_sequence<Traits::NUM_ARGS - (is_first_arg_inst ? 2 : 1)>; | ||||||
|         Invoke<method, is_first_arg_inst>(emit, ctx, inst, Indices{}); |         Invoke<func, is_first_arg_inst>(ctx, inst, Indices{}); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void EmitInst(EmitContext& ctx, IR::Inst* inst) { | ||||||
|  |     switch (inst->Opcode()) { | ||||||
|  | #define OPCODE(name, result_type, ...)                                                             \ | ||||||
|  |     case IR::Opcode::name:                                                                         \ | ||||||
|  |         return Invoke<&Emit##name>(ctx, inst); | ||||||
|  | #include "shader_recompiler/frontend/ir/opcodes.inc" | ||||||
|  | #undef OPCODE | ||||||
|  |     } | ||||||
|  |     throw LogicError("Invalid opcode {}", inst->Opcode()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Id TypeId(const EmitContext& ctx, IR::Type type) { | ||||||
|  |     switch (type) { | ||||||
|  |     case IR::Type::U1: | ||||||
|  |         return ctx.U1; | ||||||
|  |     case IR::Type::U32: | ||||||
|  |         return ctx.U32[1]; | ||||||
|  |     default: | ||||||
|  |         throw NotImplementedException("Phi node type {}", type); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| } // Anonymous namespace
 | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| EmitSPIRV::EmitSPIRV(IR::Program& program) { | std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program) { | ||||||
|     EmitContext ctx{program}; |     EmitContext ctx{program}; | ||||||
|     const Id void_function{ctx.TypeFunction(ctx.void_id)}; |     const Id void_function{ctx.TypeFunction(ctx.void_id)}; | ||||||
|     // FIXME: Forward declare functions (needs sirit support)
 |     // FIXME: Forward declare functions (needs sirit support)
 | ||||||
|  | @ -112,43 +135,17 @@ EmitSPIRV::EmitSPIRV(IR::Program& program) { | ||||||
|     if (program.info.uses_local_invocation_id) { |     if (program.info.uses_local_invocation_id) { | ||||||
|         interfaces.push_back(ctx.local_invocation_id); |         interfaces.push_back(ctx.local_invocation_id); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     const std::span interfaces_span(interfaces.data(), interfaces.size()); |     const std::span interfaces_span(interfaces.data(), interfaces.size()); | ||||||
|     ctx.AddEntryPoint(spv::ExecutionModel::Fragment, func, "main", interfaces_span); |     ctx.AddEntryPoint(spv::ExecutionModel::GLCompute, func, "main", interfaces_span); | ||||||
|     ctx.AddExecutionMode(func, spv::ExecutionMode::OriginUpperLeft); |  | ||||||
| 
 | 
 | ||||||
|     std::vector<u32> result{ctx.Assemble()}; |     const std::array<u32, 3> workgroup_size{env.WorkgroupSize()}; | ||||||
|     std::FILE* file{std::fopen("D:\\shader.spv", "wb")}; |     ctx.AddExecutionMode(func, spv::ExecutionMode::LocalSize, workgroup_size[0], workgroup_size[1], | ||||||
|     std::fwrite(result.data(), sizeof(u32), result.size(), file); |                          workgroup_size[2]); | ||||||
|     std::fclose(file); | 
 | ||||||
|     std::system("spirv-dis D:\\shader.spv") == 0 && |     return ctx.Assemble(); | ||||||
|         std::system("spirv-val --uniform-buffer-standard-layout D:\\shader.spv") == 0 && |  | ||||||
|         std::system("spirv-cross -V D:\\shader.spv") == 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitInst(EmitContext& ctx, IR::Inst* inst) { | Id EmitPhi(EmitContext& ctx, IR::Inst* inst) { | ||||||
|     switch (inst->Opcode()) { |  | ||||||
| #define OPCODE(name, result_type, ...)                                                             \ |  | ||||||
|     case IR::Opcode::name:                                                                         \ |  | ||||||
|         return Invoke<&EmitSPIRV::Emit##name>(*this, ctx, inst); |  | ||||||
| #include "shader_recompiler/frontend/ir/opcodes.inc" |  | ||||||
| #undef OPCODE |  | ||||||
|     } |  | ||||||
|     throw LogicError("Invalid opcode {}", inst->Opcode()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static Id TypeId(const EmitContext& ctx, IR::Type type) { |  | ||||||
|     switch (type) { |  | ||||||
|     case IR::Type::U1: |  | ||||||
|         return ctx.U1; |  | ||||||
|     case IR::Type::U32: |  | ||||||
|         return ctx.U32[1]; |  | ||||||
|     default: |  | ||||||
|         throw NotImplementedException("Phi node type {}", type); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Id EmitSPIRV::EmitPhi(EmitContext& ctx, IR::Inst* inst) { |  | ||||||
|     const size_t num_args{inst->NumArgs()}; |     const size_t num_args{inst->NumArgs()}; | ||||||
|     boost::container::small_vector<Id, 32> operands; |     boost::container::small_vector<Id, 32> operands; | ||||||
|     operands.reserve(num_args * 2); |     operands.reserve(num_args * 2); | ||||||
|  | @ -178,25 +175,25 @@ Id EmitSPIRV::EmitPhi(EmitContext& ctx, IR::Inst* inst) { | ||||||
|     return ctx.OpPhi(result_type, std::span(operands.data(), operands.size())); |     return ctx.OpPhi(result_type, std::span(operands.data(), operands.size())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitVoid(EmitContext&) {} | void EmitVoid(EmitContext&) {} | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitIdentity(EmitContext& ctx, const IR::Value& value) { | Id EmitIdentity(EmitContext& ctx, const IR::Value& value) { | ||||||
|     return ctx.Def(value); |     return ctx.Def(value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetZeroFromOp(EmitContext&) { | void EmitGetZeroFromOp(EmitContext&) { | ||||||
|     throw LogicError("Unreachable instruction"); |     throw LogicError("Unreachable instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetSignFromOp(EmitContext&) { | void EmitGetSignFromOp(EmitContext&) { | ||||||
|     throw LogicError("Unreachable instruction"); |     throw LogicError("Unreachable instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetCarryFromOp(EmitContext&) { | void EmitGetCarryFromOp(EmitContext&) { | ||||||
|     throw LogicError("Unreachable instruction"); |     throw LogicError("Unreachable instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetOverflowFromOp(EmitContext&) { | void EmitGetOverflowFromOp(EmitContext&) { | ||||||
|     throw LogicError("Unreachable instruction"); |     throw LogicError("Unreachable instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,223 +8,218 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/backend/spirv/emit_context.h" | #include "shader_recompiler/backend/spirv/emit_context.h" | ||||||
|  | #include "shader_recompiler/environment.h" | ||||||
| #include "shader_recompiler/frontend/ir/microinstruction.h" | #include "shader_recompiler/frontend/ir/microinstruction.h" | ||||||
| #include "shader_recompiler/frontend/ir/program.h" | #include "shader_recompiler/frontend/ir/program.h" | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| class EmitSPIRV { | [[nodiscard]] std::vector<u32> EmitSPIRV(Environment& env, IR::Program& program); | ||||||
| public: |  | ||||||
|     explicit EmitSPIRV(IR::Program& program); |  | ||||||
| 
 | 
 | ||||||
| private: | // Microinstruction emitters
 | ||||||
|     void EmitInst(EmitContext& ctx, IR::Inst* inst); | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); | ||||||
| 
 | void EmitVoid(EmitContext& ctx); | ||||||
|     // Microinstruction emitters
 | Id EmitIdentity(EmitContext& ctx, const IR::Value& value); | ||||||
|     Id EmitPhi(EmitContext& ctx, IR::Inst* inst); | void EmitBranch(EmitContext& ctx, IR::Block* label); | ||||||
|     void EmitVoid(EmitContext& ctx); | void EmitBranchConditional(EmitContext& ctx, Id condition, IR::Block* true_label, | ||||||
|     Id EmitIdentity(EmitContext& ctx, const IR::Value& value); |                            IR::Block* false_label); | ||||||
|     void EmitBranch(EmitContext& ctx, IR::Block* label); | void EmitLoopMerge(EmitContext& ctx, IR::Block* merge_label, IR::Block* continue_label); | ||||||
|     void EmitBranchConditional(EmitContext& ctx, Id condition, IR::Block* true_label, | void EmitSelectionMerge(EmitContext& ctx, IR::Block* merge_label); | ||||||
|                                IR::Block* false_label); | void EmitReturn(EmitContext& ctx); | ||||||
|     void EmitLoopMerge(EmitContext& ctx, IR::Block* merge_label, IR::Block* continue_label); | void EmitGetRegister(EmitContext& ctx); | ||||||
|     void EmitSelectionMerge(EmitContext& ctx, IR::Block* merge_label); | void EmitSetRegister(EmitContext& ctx); | ||||||
|     void EmitReturn(EmitContext& ctx); | void EmitGetPred(EmitContext& ctx); | ||||||
|     void EmitGetRegister(EmitContext& ctx); | void EmitSetPred(EmitContext& ctx); | ||||||
|     void EmitSetRegister(EmitContext& ctx); | void EmitSetGotoVariable(EmitContext& ctx); | ||||||
|     void EmitGetPred(EmitContext& ctx); | void EmitGetGotoVariable(EmitContext& ctx); | ||||||
|     void EmitSetPred(EmitContext& ctx); | Id EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | ||||||
|     void EmitSetGotoVariable(EmitContext& ctx); | void EmitGetAttribute(EmitContext& ctx); | ||||||
|     void EmitGetGotoVariable(EmitContext& ctx); | void EmitSetAttribute(EmitContext& ctx); | ||||||
|     Id EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | void EmitGetAttributeIndexed(EmitContext& ctx); | ||||||
|     void EmitGetAttribute(EmitContext& ctx); | void EmitSetAttributeIndexed(EmitContext& ctx); | ||||||
|     void EmitSetAttribute(EmitContext& ctx); | void EmitGetZFlag(EmitContext& ctx); | ||||||
|     void EmitGetAttributeIndexed(EmitContext& ctx); | void EmitGetSFlag(EmitContext& ctx); | ||||||
|     void EmitSetAttributeIndexed(EmitContext& ctx); | void EmitGetCFlag(EmitContext& ctx); | ||||||
|     void EmitGetZFlag(EmitContext& ctx); | void EmitGetOFlag(EmitContext& ctx); | ||||||
|     void EmitGetSFlag(EmitContext& ctx); | void EmitSetZFlag(EmitContext& ctx); | ||||||
|     void EmitGetCFlag(EmitContext& ctx); | void EmitSetSFlag(EmitContext& ctx); | ||||||
|     void EmitGetOFlag(EmitContext& ctx); | void EmitSetCFlag(EmitContext& ctx); | ||||||
|     void EmitSetZFlag(EmitContext& ctx); | void EmitSetOFlag(EmitContext& ctx); | ||||||
|     void EmitSetSFlag(EmitContext& ctx); | Id EmitWorkgroupId(EmitContext& ctx); | ||||||
|     void EmitSetCFlag(EmitContext& ctx); | Id EmitLocalInvocationId(EmitContext& ctx); | ||||||
|     void EmitSetOFlag(EmitContext& ctx); | Id EmitUndefU1(EmitContext& ctx); | ||||||
|     Id EmitWorkgroupId(EmitContext& ctx); | Id EmitUndefU8(EmitContext& ctx); | ||||||
|     Id EmitLocalInvocationId(EmitContext& ctx); | Id EmitUndefU16(EmitContext& ctx); | ||||||
|     Id EmitUndefU1(EmitContext& ctx); | Id EmitUndefU32(EmitContext& ctx); | ||||||
|     Id EmitUndefU8(EmitContext& ctx); | Id EmitUndefU64(EmitContext& ctx); | ||||||
|     Id EmitUndefU16(EmitContext& ctx); | void EmitLoadGlobalU8(EmitContext& ctx); | ||||||
|     Id EmitUndefU32(EmitContext& ctx); | void EmitLoadGlobalS8(EmitContext& ctx); | ||||||
|     Id EmitUndefU64(EmitContext& ctx); | void EmitLoadGlobalU16(EmitContext& ctx); | ||||||
|     void EmitLoadGlobalU8(EmitContext& ctx); | void EmitLoadGlobalS16(EmitContext& ctx); | ||||||
|     void EmitLoadGlobalS8(EmitContext& ctx); | void EmitLoadGlobal32(EmitContext& ctx); | ||||||
|     void EmitLoadGlobalU16(EmitContext& ctx); | void EmitLoadGlobal64(EmitContext& ctx); | ||||||
|     void EmitLoadGlobalS16(EmitContext& ctx); | void EmitLoadGlobal128(EmitContext& ctx); | ||||||
|     void EmitLoadGlobal32(EmitContext& ctx); | void EmitWriteGlobalU8(EmitContext& ctx); | ||||||
|     void EmitLoadGlobal64(EmitContext& ctx); | void EmitWriteGlobalS8(EmitContext& ctx); | ||||||
|     void EmitLoadGlobal128(EmitContext& ctx); | void EmitWriteGlobalU16(EmitContext& ctx); | ||||||
|     void EmitWriteGlobalU8(EmitContext& ctx); | void EmitWriteGlobalS16(EmitContext& ctx); | ||||||
|     void EmitWriteGlobalS8(EmitContext& ctx); | void EmitWriteGlobal32(EmitContext& ctx); | ||||||
|     void EmitWriteGlobalU16(EmitContext& ctx); | void EmitWriteGlobal64(EmitContext& ctx); | ||||||
|     void EmitWriteGlobalS16(EmitContext& ctx); | void EmitWriteGlobal128(EmitContext& ctx); | ||||||
|     void EmitWriteGlobal32(EmitContext& ctx); | void EmitLoadStorageU8(EmitContext& ctx); | ||||||
|     void EmitWriteGlobal64(EmitContext& ctx); | void EmitLoadStorageS8(EmitContext& ctx); | ||||||
|     void EmitWriteGlobal128(EmitContext& ctx); | void EmitLoadStorageU16(EmitContext& ctx); | ||||||
|     void EmitLoadStorageU8(EmitContext& ctx); | void EmitLoadStorageS16(EmitContext& ctx); | ||||||
|     void EmitLoadStorageS8(EmitContext& ctx); | Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | ||||||
|     void EmitLoadStorageU16(EmitContext& ctx); | void EmitLoadStorage64(EmitContext& ctx); | ||||||
|     void EmitLoadStorageS16(EmitContext& ctx); | void EmitLoadStorage128(EmitContext& ctx); | ||||||
|     Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); | void EmitWriteStorageU8(EmitContext& ctx); | ||||||
|     void EmitLoadStorage64(EmitContext& ctx); | void EmitWriteStorageS8(EmitContext& ctx); | ||||||
|     void EmitLoadStorage128(EmitContext& ctx); | void EmitWriteStorageU16(EmitContext& ctx); | ||||||
|     void EmitWriteStorageU8(EmitContext& ctx); | void EmitWriteStorageS16(EmitContext& ctx); | ||||||
|     void EmitWriteStorageS8(EmitContext& ctx); | void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, | ||||||
|     void EmitWriteStorageU16(EmitContext& ctx); |                         Id value); | ||||||
|     void EmitWriteStorageS16(EmitContext& ctx); | void EmitWriteStorage64(EmitContext& ctx); | ||||||
|     void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, | void EmitWriteStorage128(EmitContext& ctx); | ||||||
|                             Id value); | void EmitCompositeConstructU32x2(EmitContext& ctx); | ||||||
|     void EmitWriteStorage64(EmitContext& ctx); | void EmitCompositeConstructU32x3(EmitContext& ctx); | ||||||
|     void EmitWriteStorage128(EmitContext& ctx); | void EmitCompositeConstructU32x4(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructU32x2(EmitContext& ctx); | void EmitCompositeExtractU32x2(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructU32x3(EmitContext& ctx); | Id EmitCompositeExtractU32x3(EmitContext& ctx, Id vector, u32 index); | ||||||
|     void EmitCompositeConstructU32x4(EmitContext& ctx); | void EmitCompositeExtractU32x4(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractU32x2(EmitContext& ctx); | void EmitCompositeConstructF16x2(EmitContext& ctx); | ||||||
|     Id EmitCompositeExtractU32x3(EmitContext& ctx, Id vector, u32 index); | void EmitCompositeConstructF16x3(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractU32x4(EmitContext& ctx); | void EmitCompositeConstructF16x4(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF16x2(EmitContext& ctx); | void EmitCompositeExtractF16x2(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF16x3(EmitContext& ctx); | void EmitCompositeExtractF16x3(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF16x4(EmitContext& ctx); | void EmitCompositeExtractF16x4(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF16x2(EmitContext& ctx); | void EmitCompositeConstructF32x2(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF16x3(EmitContext& ctx); | void EmitCompositeConstructF32x3(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF16x4(EmitContext& ctx); | void EmitCompositeConstructF32x4(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF32x2(EmitContext& ctx); | void EmitCompositeExtractF32x2(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF32x3(EmitContext& ctx); | void EmitCompositeExtractF32x3(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF32x4(EmitContext& ctx); | void EmitCompositeExtractF32x4(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF32x2(EmitContext& ctx); | void EmitCompositeConstructF64x2(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF32x3(EmitContext& ctx); | void EmitCompositeConstructF64x3(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF32x4(EmitContext& ctx); | void EmitCompositeConstructF64x4(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF64x2(EmitContext& ctx); | void EmitCompositeExtractF64x2(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF64x3(EmitContext& ctx); | void EmitCompositeExtractF64x3(EmitContext& ctx); | ||||||
|     void EmitCompositeConstructF64x4(EmitContext& ctx); | void EmitCompositeExtractF64x4(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF64x2(EmitContext& ctx); | void EmitSelect8(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF64x3(EmitContext& ctx); | void EmitSelect16(EmitContext& ctx); | ||||||
|     void EmitCompositeExtractF64x4(EmitContext& ctx); | void EmitSelect32(EmitContext& ctx); | ||||||
|     void EmitSelect8(EmitContext& ctx); | void EmitSelect64(EmitContext& ctx); | ||||||
|     void EmitSelect16(EmitContext& ctx); | void EmitBitCastU16F16(EmitContext& ctx); | ||||||
|     void EmitSelect32(EmitContext& ctx); | Id EmitBitCastU32F32(EmitContext& ctx, Id value); | ||||||
|     void EmitSelect64(EmitContext& ctx); | void EmitBitCastU64F64(EmitContext& ctx); | ||||||
|     void EmitBitCastU16F16(EmitContext& ctx); | void EmitBitCastF16U16(EmitContext& ctx); | ||||||
|     Id EmitBitCastU32F32(EmitContext& ctx, Id value); | Id EmitBitCastF32U32(EmitContext& ctx, Id value); | ||||||
|     void EmitBitCastU64F64(EmitContext& ctx); | void EmitBitCastF64U64(EmitContext& ctx); | ||||||
|     void EmitBitCastF16U16(EmitContext& ctx); | void EmitPackUint2x32(EmitContext& ctx); | ||||||
|     Id EmitBitCastF32U32(EmitContext& ctx, Id value); | void EmitUnpackUint2x32(EmitContext& ctx); | ||||||
|     void EmitBitCastF64U64(EmitContext& ctx); | void EmitPackFloat2x16(EmitContext& ctx); | ||||||
|     void EmitPackUint2x32(EmitContext& ctx); | void EmitUnpackFloat2x16(EmitContext& ctx); | ||||||
|     void EmitUnpackUint2x32(EmitContext& ctx); | void EmitPackDouble2x32(EmitContext& ctx); | ||||||
|     void EmitPackFloat2x16(EmitContext& ctx); | void EmitUnpackDouble2x32(EmitContext& ctx); | ||||||
|     void EmitUnpackFloat2x16(EmitContext& ctx); | void EmitGetZeroFromOp(EmitContext& ctx); | ||||||
|     void EmitPackDouble2x32(EmitContext& ctx); | void EmitGetSignFromOp(EmitContext& ctx); | ||||||
|     void EmitUnpackDouble2x32(EmitContext& ctx); | void EmitGetCarryFromOp(EmitContext& ctx); | ||||||
|     void EmitGetZeroFromOp(EmitContext& ctx); | void EmitGetOverflowFromOp(EmitContext& ctx); | ||||||
|     void EmitGetSignFromOp(EmitContext& ctx); | void EmitFPAbs16(EmitContext& ctx); | ||||||
|     void EmitGetCarryFromOp(EmitContext& ctx); | void EmitFPAbs32(EmitContext& ctx); | ||||||
|     void EmitGetOverflowFromOp(EmitContext& ctx); | void EmitFPAbs64(EmitContext& ctx); | ||||||
|     void EmitFPAbs16(EmitContext& ctx); | Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     void EmitFPAbs32(EmitContext& ctx); | Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     void EmitFPAbs64(EmitContext& ctx); | Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); | ||||||
|     Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); | ||||||
|     Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); | ||||||
|     Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); | void EmitFPMax32(EmitContext& ctx); | ||||||
|     Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); | void EmitFPMax64(EmitContext& ctx); | ||||||
|     Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); | void EmitFPMin32(EmitContext& ctx); | ||||||
|     void EmitFPMax32(EmitContext& ctx); | void EmitFPMin64(EmitContext& ctx); | ||||||
|     void EmitFPMax64(EmitContext& ctx); | Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     void EmitFPMin32(EmitContext& ctx); | Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     void EmitFPMin64(EmitContext& ctx); | Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | void EmitFPNeg16(EmitContext& ctx); | ||||||
|     Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | void EmitFPNeg32(EmitContext& ctx); | ||||||
|     Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | void EmitFPNeg64(EmitContext& ctx); | ||||||
|     void EmitFPNeg16(EmitContext& ctx); | void EmitFPRecip32(EmitContext& ctx); | ||||||
|     void EmitFPNeg32(EmitContext& ctx); | void EmitFPRecip64(EmitContext& ctx); | ||||||
|     void EmitFPNeg64(EmitContext& ctx); | void EmitFPRecipSqrt32(EmitContext& ctx); | ||||||
|     void EmitFPRecip32(EmitContext& ctx); | void EmitFPRecipSqrt64(EmitContext& ctx); | ||||||
|     void EmitFPRecip64(EmitContext& ctx); | void EmitFPSqrt(EmitContext& ctx); | ||||||
|     void EmitFPRecipSqrt32(EmitContext& ctx); | void EmitFPSin(EmitContext& ctx); | ||||||
|     void EmitFPRecipSqrt64(EmitContext& ctx); | void EmitFPSinNotReduced(EmitContext& ctx); | ||||||
|     void EmitFPSqrt(EmitContext& ctx); | void EmitFPExp2(EmitContext& ctx); | ||||||
|     void EmitFPSin(EmitContext& ctx); | void EmitFPExp2NotReduced(EmitContext& ctx); | ||||||
|     void EmitFPSinNotReduced(EmitContext& ctx); | void EmitFPCos(EmitContext& ctx); | ||||||
|     void EmitFPExp2(EmitContext& ctx); | void EmitFPCosNotReduced(EmitContext& ctx); | ||||||
|     void EmitFPExp2NotReduced(EmitContext& ctx); | void EmitFPLog2(EmitContext& ctx); | ||||||
|     void EmitFPCos(EmitContext& ctx); | void EmitFPSaturate16(EmitContext& ctx); | ||||||
|     void EmitFPCosNotReduced(EmitContext& ctx); | void EmitFPSaturate32(EmitContext& ctx); | ||||||
|     void EmitFPLog2(EmitContext& ctx); | void EmitFPSaturate64(EmitContext& ctx); | ||||||
|     void EmitFPSaturate16(EmitContext& ctx); | void EmitFPRoundEven16(EmitContext& ctx); | ||||||
|     void EmitFPSaturate32(EmitContext& ctx); | void EmitFPRoundEven32(EmitContext& ctx); | ||||||
|     void EmitFPSaturate64(EmitContext& ctx); | void EmitFPRoundEven64(EmitContext& ctx); | ||||||
|     void EmitFPRoundEven16(EmitContext& ctx); | void EmitFPFloor16(EmitContext& ctx); | ||||||
|     void EmitFPRoundEven32(EmitContext& ctx); | void EmitFPFloor32(EmitContext& ctx); | ||||||
|     void EmitFPRoundEven64(EmitContext& ctx); | void EmitFPFloor64(EmitContext& ctx); | ||||||
|     void EmitFPFloor16(EmitContext& ctx); | void EmitFPCeil16(EmitContext& ctx); | ||||||
|     void EmitFPFloor32(EmitContext& ctx); | void EmitFPCeil32(EmitContext& ctx); | ||||||
|     void EmitFPFloor64(EmitContext& ctx); | void EmitFPCeil64(EmitContext& ctx); | ||||||
|     void EmitFPCeil16(EmitContext& ctx); | void EmitFPTrunc16(EmitContext& ctx); | ||||||
|     void EmitFPCeil32(EmitContext& ctx); | void EmitFPTrunc32(EmitContext& ctx); | ||||||
|     void EmitFPCeil64(EmitContext& ctx); | void EmitFPTrunc64(EmitContext& ctx); | ||||||
|     void EmitFPTrunc16(EmitContext& ctx); | Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | ||||||
|     void EmitFPTrunc32(EmitContext& ctx); | void EmitIAdd64(EmitContext& ctx); | ||||||
|     void EmitFPTrunc64(EmitContext& ctx); | Id EmitISub32(EmitContext& ctx, Id a, Id b); | ||||||
|     Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); | void EmitISub64(EmitContext& ctx); | ||||||
|     void EmitIAdd64(EmitContext& ctx); | Id EmitIMul32(EmitContext& ctx, Id a, Id b); | ||||||
|     Id EmitISub32(EmitContext& ctx, Id a, Id b); | void EmitINeg32(EmitContext& ctx); | ||||||
|     void EmitISub64(EmitContext& ctx); | void EmitIAbs32(EmitContext& ctx); | ||||||
|     Id EmitIMul32(EmitContext& ctx, Id a, Id b); | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); | ||||||
|     void EmitINeg32(EmitContext& ctx); | void EmitShiftRightLogical32(EmitContext& ctx); | ||||||
|     void EmitIAbs32(EmitContext& ctx); | void EmitShiftRightArithmetic32(EmitContext& ctx); | ||||||
|     Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift); | void EmitBitwiseAnd32(EmitContext& ctx); | ||||||
|     void EmitShiftRightLogical32(EmitContext& ctx); | void EmitBitwiseOr32(EmitContext& ctx); | ||||||
|     void EmitShiftRightArithmetic32(EmitContext& ctx); | void EmitBitwiseXor32(EmitContext& ctx); | ||||||
|     void EmitBitwiseAnd32(EmitContext& ctx); | void EmitBitFieldInsert(EmitContext& ctx); | ||||||
|     void EmitBitwiseOr32(EmitContext& ctx); | void EmitBitFieldSExtract(EmitContext& ctx); | ||||||
|     void EmitBitwiseXor32(EmitContext& ctx); | Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); | ||||||
|     void EmitBitFieldInsert(EmitContext& ctx); | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); | ||||||
|     void EmitBitFieldSExtract(EmitContext& ctx); | void EmitULessThan(EmitContext& ctx); | ||||||
|     Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count); | void EmitIEqual(EmitContext& ctx); | ||||||
|     Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs); | void EmitSLessThanEqual(EmitContext& ctx); | ||||||
|     void EmitULessThan(EmitContext& ctx); | void EmitULessThanEqual(EmitContext& ctx); | ||||||
|     void EmitIEqual(EmitContext& ctx); | Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); | ||||||
|     void EmitSLessThanEqual(EmitContext& ctx); | void EmitUGreaterThan(EmitContext& ctx); | ||||||
|     void EmitULessThanEqual(EmitContext& ctx); | void EmitINotEqual(EmitContext& ctx); | ||||||
|     Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs); | void EmitSGreaterThanEqual(EmitContext& ctx); | ||||||
|     void EmitUGreaterThan(EmitContext& ctx); | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | ||||||
|     void EmitINotEqual(EmitContext& ctx); | void EmitLogicalOr(EmitContext& ctx); | ||||||
|     void EmitSGreaterThanEqual(EmitContext& ctx); | void EmitLogicalAnd(EmitContext& ctx); | ||||||
|     Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | void EmitLogicalXor(EmitContext& ctx); | ||||||
|     void EmitLogicalOr(EmitContext& ctx); | void EmitLogicalNot(EmitContext& ctx); | ||||||
|     void EmitLogicalAnd(EmitContext& ctx); | void EmitConvertS16F16(EmitContext& ctx); | ||||||
|     void EmitLogicalXor(EmitContext& ctx); | void EmitConvertS16F32(EmitContext& ctx); | ||||||
|     void EmitLogicalNot(EmitContext& ctx); | void EmitConvertS16F64(EmitContext& ctx); | ||||||
|     void EmitConvertS16F16(EmitContext& ctx); | void EmitConvertS32F16(EmitContext& ctx); | ||||||
|     void EmitConvertS16F32(EmitContext& ctx); | void EmitConvertS32F32(EmitContext& ctx); | ||||||
|     void EmitConvertS16F64(EmitContext& ctx); | void EmitConvertS32F64(EmitContext& ctx); | ||||||
|     void EmitConvertS32F16(EmitContext& ctx); | void EmitConvertS64F16(EmitContext& ctx); | ||||||
|     void EmitConvertS32F32(EmitContext& ctx); | void EmitConvertS64F32(EmitContext& ctx); | ||||||
|     void EmitConvertS32F64(EmitContext& ctx); | void EmitConvertS64F64(EmitContext& ctx); | ||||||
|     void EmitConvertS64F16(EmitContext& ctx); | void EmitConvertU16F16(EmitContext& ctx); | ||||||
|     void EmitConvertS64F32(EmitContext& ctx); | void EmitConvertU16F32(EmitContext& ctx); | ||||||
|     void EmitConvertS64F64(EmitContext& ctx); | void EmitConvertU16F64(EmitContext& ctx); | ||||||
|     void EmitConvertU16F16(EmitContext& ctx); | void EmitConvertU32F16(EmitContext& ctx); | ||||||
|     void EmitConvertU16F32(EmitContext& ctx); | void EmitConvertU32F32(EmitContext& ctx); | ||||||
|     void EmitConvertU16F64(EmitContext& ctx); | void EmitConvertU32F64(EmitContext& ctx); | ||||||
|     void EmitConvertU32F16(EmitContext& ctx); | void EmitConvertU64F16(EmitContext& ctx); | ||||||
|     void EmitConvertU32F32(EmitContext& ctx); | void EmitConvertU64F32(EmitContext& ctx); | ||||||
|     void EmitConvertU32F64(EmitContext& ctx); | void EmitConvertU64F64(EmitContext& ctx); | ||||||
|     void EmitConvertU64F16(EmitContext& ctx); | void EmitConvertU64U32(EmitContext& ctx); | ||||||
|     void EmitConvertU64F32(EmitContext& ctx); | void EmitConvertU32U64(EmitContext& ctx); | ||||||
|     void EmitConvertU64F64(EmitContext& ctx); |  | ||||||
|     void EmitConvertU64U32(EmitContext& ctx); |  | ||||||
|     void EmitConvertU32U64(EmitContext& ctx); |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| } // namespace Shader::Backend::SPIRV
 | } // namespace Shader::Backend::SPIRV
 | ||||||
|  |  | ||||||
|  | @ -6,51 +6,51 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitCastU16F16(EmitContext&) { | void EmitBitCastU16F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitBitCastU32F32(EmitContext& ctx, Id value) { | Id EmitBitCastU32F32(EmitContext& ctx, Id value) { | ||||||
|     return ctx.OpBitcast(ctx.U32[1], value); |     return ctx.OpBitcast(ctx.U32[1], value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitCastU64F64(EmitContext&) { | void EmitBitCastU64F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitCastF16U16(EmitContext&) { | void EmitBitCastF16U16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitBitCastF32U32(EmitContext& ctx, Id value) { | Id EmitBitCastF32U32(EmitContext& ctx, Id value) { | ||||||
|     return ctx.OpBitcast(ctx.F32[1], value); |     return ctx.OpBitcast(ctx.F32[1], value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitCastF64U64(EmitContext&) { | void EmitBitCastF64U64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitPackUint2x32(EmitContext&) { | void EmitPackUint2x32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitUnpackUint2x32(EmitContext&) { | void EmitUnpackUint2x32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitPackFloat2x16(EmitContext&) { | void EmitPackFloat2x16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitUnpackFloat2x16(EmitContext&) { | void EmitUnpackFloat2x16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitPackDouble2x32(EmitContext&) { | void EmitPackDouble2x32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitUnpackDouble2x32(EmitContext&) { | void EmitUnpackDouble2x32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,99 +6,99 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructU32x2(EmitContext&) { | void EmitCompositeConstructU32x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructU32x3(EmitContext&) { | void EmitCompositeConstructU32x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructU32x4(EmitContext&) { | void EmitCompositeConstructU32x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractU32x2(EmitContext&) { | void EmitCompositeExtractU32x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitCompositeExtractU32x3(EmitContext& ctx, Id vector, u32 index) { | Id EmitCompositeExtractU32x3(EmitContext& ctx, Id vector, u32 index) { | ||||||
|     return ctx.OpCompositeExtract(ctx.U32[1], vector, index); |     return ctx.OpCompositeExtract(ctx.U32[1], vector, index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractU32x4(EmitContext&) { | void EmitCompositeExtractU32x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF16x2(EmitContext&) { | void EmitCompositeConstructF16x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF16x3(EmitContext&) { | void EmitCompositeConstructF16x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF16x4(EmitContext&) { | void EmitCompositeConstructF16x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF16x2(EmitContext&) { | void EmitCompositeExtractF16x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF16x3(EmitContext&) { | void EmitCompositeExtractF16x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF16x4(EmitContext&) { | void EmitCompositeExtractF16x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF32x2(EmitContext&) { | void EmitCompositeConstructF32x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF32x3(EmitContext&) { | void EmitCompositeConstructF32x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF32x4(EmitContext&) { | void EmitCompositeConstructF32x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF32x2(EmitContext&) { | void EmitCompositeExtractF32x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF32x3(EmitContext&) { | void EmitCompositeExtractF32x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF32x4(EmitContext&) { | void EmitCompositeExtractF32x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF64x2(EmitContext&) { | void EmitCompositeConstructF64x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF64x3(EmitContext&) { | void EmitCompositeConstructF64x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeConstructF64x4(EmitContext&) { | void EmitCompositeConstructF64x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF64x2(EmitContext&) { | void EmitCompositeExtractF64x2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF64x3(EmitContext&) { | void EmitCompositeExtractF64x3(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitCompositeExtractF64x4(EmitContext&) { | void EmitCompositeExtractF64x4(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,31 +6,31 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetRegister(EmitContext&) { | void EmitGetRegister(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetRegister(EmitContext&) { | void EmitSetRegister(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetPred(EmitContext&) { | void EmitGetPred(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetPred(EmitContext&) { | void EmitSetPred(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetGotoVariable(EmitContext&) { | void EmitSetGotoVariable(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetGotoVariable(EmitContext&) { | void EmitGetGotoVariable(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { | Id EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { | ||||||
|     if (!binding.IsImmediate()) { |     if (!binding.IsImmediate()) { | ||||||
|         throw NotImplementedException("Constant buffer indexing"); |         throw NotImplementedException("Constant buffer indexing"); | ||||||
|     } |     } | ||||||
|  | @ -43,59 +43,59 @@ Id EmitSPIRV::EmitGetCbuf(EmitContext& ctx, const IR::Value& binding, const IR:: | ||||||
|     return ctx.OpLoad(ctx.U32[1], access_chain); |     return ctx.OpLoad(ctx.U32[1], access_chain); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetAttribute(EmitContext&) { | void EmitGetAttribute(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetAttribute(EmitContext&) { | void EmitSetAttribute(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetAttributeIndexed(EmitContext&) { | void EmitGetAttributeIndexed(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetAttributeIndexed(EmitContext&) { | void EmitSetAttributeIndexed(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetZFlag(EmitContext&) { | void EmitGetZFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetSFlag(EmitContext&) { | void EmitGetSFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetCFlag(EmitContext&) { | void EmitGetCFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitGetOFlag(EmitContext&) { | void EmitGetOFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetZFlag(EmitContext&) { | void EmitSetZFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetSFlag(EmitContext&) { | void EmitSetSFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetCFlag(EmitContext&) { | void EmitSetCFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSetOFlag(EmitContext&) { | void EmitSetOFlag(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitWorkgroupId(EmitContext& ctx) { | Id EmitWorkgroupId(EmitContext& ctx) { | ||||||
|     return ctx.OpLoad(ctx.U32[3], ctx.workgroup_id); |     return ctx.OpLoad(ctx.U32[3], ctx.workgroup_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitLocalInvocationId(EmitContext& ctx) { | Id EmitLocalInvocationId(EmitContext& ctx) { | ||||||
|     return ctx.OpLoad(ctx.U32[3], ctx.local_invocation_id); |     return ctx.OpLoad(ctx.U32[3], ctx.local_invocation_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,25 +6,25 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBranch(EmitContext& ctx, IR::Block* label) { | void EmitBranch(EmitContext& ctx, IR::Block* label) { | ||||||
|     ctx.OpBranch(label->Definition<Id>()); |     ctx.OpBranch(label->Definition<Id>()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBranchConditional(EmitContext& ctx, Id condition, IR::Block* true_label, | void EmitBranchConditional(EmitContext& ctx, Id condition, IR::Block* true_label, | ||||||
|                                       IR::Block* false_label) { |                                       IR::Block* false_label) { | ||||||
|     ctx.OpBranchConditional(condition, true_label->Definition<Id>(), false_label->Definition<Id>()); |     ctx.OpBranchConditional(condition, true_label->Definition<Id>(), false_label->Definition<Id>()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoopMerge(EmitContext& ctx, IR::Block* merge_label, IR::Block* continue_label) { | void EmitLoopMerge(EmitContext& ctx, IR::Block* merge_label, IR::Block* continue_label) { | ||||||
|     ctx.OpLoopMerge(merge_label->Definition<Id>(), continue_label->Definition<Id>(), |     ctx.OpLoopMerge(merge_label->Definition<Id>(), continue_label->Definition<Id>(), | ||||||
|                     spv::LoopControlMask::MaskNone); |                     spv::LoopControlMask::MaskNone); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSelectionMerge(EmitContext& ctx, IR::Block* merge_label) { | void EmitSelectionMerge(EmitContext& ctx, IR::Block* merge_label) { | ||||||
|     ctx.OpSelectionMerge(merge_label->Definition<Id>(), spv::SelectionControlMask::MaskNone); |     ctx.OpSelectionMerge(merge_label->Definition<Id>(), spv::SelectionControlMask::MaskNone); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitReturn(EmitContext& ctx) { | void EmitReturn(EmitContext& ctx) { | ||||||
|     ctx.OpReturn(); |     ctx.OpReturn(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,187 +33,187 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) { | ||||||
| 
 | 
 | ||||||
| } // Anonymous namespace
 | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPAbs16(EmitContext&) { | void EmitFPAbs16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPAbs32(EmitContext&) { | void EmitFPAbs32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPAbs64(EmitContext&) { | void EmitFPAbs64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFAdd(ctx.F16[1], a, b)); |     return Decorate(ctx, inst, ctx.OpFAdd(ctx.F16[1], a, b)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFAdd(ctx.F32[1], a, b)); |     return Decorate(ctx, inst, ctx.OpFAdd(ctx.F32[1], a, b)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFAdd(ctx.F64[1], a, b)); |     return Decorate(ctx, inst, ctx.OpFAdd(ctx.F64[1], a, b)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) { | Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFma(ctx.F16[1], a, b, c)); |     return Decorate(ctx, inst, ctx.OpFma(ctx.F16[1], a, b, c)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) { | Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFma(ctx.F32[1], a, b, c)); |     return Decorate(ctx, inst, ctx.OpFma(ctx.F32[1], a, b, c)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) { | Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c)); |     return Decorate(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPMax32(EmitContext&) { | void EmitFPMax32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPMax64(EmitContext&) { | void EmitFPMax64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPMin32(EmitContext&) { | void EmitFPMin32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPMin64(EmitContext&) { | void EmitFPMin64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b)); |     return Decorate(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFMul(ctx.F32[1], a, b)); |     return Decorate(ctx, inst, ctx.OpFMul(ctx.F32[1], a, b)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b)); |     return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPNeg16(EmitContext&) { | void EmitFPNeg16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPNeg32(EmitContext&) { | void EmitFPNeg32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPNeg64(EmitContext&) { | void EmitFPNeg64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRecip32(EmitContext&) { | void EmitFPRecip32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRecip64(EmitContext&) { | void EmitFPRecip64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRecipSqrt32(EmitContext&) { | void EmitFPRecipSqrt32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRecipSqrt64(EmitContext&) { | void EmitFPRecipSqrt64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPSqrt(EmitContext&) { | void EmitFPSqrt(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPSin(EmitContext&) { | void EmitFPSin(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPSinNotReduced(EmitContext&) { | void EmitFPSinNotReduced(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPExp2(EmitContext&) { | void EmitFPExp2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPExp2NotReduced(EmitContext&) { | void EmitFPExp2NotReduced(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPCos(EmitContext&) { | void EmitFPCos(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPCosNotReduced(EmitContext&) { | void EmitFPCosNotReduced(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPLog2(EmitContext&) { | void EmitFPLog2(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPSaturate16(EmitContext&) { | void EmitFPSaturate16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPSaturate32(EmitContext&) { | void EmitFPSaturate32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPSaturate64(EmitContext&) { | void EmitFPSaturate64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRoundEven16(EmitContext&) { | void EmitFPRoundEven16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRoundEven32(EmitContext&) { | void EmitFPRoundEven32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPRoundEven64(EmitContext&) { | void EmitFPRoundEven64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPFloor16(EmitContext&) { | void EmitFPFloor16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPFloor32(EmitContext&) { | void EmitFPFloor32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPFloor64(EmitContext&) { | void EmitFPFloor64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPCeil16(EmitContext&) { | void EmitFPCeil16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPCeil32(EmitContext&) { | void EmitFPCeil32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPCeil64(EmitContext&) { | void EmitFPCeil64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPTrunc16(EmitContext&) { | void EmitFPTrunc16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPTrunc32(EmitContext&) { | void EmitFPTrunc32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitFPTrunc64(EmitContext&) { | void EmitFPTrunc64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,126 +6,126 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { | ||||||
|     if (inst->HasAssociatedPseudoOperation()) { |     if (inst->HasAssociatedPseudoOperation()) { | ||||||
|         throw NotImplementedException("Pseudo-operations on IAdd32"); |         throw NotImplementedException("Pseudo-operations on IAdd32"); | ||||||
|     } |     } | ||||||
|     return ctx.OpIAdd(ctx.U32[1], a, b); |     return ctx.OpIAdd(ctx.U32[1], a, b); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitIAdd64(EmitContext&) { | void EmitIAdd64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitISub32(EmitContext& ctx, Id a, Id b) { | Id EmitISub32(EmitContext& ctx, Id a, Id b) { | ||||||
|     return ctx.OpISub(ctx.U32[1], a, b); |     return ctx.OpISub(ctx.U32[1], a, b); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitISub64(EmitContext&) { | void EmitISub64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitIMul32(EmitContext& ctx, Id a, Id b) { | Id EmitIMul32(EmitContext& ctx, Id a, Id b) { | ||||||
|     return ctx.OpIMul(ctx.U32[1], a, b); |     return ctx.OpIMul(ctx.U32[1], a, b); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitINeg32(EmitContext&) { | void EmitINeg32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitIAbs32(EmitContext&) { | void EmitIAbs32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) { | Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) { | ||||||
|     return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); |     return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitShiftRightLogical32(EmitContext&) { | void EmitShiftRightLogical32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitShiftRightArithmetic32(EmitContext&) { | void EmitShiftRightArithmetic32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitwiseAnd32(EmitContext&) { | void EmitBitwiseAnd32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitwiseOr32(EmitContext&) { | void EmitBitwiseOr32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitwiseXor32(EmitContext&) { | void EmitBitwiseXor32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitFieldInsert(EmitContext&) { | void EmitBitFieldInsert(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitBitFieldSExtract(EmitContext&) { | void EmitBitFieldSExtract(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count) { | Id EmitBitFieldUExtract(EmitContext& ctx, Id base, Id offset, Id count) { | ||||||
|     return ctx.OpBitFieldUExtract(ctx.U32[1], base, offset, count); |     return ctx.OpBitFieldUExtract(ctx.U32[1], base, offset, count); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) { | Id EmitSLessThan(EmitContext& ctx, Id lhs, Id rhs) { | ||||||
|     return ctx.OpSLessThan(ctx.U1, lhs, rhs); |     return ctx.OpSLessThan(ctx.U1, lhs, rhs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitULessThan(EmitContext&) { | void EmitULessThan(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitIEqual(EmitContext&) { | void EmitIEqual(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSLessThanEqual(EmitContext&) { | void EmitSLessThanEqual(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitULessThanEqual(EmitContext&) { | void EmitULessThanEqual(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { | Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs) { | ||||||
|     return ctx.OpSGreaterThan(ctx.U1, lhs, rhs); |     return ctx.OpSGreaterThan(ctx.U1, lhs, rhs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitUGreaterThan(EmitContext&) { | void EmitUGreaterThan(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitINotEqual(EmitContext&) { | void EmitINotEqual(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSGreaterThanEqual(EmitContext&) { | void EmitSGreaterThanEqual(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs) { | ||||||
|     return ctx.OpUGreaterThanEqual(ctx.U1, lhs, rhs); |     return ctx.OpUGreaterThanEqual(ctx.U1, lhs, rhs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLogicalOr(EmitContext&) { | void EmitLogicalOr(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLogicalAnd(EmitContext&) { | void EmitLogicalAnd(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLogicalXor(EmitContext&) { | void EmitLogicalXor(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLogicalNot(EmitContext&) { | void EmitLogicalNot(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,83 +6,83 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS16F16(EmitContext&) { | void EmitConvertS16F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS16F32(EmitContext&) { | void EmitConvertS16F32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS16F64(EmitContext&) { | void EmitConvertS16F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS32F16(EmitContext&) { | void EmitConvertS32F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS32F32(EmitContext&) { | void EmitConvertS32F32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS32F64(EmitContext&) { | void EmitConvertS32F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS64F16(EmitContext&) { | void EmitConvertS64F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS64F32(EmitContext&) { | void EmitConvertS64F32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertS64F64(EmitContext&) { | void EmitConvertS64F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU16F16(EmitContext&) { | void EmitConvertU16F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU16F32(EmitContext&) { | void EmitConvertU16F32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU16F64(EmitContext&) { | void EmitConvertU16F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU32F16(EmitContext&) { | void EmitConvertU32F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU32F32(EmitContext&) { | void EmitConvertU32F32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU32F64(EmitContext&) { | void EmitConvertU32F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU64F16(EmitContext&) { | void EmitConvertU64F16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU64F32(EmitContext&) { | void EmitConvertU64F32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU64F64(EmitContext&) { | void EmitConvertU64F64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU64U32(EmitContext&) { | void EmitConvertU64U32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitConvertU32U64(EmitContext&) { | void EmitConvertU32U64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,79 +22,79 @@ static Id StorageIndex(EmitContext& ctx, const IR::Value& offset, size_t element | ||||||
|     return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); |     return ctx.OpShiftRightLogical(ctx.U32[1], index, shift_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobalU8(EmitContext&) { | void EmitLoadGlobalU8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobalS8(EmitContext&) { | void EmitLoadGlobalS8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobalU16(EmitContext&) { | void EmitLoadGlobalU16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobalS16(EmitContext&) { | void EmitLoadGlobalS16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobal32(EmitContext&) { | void EmitLoadGlobal32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobal64(EmitContext&) { | void EmitLoadGlobal64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadGlobal128(EmitContext&) { | void EmitLoadGlobal128(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobalU8(EmitContext&) { | void EmitWriteGlobalU8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobalS8(EmitContext&) { | void EmitWriteGlobalS8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobalU16(EmitContext&) { | void EmitWriteGlobalU16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobalS16(EmitContext&) { | void EmitWriteGlobalS16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobal32(EmitContext&) { | void EmitWriteGlobal32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobal64(EmitContext&) { | void EmitWriteGlobal64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteGlobal128(EmitContext&) { | void EmitWriteGlobal128(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadStorageU8(EmitContext&) { | void EmitLoadStorageU8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadStorageS8(EmitContext&) { | void EmitLoadStorageS8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadStorageU16(EmitContext&) { | void EmitLoadStorageU16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadStorageS16(EmitContext&) { | void EmitLoadStorageS16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, | Id EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, | ||||||
|                                 const IR::Value& offset) { |                                 const IR::Value& offset) { | ||||||
|     if (!binding.IsImmediate()) { |     if (!binding.IsImmediate()) { | ||||||
|         throw NotImplementedException("Dynamic storage buffer indexing"); |         throw NotImplementedException("Dynamic storage buffer indexing"); | ||||||
|  | @ -105,31 +105,31 @@ Id EmitSPIRV::EmitLoadStorage32(EmitContext& ctx, const IR::Value& binding, | ||||||
|     return ctx.OpLoad(ctx.U32[1], pointer); |     return ctx.OpLoad(ctx.U32[1], pointer); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadStorage64(EmitContext&) { | void EmitLoadStorage64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitLoadStorage128(EmitContext&) { | void EmitLoadStorage128(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorageU8(EmitContext&) { | void EmitWriteStorageU8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorageS8(EmitContext&) { | void EmitWriteStorageS8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorageU16(EmitContext&) { | void EmitWriteStorageU16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorageS16(EmitContext&) { | void EmitWriteStorageS16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, | void EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, | ||||||
|                                    const IR::Value& offset, Id value) { |                                    const IR::Value& offset, Id value) { | ||||||
|     if (!binding.IsImmediate()) { |     if (!binding.IsImmediate()) { | ||||||
|         throw NotImplementedException("Dynamic storage buffer indexing"); |         throw NotImplementedException("Dynamic storage buffer indexing"); | ||||||
|  | @ -140,11 +140,11 @@ void EmitSPIRV::EmitWriteStorage32(EmitContext& ctx, const IR::Value& binding, | ||||||
|     ctx.OpStore(pointer, value); |     ctx.OpStore(pointer, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorage64(EmitContext&) { | void EmitWriteStorage64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitWriteStorage128(EmitContext&) { | void EmitWriteStorage128(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,19 +6,19 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSelect8(EmitContext&) { | void EmitSelect8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSelect16(EmitContext&) { | void EmitSelect16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSelect32(EmitContext&) { | void EmitSelect32(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmitSPIRV::EmitSelect64(EmitContext&) { | void EmitSelect64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,23 +6,23 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Backend::SPIRV { | namespace Shader::Backend::SPIRV { | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitUndefU1(EmitContext& ctx) { | Id EmitUndefU1(EmitContext& ctx) { | ||||||
|     return ctx.OpUndef(ctx.U1); |     return ctx.OpUndef(ctx.U1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitUndefU8(EmitContext&) { | Id EmitUndefU8(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitUndefU16(EmitContext&) { | Id EmitUndefU16(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitUndefU32(EmitContext& ctx) { | Id EmitUndefU32(EmitContext& ctx) { | ||||||
|     return ctx.OpUndef(ctx.U32[1]); |     return ctx.OpUndef(ctx.U32[1]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Id EmitSPIRV::EmitUndefU64(EmitContext&) { | Id EmitUndefU64(EmitContext&) { | ||||||
|     throw NotImplementedException("SPIR-V Instruction"); |     throw NotImplementedException("SPIR-V Instruction"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <array> | ||||||
|  | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| 
 | 
 | ||||||
| namespace Shader { | namespace Shader { | ||||||
|  | @ -8,7 +10,9 @@ class Environment { | ||||||
| public: | public: | ||||||
|     virtual ~Environment() = default; |     virtual ~Environment() = default; | ||||||
| 
 | 
 | ||||||
|     [[nodiscard]] virtual u64 ReadInstruction(u32 address) const = 0; |     [[nodiscard]] virtual u64 ReadInstruction(u32 address) = 0; | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] virtual std::array<u32, 3> WorkgroupSize() = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Shader
 | } // namespace Shader
 | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ FileEnvironment::FileEnvironment(const char* path) { | ||||||
| 
 | 
 | ||||||
| FileEnvironment::~FileEnvironment() = default; | FileEnvironment::~FileEnvironment() = default; | ||||||
| 
 | 
 | ||||||
| u64 FileEnvironment::ReadInstruction(u32 offset) const { | u64 FileEnvironment::ReadInstruction(u32 offset) { | ||||||
|     if (offset % 8 != 0) { |     if (offset % 8 != 0) { | ||||||
|         throw InvalidArgument("offset={} is not aligned to 8", offset); |         throw InvalidArgument("offset={} is not aligned to 8", offset); | ||||||
|     } |     } | ||||||
|  | @ -39,4 +39,8 @@ u64 FileEnvironment::ReadInstruction(u32 offset) const { | ||||||
|     return data[offset / 8]; |     return data[offset / 8]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::array<u32, 3> FileEnvironment::WorkgroupSize() { | ||||||
|  |     return {1, 1, 1}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace Shader
 | } // namespace Shader
 | ||||||
|  |  | ||||||
|  | @ -12,7 +12,9 @@ public: | ||||||
|     explicit FileEnvironment(const char* path); |     explicit FileEnvironment(const char* path); | ||||||
|     ~FileEnvironment() override; |     ~FileEnvironment() override; | ||||||
| 
 | 
 | ||||||
|     u64 ReadInstruction(u32 offset) const override; |     u64 ReadInstruction(u32 offset) override; | ||||||
|  | 
 | ||||||
|  |     std::array<u32, 3> WorkgroupSize() override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     std::vector<u64> data; |     std::vector<u64> data; | ||||||
|  |  | ||||||
|  | @ -127,6 +127,8 @@ static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_ind | ||||||
|         return fmt::format("#{}", arg.U32()); |         return fmt::format("#{}", arg.U32()); | ||||||
|     case Type::U64: |     case Type::U64: | ||||||
|         return fmt::format("#{}", arg.U64()); |         return fmt::format("#{}", arg.U64()); | ||||||
|  |     case Type::F32: | ||||||
|  |         return fmt::format("#{}", arg.F32()); | ||||||
|     case Type::Reg: |     case Type::Reg: | ||||||
|         return fmt::format("{}", arg.Reg()); |         return fmt::format("{}", arg.Reg()); | ||||||
|     case Type::Pred: |     case Type::Pred: | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ BlockList PostOrder(const BlockList& blocks) { | ||||||
|         if (!visited.insert(branch).second) { |         if (!visited.insert(branch).second) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         // Calling push_back twice is faster than insert on msvc
 |         // Calling push_back twice is faster than insert on MSVC
 | ||||||
|         block_stack.push_back(block); |         block_stack.push_back(block); | ||||||
|         block_stack.push_back(branch); |         block_stack.push_back(branch); | ||||||
|         return true; |         return true; | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | ||||||
|         Optimization::VerificationPass(function); |         Optimization::VerificationPass(function); | ||||||
|     } |     } | ||||||
|     Optimization::CollectShaderInfoPass(program); |     Optimization::CollectShaderInfoPass(program); | ||||||
|     //*/
 |     fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||||||
|     return program; |     return program; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,14 @@ void TranslatorVisitor::F(IR::Reg dest_reg, const IR::F32& value) { | ||||||
|     X(dest_reg, ir.BitCast<IR::U32>(value)); |     X(dest_reg, ir.BitCast<IR::U32>(value)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | IR::U32 TranslatorVisitor::GetReg8(u64 insn) { | ||||||
|  |     union { | ||||||
|  |         u64 raw; | ||||||
|  |         BitField<8, 8, IR::Reg> index; | ||||||
|  |     } const reg{insn}; | ||||||
|  |     return X(reg.index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| IR::U32 TranslatorVisitor::GetReg20(u64 insn) { | IR::U32 TranslatorVisitor::GetReg20(u64 insn) { | ||||||
|     union { |     union { | ||||||
|         u64 raw; |         u64 raw; | ||||||
|  |  | ||||||
|  | @ -301,6 +301,7 @@ public: | ||||||
|     void X(IR::Reg dest_reg, const IR::U32& value); |     void X(IR::Reg dest_reg, const IR::U32& value); | ||||||
|     void F(IR::Reg dest_reg, const IR::F32& value); |     void F(IR::Reg dest_reg, const IR::F32& value); | ||||||
| 
 | 
 | ||||||
|  |     [[nodiscard]] IR::U32 GetReg8(u64 insn); | ||||||
|     [[nodiscard]] IR::U32 GetReg20(u64 insn); |     [[nodiscard]] IR::U32 GetReg20(u64 insn); | ||||||
|     [[nodiscard]] IR::U32 GetReg39(u64 insn); |     [[nodiscard]] IR::U32 GetReg39(u64 insn); | ||||||
|     [[nodiscard]] IR::F32 GetReg20F(u64 insn); |     [[nodiscard]] IR::F32 GetReg20F(u64 insn); | ||||||
|  |  | ||||||
|  | @ -10,36 +10,35 @@ | ||||||
| 
 | 
 | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
| namespace { | namespace { | ||||||
| union MOV { | void MOV(TranslatorVisitor& v, u64 insn, const IR::U32& src, bool is_mov32i = false) { | ||||||
|     u64 raw; |     union { | ||||||
|     BitField<0, 8, IR::Reg> dest_reg; |         u64 raw; | ||||||
|     BitField<20, 8, IR::Reg> src_reg; |         BitField<0, 8, IR::Reg> dest_reg; | ||||||
|     BitField<39, 4, u64> mask; |         BitField<39, 4, u64> mask; | ||||||
| }; |         BitField<12, 4, u64> mov32i_mask; | ||||||
|  |     } const mov{insn}; | ||||||
| 
 | 
 | ||||||
| void CheckMask(MOV mov) { |     if ((is_mov32i ? mov.mov32i_mask : mov.mask) != 0xf) { | ||||||
|     if (mov.mask != 0xf) { |  | ||||||
|         throw NotImplementedException("Non-full move mask"); |         throw NotImplementedException("Non-full move mask"); | ||||||
|     } |     } | ||||||
|  |     v.X(mov.dest_reg, src); | ||||||
| } | } | ||||||
| } // Anonymous namespace
 | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| void TranslatorVisitor::MOV_reg(u64 insn) { | void TranslatorVisitor::MOV_reg(u64 insn) { | ||||||
|     const MOV mov{insn}; |     MOV(*this, insn, GetReg8(insn)); | ||||||
|     CheckMask(mov); |  | ||||||
|     X(mov.dest_reg, X(mov.src_reg)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TranslatorVisitor::MOV_cbuf(u64 insn) { | void TranslatorVisitor::MOV_cbuf(u64 insn) { | ||||||
|     const MOV mov{insn}; |     MOV(*this, insn, GetCbuf(insn)); | ||||||
|     CheckMask(mov); |  | ||||||
|     X(mov.dest_reg, GetCbuf(insn)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TranslatorVisitor::MOV_imm(u64 insn) { | void TranslatorVisitor::MOV_imm(u64 insn) { | ||||||
|     const MOV mov{insn}; |     MOV(*this, insn, GetImm20(insn)); | ||||||
|     CheckMask(mov); | } | ||||||
|     X(mov.dest_reg, GetImm20(insn)); | 
 | ||||||
|  | void TranslatorVisitor::MOV32I(u64 insn) { | ||||||
|  |     MOV(*this, insn, GetImm32(insn), true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace Shader::Maxwell
 | } // namespace Shader::Maxwell
 | ||||||
|  |  | ||||||
|  | @ -617,10 +617,6 @@ void TranslatorVisitor::MEMBAR(u64) { | ||||||
|     ThrowNotImplemented(Opcode::MEMBAR); |     ThrowNotImplemented(Opcode::MEMBAR); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TranslatorVisitor::MOV32I(u64) { |  | ||||||
|     ThrowNotImplemented(Opcode::MOV32I); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void TranslatorVisitor::NOP(u64) { | void TranslatorVisitor::NOP(u64) { | ||||||
|     ThrowNotImplemented(Opcode::NOP); |     ThrowNotImplemented(Opcode::NOP); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -76,5 +76,5 @@ int main() { | ||||||
|     fmt::print(stdout, "{}\n", cfg.Dot()); |     fmt::print(stdout, "{}\n", cfg.Dot()); | ||||||
|     IR::Program program{TranslateProgram(inst_pool, block_pool, env, cfg)}; |     IR::Program program{TranslateProgram(inst_pool, block_pool, env, cfg)}; | ||||||
|     fmt::print(stdout, "{}\n", IR::DumpProgram(program)); |     fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||||||
|     Backend::SPIRV::EmitSPIRV spirv{program}; |     void(Backend::SPIRV::EmitSPIRV(env, program)); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								src/shader_recompiler/profile.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/shader_recompiler/profile.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | // Copyright 2021 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | namespace Shader { | ||||||
|  | 
 | ||||||
|  | struct Profile { | ||||||
|  |     bool unified_descriptor_binding; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace Shader
 | ||||||
							
								
								
									
										27
									
								
								src/shader_recompiler/recompiler.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/shader_recompiler/recompiler.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | // Copyright 2021 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "shader_recompiler/backend/spirv/emit_spirv.h" | ||||||
|  | #include "shader_recompiler/environment.h" | ||||||
|  | #include "shader_recompiler/frontend/maxwell/control_flow.h" | ||||||
|  | #include "shader_recompiler/frontend/maxwell/program.h" | ||||||
|  | #include "shader_recompiler/object_pool.h" | ||||||
|  | #include "shader_recompiler/recompiler.h" | ||||||
|  | 
 | ||||||
|  | namespace Shader { | ||||||
|  | 
 | ||||||
|  | std::pair<Info, std::vector<u32>> RecompileSPIRV(Environment& env, u32 start_address) { | ||||||
|  |     ObjectPool<Maxwell::Flow::Block> flow_block_pool; | ||||||
|  |     ObjectPool<IR::Inst> inst_pool; | ||||||
|  |     ObjectPool<IR::Block> block_pool; | ||||||
|  | 
 | ||||||
|  |     Maxwell::Flow::CFG cfg{env, flow_block_pool, start_address}; | ||||||
|  |     IR::Program program{Maxwell::TranslateProgram(inst_pool, block_pool, env, cfg)}; | ||||||
|  |     return {std::move(program.info), Backend::SPIRV::EmitSPIRV(env, program)}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Shader
 | ||||||
							
								
								
									
										18
									
								
								src/shader_recompiler/recompiler.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/shader_recompiler/recompiler.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | // Copyright 2021 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <utility> | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "shader_recompiler/environment.h" | ||||||
|  | #include "shader_recompiler/shader_info.h" | ||||||
|  | 
 | ||||||
|  | namespace Shader { | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] std::pair<Info, std::vector<u32>> RecompileSPIRV(Environment& env, u32 start_address); | ||||||
|  | 
 | ||||||
|  | } // namespace Shader
 | ||||||
|  | @ -43,9 +43,6 @@ add_library(video_core STATIC | ||||||
|     engines/maxwell_3d.h |     engines/maxwell_3d.h | ||||||
|     engines/maxwell_dma.cpp |     engines/maxwell_dma.cpp | ||||||
|     engines/maxwell_dma.h |     engines/maxwell_dma.h | ||||||
|     engines/shader_bytecode.h |  | ||||||
|     engines/shader_header.h |  | ||||||
|     engines/shader_type.h |  | ||||||
|     framebuffer_config.h |     framebuffer_config.h | ||||||
|     macro/macro.cpp |     macro/macro.cpp | ||||||
|     macro/macro.h |     macro/macro.h | ||||||
|  | @ -123,6 +120,7 @@ add_library(video_core STATIC | ||||||
|     renderer_vulkan/vk_master_semaphore.h |     renderer_vulkan/vk_master_semaphore.h | ||||||
|     renderer_vulkan/vk_pipeline_cache.cpp |     renderer_vulkan/vk_pipeline_cache.cpp | ||||||
|     renderer_vulkan/vk_pipeline_cache.h |     renderer_vulkan/vk_pipeline_cache.h | ||||||
|  |     renderer_vulkan/vk_pipeline.h | ||||||
|     renderer_vulkan/vk_query_cache.cpp |     renderer_vulkan/vk_query_cache.cpp | ||||||
|     renderer_vulkan/vk_query_cache.h |     renderer_vulkan/vk_query_cache.h | ||||||
|     renderer_vulkan/vk_rasterizer.cpp |     renderer_vulkan/vk_rasterizer.cpp | ||||||
|  | @ -201,7 +199,7 @@ add_library(video_core STATIC | ||||||
| create_target_directory_groups(video_core) | create_target_directory_groups(video_core) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(video_core PUBLIC common core) | target_link_libraries(video_core PUBLIC common core) | ||||||
| target_link_libraries(video_core PRIVATE glad xbyak) | target_link_libraries(video_core PRIVATE glad shader_recompiler xbyak) | ||||||
| 
 | 
 | ||||||
| if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) | if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) | ||||||
|     add_dependencies(video_core ffmpeg-build) |     add_dependencies(video_core ffmpeg-build) | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "video_core/engines/engine_interface.h" | #include "video_core/engines/engine_interface.h" | ||||||
| #include "video_core/engines/engine_upload.h" | #include "video_core/engines/engine_upload.h" | ||||||
| #include "video_core/engines/shader_type.h" |  | ||||||
| #include "video_core/gpu.h" | #include "video_core/gpu.h" | ||||||
| #include "video_core/textures/texture.h" | #include "video_core/textures/texture.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,158 +0,0 @@ | ||||||
| // Copyright 2018 yuzu Emulator Project
 |  | ||||||
| // Licensed under GPLv2 or any later version
 |  | ||||||
| // Refer to the license.txt file included.
 |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <array> |  | ||||||
| #include <optional> |  | ||||||
| 
 |  | ||||||
| #include "common/bit_field.h" |  | ||||||
| #include "common/common_funcs.h" |  | ||||||
| #include "common/common_types.h" |  | ||||||
| 
 |  | ||||||
| namespace Tegra::Shader { |  | ||||||
| 
 |  | ||||||
| enum class OutputTopology : u32 { |  | ||||||
|     PointList = 1, |  | ||||||
|     LineStrip = 6, |  | ||||||
|     TriangleStrip = 7, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum class PixelImap : u8 { |  | ||||||
|     Unused = 0, |  | ||||||
|     Constant = 1, |  | ||||||
|     Perspective = 2, |  | ||||||
|     ScreenLinear = 3, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Documentation in:
 |  | ||||||
| // http://download.nvidia.com/open-gpu-doc/Shader-Program-Header/1/Shader-Program-Header.html
 |  | ||||||
| struct Header { |  | ||||||
|     union { |  | ||||||
|         BitField<0, 5, u32> sph_type; |  | ||||||
|         BitField<5, 5, u32> version; |  | ||||||
|         BitField<10, 4, u32> shader_type; |  | ||||||
|         BitField<14, 1, u32> mrt_enable; |  | ||||||
|         BitField<15, 1, u32> kills_pixels; |  | ||||||
|         BitField<16, 1, u32> does_global_store; |  | ||||||
|         BitField<17, 4, u32> sass_version; |  | ||||||
|         BitField<21, 5, u32> reserved; |  | ||||||
|         BitField<26, 1, u32> does_load_or_store; |  | ||||||
|         BitField<27, 1, u32> does_fp64; |  | ||||||
|         BitField<28, 4, u32> stream_out_mask; |  | ||||||
|     } common0; |  | ||||||
| 
 |  | ||||||
|     union { |  | ||||||
|         BitField<0, 24, u32> shader_local_memory_low_size; |  | ||||||
|         BitField<24, 8, u32> per_patch_attribute_count; |  | ||||||
|     } common1; |  | ||||||
| 
 |  | ||||||
|     union { |  | ||||||
|         BitField<0, 24, u32> shader_local_memory_high_size; |  | ||||||
|         BitField<24, 8, u32> threads_per_input_primitive; |  | ||||||
|     } common2; |  | ||||||
| 
 |  | ||||||
|     union { |  | ||||||
|         BitField<0, 24, u32> shader_local_memory_crs_size; |  | ||||||
|         BitField<24, 4, OutputTopology> output_topology; |  | ||||||
|         BitField<28, 4, u32> reserved; |  | ||||||
|     } common3; |  | ||||||
| 
 |  | ||||||
|     union { |  | ||||||
|         BitField<0, 12, u32> max_output_vertices; |  | ||||||
|         BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
 |  | ||||||
|         BitField<20, 4, u32> reserved; |  | ||||||
|         BitField<24, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
 |  | ||||||
|     } common4; |  | ||||||
| 
 |  | ||||||
|     union { |  | ||||||
|         struct { |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(3);  // ImapSystemValuesA
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(1);  // ImapSystemValuesB
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(16); // ImapGenericVector[32]
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(2);  // ImapColor
 |  | ||||||
|             union { |  | ||||||
|                 BitField<0, 8, u16> clip_distances; |  | ||||||
|                 BitField<8, 1, u16> point_sprite_s; |  | ||||||
|                 BitField<9, 1, u16> point_sprite_t; |  | ||||||
|                 BitField<10, 1, u16> fog_coordinate; |  | ||||||
|                 BitField<12, 1, u16> tessellation_eval_point_u; |  | ||||||
|                 BitField<13, 1, u16> tessellation_eval_point_v; |  | ||||||
|                 BitField<14, 1, u16> instance_id; |  | ||||||
|                 BitField<15, 1, u16> vertex_id; |  | ||||||
|             }; |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(5);  // ImapFixedFncTexture[10]
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(1);  // ImapReserved
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(3);  // OmapSystemValuesA
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(1);  // OmapSystemValuesB
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(16); // OmapGenericVector[32]
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(2);  // OmapColor
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(2);  // OmapSystemValuesC
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(5);  // OmapFixedFncTexture[10]
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(1);  // OmapReserved
 |  | ||||||
|         } vtg; |  | ||||||
| 
 |  | ||||||
|         struct { |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(3); // ImapSystemValuesA
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(1); // ImapSystemValuesB
 |  | ||||||
| 
 |  | ||||||
|             union { |  | ||||||
|                 BitField<0, 2, PixelImap> x; |  | ||||||
|                 BitField<2, 2, PixelImap> y; |  | ||||||
|                 BitField<4, 2, PixelImap> z; |  | ||||||
|                 BitField<6, 2, PixelImap> w; |  | ||||||
|                 u8 raw; |  | ||||||
|             } imap_generic_vector[32]; |  | ||||||
| 
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(2);  // ImapColor
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(2);  // ImapSystemValuesC
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(10); // ImapFixedFncTexture[10]
 |  | ||||||
|             INSERT_PADDING_BYTES_NOINIT(2);  // ImapReserved
 |  | ||||||
| 
 |  | ||||||
|             struct { |  | ||||||
|                 u32 target; |  | ||||||
|                 union { |  | ||||||
|                     BitField<0, 1, u32> sample_mask; |  | ||||||
|                     BitField<1, 1, u32> depth; |  | ||||||
|                     BitField<2, 30, u32> reserved; |  | ||||||
|                 }; |  | ||||||
|             } omap; |  | ||||||
| 
 |  | ||||||
|             bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const { |  | ||||||
|                 const u32 bit = render_target * 4 + component; |  | ||||||
|                 return omap.target & (1 << bit); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             PixelImap GetPixelImap(u32 attribute) const { |  | ||||||
|                 const auto get_index = [this, attribute](u32 index) { |  | ||||||
|                     return static_cast<PixelImap>( |  | ||||||
|                         (imap_generic_vector[attribute].raw >> (index * 2)) & 3); |  | ||||||
|                 }; |  | ||||||
| 
 |  | ||||||
|                 std::optional<PixelImap> result; |  | ||||||
|                 for (u32 component = 0; component < 4; ++component) { |  | ||||||
|                     const PixelImap index = get_index(component); |  | ||||||
|                     if (index == PixelImap::Unused) { |  | ||||||
|                         continue; |  | ||||||
|                     } |  | ||||||
|                     if (result && result != index) { |  | ||||||
|                         LOG_CRITICAL(HW_GPU, "Generic attribute conflict in interpolation mode"); |  | ||||||
|                     } |  | ||||||
|                     result = index; |  | ||||||
|                 } |  | ||||||
|                 return result.value_or(PixelImap::Unused); |  | ||||||
|             } |  | ||||||
|         } ps; |  | ||||||
| 
 |  | ||||||
|         std::array<u32, 0xF> raw; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     u64 GetLocalMemorySize() const { |  | ||||||
|         return (common1.shader_local_memory_low_size | |  | ||||||
|                 (common2.shader_local_memory_high_size << 24)); |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| static_assert(sizeof(Header) == 0x50, "Incorrect structure size"); |  | ||||||
| 
 |  | ||||||
| } // namespace Tegra::Shader
 |  | ||||||
|  | @ -4,6 +4,9 @@ | ||||||
| 
 | 
 | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
|  | #include <boost/container/small_vector.hpp> | ||||||
|  | 
 | ||||||
|  | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||||||
| #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | ||||||
| #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | ||||||
| #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | ||||||
|  | @ -13,9 +16,142 @@ | ||||||
| #include "video_core/vulkan_common/vulkan_wrapper.h" | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||||||
| 
 | 
 | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
|  | namespace { | ||||||
|  | vk::DescriptorSetLayout CreateDescriptorSetLayout(const Device& device, const Shader::Info& info) { | ||||||
|  |     boost::container::small_vector<VkDescriptorSetLayoutBinding, 24> bindings; | ||||||
|  |     u32 binding{}; | ||||||
|  |     for ([[maybe_unused]] const auto& desc : info.constant_buffer_descriptors) { | ||||||
|  |         bindings.push_back({ | ||||||
|  |             .binding = binding, | ||||||
|  |             .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | ||||||
|  |             .descriptorCount = 1, | ||||||
|  |             .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||||||
|  |             .pImmutableSamplers = nullptr, | ||||||
|  |         }); | ||||||
|  |         ++binding; | ||||||
|  |     } | ||||||
|  |     for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { | ||||||
|  |         bindings.push_back({ | ||||||
|  |             .binding = binding, | ||||||
|  |             .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||||||
|  |             .descriptorCount = 1, | ||||||
|  |             .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||||||
|  |             .pImmutableSamplers = nullptr, | ||||||
|  |         }); | ||||||
|  |         ++binding; | ||||||
|  |     } | ||||||
|  |     return device.GetLogical().CreateDescriptorSetLayout({ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .bindingCount = static_cast<u32>(bindings.size()), | ||||||
|  |         .pBindings = bindings.data(), | ||||||
|  |     }); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| ComputePipeline::ComputePipeline() = default; | vk::DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplate( | ||||||
|  |     const Device& device, const Shader::Info& info, VkDescriptorSetLayout descriptor_set_layout, | ||||||
|  |     VkPipelineLayout pipeline_layout) { | ||||||
|  |     boost::container::small_vector<VkDescriptorUpdateTemplateEntry, 24> entries; | ||||||
|  |     size_t offset{}; | ||||||
|  |     u32 binding{}; | ||||||
|  |     for ([[maybe_unused]] const auto& desc : info.constant_buffer_descriptors) { | ||||||
|  |         entries.push_back({ | ||||||
|  |             .dstBinding = binding, | ||||||
|  |             .dstArrayElement = 0, | ||||||
|  |             .descriptorCount = 1, | ||||||
|  |             .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, | ||||||
|  |             .offset = offset, | ||||||
|  |             .stride = sizeof(DescriptorUpdateEntry), | ||||||
|  |         }); | ||||||
|  |         ++binding; | ||||||
|  |         offset += sizeof(DescriptorUpdateEntry); | ||||||
|  |     } | ||||||
|  |     for ([[maybe_unused]] const auto& desc : info.storage_buffers_descriptors) { | ||||||
|  |         entries.push_back({ | ||||||
|  |             .dstBinding = binding, | ||||||
|  |             .dstArrayElement = 0, | ||||||
|  |             .descriptorCount = 1, | ||||||
|  |             .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||||||
|  |             .offset = offset, | ||||||
|  |             .stride = sizeof(DescriptorUpdateEntry), | ||||||
|  |         }); | ||||||
|  |         ++binding; | ||||||
|  |         offset += sizeof(DescriptorUpdateEntry); | ||||||
|  |     } | ||||||
|  |     return device.GetLogical().CreateDescriptorUpdateTemplateKHR({ | ||||||
|  |         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, | ||||||
|  |         .pNext = nullptr, | ||||||
|  |         .flags = 0, | ||||||
|  |         .descriptorUpdateEntryCount = static_cast<u32>(entries.size()), | ||||||
|  |         .pDescriptorUpdateEntries = entries.data(), | ||||||
|  |         .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, | ||||||
|  |         .descriptorSetLayout = descriptor_set_layout, | ||||||
|  |         .pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE, | ||||||
|  |         .pipelineLayout = pipeline_layout, | ||||||
|  |         .set = 0, | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| ComputePipeline::~ComputePipeline() = default; | ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, | ||||||
|  |                                  VKUpdateDescriptorQueue& update_descriptor_queue_, | ||||||
|  |                                  const Shader::Info& info_, vk::ShaderModule spv_module_) | ||||||
|  |     : update_descriptor_queue{&update_descriptor_queue_}, info{info_}, | ||||||
|  |       spv_module(std::move(spv_module_)), | ||||||
|  |       descriptor_set_layout(CreateDescriptorSetLayout(device, info)), | ||||||
|  |       descriptor_allocator(descriptor_pool, *descriptor_set_layout), | ||||||
|  |       pipeline_layout{device.GetLogical().CreatePipelineLayout({ | ||||||
|  |           .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||||||
|  |           .pNext = nullptr, | ||||||
|  |           .flags = 0, | ||||||
|  |           .setLayoutCount = 1, | ||||||
|  |           .pSetLayouts = descriptor_set_layout.address(), | ||||||
|  |           .pushConstantRangeCount = 0, | ||||||
|  |           .pPushConstantRanges = nullptr, | ||||||
|  |       })}, | ||||||
|  |       descriptor_update_template{ | ||||||
|  |           CreateDescriptorUpdateTemplate(device, info, *descriptor_set_layout, *pipeline_layout)}, | ||||||
|  |       pipeline{device.GetLogical().CreateComputePipeline({ | ||||||
|  |           .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | ||||||
|  |           .pNext = nullptr, | ||||||
|  |           .flags = 0, | ||||||
|  |           .stage{ | ||||||
|  |               .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||||||
|  |               .pNext = nullptr, | ||||||
|  |               .flags = 0, | ||||||
|  |               .stage = VK_SHADER_STAGE_COMPUTE_BIT, | ||||||
|  |               .module = *spv_module, | ||||||
|  |               .pName = "main", | ||||||
|  |               .pSpecializationInfo = nullptr, | ||||||
|  |           }, | ||||||
|  |           .layout = *pipeline_layout, | ||||||
|  |           .basePipelineHandle = 0, | ||||||
|  |           .basePipelineIndex = 0, | ||||||
|  |       })} {} | ||||||
|  | 
 | ||||||
|  | void ComputePipeline::ConfigureBufferCache(BufferCache& buffer_cache) { | ||||||
|  |     u32 enabled_uniforms{}; | ||||||
|  |     for (const auto& desc : info.constant_buffer_descriptors) { | ||||||
|  |         enabled_uniforms |= ((1ULL << desc.count) - 1) << desc.index; | ||||||
|  |     } | ||||||
|  |     buffer_cache.SetEnabledComputeUniformBuffers(enabled_uniforms); | ||||||
|  | 
 | ||||||
|  |     buffer_cache.UnbindComputeStorageBuffers(); | ||||||
|  |     size_t index{}; | ||||||
|  |     for (const auto& desc : info.storage_buffers_descriptors) { | ||||||
|  |         ASSERT(desc.count == 1); | ||||||
|  |         buffer_cache.BindComputeStorageBuffer(index, desc.cbuf_index, desc.cbuf_offset, true); | ||||||
|  |         ++index; | ||||||
|  |     } | ||||||
|  |     buffer_cache.UpdateComputeBuffers(); | ||||||
|  |     buffer_cache.BindHostComputeBuffers(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | VkDescriptorSet ComputePipeline::UpdateDescriptorSet() { | ||||||
|  |     const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; | ||||||
|  |     update_descriptor_queue->Send(*descriptor_update_template, descriptor_set); | ||||||
|  |     return descriptor_set; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| } // namespace Vulkan
 | } // namespace Vulkan
 | ||||||
|  |  | ||||||
|  | @ -5,19 +5,52 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "shader_recompiler/shader_info.h" | ||||||
|  | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||||||
| #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | ||||||
|  | #include "video_core/renderer_vulkan/vk_pipeline.h" | ||||||
|  | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | ||||||
| #include "video_core/vulkan_common/vulkan_wrapper.h" | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||||||
| 
 | 
 | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
| 
 | 
 | ||||||
| class Device; | class Device; | ||||||
| class VKScheduler; |  | ||||||
| class VKUpdateDescriptorQueue; |  | ||||||
| 
 | 
 | ||||||
| class ComputePipeline { | class ComputePipeline : public Pipeline { | ||||||
| public: | public: | ||||||
|     explicit ComputePipeline(); |     explicit ComputePipeline() = default; | ||||||
|     ~ComputePipeline(); |     explicit ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, | ||||||
|  |                              VKUpdateDescriptorQueue& update_descriptor_queue, | ||||||
|  |                              const Shader::Info& info, vk::ShaderModule spv_module); | ||||||
|  | 
 | ||||||
|  |     ComputePipeline& operator=(ComputePipeline&&) noexcept = default; | ||||||
|  |     ComputePipeline(ComputePipeline&&) noexcept = default; | ||||||
|  | 
 | ||||||
|  |     ComputePipeline& operator=(const ComputePipeline&) = delete; | ||||||
|  |     ComputePipeline(const ComputePipeline&) = delete; | ||||||
|  | 
 | ||||||
|  |     void ConfigureBufferCache(BufferCache& buffer_cache); | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] VkDescriptorSet UpdateDescriptorSet(); | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] VkPipeline Handle() const noexcept { | ||||||
|  |         return *pipeline; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] VkPipelineLayout PipelineLayout() const noexcept { | ||||||
|  |         return *pipeline_layout; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     VKUpdateDescriptorQueue* update_descriptor_queue; | ||||||
|  |     Shader::Info info; | ||||||
|  | 
 | ||||||
|  |     vk::ShaderModule spv_module; | ||||||
|  |     vk::DescriptorSetLayout descriptor_set_layout; | ||||||
|  |     DescriptorAllocator descriptor_allocator; | ||||||
|  |     vk::PipelineLayout pipeline_layout; | ||||||
|  |     vk::DescriptorUpdateTemplateKHR descriptor_update_template; | ||||||
|  |     vk::Pipeline pipeline; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Vulkan
 | } // namespace Vulkan
 | ||||||
|  |  | ||||||
|  | @ -19,9 +19,7 @@ constexpr std::size_t SETS_GROW_RATE = 0x20; | ||||||
| DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool_, | DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool_, | ||||||
|                                          VkDescriptorSetLayout layout_) |                                          VkDescriptorSetLayout layout_) | ||||||
|     : ResourcePool(descriptor_pool_.master_semaphore, SETS_GROW_RATE), |     : ResourcePool(descriptor_pool_.master_semaphore, SETS_GROW_RATE), | ||||||
|       descriptor_pool{descriptor_pool_}, layout{layout_} {} |       descriptor_pool{&descriptor_pool_}, layout{layout_} {} | ||||||
| 
 |  | ||||||
| DescriptorAllocator::~DescriptorAllocator() = default; |  | ||||||
| 
 | 
 | ||||||
| VkDescriptorSet DescriptorAllocator::Commit() { | VkDescriptorSet DescriptorAllocator::Commit() { | ||||||
|     const std::size_t index = CommitResource(); |     const std::size_t index = CommitResource(); | ||||||
|  | @ -29,7 +27,7 @@ VkDescriptorSet DescriptorAllocator::Commit() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) { | void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) { | ||||||
|     descriptors_allocations.push_back(descriptor_pool.AllocateDescriptors(layout, end - begin)); |     descriptors_allocations.push_back(descriptor_pool->AllocateDescriptors(layout, end - begin)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| VKDescriptorPool::VKDescriptorPool(const Device& device_, VKScheduler& scheduler) | VKDescriptorPool::VKDescriptorPool(const Device& device_, VKScheduler& scheduler) | ||||||
|  |  | ||||||
|  | @ -17,8 +17,12 @@ class VKScheduler; | ||||||
| 
 | 
 | ||||||
| class DescriptorAllocator final : public ResourcePool { | class DescriptorAllocator final : public ResourcePool { | ||||||
| public: | public: | ||||||
|  |     explicit DescriptorAllocator() = default; | ||||||
|     explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, VkDescriptorSetLayout layout); |     explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, VkDescriptorSetLayout layout); | ||||||
|     ~DescriptorAllocator() override; |     ~DescriptorAllocator() override = default; | ||||||
|  | 
 | ||||||
|  |     DescriptorAllocator& operator=(DescriptorAllocator&&) noexcept = default; | ||||||
|  |     DescriptorAllocator(DescriptorAllocator&&) noexcept = default; | ||||||
| 
 | 
 | ||||||
|     DescriptorAllocator& operator=(const DescriptorAllocator&) = delete; |     DescriptorAllocator& operator=(const DescriptorAllocator&) = delete; | ||||||
|     DescriptorAllocator(const DescriptorAllocator&) = delete; |     DescriptorAllocator(const DescriptorAllocator&) = delete; | ||||||
|  | @ -29,8 +33,8 @@ protected: | ||||||
|     void Allocate(std::size_t begin, std::size_t end) override; |     void Allocate(std::size_t begin, std::size_t end) override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     VKDescriptorPool& descriptor_pool; |     VKDescriptorPool* descriptor_pool{}; | ||||||
|     const VkDescriptorSetLayout layout; |     VkDescriptorSetLayout layout{}; | ||||||
| 
 | 
 | ||||||
|     std::vector<vk::DescriptorSets> descriptors_allocations; |     std::vector<vk::DescriptorSets> descriptors_allocations; | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								src/video_core/renderer_vulkan/vk_pipeline.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/video_core/renderer_vulkan/vk_pipeline.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | // Copyright 2019 yuzu Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <cstddef> | ||||||
|  | 
 | ||||||
|  | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||||||
|  | 
 | ||||||
|  | namespace Vulkan { | ||||||
|  | 
 | ||||||
|  | class Pipeline { | ||||||
|  | public: | ||||||
|  |     /// Add a reference count to the pipeline
 | ||||||
|  |     void AddRef() noexcept { | ||||||
|  |         ++ref_count; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] bool RemoveRef() noexcept { | ||||||
|  |         --ref_count; | ||||||
|  |         return ref_count == 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] u64 UsageTick() const noexcept { | ||||||
|  |         return usage_tick; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     u64 usage_tick{}; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     size_t ref_count{}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace Vulkan
 | ||||||
|  | @ -12,6 +12,8 @@ | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
|  | #include "shader_recompiler/environment.h" | ||||||
|  | #include "shader_recompiler/recompiler.h" | ||||||
| #include "video_core/engines/kepler_compute.h" | #include "video_core/engines/kepler_compute.h" | ||||||
| #include "video_core/engines/maxwell_3d.h" | #include "video_core/engines/maxwell_3d.h" | ||||||
| #include "video_core/memory_manager.h" | #include "video_core/memory_manager.h" | ||||||
|  | @ -22,43 +24,105 @@ | ||||||
| #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | ||||||
| #include "video_core/renderer_vulkan/vk_rasterizer.h" | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||||||
| #include "video_core/renderer_vulkan/vk_scheduler.h" | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||||||
|  | #include "video_core/renderer_vulkan/vk_shader_util.h" | ||||||
| #include "video_core/renderer_vulkan/vk_update_descriptor.h" | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | ||||||
| #include "video_core/shader_cache.h" | #include "video_core/shader_cache.h" | ||||||
| #include "video_core/shader_notify.h" | #include "video_core/shader_notify.h" | ||||||
| #include "video_core/vulkan_common/vulkan_device.h" | #include "video_core/vulkan_common/vulkan_device.h" | ||||||
| #include "video_core/vulkan_common/vulkan_wrapper.h" | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||||||
| 
 | 
 | ||||||
|  | #pragma optimize("", off) | ||||||
|  | 
 | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
| MICROPROFILE_DECLARE(Vulkan_PipelineCache); | MICROPROFILE_DECLARE(Vulkan_PipelineCache); | ||||||
| 
 | 
 | ||||||
| using Tegra::Engines::ShaderType; | using Tegra::Engines::ShaderType; | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| size_t StageFromProgram(size_t program) { | class Environment final : public Shader::Environment { | ||||||
|     return program == 0 ? 0 : program - 1; | public: | ||||||
| } |     explicit Environment(Tegra::Engines::KeplerCompute& kepler_compute_, | ||||||
|  |                          Tegra::MemoryManager& gpu_memory_, GPUVAddr program_base_) | ||||||
|  |         : kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, program_base{program_base_} {} | ||||||
| 
 | 
 | ||||||
| ShaderType StageFromProgram(Maxwell::ShaderProgram program) { |     ~Environment() override = default; | ||||||
|     return static_cast<ShaderType>(StageFromProgram(static_cast<size_t>(program))); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| ShaderType GetShaderType(Maxwell::ShaderProgram program) { |     [[nodiscard]] std::optional<u128> Analyze(u32 start_address) { | ||||||
|     switch (program) { |         const std::optional<u64> size{TryFindSize(start_address)}; | ||||||
|     case Maxwell::ShaderProgram::VertexB: |         if (!size) { | ||||||
|         return ShaderType::Vertex; |             return std::nullopt; | ||||||
|     case Maxwell::ShaderProgram::TesselationControl: |         } | ||||||
|         return ShaderType::TesselationControl; |         cached_lowest = start_address; | ||||||
|     case Maxwell::ShaderProgram::TesselationEval: |         cached_highest = start_address + static_cast<u32>(*size); | ||||||
|         return ShaderType::TesselationEval; |         return Common::CityHash128(reinterpret_cast<const char*>(code.data()), code.size()); | ||||||
|     case Maxwell::ShaderProgram::Geometry: |  | ||||||
|         return ShaderType::Geometry; |  | ||||||
|     case Maxwell::ShaderProgram::Fragment: |  | ||||||
|         return ShaderType::Fragment; |  | ||||||
|     default: |  | ||||||
|         UNIMPLEMENTED_MSG("program={}", program); |  | ||||||
|         return ShaderType::Vertex; |  | ||||||
|     } |     } | ||||||
| } | 
 | ||||||
|  |     [[nodiscard]] size_t ShaderSize() const noexcept { | ||||||
|  |         return read_highest - read_lowest + INST_SIZE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [[nodiscard]] u128 ComputeHash() const { | ||||||
|  |         const size_t size{ShaderSize()}; | ||||||
|  |         auto data = std::make_unique<u64[]>(size); | ||||||
|  |         gpu_memory.ReadBlock(program_base + read_lowest, data.get(), size); | ||||||
|  |         return Common::CityHash128(reinterpret_cast<const char*>(data.get()), size); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u64 ReadInstruction(u32 address) override { | ||||||
|  |         read_lowest = std::min(read_lowest, address); | ||||||
|  |         read_highest = std::max(read_highest, address); | ||||||
|  | 
 | ||||||
|  |         if (address >= cached_lowest && address < cached_highest) { | ||||||
|  |             return code[address / INST_SIZE]; | ||||||
|  |         } | ||||||
|  |         return gpu_memory.Read<u64>(program_base + address); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::array<u32, 3> WorkgroupSize() override { | ||||||
|  |         const auto& qmd{kepler_compute.launch_description}; | ||||||
|  |         return {qmd.block_dim_x, qmd.block_dim_y, qmd.block_dim_z}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     static constexpr size_t INST_SIZE = sizeof(u64); | ||||||
|  |     static constexpr size_t BLOCK_SIZE = 0x1000; | ||||||
|  |     static constexpr size_t MAXIMUM_SIZE = 0x100000; | ||||||
|  | 
 | ||||||
|  |     static constexpr u64 SELF_BRANCH_A = 0xE2400FFFFF87000FULL; | ||||||
|  |     static constexpr u64 SELF_BRANCH_B = 0xE2400FFFFF07000FULL; | ||||||
|  | 
 | ||||||
|  |     std::optional<u64> TryFindSize(u32 start_address) { | ||||||
|  |         GPUVAddr guest_addr = program_base + start_address; | ||||||
|  |         size_t offset = 0; | ||||||
|  |         size_t size = BLOCK_SIZE; | ||||||
|  |         while (size <= MAXIMUM_SIZE) { | ||||||
|  |             code.resize(size / INST_SIZE); | ||||||
|  |             u64* const data = code.data() + offset / INST_SIZE; | ||||||
|  |             gpu_memory.ReadBlock(guest_addr, data, BLOCK_SIZE); | ||||||
|  |             for (size_t i = 0; i < BLOCK_SIZE; i += INST_SIZE) { | ||||||
|  |                 const u64 inst = data[i / INST_SIZE]; | ||||||
|  |                 if (inst == SELF_BRANCH_A || inst == SELF_BRANCH_B) { | ||||||
|  |                     return offset + i; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             guest_addr += BLOCK_SIZE; | ||||||
|  |             size += BLOCK_SIZE; | ||||||
|  |             offset += BLOCK_SIZE; | ||||||
|  |         } | ||||||
|  |         return std::nullopt; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Tegra::Engines::KeplerCompute& kepler_compute; | ||||||
|  |     Tegra::MemoryManager& gpu_memory; | ||||||
|  |     GPUVAddr program_base; | ||||||
|  | 
 | ||||||
|  |     u32 read_lowest = 0; | ||||||
|  |     u32 read_highest = 0; | ||||||
|  | 
 | ||||||
|  |     std::vector<u64> code; | ||||||
|  |     u32 cached_lowest = std::numeric_limits<u32>::max(); | ||||||
|  |     u32 cached_highest = 0; | ||||||
|  | }; | ||||||
| } // Anonymous namespace
 | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| size_t ComputePipelineCacheKey::Hash() const noexcept { | size_t ComputePipelineCacheKey::Hash() const noexcept { | ||||||
|  | @ -70,35 +134,91 @@ bool ComputePipelineCacheKey::operator==(const ComputePipelineCacheKey& rhs) con | ||||||
|     return std::memcmp(&rhs, this, sizeof *this) == 0; |     return std::memcmp(&rhs, this, sizeof *this) == 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Shader::Shader() = default; |  | ||||||
| 
 |  | ||||||
| Shader::~Shader() = default; |  | ||||||
| 
 |  | ||||||
| PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, | PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, | ||||||
|                              Tegra::Engines::Maxwell3D& maxwell3d_, |                              Tegra::Engines::Maxwell3D& maxwell3d_, | ||||||
|                              Tegra::Engines::KeplerCompute& kepler_compute_, |                              Tegra::Engines::KeplerCompute& kepler_compute_, | ||||||
|                              Tegra::MemoryManager& gpu_memory_, const Device& device_, |                              Tegra::MemoryManager& gpu_memory_, const Device& device_, | ||||||
|                              VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_, |                              VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_, | ||||||
|                              VKUpdateDescriptorQueue& update_descriptor_queue_) |                              VKUpdateDescriptorQueue& update_descriptor_queue_) | ||||||
|     : VideoCommon::ShaderCache<Shader>{rasterizer_}, gpu{gpu_}, maxwell3d{maxwell3d_}, |     : VideoCommon::ShaderCache<ShaderInfo>{rasterizer_}, gpu{gpu_}, maxwell3d{maxwell3d_}, | ||||||
|       kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_}, |       kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_}, | ||||||
|       scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, update_descriptor_queue{ |       scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, update_descriptor_queue{ | ||||||
|                                                                     update_descriptor_queue_} {} |                                                                     update_descriptor_queue_} {} | ||||||
| 
 | 
 | ||||||
| PipelineCache::~PipelineCache() = default; | PipelineCache::~PipelineCache() = default; | ||||||
| 
 | 
 | ||||||
| ComputePipeline& PipelineCache::GetComputePipeline(const ComputePipelineCacheKey& key) { | ComputePipeline* PipelineCache::CurrentComputePipeline() { | ||||||
|     MICROPROFILE_SCOPE(Vulkan_PipelineCache); |     MICROPROFILE_SCOPE(Vulkan_PipelineCache); | ||||||
| 
 | 
 | ||||||
|     const auto [pair, is_cache_miss] = compute_cache.try_emplace(key); |     const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()}; | ||||||
|     auto& entry = pair->second; |     const auto& qmd{kepler_compute.launch_description}; | ||||||
|     if (!is_cache_miss) { |     const GPUVAddr shader_addr{program_base + qmd.program_start}; | ||||||
|         return *entry; |     const std::optional<VAddr> cpu_shader_addr{gpu_memory.GpuToCpuAddress(shader_addr)}; | ||||||
|  |     if (!cpu_shader_addr) { | ||||||
|  |         return nullptr; | ||||||
|     } |     } | ||||||
|     LOG_INFO(Render_Vulkan, "Compile 0x{:016X}", key.Hash()); |     ShaderInfo* const shader{TryGet(*cpu_shader_addr)}; | ||||||
|     throw "Bad"; |     if (!shader) { | ||||||
|  |         return CreateComputePipelineWithoutShader(*cpu_shader_addr); | ||||||
|  |     } | ||||||
|  |     const ComputePipelineCacheKey key{MakeComputePipelineKey(shader->unique_hash)}; | ||||||
|  |     const auto [pair, is_new]{compute_cache.try_emplace(key)}; | ||||||
|  |     auto& pipeline{pair->second}; | ||||||
|  |     if (!is_new) { | ||||||
|  |         return &pipeline; | ||||||
|  |     } | ||||||
|  |     pipeline = CreateComputePipeline(shader); | ||||||
|  |     shader->compute_users.push_back(key); | ||||||
|  |     return &pipeline; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PipelineCache::OnShaderRemoval(Shader*) {} | ComputePipeline PipelineCache::CreateComputePipeline(ShaderInfo* shader_info) { | ||||||
|  |     const GPUVAddr program_base{kepler_compute.regs.code_loc.Address()}; | ||||||
|  |     const auto& qmd{kepler_compute.launch_description}; | ||||||
|  |     Environment env{kepler_compute, gpu_memory, program_base}; | ||||||
|  |     if (const std::optional<u128> cached_hash{env.Analyze(qmd.program_start)}) { | ||||||
|  |         // TODO: Load from cache
 | ||||||
|  |     } | ||||||
|  |     const auto [info, code]{Shader::RecompileSPIRV(env, qmd.program_start)}; | ||||||
|  |     shader_info->unique_hash = env.ComputeHash(); | ||||||
|  |     shader_info->size_bytes = env.ShaderSize(); | ||||||
|  |     return ComputePipeline{device, descriptor_pool, update_descriptor_queue, info, | ||||||
|  |                            BuildShader(device, code)}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ComputePipeline* PipelineCache::CreateComputePipelineWithoutShader(VAddr shader_cpu_addr) { | ||||||
|  |     ShaderInfo shader; | ||||||
|  |     ComputePipeline pipeline{CreateComputePipeline(&shader)}; | ||||||
|  |     const ComputePipelineCacheKey key{MakeComputePipelineKey(shader.unique_hash)}; | ||||||
|  |     shader.compute_users.push_back(key); | ||||||
|  |     pipeline.AddRef(); | ||||||
|  | 
 | ||||||
|  |     const size_t size_bytes{shader.size_bytes}; | ||||||
|  |     Register(std::make_unique<ShaderInfo>(std::move(shader)), shader_cpu_addr, size_bytes); | ||||||
|  |     return &compute_cache.emplace(key, std::move(pipeline)).first->second; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ComputePipelineCacheKey PipelineCache::MakeComputePipelineKey(u128 unique_hash) const { | ||||||
|  |     const auto& qmd{kepler_compute.launch_description}; | ||||||
|  |     return { | ||||||
|  |         .unique_hash = unique_hash, | ||||||
|  |         .shared_memory_size = qmd.shared_alloc, | ||||||
|  |         .workgroup_size{qmd.block_dim_x, qmd.block_dim_y, qmd.block_dim_z}, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PipelineCache::OnShaderRemoval(ShaderInfo* shader) { | ||||||
|  |     for (const ComputePipelineCacheKey& key : shader->compute_users) { | ||||||
|  |         const auto it = compute_cache.find(key); | ||||||
|  |         ASSERT(it != compute_cache.end()); | ||||||
|  | 
 | ||||||
|  |         Pipeline& pipeline = it->second; | ||||||
|  |         if (pipeline.RemoveRef()) { | ||||||
|  |             // Wait for the pipeline to be free of GPU usage before destroying it
 | ||||||
|  |             scheduler.Wait(pipeline.UsageTick()); | ||||||
|  |             compute_cache.erase(it); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| } // namespace Vulkan
 | } // namespace Vulkan
 | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ class VKUpdateDescriptorQueue; | ||||||
| using Maxwell = Tegra::Engines::Maxwell3D::Regs; | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||||||
| 
 | 
 | ||||||
| struct ComputePipelineCacheKey { | struct ComputePipelineCacheKey { | ||||||
|     GPUVAddr shader; |     u128 unique_hash; | ||||||
|     u32 shared_memory_size; |     u32 shared_memory_size; | ||||||
|     std::array<u32, 3> workgroup_size; |     std::array<u32, 3> workgroup_size; | ||||||
| 
 | 
 | ||||||
|  | @ -67,13 +67,13 @@ struct hash<Vulkan::ComputePipelineCacheKey> { | ||||||
| 
 | 
 | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
| 
 | 
 | ||||||
| class Shader { | struct ShaderInfo { | ||||||
| public: |     u128 unique_hash{}; | ||||||
|     explicit Shader(); |     size_t size_bytes{}; | ||||||
|     ~Shader(); |     std::vector<ComputePipelineCacheKey> compute_users; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class PipelineCache final : public VideoCommon::ShaderCache<Shader> { | class PipelineCache final : public VideoCommon::ShaderCache<ShaderInfo> { | ||||||
| public: | public: | ||||||
|     explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu, |     explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::GPU& gpu, | ||||||
|                            Tegra::Engines::Maxwell3D& maxwell3d, |                            Tegra::Engines::Maxwell3D& maxwell3d, | ||||||
|  | @ -83,12 +83,18 @@ public: | ||||||
|                            VKUpdateDescriptorQueue& update_descriptor_queue); |                            VKUpdateDescriptorQueue& update_descriptor_queue); | ||||||
|     ~PipelineCache() override; |     ~PipelineCache() override; | ||||||
| 
 | 
 | ||||||
|     ComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key); |     [[nodiscard]] ComputePipeline* CurrentComputePipeline(); | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     void OnShaderRemoval(Shader* shader) final; |     void OnShaderRemoval(ShaderInfo* shader) override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     ComputePipeline CreateComputePipeline(ShaderInfo* shader); | ||||||
|  | 
 | ||||||
|  |     ComputePipeline* CreateComputePipelineWithoutShader(VAddr shader_cpu_addr); | ||||||
|  | 
 | ||||||
|  |     ComputePipelineCacheKey MakeComputePipelineKey(u128 unique_hash) const; | ||||||
|  | 
 | ||||||
|     Tegra::GPU& gpu; |     Tegra::GPU& gpu; | ||||||
|     Tegra::Engines::Maxwell3D& maxwell3d; |     Tegra::Engines::Maxwell3D& maxwell3d; | ||||||
|     Tegra::Engines::KeplerCompute& kepler_compute; |     Tegra::Engines::KeplerCompute& kepler_compute; | ||||||
|  | @ -99,13 +105,7 @@ private: | ||||||
|     VKDescriptorPool& descriptor_pool; |     VKDescriptorPool& descriptor_pool; | ||||||
|     VKUpdateDescriptorQueue& update_descriptor_queue; |     VKUpdateDescriptorQueue& update_descriptor_queue; | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<Shader> null_shader; |     std::unordered_map<ComputePipelineCacheKey, ComputePipeline> compute_cache; | ||||||
|     std::unique_ptr<Shader> null_kernel; |  | ||||||
| 
 |  | ||||||
|     std::array<Shader*, Maxwell::MaxShaderProgram> last_shaders{}; |  | ||||||
| 
 |  | ||||||
|     std::mutex pipeline_cache; |  | ||||||
|     std::unordered_map<ComputePipelineCacheKey, std::unique_ptr<ComputePipeline>> compute_cache; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Vulkan
 | } // namespace Vulkan
 | ||||||
|  |  | ||||||
|  | @ -36,6 +36,8 @@ | ||||||
| #include "video_core/vulkan_common/vulkan_device.h" | #include "video_core/vulkan_common/vulkan_device.h" | ||||||
| #include "video_core/vulkan_common/vulkan_wrapper.h" | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||||||
| 
 | 
 | ||||||
|  | #pragma optimize("", off) | ||||||
|  | 
 | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
| 
 | 
 | ||||||
| using Maxwell = Tegra::Engines::Maxwell3D::Regs; | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | ||||||
|  | @ -237,7 +239,26 @@ void RasterizerVulkan::Clear() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RasterizerVulkan::DispatchCompute() { | void RasterizerVulkan::DispatchCompute() { | ||||||
|     UNREACHABLE_MSG("Not implemented"); |     ComputePipeline* const pipeline{pipeline_cache.CurrentComputePipeline()}; | ||||||
|  |     if (!pipeline) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     std::scoped_lock lock{buffer_cache.mutex}; | ||||||
|  |     update_descriptor_queue.Acquire(); | ||||||
|  |     pipeline->ConfigureBufferCache(buffer_cache); | ||||||
|  |     const VkDescriptorSet descriptor_set{pipeline->UpdateDescriptorSet()}; | ||||||
|  | 
 | ||||||
|  |     const auto& qmd{kepler_compute.launch_description}; | ||||||
|  |     const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z}; | ||||||
|  |     const VkPipeline pipeline_handle{pipeline->Handle()}; | ||||||
|  |     const VkPipelineLayout pipeline_layout{pipeline->PipelineLayout()}; | ||||||
|  |     scheduler.Record( | ||||||
|  |         [pipeline_handle, pipeline_layout, dim, descriptor_set](vk::CommandBuffer cmdbuf) { | ||||||
|  |             cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_handle); | ||||||
|  |             cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, | ||||||
|  |                                       descriptor_set, nullptr); | ||||||
|  |             cmdbuf.Dispatch(dim[0], dim[1], dim[2]); | ||||||
|  |         }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) { | void RasterizerVulkan::ResetCounter(VideoCore::QueryType type) { | ||||||
|  |  | ||||||
|  | @ -21,7 +21,6 @@ | ||||||
| #include "video_core/renderer_vulkan/vk_buffer_cache.h" | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||||||
| #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | ||||||
| #include "video_core/renderer_vulkan/vk_fence_manager.h" | #include "video_core/renderer_vulkan/vk_fence_manager.h" | ||||||
| #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" |  | ||||||
| #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | ||||||
| #include "video_core/renderer_vulkan/vk_query_cache.h" | #include "video_core/renderer_vulkan/vk_query_cache.h" | ||||||
| #include "video_core/renderer_vulkan/vk_scheduler.h" | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||||||
|  | @ -150,8 +149,6 @@ private: | ||||||
|     BlitImageHelper blit_image; |     BlitImageHelper blit_image; | ||||||
|     ASTCDecoderPass astc_decoder_pass; |     ASTCDecoderPass astc_decoder_pass; | ||||||
| 
 | 
 | ||||||
|     GraphicsPipelineCacheKey graphics_key; |  | ||||||
| 
 |  | ||||||
|     TextureCacheRuntime texture_cache_runtime; |     TextureCacheRuntime texture_cache_runtime; | ||||||
|     TextureCache texture_cache; |     TextureCache texture_cache; | ||||||
|     BufferCacheRuntime buffer_cache_runtime; |     BufferCacheRuntime buffer_cache_runtime; | ||||||
|  |  | ||||||
|  | @ -10,18 +10,16 @@ | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
| 
 | 
 | ||||||
| ResourcePool::ResourcePool(MasterSemaphore& master_semaphore_, size_t grow_step_) | ResourcePool::ResourcePool(MasterSemaphore& master_semaphore_, size_t grow_step_) | ||||||
|     : master_semaphore{master_semaphore_}, grow_step{grow_step_} {} |     : master_semaphore{&master_semaphore_}, grow_step{grow_step_} {} | ||||||
| 
 |  | ||||||
| ResourcePool::~ResourcePool() = default; |  | ||||||
| 
 | 
 | ||||||
| size_t ResourcePool::CommitResource() { | size_t ResourcePool::CommitResource() { | ||||||
|     // Refresh semaphore to query updated results
 |     // Refresh semaphore to query updated results
 | ||||||
|     master_semaphore.Refresh(); |     master_semaphore->Refresh(); | ||||||
|     const u64 gpu_tick = master_semaphore.KnownGpuTick(); |     const u64 gpu_tick = master_semaphore->KnownGpuTick(); | ||||||
|     const auto search = [this, gpu_tick](size_t begin, size_t end) -> std::optional<size_t> { |     const auto search = [this, gpu_tick](size_t begin, size_t end) -> std::optional<size_t> { | ||||||
|         for (size_t iterator = begin; iterator < end; ++iterator) { |         for (size_t iterator = begin; iterator < end; ++iterator) { | ||||||
|             if (gpu_tick >= ticks[iterator]) { |             if (gpu_tick >= ticks[iterator]) { | ||||||
|                 ticks[iterator] = master_semaphore.CurrentTick(); |                 ticks[iterator] = master_semaphore->CurrentTick(); | ||||||
|                 return iterator; |                 return iterator; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -36,7 +34,7 @@ size_t ResourcePool::CommitResource() { | ||||||
|             // Both searches failed, the pool is full; handle it.
 |             // Both searches failed, the pool is full; handle it.
 | ||||||
|             const size_t free_resource = ManageOverflow(); |             const size_t free_resource = ManageOverflow(); | ||||||
| 
 | 
 | ||||||
|             ticks[free_resource] = master_semaphore.CurrentTick(); |             ticks[free_resource] = master_semaphore->CurrentTick(); | ||||||
|             found = free_resource; |             found = free_resource; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -18,8 +18,16 @@ class MasterSemaphore; | ||||||
|  */ |  */ | ||||||
| class ResourcePool { | class ResourcePool { | ||||||
| public: | public: | ||||||
|  |     explicit ResourcePool() = default; | ||||||
|     explicit ResourcePool(MasterSemaphore& master_semaphore, size_t grow_step); |     explicit ResourcePool(MasterSemaphore& master_semaphore, size_t grow_step); | ||||||
|     virtual ~ResourcePool(); | 
 | ||||||
|  |     virtual ~ResourcePool() = default; | ||||||
|  | 
 | ||||||
|  |     ResourcePool& operator=(ResourcePool&&) noexcept = default; | ||||||
|  |     ResourcePool(ResourcePool&&) noexcept = default; | ||||||
|  | 
 | ||||||
|  |     ResourcePool& operator=(const ResourcePool&) = default; | ||||||
|  |     ResourcePool(const ResourcePool&) = default; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|     size_t CommitResource(); |     size_t CommitResource(); | ||||||
|  | @ -34,7 +42,7 @@ private: | ||||||
|     /// Allocates a new page of resources.
 |     /// Allocates a new page of resources.
 | ||||||
|     void Grow(); |     void Grow(); | ||||||
| 
 | 
 | ||||||
|     MasterSemaphore& master_semaphore; |     MasterSemaphore* master_semaphore{}; | ||||||
|     size_t grow_step = 0;     ///< Number of new resources created after an overflow
 |     size_t grow_step = 0;     ///< Number of new resources created after an overflow
 | ||||||
|     size_t hint_iterator = 0; ///< Hint to where the next free resources is likely to be found
 |     size_t hint_iterator = 0; ///< Hint to where the next free resources is likely to be found
 | ||||||
|     std::vector<u64> ticks;   ///< Ticks for each resource
 |     std::vector<u64> ticks;   ///< Ticks for each resource
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 ReinUsesLisp
						ReinUsesLisp