From 1208d22547d4ac24b581d421157b074c97cb9983 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 12 Sep 2026 13:08:23 +0200 Subject: [PATCH] Fix Windows Clang SPIR-V serialization with typed operands --- .../recompiler/backend/spirv/SpirvBuilder.cpp | 97 ++--- .../recompiler/backend/spirv/SpirvBuilder.h | 112 +++++- .../backend/spirv/spirvEmitterAlu.cpp | 40 +-- .../backend/spirv/spirvEmitterAluHelpers.cpp | 113 +++--- .../backend/spirv/spirvEmitterAnalysis.cpp | 43 ++- .../backend/spirv/spirvEmitterFlow.cpp | 338 +++++++++--------- .../backend/spirv/spirvEmitterHelpers.cpp | 148 ++++---- .../backend/spirv/spirvEmitterImage.cpp | 283 ++++++++------- .../backend/spirv/spirvEmitterInternal.h | 73 ++-- .../backend/spirv/spirvEmitterMemory.cpp | 170 ++++----- .../spirv/spirvEmitterMemoryHelpers.cpp | 124 +++---- .../backend/spirv/spirvEmitterMesh.cpp | 102 +++--- .../backend/spirv/spirvEmitterModule.cpp | 170 ++++----- .../backend/spirv/spirvEmitterProgram.cpp | 219 ++++++------ src/graphics/shader/rectListShader.cpp | 31 +- tests/ShaderRecompilerComputeTests.cpp | 84 +++-- tests/shaderCfgTests.cpp | 141 +++++++- 17 files changed, 1204 insertions(+), 1084 deletions(-) diff --git a/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.cpp b/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.cpp index 996a1abd7..10efe2ca0 100644 --- a/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.cpp @@ -15,8 +15,8 @@ static void AppendInstructionWords(std::vector& section, const uint32_ if (words_num == 0) { return; } - const auto opcode = words[0]; - const auto word_count = static_cast(words_num); + const uint32_t opcode = words[0]; + const auto word_count = static_cast(words_num); section.push_back((word_count << spv::WordCountShift) | opcode); section.insert(section.end(), words + 1, words + words_num); } @@ -38,7 +38,7 @@ void Builder::RequireVersion(uint32_t version) { void Builder::RequireCapability(spv::Capability capability) { if (m_required_capabilities.insert(capability).second) { - AppendInstruction(m_capabilities, spv::OpCapability, {static_cast(capability)}); + AppendInstruction(m_capabilities, spv::OpCapability, capability); } } @@ -62,38 +62,25 @@ uint32_t Builder::Import(const char* name) { return id; } -uint32_t Builder::Type(spv::Op opcode, std::initializer_list operands) { - return Type(opcode, std::vector(operands)); -} - -uint32_t Builder::Type(spv::Op opcode, const std::vector& operands) { - std::vector key; - key.reserve(operands.size() + 2u); - key.push_back(opcode); - key.push_back(static_cast(operands.size())); - key.insert(key.end(), operands.begin(), operands.end()); +uint32_t Builder::DeclareType(spv::Op opcode, std::vector key) { if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) { return it->second; } const auto id = AllocateId(); + AppendInstruction(m_declarations, opcode, id, std::span(key).subspan(2)); m_declaration_ids.emplace(std::move(key), id); - std::vector words {static_cast(opcode), id}; - words.insert(words.end(), operands.begin(), operands.end()); - AppendInstructionWords(m_declarations, words.data(), words.size()); return id; } -uint32_t Builder::DecoratedType(spv::Op opcode, std::initializer_list operands, - std::initializer_list annotations) { +uint32_t Builder::DeclareDecoratedType(spv::Op opcode, std::vector key, + std::initializer_list annotations) { if (annotations.size() == 0) { - return Type(opcode, operands); + return DeclareType(opcode, std::move(key)); } - std::vector key {static_cast(opcode), - static_cast(operands.size())}; - key.insert(key.end(), operands.begin(), operands.end()); + const auto operand_count = key[1]; key.push_back(static_cast(annotations.size())); for (const auto& annotation: annotations) { - key.push_back(annotation.opcode); + AppendOperand(key, annotation.opcode); key.push_back(static_cast(annotation.operands.size())); key.insert(key.end(), annotation.operands.begin(), annotation.operands.end()); } @@ -101,37 +88,23 @@ uint32_t Builder::DecoratedType(spv::Op opcode, std::initializer_list return it->second; } const auto id = AllocateId(); + AppendInstruction(m_declarations, opcode, id, + std::span(key).subspan(2, operand_count)); m_declaration_ids.emplace(std::move(key), id); - std::vector words {static_cast(opcode), id}; - words.insert(words.end(), operands.begin(), operands.end()); - AppendInstructionWords(m_declarations, words.data(), words.size()); for (const auto& annotation: annotations) { - words = {static_cast(annotation.opcode), id}; - words.insert(words.end(), annotation.operands.begin(), annotation.operands.end()); - AppendInstructionWords(m_annotations, words.data(), words.size()); + AppendInstruction(m_annotations, annotation.opcode, id, annotation.operands); } return id; } -uint32_t Builder::Constant(spv::Op opcode, uint32_t type, - std::initializer_list operands) { - return Constant(opcode, type, std::vector(operands)); -} - -uint32_t Builder::Constant(spv::Op opcode, uint32_t type, const std::vector& operands) { - std::vector key; - key.reserve(operands.size() + 2u); - key.push_back(opcode); - key.push_back(type); - key.insert(key.end(), operands.begin(), operands.end()); +uint32_t Builder::DeclareConstant(spv::Op opcode, std::vector key) { if (const auto it = m_declaration_ids.find(key); it != m_declaration_ids.end()) { return it->second; } const auto id = AllocateId(); + AppendInstruction(m_declarations, opcode, key[1], id, + std::span(key).subspan(2)); m_declaration_ids.emplace(std::move(key), id); - std::vector words {static_cast(opcode), type, id}; - words.insert(words.end(), operands.begin(), operands.end()); - AppendInstructionWords(m_declarations, words.data(), words.size()); return id; } @@ -143,8 +116,7 @@ uint32_t Builder::DefineGlobalVariable(uint32_t pointer_type, spv::StorageClass void Builder::DefineGlobalVariable(uint32_t id, uint32_t pointer_type, spv::StorageClass storage_class) { - AppendInstruction(m_declarations, spv::OpVariable, - {pointer_type, id, static_cast(storage_class)}); + AppendInstruction(m_declarations, spv::OpVariable, pointer_type, id, storage_class); } void Builder::AppendString(std::vector& words, const char* text) { @@ -163,27 +135,14 @@ void Builder::AppendString(std::vector& words, const char* text) { } } -void Builder::AppendInstruction(std::vector& section, spv::Op opcode, - const std::vector& operands) { - const uint32_t word_count = static_cast(operands.size() + 1u); - section.push_back((word_count << spv::WordCountShift) | opcode); - section.insert(section.end(), operands.begin(), operands.end()); -} - -void Builder::AppendInstruction(std::vector& section, spv::Op opcode, - std::initializer_list operands) { - const uint32_t word_count = static_cast(operands.size() + 1u); - section.push_back((word_count << spv::WordCountShift) | opcode); - section.insert(section.end(), operands.begin(), operands.end()); -} - -void Builder::AddMemoryModel(std::initializer_list operands) { - AppendInstruction(m_memory_model, spv::OpMemoryModel, operands); +void Builder::AddMemoryModel(spv::AddressingModel addressing_model, spv::MemoryModel memory_model) { + AppendInstruction(m_memory_model, spv::OpMemoryModel, addressing_model, memory_model); } void Builder::AddEntryPoint(spv::ExecutionModel execution_model, uint32_t entry_point, const char* name, const std::vector& interfaces) { - std::vector operands = {static_cast(execution_model), entry_point}; + std::vector operands; + AppendOperands(operands, execution_model, entry_point); AppendString(operands, name); operands.insert(operands.end(), interfaces.begin(), interfaces.end()); if (m_version >= 0x00010400u) { @@ -201,25 +160,13 @@ void Builder::AddEntryPoint(spv::ExecutionModel execution_model, uint32_t entry_ AppendInstruction(m_entry_points, spv::OpEntryPoint, operands); } -void Builder::AddExecutionMode(std::initializer_list operands) { - AppendInstruction(m_execution_modes, spv::OpExecutionMode, operands); -} - void Builder::AddName(uint32_t target, const char* name) { std::vector operands = {target}; AppendString(operands, name); AppendInstruction(m_debug, spv::OpName, operands); } -void Builder::AddAnnotation(std::initializer_list words) { - AppendInstructionWords(m_annotations, words.begin(), words.size()); -} - -void Builder::AddFunction(std::initializer_list words) { - AppendInstructionWords(m_functions, words.begin(), words.size()); -} - -void Builder::AddFunction(const std::vector& words) { +void Builder::AddFunction(std::span words) { AppendInstructionWords(m_functions, words.data(), words.size()); } diff --git a/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.h b/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.h index 206091bfe..307716dea 100644 --- a/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.h +++ b/src/graphics/shader/recompiler/backend/spirv/SpirvBuilder.h @@ -4,17 +4,21 @@ #include "common/common.h" #include +#include #include #include +#include #include #include +#include +#include #include namespace Libs::Graphics::ShaderRecompiler::Spirv { struct TypeAnnotation { spv::Op opcode = spv::OpNop; - std::vector operands; + std::vector operands; // Already encoded operand words. }; struct DeferredPhi { @@ -32,33 +36,109 @@ public: void RequireCapability(spv::Capability capability); void RequireExtension(const char* name); uint32_t Import(const char* name); - uint32_t Type(spv::Op opcode, std::initializer_list operands = {}); - uint32_t Type(spv::Op opcode, const std::vector& operands); - uint32_t DecoratedType(spv::Op opcode, std::initializer_list operands, - std::initializer_list annotations); - uint32_t Constant(spv::Op opcode, uint32_t type, std::initializer_list operands = {}); - uint32_t Constant(spv::Op opcode, uint32_t type, const std::vector& operands); + template + uint32_t Type(spv::Op opcode, const Args&... operands) { + return DeclareType(opcode, MakeTypeKey(opcode, operands...)); + } + + template + uint32_t DecoratedType(spv::Op opcode, std::initializer_list annotations, + const Args&... operands) { + return DeclareDecoratedType(opcode, MakeTypeKey(opcode, operands...), annotations); + } + + template + uint32_t Constant(spv::Op opcode, uint32_t type, const Args&... operands) { + std::vector key; + key.reserve(2u + (0u + ... + OperandWordCount(operands))); + AppendOperands(key, opcode, type, operands...); + return DeclareConstant(opcode, std::move(key)); + } + uint32_t DefineGlobalVariable(uint32_t pointer_type, spv::StorageClass storage_class); void DefineGlobalVariable(uint32_t id, uint32_t pointer_type, spv::StorageClass storage_class); - void AddMemoryModel(std::initializer_list operands); + void AddMemoryModel(spv::AddressingModel addressing_model, spv::MemoryModel memory_model); void AddEntryPoint(spv::ExecutionModel execution_model, uint32_t entry_point, const char* name, const std::vector& interfaces); - void AddExecutionMode(std::initializer_list operands); - void AddName(uint32_t target, const char* name); - void AddAnnotation(std::initializer_list words); - void AddFunction(std::initializer_list words); - void AddFunction(const std::vector& words); + template + void AddExecutionMode(uint32_t entry_point, spv::ExecutionMode mode, const Args&... operands) { + AppendInstruction(m_execution_modes, spv::OpExecutionMode, entry_point, mode, operands...); + } + + void AddName(uint32_t target, const char* name); + template + void AddAnnotation(spv::Op opcode, const Args&... operands) { + AppendInstruction(m_annotations, opcode, operands...); + } + + template + void AddFunction(spv::Op opcode, const Args&... operands) { + AppendInstruction(m_functions, opcode, operands...); + } + + void AddFunction(std::span words); DeferredPhi AddDeferredPhi(uint32_t type, uint32_t result, size_t incoming_count); void PatchDeferredPhi(DeferredPhi phi, size_t incoming, uint32_t value, uint32_t parent); [[nodiscard]] std::vector Build() const; private: + static void AppendOperand(std::vector& words, uint32_t value) { + words.push_back(value); + } + + static void AppendOperand(std::vector& words, int32_t value) { + words.push_back(static_cast(value)); + } + + template + requires std::is_enum_v + static void AppendOperand(std::vector& words, T value) { + static_assert(sizeof(T) == sizeof(uint32_t)); + words.push_back(static_cast(value)); + } + + static void AppendOperand(std::vector& words, std::span values) { + words.insert(words.end(), values.begin(), values.end()); + } + + template + static void AppendOperands(std::vector& words, const Args&... operands) { + (AppendOperand(words, operands), ...); + } + + template + static size_t OperandWordCount(const T& operand) { + if constexpr (std::is_integral_v || std::is_enum_v) { + return 1; + } else { + return std::size(operand); + } + } + + template + static std::vector MakeTypeKey(spv::Op opcode, const Args&... operands) { + const auto operand_count = static_cast((0u + ... + OperandWordCount(operands))); + std::vector key; + key.reserve(2u + operand_count); + AppendOperands(key, opcode, operand_count, operands...); + return key; + } + + template static void AppendInstruction(std::vector& section, spv::Op opcode, - const std::vector& operands); - static void AppendInstruction(std::vector& section, spv::Op opcode, - std::initializer_list operands); + const Args&... operands) { + const auto offset = section.size(); + AppendOperands(section, opcode, operands...); + const auto word_count = static_cast(section.size() - offset); + section[offset] |= word_count << spv::WordCountShift; + } + + uint32_t DeclareType(spv::Op opcode, std::vector key); + uint32_t DeclareDecoratedType(spv::Op opcode, std::vector key, + std::initializer_list annotations); + uint32_t DeclareConstant(spv::Op opcode, std::vector key); static void AppendString(std::vector& words, const char* text); uint32_t m_next_id = 1; diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp index fde9f073f..e2da2ef83 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAlu.cpp @@ -12,14 +12,14 @@ struct Pair { Pair ExtractPair(EmitterState& state, uint32_t value) { Pair result {state.builder.AllocateId(), state.builder.AllocateId()}; - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), result.low, value, 0}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), result.high, value, 1}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), result.low, value, 0); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), result.high, value, 1); return result; } uint32_t MakePair(EmitterState& state, uint32_t low, uint32_t high) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeU64(state), result, low, high}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeU64(state), result, low, high); return result; } @@ -31,7 +31,7 @@ uint32_t CompareEqual64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_va } uint32_t CompareOrdered64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value, - uint32_t high_compare, uint32_t low_compare) { + spv::Op high_compare, spv::Op low_compare) { const auto lhs = ExtractPair(state, lhs_value); const auto rhs = ExtractPair(state, rhs_value); const auto high_equal = Binary(state, spv::OpIEqual, TypeBool(state), lhs.high, rhs.high); @@ -51,10 +51,10 @@ uint32_t EmitMulHigh(EmitterState& state, uint32_t lhs, uint32_t rhs, bool signe rhs_operand = Unary(state, spv::OpBitcast, TypeI32(state), rhs); } const auto extended = state.builder.AllocateId(); - state.builder.AddFunction({signed_value ? spv::OpSMulExtended : spv::OpUMulExtended, pair_type, - extended, lhs_operand, rhs_operand}); + state.builder.AddFunction(signed_value ? spv::OpSMulExtended : spv::OpUMulExtended, pair_type, + extended, lhs_operand, rhs_operand); const auto high = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeExtract, operand_type, high, extended, 1}); + state.builder.AddFunction(spv::OpCompositeExtract, operand_type, high, extended, 1); return signed_value ? Unary(state, spv::OpBitcast, TypeU32(state), high) : high; } @@ -96,7 +96,7 @@ uint32_t EmitShift64(EmitterState& state, spv::Op opcode, uint32_t value, uint32 Select(state, TypeU32(state), at_least_32, fill, high)); } -uint32_t EmitConstantShift64(EmitterState& state, uint32_t opcode, uint32_t value, uint32_t shift) { +uint32_t EmitConstantShift64(EmitterState& state, spv::Op opcode, uint32_t value, uint32_t shift) { shift &= 63u; if (shift == 0u) { return value; @@ -173,10 +173,10 @@ uint32_t EmitF32ToU32(EmitterState& state, uint32_t src, bool signed_value) { const auto converted_raw = state.builder.AllocateId(); if (signed_value) { const auto converted_i = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertFToS, TypeI32(state), converted_i, trunc}); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), converted_raw, converted_i}); + state.builder.AddFunction(spv::OpConvertFToS, TypeI32(state), converted_i, trunc); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), converted_raw, converted_i); } else { - state.builder.AddFunction({spv::OpConvertFToU, TypeU32(state), converted_raw, trunc}); + state.builder.AddFunction(spv::OpConvertFToU, TypeU32(state), converted_raw, trunc); } const auto nan = EmitClassifyF32(state, src).nan; if (signed_value) { @@ -218,10 +218,10 @@ uint32_t EmitFindUMsb64(EmitterState& state, uint32_t value) { const auto pair = ExtractPair(state, value); const auto high_i = state.builder.AllocateId(); const auto low_i = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpExtInst, TypeI32(state), high_i, GlslStd450(state), GLSLstd450FindUMsb, pair.high}); - state.builder.AddFunction( - {spv::OpExtInst, TypeI32(state), low_i, GlslStd450(state), GLSLstd450FindUMsb, pair.low}); + state.builder.AddFunction(spv::OpExtInst, TypeI32(state), high_i, GlslStd450(state), + GLSLstd450FindUMsb, pair.high); + state.builder.AddFunction(spv::OpExtInst, TypeI32(state), low_i, GlslStd450(state), + GLSLstd450FindUMsb, pair.low); const auto high = Unary(state, spv::OpBitcast, TypeU32(state), high_i); const auto low = Unary(state, spv::OpBitcast, TypeU32(state), low_i); const auto high_nonzero = @@ -260,9 +260,9 @@ uint32_t EmitIAdd64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value) const auto low_pair = state.builder.AllocateId(); const auto low = state.builder.AllocateId(); const auto carry = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpIAddCarry, TypeU32Pair(state), low_pair, lhs.low, rhs.low}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), low, low_pair, 0}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), carry, low_pair, 1}); + state.builder.AddFunction(spv::OpIAddCarry, TypeU32Pair(state), low_pair, lhs.low, rhs.low); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), low, low_pair, 0); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), carry, low_pair, 1); const auto high0 = Binary(state, spv::OpIAdd, TypeU32(state), lhs.high, rhs.high); const auto high = Binary(state, spv::OpIAdd, TypeU32(state), high0, carry); return MakePair(state, low, high); @@ -278,8 +278,8 @@ uint32_t EmitConvertU8U32(EmitterState& state, uint32_t arg0) { uint32_t EmitConvertF16F32(EmitterState& state, uint32_t arg0) { const auto pair = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeF32Vector(state, 2), pair, arg0, ConstantF32(state, 0)}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(state, 2), pair, arg0, + ConstantF32(state, 0)); return EmitPackHalf2x16(state, pair); } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp index 330fd3b9b..273f224b4 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAluHelpers.cpp @@ -4,35 +4,35 @@ namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter { uint32_t EmitAndConstant(EmitterState& state, uint32_t value, uint32_t mask) { const auto ret = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), ret, value, ConstantU32(state, mask)}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), ret, value, + ConstantU32(state, mask)); return ret; } uint32_t EmitShiftRightConstant(EmitterState& state, uint32_t value, uint32_t shift) { const auto ret = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpShiftRightLogical, TypeU32(state), ret, value, ConstantU32(state, shift)}); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), ret, value, + ConstantU32(state, shift)); return ret; } -uint32_t EmitCompareU32Constant(EmitterState& state, uint32_t opcode, uint32_t value, +uint32_t EmitCompareU32Constant(EmitterState& state, spv::Op opcode, uint32_t value, uint32_t constant) { const auto ret = state.builder.AllocateId(); - state.builder.AddFunction({opcode, TypeBool(state), ret, value, ConstantU32(state, constant)}); + state.builder.AddFunction(opcode, TypeBool(state), ret, value, ConstantU32(state, constant)); return ret; } uint32_t EmitSubConstantMinusU32(EmitterState& state, uint32_t constant, uint32_t value) { const auto ret = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpISub, TypeU32(state), ret, ConstantU32(state, constant), value}); + state.builder.AddFunction(spv::OpISub, TypeU32(state), ret, ConstantU32(state, constant), + value); return ret; } uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32) { const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, f32}); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, f32); const auto sign = EmitAndConstant(state, EmitShiftRightConstant(state, bits, 16), 0x8000u); const auto exp = EmitAndConstant(state, EmitShiftRightConstant(state, bits, 23), 0xffu); @@ -43,13 +43,12 @@ uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32) { const auto normal_mant = EmitShiftRightConstant(state, mant, 13); const auto normal_payload = state.builder.AllocateId(); const auto normal = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpISub, TypeU32(state), half_exp, exp, ConstantU32(state, 112)}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), normal_exp, half_exp, ConstantU32(state, 10)}); - state.builder.AddFunction( - {spv::OpBitwiseOr, TypeU32(state), normal_payload, normal_exp, normal_mant}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), normal, sign, normal_payload}); + state.builder.AddFunction(spv::OpISub, TypeU32(state), half_exp, exp, ConstantU32(state, 112)); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), normal_exp, half_exp, + ConstantU32(state, 10)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), normal_payload, normal_exp, + normal_mant); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), normal, sign, normal_payload); const auto mant_with_hidden = EmitOrU32(state, mant, ConstantU32(state, 0x00800000u)); const auto raw_sub_shift = EmitSubConstantMinusU32(state, 126, exp); @@ -61,9 +60,9 @@ uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32) { EmitSelectValueU32(state, exp_gt_112, ConstantU32(state, 14), sub_shift_low); const auto sub_mant = state.builder.AllocateId(); const auto subnormal = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpShiftRightLogical, TypeU32(state), sub_mant, mant_with_hidden, sub_shift}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), subnormal, sign, sub_mant}); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), sub_mant, mant_with_hidden, + sub_shift); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), subnormal, sign, sub_mant); const auto nan_payload = EmitOrU32(state, EmitShiftRightConstant(state, mant, 13), ConstantU32(state, 0x0200u)); @@ -86,18 +85,18 @@ uint32_t EmitF32ToF16RtzBits(EmitterState& state, uint32_t f32) { uint32_t EmitMinMaxU32Value(EmitterState& state, uint32_t lhs, uint32_t rhs, bool max_value) { const auto cond = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - state.builder.AddFunction( - {max_value ? spv::OpUGreaterThan : spv::OpULessThan, TypeBool(state), cond, lhs, rhs}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), ret, cond, lhs, rhs}); + state.builder.AddFunction(max_value ? spv::OpUGreaterThan : spv::OpULessThan, TypeBool(state), + cond, lhs, rhs); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), ret, cond, lhs, rhs); return ret; } uint32_t EmitMinMaxI32Value(EmitterState& state, uint32_t lhs, uint32_t rhs, bool max_value) { const auto cond = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - state.builder.AddFunction( - {max_value ? spv::OpSGreaterThan : spv::OpSLessThan, TypeBool(state), cond, lhs, rhs}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), ret, cond, lhs, rhs}); + state.builder.AddFunction(max_value ? spv::OpSGreaterThan : spv::OpSLessThan, TypeBool(state), + cond, lhs, rhs); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), ret, cond, lhs, rhs); return ret; } @@ -184,8 +183,8 @@ uint32_t EmitMinMaxF32Value(EmitterState& state, uint32_t lhs, uint32_t rhs, boo const auto rhs_class = EmitClassifyF32(state, rhs); const auto numeric_cond = state.builder.AllocateId(); - state.builder.AddFunction({max_value ? spv::OpFOrdGreaterThanEqual : spv::OpFOrdLessThan, - TypeBool(state), numeric_cond, lhs, rhs}); + state.builder.AddFunction(max_value ? spv::OpFOrdGreaterThanEqual : spv::OpFOrdLessThan, + TypeBool(state), numeric_cond, lhs, rhs); const auto ordered_bits = EmitSelectValueU32(state, numeric_cond, lhs_class.bits, rhs_class.bits); @@ -209,18 +208,18 @@ uint32_t EmitFlushF32DenormToSignedZero(EmitterState& state, uint32_t value) { const auto flush = state.builder.AllocateId(); const auto selected = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, value}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), abs_bits, bits, ConstantU32(state, 0x7fffffffu)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), sign_bits, bits, ConstantU32(state, 0x80000000u)}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), non_zero, abs_bits, ConstantU32(state, 0)}); - state.builder.AddFunction( - {spv::OpULessThan, TypeBool(state), subnormal, abs_bits, ConstantU32(state, 0x00800000u)}); - state.builder.AddFunction({spv::OpLogicalAnd, TypeBool(state), flush, non_zero, subnormal}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), selected, flush, sign_bits, bits}); - state.builder.AddFunction({spv::OpBitcast, TypeF32(state), ret, selected}); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, value); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), abs_bits, bits, + ConstantU32(state, 0x7fffffffu)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), sign_bits, bits, + ConstantU32(state, 0x80000000u)); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), non_zero, abs_bits, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), subnormal, abs_bits, + ConstantU32(state, 0x00800000u)); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), flush, non_zero, subnormal); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), selected, flush, sign_bits, bits); + state.builder.AddFunction(spv::OpBitcast, TypeF32(state), ret, selected); return ret; } @@ -232,35 +231,35 @@ uint32_t EmitTrigCycleF32(EmitterState& state, uint32_t src, bool preserve_signe const auto finite = state.builder.AllocateId(); const auto large_finite = state.builder.AllocateId(); const auto reduced = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpExtInst, TypeF32(state), fract, GlslStd450(state), GLSLstd450Fract, src}); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, src}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), abs_bits, bits, ConstantU32(state, 0x7fffffffu)}); - state.builder.AddFunction({spv::OpUGreaterThanEqual, TypeBool(state), large, abs_bits, - ConstantU32(state, 0x4b000000u)}); - state.builder.AddFunction( - {spv::OpULessThan, TypeBool(state), finite, abs_bits, ConstantU32(state, 0x7f800000u)}); - state.builder.AddFunction({spv::OpLogicalAnd, TypeBool(state), large_finite, large, finite}); - state.builder.AddFunction( - {spv::OpSelect, TypeF32(state), reduced, large_finite, ConstantF32(state, 0), fract}); + state.builder.AddFunction(spv::OpExtInst, TypeF32(state), fract, GlslStd450(state), + GLSLstd450Fract, src); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, src); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), abs_bits, bits, + ConstantU32(state, 0x7fffffffu)); + state.builder.AddFunction(spv::OpUGreaterThanEqual, TypeBool(state), large, abs_bits, + ConstantU32(state, 0x4b000000u)); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), finite, abs_bits, + ConstantU32(state, 0x7f800000u)); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), large_finite, large, finite); + state.builder.AddFunction(spv::OpSelect, TypeF32(state), reduced, large_finite, + ConstantF32(state, 0), fract); if (!preserve_signed_zero) { return reduced; } const auto zero = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpIEqual, TypeBool(state), zero, abs_bits, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpSelect, TypeF32(state), ret, zero, src, reduced}); + state.builder.AddFunction(spv::OpIEqual, TypeBool(state), zero, abs_bits, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpSelect, TypeF32(state), ret, zero, src, reduced); return ret; } uint32_t EmitF16BitsToF32(EmitterState& state, uint32_t bits) { const auto unpacked = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpExtInst, TypeF32Vector(state, 2), unpacked, GlslStd450(state), - GLSLstd450UnpackHalf2x16, bits}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeF32(state), ret, unpacked, 0}); + state.builder.AddFunction(spv::OpExtInst, TypeF32Vector(state, 2), unpacked, GlslStd450(state), + GLSLstd450UnpackHalf2x16, bits); + state.builder.AddFunction(spv::OpCompositeExtract, TypeF32(state), ret, unpacked, 0); return ret; } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp index 3280f7972..481d1965f 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterAnalysis.cpp @@ -82,8 +82,8 @@ uint32_t DescriptorElementPointer(EmitterState& state, uint32_t result_ptr_type, ExitDescriptorBindingFailure(state, kind, resource, variable_name); } const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, result_ptr_type, pointer, variable_id, - ConstantU32(state, array_index)}); + state.builder.AddFunction(spv::OpAccessChain, result_ptr_type, pointer, variable_id, + ConstantU32(state, array_index)); return pointer; } @@ -109,8 +109,7 @@ uint32_t ImageScalarType(EmitterState& state, Prospero::TextureNumericClass nume uint32_t ImageVectorType(EmitterState& state, Prospero::TextureNumericClass numeric_class, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, - {ImageScalarType(state, numeric_class), components}); + return state.builder.Type(spv::OpTypeVector, ImageScalarType(state, numeric_class), components); } uint32_t ImageType(EmitterState& state, const IR::ImageResource& image) { @@ -131,10 +130,9 @@ uint32_t ImageType(EmitterState& state, const IR::ImageResource& image) { EXIT("invalid image resource class"); } const auto& info = ImageDimensionInfoFor(image.dimension); - return state.builder.Type(spv::OpTypeImage, - {ImageScalarType(state, image.numeric_class), info.spirv_dimension, - image.depth_compare ? 1u : 0u, info.arrayed, info.multisampled, - sampled, format}); + return state.builder.Type(spv::OpTypeImage, ImageScalarType(state, image.numeric_class), + info.spirv_dimension, image.depth_compare ? 1u : 0u, info.arrayed, + info.multisampled, sampled, format); } uint32_t ImageViewSizeType(EmitterState& state, ImageDimension dimension) { @@ -154,12 +152,12 @@ uint32_t LoadSampledImageDescriptor(EmitterState& state, uint32_t resource) { const auto array_index = ResourceForDescriptor(state, *kind, resource); const auto variable = state.image_variables[IR::ImageBindingIndex(*kind)]; const auto pointer_type = state.builder.Type( - spv::OpTypePointer, {spv::StorageClassUniformConstant, ImageType(state, image_resource)}); + spv::OpTypePointer, spv::StorageClassUniformConstant, ImageType(state, image_resource)); const auto pointer = DescriptorElementPointer(state, pointer_type, variable, array_index, *kind, resource, "sampled image descriptor array was not emitted"); const auto image = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, ImageType(state, image_resource), image, pointer}); + state.builder.AddFunction(spv::OpLoad, ImageType(state, image_resource), image, pointer); return image; } @@ -168,12 +166,12 @@ uint32_t LoadSamplerDescriptor(EmitterState& state, uint32_t sampler) { ResourceForDescriptor(state, IR::DescriptorBindingKind::Samplers, sampler); const auto sampler_type = state.builder.Type(spv::OpTypeSampler); const auto pointer_type = - state.builder.Type(spv::OpTypePointer, {spv::StorageClassUniformConstant, sampler_type}); + state.builder.Type(spv::OpTypePointer, spv::StorageClassUniformConstant, sampler_type); const auto pointer = DescriptorElementPointer( state, pointer_type, state.sampler_variable, array_index, IR::DescriptorBindingKind::Samplers, sampler, "sampler descriptor array was not emitted"); const auto sampler_id = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, sampler_type, sampler_id, pointer}); + state.builder.AddFunction(spv::OpLoad, sampler_type, sampler_id, pointer); return sampler_id; } @@ -183,9 +181,8 @@ uint32_t MakeSampledImage(EmitterState& state, uint32_t resource, uint32_t sampl const auto sampler_id = LoadSamplerDescriptor(state, sampler); const auto sampled_image = state.builder.AllocateId(); const auto sampled_type = - state.builder.Type(spv::OpTypeSampledImage, {ImageType(state, image_resource)}); - state.builder.AddFunction( - {spv::OpSampledImage, sampled_type, sampled_image, image, sampler_id}); + state.builder.Type(spv::OpTypeSampledImage, ImageType(state, image_resource)); + state.builder.AddFunction(spv::OpSampledImage, sampled_type, sampled_image, image, sampler_id); return sampled_image; } @@ -194,9 +191,9 @@ uint32_t StorageImageDescriptorPointer(EmitterState& state, uint32_t resource) { EXIT_IF(image.resource_class != IR::ImageResourceClass::Storage); const auto kind = IR::DescriptorBindingForImage(image); EXIT_IF(!kind.has_value()); - const auto array_index = ResourceForDescriptor(state, *kind, resource); + const auto array_index = ResourceForDescriptor(state, *kind, resource); const auto pointer_type = state.builder.Type( - spv::OpTypePointer, {spv::StorageClassUniformConstant, ImageType(state, image)}); + spv::OpTypePointer, spv::StorageClassUniformConstant, ImageType(state, image)); const auto variable = state.image_variables[IR::ImageBindingIndex(*kind)]; return DescriptorElementPointer(state, pointer_type, variable, array_index, *kind, resource, "storage image descriptor array was not emitted"); @@ -214,18 +211,18 @@ void EmitStorageImageWrite(EmitterState& state, uint32_t resource, uint32_t mip_ const auto array_index = ResourceForDescriptor(state, *kind, resource); const auto image_type = ImageType(state, image); const auto pointer_type = - state.builder.Type(spv::OpTypePointer, {spv::StorageClassUniformConstant, image_type}); + state.builder.Type(spv::OpTypePointer, spv::StorageClassUniformConstant, image_type); const auto variable = state.image_variables[IR::ImageBindingIndex(*kind)]; const auto LoadAt = [&](uint32_t array_index) { const auto pointer = DescriptorElementPointer(state, pointer_type, variable, array_index, *kind, resource, "storage image descriptor array was not emitted"); const auto descriptor = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, image_type, descriptor, pointer}); + state.builder.AddFunction(spv::OpLoad, image_type, descriptor, pointer); return descriptor; }; if (image.mip_mode != IR::ImageMipMode::DynamicStorage) { - state.builder.AddFunction({spv::OpImageWrite, LoadAt(array_index), coord, texel}); + state.builder.AddFunction(spv::OpImageWrite, LoadAt(array_index), coord, texel); return; } if (image.mip_count == 0u) { @@ -241,12 +238,12 @@ void EmitStorageImageWrite(EmitterState& state, uint32_t resource, uint32_t mip_ words.push_back(mip); words.push_back(labels[mip]); } - state.builder.AddFunction({spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone}); + state.builder.AddFunction(spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone); state.builder.AddFunction(words); for (uint32_t mip = 0; mip < image.mip_count; mip++) { EmitLabel(state, labels[mip]); - state.builder.AddFunction({spv::OpImageWrite, LoadAt(array_index + mip), coord, texel}); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpImageWrite, LoadAt(array_index + mip), coord, texel); + state.builder.AddFunction(spv::OpBranch, merge_label); } EmitLabel(state, merge_label); } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterFlow.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterFlow.cpp index e1ceb4d8a..8624668de 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterFlow.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterFlow.cpp @@ -45,28 +45,28 @@ uint32_t EmitBuiltinU32(EmitterState& state, IR::StageInputKind kind, uint32_t c if (kind == IR::StageInputKind::FrontFacing) { const auto value = state.builder.AllocateId(); const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeBool(state), value, variable}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), bits, value, - ConstantU32(state, 1), ConstantU32(state, 0)}); + state.builder.AddFunction(spv::OpLoad, TypeBool(state), value, variable); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), bits, value, ConstantU32(state, 1), + ConstantU32(state, 0)); return bits; } if (kind == IR::StageInputKind::VertexIndex || kind == IR::StageInputKind::InstanceIndex || kind == IR::StageInputKind::Layer || kind == IR::StageInputKind::SampleId) { const auto value = state.builder.AllocateId(); const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeI32(state), value, variable}); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, value}); + state.builder.AddFunction(spv::OpLoad, TypeI32(state), value, variable); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, value); return bits; } if (kind == IR::StageInputKind::FragCoord) { const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassInput, TypeF32(state)), - pointer, variable, ConstantU32(state, component)}); - state.builder.AddFunction({spv::OpLoad, TypeF32(state), value, pointer}); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, value}); + state.builder.AddFunction(spv::OpAccessChain, + TypePointer(state, spv::StorageClassInput, TypeF32(state)), + pointer, variable, ConstantU32(state, component)); + state.builder.AddFunction(spv::OpLoad, TypeF32(state), value, pointer); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, value); return bits; } if (kind == IR::StageInputKind::BaryCoordSmooth || @@ -74,11 +74,11 @@ uint32_t EmitBuiltinU32(EmitterState& state, IR::StageInputKind kind, uint32_t c const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassInput, TypeF32(state)), - pointer, variable, ConstantU32(state, component + 1u)}); - state.builder.AddFunction({spv::OpLoad, TypeF32(state), value, pointer}); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, value}); + state.builder.AddFunction(spv::OpAccessChain, + TypePointer(state, spv::StorageClassInput, TypeF32(state)), + pointer, variable, ConstantU32(state, component + 1u)); + state.builder.AddFunction(spv::OpLoad, TypeF32(state), value, pointer); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, value); return bits; } return EmitInputComponentU32(state, kind, component); @@ -99,37 +99,37 @@ uint32_t EmitDppWriteCondition(ValueEmitContext& ctx, const IR::DppMoveFlags& fl const auto bank_ok = state.builder.AllocateId(); const auto row_ok = state.builder.AllocateId(); const auto masks_ok = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpShiftRightLogical, TypeU32(state), bank_shift, lane, ConstantU32(state, 2)}); - state.builder.AddFunction( - {spv::OpShiftRightLogical, TypeU32(state), row_shift, lane, ConstantU32(state, 4)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), bank, bank_shift, ConstantU32(state, 3)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), row, row_shift, ConstantU32(state, 3)}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), bank_bit, ConstantU32(state, 1), bank}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), row_bit, ConstantU32(state, 1), row}); - state.builder.AddFunction({spv::OpBitwiseAnd, TypeU32(state), bank_hit, - ConstantU32(state, flags.bank_mask), bank_bit}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), row_hit, ConstantU32(state, flags.row_mask), row_bit}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), bank_ok, bank_hit, ConstantU32(state, 0)}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), row_ok, row_hit, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpLogicalAnd, TypeBool(state), masks_ok, bank_ok, row_ok}); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), bank_shift, lane, + ConstantU32(state, 2)); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), row_shift, lane, + ConstantU32(state, 4)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), bank, bank_shift, + ConstantU32(state, 3)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), row, row_shift, + ConstantU32(state, 3)); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), bank_bit, + ConstantU32(state, 1), bank); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), row_bit, + ConstantU32(state, 1), row); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), bank_hit, + ConstantU32(state, flags.bank_mask), bank_bit); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), row_hit, + ConstantU32(state, flags.row_mask), row_bit); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), bank_ok, bank_hit, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), row_ok, row_hit, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), masks_ok, bank_ok, row_ok); uint32_t writable = masks_ok; if (!flags.bound_control) { const auto target = EmitDppTargetLane(state, flags.control); const auto bounded = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpLogicalAnd, TypeBool(state), bounded, writable, target.valid}); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), bounded, writable, + target.valid); writable = bounded; } const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLogicalAnd, TypeBool(state), result, exec, writable}); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), result, exec, writable); return result; } @@ -144,11 +144,10 @@ uint32_t EmitAttribute(EmitterState& state, uint32_t attr, uint32_t chan) { const auto load_per_vertex = [&](uint32_t vertex) { const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassInput, TypeF32(state)), - pointer, input->variable_id, ConstantU32(state, vertex), - ConstantU32(state, chan & 3u)}); - state.builder.AddFunction({spv::OpLoad, TypeF32(state), value, pointer}); + state.builder.AddFunction( + spv::OpAccessChain, TypePointer(state, spv::StorageClassInput, TypeF32(state)), pointer, + input->variable_id, ConstantU32(state, vertex), ConstantU32(state, chan & 3u)); + state.builder.AddFunction(spv::OpLoad, TypeF32(state), value, pointer); return value; }; if (input->per_vertex) { @@ -161,31 +160,31 @@ uint32_t EmitAttribute(EmitterState& state, uint32_t attr, uint32_t chan) { const auto pointer = state.builder.AllocateId(); const auto weight = state.builder.AllocateId(); const auto product = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassInput, TypeF32(state)), - pointer, barycentric, ConstantU32(state, vertex)}); - state.builder.AddFunction({spv::OpLoad, TypeF32(state), weight, pointer}); - state.builder.AddFunction( - {spv::OpFMul, TypeF32(state), product, load_per_vertex(vertex), weight}); + state.builder.AddFunction(spv::OpAccessChain, + TypePointer(state, spv::StorageClassInput, TypeF32(state)), + pointer, barycentric, ConstantU32(state, vertex)); + state.builder.AddFunction(spv::OpLoad, TypeF32(state), weight, pointer); + state.builder.AddFunction(spv::OpFMul, TypeF32(state), product, load_per_vertex(vertex), + weight); if (vertex == 0u) { sum = product; } else { const auto next = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpFAdd, TypeF32(state), next, sum, product}); + state.builder.AddFunction(spv::OpFAdd, TypeF32(state), next, sum, product); sum = next; } } const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, sum}); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, sum); return bits; } const auto vector = state.builder.AllocateId(); const auto component = state.builder.AllocateId(); const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeF32Vector(state, 4), vector, input->variable_id}); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeF32(state), component, vector, chan & 3u}); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, component}); + state.builder.AddFunction(spv::OpLoad, TypeF32Vector(state, 4), vector, input->variable_id); + state.builder.AddFunction(spv::OpCompositeExtract, TypeF32(state), component, vector, + chan & 3u); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, component); return bits; } @@ -199,11 +198,10 @@ uint32_t EmitInterpolationParameter(ValueEmitContext& ctx, uint32_t attr, uint32 const auto load_vertex = [&](uint32_t vertex) { const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassInput, TypeF32(state)), - pointer, input->variable_id, ConstantU32(state, vertex), - ConstantU32(state, chan & 3u)}); - state.builder.AddFunction({spv::OpLoad, TypeF32(state), value, pointer}); + state.builder.AddFunction( + spv::OpAccessChain, TypePointer(state, spv::StorageClassInput, TypeF32(state)), pointer, + input->variable_id, ConstantU32(state, vertex), ConstantU32(state, chan & 3u)); + state.builder.AddFunction(spv::OpLoad, TypeF32(state), value, pointer); return value; }; @@ -211,11 +209,11 @@ uint32_t EmitInterpolationParameter(ValueEmitContext& ctx, uint32_t attr, uint32 uint32_t value = load_vertex(selected_vertex); if (!PixelParameterIsCustom(state, attr) && mode < 2u) { const auto delta = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpFSub, TypeF32(state), delta, value, load_vertex(0)}); + state.builder.AddFunction(spv::OpFSub, TypeF32(state), delta, value, load_vertex(0)); value = delta; } const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, value}); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, value); return bits; } @@ -229,8 +227,8 @@ uint32_t MrtOutputMode(const EmitterState& state, const IR::ExportInfo& exp) { uint32_t ExportRawComponent(ValueEmitContext& ctx, uint32_t vector, uint32_t component) { const auto value = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(ctx.state), value, vector, component}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), value, vector, + component); return value; } @@ -248,22 +246,21 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo } const auto packed = state.builder.AllocateId(); const auto unpacked = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(state), packed, data, pair}); - state.builder.AddFunction({spv::OpExtInst, TypeF32Vector(state, 2), unpacked, - GlslStd450(state), unpack, packed}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), packed, data, pair); + state.builder.AddFunction(spv::OpExtInst, TypeF32Vector(state, 2), unpacked, + GlslStd450(state), unpack, packed); for (uint32_t lane = 0; lane < 2u; lane++) { const auto component = pair * 2u + lane; if (((exp.en >> component) & 1u) != 0u) { f32[component] = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeF32(state), f32[component], unpacked, lane}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeF32(state), + f32[component], unpacked, lane); } } } const auto vector = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeF32Vector(state, 4), vector, - f32[0], f32[1], f32[2], f32[3]}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(state, 4), vector, + f32[0], f32[1], f32[2], f32[3]); return vector; } uint32_t raw[4] = { @@ -284,9 +281,9 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo continue; } raw[component] = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitFieldUExtract, TypeU32(state), raw[component], - packed, ConstantU32(state, lane * 16u), - ConstantU32(state, 16)}); + state.builder.AddFunction(spv::OpBitFieldUExtract, TypeU32(state), raw[component], + packed, ConstantU32(state, lane * 16u), + ConstantU32(state, 16)); } } } else { @@ -298,18 +295,18 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo } if (uint_output) { const auto vector = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(state, 4), vector, - raw[0], raw[1], raw[2], raw[3]}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(state, 4), vector, + raw[0], raw[1], raw[2], raw[3]); return vector; } uint32_t f32[4] {}; for (uint32_t component = 0; component < 4u; component++) { f32[component] = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeF32(state), f32[component], raw[component]}); + state.builder.AddFunction(spv::OpBitcast, TypeF32(state), f32[component], raw[component]); } const auto vector = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeF32Vector(state, 4), vector, f32[0], - f32[1], f32[2], f32[3]}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(state, 4), vector, f32[0], + f32[1], f32[2], f32[3]); return vector; } @@ -325,19 +322,19 @@ void EmitAuxPositionExport(ValueEmitContext& ctx, uint32_t data, const IR::Expor const auto raw = ExportRawComponent(ctx, data, component); if (output.layer) { const auto layer = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), layer, raw, ConstantU32(state, 0x7ffu)}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), layer, raw, + ConstantU32(state, 0x7ffu)); const auto pointer = state.program.stage == ShaderType::Mesh ? MeshOutputPointer(state, IR::StageOutputKind::Layer) : state.layer_variable; - state.builder.AddFunction({spv::OpStore, pointer, layer}); + state.builder.AddFunction(spv::OpStore, pointer, layer); } if (output.viewport) { // GFX10 MISC.z packs the viewport index in bits 16..19 alongside the layer. const auto viewport = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitFieldUExtract, TypeU32(state), viewport, raw, - ConstantU32(state, 16), ConstantU32(state, 4)}); - state.builder.AddFunction({spv::OpStore, state.viewport_index_variable, viewport}); + state.builder.AddFunction(spv::OpBitFieldUExtract, TypeU32(state), viewport, raw, + ConstantU32(state, 16), ConstantU32(state, 4)); + state.builder.AddFunction(spv::OpStore, state.viewport_index_variable, viewport); } continue; } @@ -348,9 +345,9 @@ void EmitAuxPositionExport(ValueEmitContext& ctx, uint32_t data, const IR::Expor const auto raw = ExportRawComponent(ctx, data, component); const auto f32 = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeF32(state), f32, raw}); + state.builder.AddFunction(spv::OpBitcast, TypeF32(state), f32, raw); if (output.point_size) { - state.builder.AddFunction({spv::OpStore, state.point_size_variable, f32}); + state.builder.AddFunction(spv::OpStore, state.point_size_variable, f32); continue; } auto StoreDistance = [&](uint32_t variable, uint32_t index) { @@ -358,10 +355,10 @@ void EmitAuxPositionExport(ValueEmitContext& ctx, uint32_t data, const IR::Expor return; } const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassOutput, TypeF32(state)), - pointer, variable, ConstantU32(state, index)}); - state.builder.AddFunction({spv::OpStore, pointer, f32}); + state.builder.AddFunction(spv::OpAccessChain, + TypePointer(state, spv::StorageClassOutput, TypeF32(state)), + pointer, variable, ConstantU32(state, index)); + state.builder.AddFunction(spv::OpStore, pointer, f32); }; StoreDistance(state.clip_distance_variable, output.clip_distance); StoreDistance(state.cull_distance_variable, output.cull_distance); @@ -374,14 +371,14 @@ uint32_t ConvertClipCoordinate(EmitterState& state, uint32_t coordinate, float s const auto biased = state.builder.AllocateId(); const auto divided = state.builder.AllocateId(); const auto ndc = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpFMul, TypeF32(state), window, coordinate, ConstantF32Value(state, scale)}); - state.builder.AddFunction( - {spv::OpFAdd, TypeF32(state), biased, window, ConstantF32Value(state, offset)}); - state.builder.AddFunction( - {spv::OpFDiv, TypeF32(state), divided, biased, ConstantF32Value(state, half_extent)}); - state.builder.AddFunction( - {spv::OpFSub, TypeF32(state), ndc, divided, ConstantF32Value(state, 1.0f)}); + state.builder.AddFunction(spv::OpFMul, TypeF32(state), window, coordinate, + ConstantF32Value(state, scale)); + state.builder.AddFunction(spv::OpFAdd, TypeF32(state), biased, window, + ConstantF32Value(state, offset)); + state.builder.AddFunction(spv::OpFDiv, TypeF32(state), divided, biased, + ConstantF32Value(state, half_extent)); + state.builder.AddFunction(spv::OpFSub, TypeF32(state), ndc, divided, + ConstantF32Value(state, 1.0f)); return ndc; } @@ -390,16 +387,16 @@ uint32_t ConvertPositionToClipSpace(EmitterState& state, uint32_t position) { uint32_t components[4] {}; for (uint32_t i = 0; i < 4; i++) { components[i] = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeF32(state), components[i], position, i}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeF32(state), components[i], position, + i); } components[0] = ConvertClipCoordinate(state, components[0], transform.scale[0], transform.offset[0], transform.half_extent[0]); components[1] = ConvertClipCoordinate(state, components[1], transform.scale[1], transform.offset[1], transform.half_extent[1]); const auto converted = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeF32Vector(state, 4), converted, - components[0], components[1], components[2], components[3]}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(state, 4), converted, + components[0], components[1], components[2], components[3]); return converted; } @@ -411,17 +408,17 @@ uint32_t EmitWqmU64(EmitterState& state, uint32_t value) { const auto merged_two = state.builder.AllocateId(); const auto quad_bits = state.builder.AllocateId(); const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpShiftRightLogical, TypeU64(state), shifted_one, value, - ConstantU64(state, 0x0000000100000001ull)}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU64(state), merged_one, value, shifted_one}); - state.builder.AddFunction({spv::OpShiftRightLogical, TypeU64(state), shifted_two, merged_one, - ConstantU64(state, 0x0000000200000002ull)}); - state.builder.AddFunction( - {spv::OpBitwiseOr, TypeU64(state), merged_two, merged_one, shifted_two}); - state.builder.AddFunction({spv::OpBitwiseAnd, TypeU64(state), quad_bits, merged_two, - ConstantU64(state, 0x1111111111111111ull)}); - state.builder.AddFunction({spv::OpIMul, TypeU64(state), result, quad_bits, - ConstantU64(state, 0x0000000f0000000full)}); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU64(state), shifted_one, value, + ConstantU64(state, 0x0000000100000001ull)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU64(state), merged_one, value, shifted_one); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU64(state), shifted_two, merged_one, + ConstantU64(state, 0x0000000200000002ull)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU64(state), merged_two, merged_one, + shifted_two); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU64(state), quad_bits, merged_two, + ConstantU64(state, 0x1111111111111111ull)); + state.builder.AddFunction(spv::OpIMul, TypeU64(state), result, quad_bits, + ConstantU64(state, 0x0000000f0000000full)); return result; } @@ -432,9 +429,9 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) { if (state.program.stage == ShaderType::Pixel && exp.vm && state.requirements.pixel_valid_mask && state.pixel_valid_mask_variable != 0) { const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), value, exec, - ConstantU32(state, 1), ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpStore, state.pixel_valid_mask_variable, value}); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), value, exec, ConstantU32(state, 1), + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpStore, state.pixel_valid_mask_variable, value); } if (exp.kind == IR::ExportTargetKind::Null || exp.en == 0u) { return; @@ -443,8 +440,8 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) { const auto data = ctx.Arg(inst, 0); if (exp.kind == IR::ExportTargetKind::Primitive) { if (state.program.stage == ShaderType::Mesh) { - state.builder.AddFunction( - {spv::OpStore, MeshPrimitivePointer(state), ExportRawComponent(ctx, data, 0)}); + state.builder.AddFunction(spv::OpStore, MeshPrimitivePointer(state), + ExportRawComponent(ctx, data, 0)); } return; } @@ -456,19 +453,18 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) { if ((exp.en & 1u) != 0u && state.depth_variable != 0) { const auto raw = ExportRawComponent(ctx, data, 0); const auto f32 = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeF32(state), f32, raw}); - state.builder.AddFunction({spv::OpStore, state.depth_variable, f32}); + state.builder.AddFunction(spv::OpBitcast, TypeF32(state), f32, raw); + state.builder.AddFunction(spv::OpStore, state.depth_variable, f32); } if ((exp.en & 4u) != 0u && state.sample_mask_variable != 0) { const auto raw = ExportRawComponent(ctx, data, 2); const auto value = state.builder.AllocateId(); const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeI32(state), value, raw}); + state.builder.AddFunction(spv::OpBitcast, TypeI32(state), value, raw); state.builder.AddFunction( - {spv::OpAccessChain, - TypePointer(state, spv::StorageClassOutput, TypeI32(state)), pointer, - state.sample_mask_variable, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpStore, pointer, value}); + spv::OpAccessChain, TypePointer(state, spv::StorageClassOutput, TypeI32(state)), + pointer, state.sample_mask_variable, ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpStore, pointer, value); } return; } @@ -485,9 +481,9 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) { const auto mapping = state.input_info.pixel->target_export_mapping[exp.index]; if (!mapping.IsIdentity()) { const auto mapped = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpVectorShuffle, vector_type, mapped, value, value, - mapping.Map(0), mapping.Map(1), mapping.Map(2), - mapping.Map(3)}); + state.builder.AddFunction(spv::OpVectorShuffle, vector_type, mapped, value, value, + mapping.Map(0), mapping.Map(1), mapping.Map(2), + mapping.Map(3)); value = mapped; } } @@ -499,17 +495,17 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) { const auto kind = exp.kind == IR::ExportTargetKind::Position ? IR::StageOutputKind::Position : IR::StageOutputKind::Parameter; - state.builder.AddFunction( - {spv::OpStore, MeshOutputPointer(state, kind, exp.index), value}); + state.builder.AddFunction(spv::OpStore, MeshOutputPointer(state, kind, exp.index), + value); } else if (exp.kind == IR::ExportTargetKind::Position) { const auto pointer = state.builder.AllocateId(); state.builder.AddFunction( - {spv::OpAccessChain, - TypePointer(state, spv::StorageClassOutput, TypeF32Vector(state, 4)), pointer, - variable, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpStore, pointer, value}); + spv::OpAccessChain, + TypePointer(state, spv::StorageClassOutput, TypeF32Vector(state, 4)), pointer, + variable, ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpStore, pointer, value); } else { - state.builder.AddFunction({spv::OpStore, variable, value}); + state.builder.AddFunction(spv::OpStore, variable, value); } }); } @@ -523,9 +519,9 @@ void EmitVoid(ValueEmitContext&) {} void EmitBarrier(EmitterState& state) { const auto semantics = spv::MemorySemanticsAcquireReleaseMask | spv::MemorySemanticsWorkgroupMemoryMask; - state.builder.AddFunction({spv::OpControlBarrier, ConstantU32(state, spv::ScopeWorkgroup), - ConstantU32(state, spv::ScopeWorkgroup), - ConstantU32(state, semantics)}); + state.builder.AddFunction(spv::OpControlBarrier, ConstantU32(state, spv::ScopeWorkgroup), + ConstantU32(state, spv::ScopeWorkgroup), + ConstantU32(state, semantics)); } uint32_t EmitMeshDrawParameter(ValueEmitContext& ctx, const IR::Inst& inst) { @@ -536,10 +532,10 @@ uint32_t EmitMeshDrawParameter(ValueEmitContext& ctx, const IR::Inst& inst) { ctx.Fail(inst, "invalid mesh draw parameter"); } const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypePushConstantElementPointer(state), pointer, - state.push_constant_variable, ConstantU32(state, 0), - ConstantU32(state, index)}); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), result, pointer}); + state.builder.AddFunction(spv::OpAccessChain, TypePushConstantElementPointer(state), pointer, + state.push_constant_variable, ConstantU32(state, 0), + ConstantU32(state, index)); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), result, pointer); return result; } @@ -559,7 +555,7 @@ uint32_t EmitGetBuiltin(ValueEmitContext& ctx, IR::Value kind, IR::Value index) uint32_t EmitUndefU1(EmitterState& state, const IR::Inst& inst) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpUndef, TypeId(state, inst.GetType()), result}); + state.builder.AddFunction(spv::OpUndef, TypeId(state, inst.GetType()), result); return result; } @@ -574,8 +570,8 @@ uint32_t EmitDppMoveU32(ValueEmitContext& ctx, const IR::Inst& inst) { const auto ballot = ctx.Ballot(inst.Arg(1)); const auto source_active = EmitBallotLaneActiveBool(state, ballot, target.lane); const auto can_fetch = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpLogicalAnd, TypeBool(state), can_fetch, target.valid, source_active}); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), can_fetch, target.valid, + source_active); return EmitNative(ctx.state, can_fetch, shuffled, ConstantU32(state, 0)); } @@ -604,8 +600,8 @@ uint32_t EmitReadLane(ValueEmitContext& ctx, const IR::Inst& inst) { uint32_t EmitWriteLane(ValueEmitContext& ctx, const IR::Inst& inst) { auto& state = ctx.state; const auto hit = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpIEqual, TypeBool(state), hit, - EmitSubgroupLocalInvocationId(state), ctx.Arg(inst, 2)}); + state.builder.AddFunction(spv::OpIEqual, TypeBool(state), hit, + EmitSubgroupLocalInvocationId(state), ctx.Arg(inst, 2)); return EmitNative(ctx.state, hit, ctx.Arg(inst, 1), ctx.Arg(inst, 0)); } @@ -624,35 +620,35 @@ uint32_t EmitPermlane16U32(ValueEmitContext& ctx, const IR::Inst& inst) { const auto shifted = state.builder.AllocateId(); const auto index = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), row, subid, ConstantU32(state, 0xfffffff0u)}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), row, subid, + ConstantU32(state, 0xfffffff0u)); if (flags.x16) { - state.builder.AddFunction( - {spv::OpBitwiseXor, TypeU32(state), row_value, row, ConstantU32(state, 16)}); + state.builder.AddFunction(spv::OpBitwiseXor, TypeU32(state), row_value, row, + ConstantU32(state, 16)); } else { - state.builder.AddFunction({spv::OpCopyObject, TypeU32(state), row_value, row}); + state.builder.AddFunction(spv::OpCopyObject, TypeU32(state), row_value, row); } - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, 15)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane8, lane, ConstantU32(state, 7)}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), shift, lane8, ConstantU32(state, 2)}); - state.builder.AddFunction( - {spv::OpUGreaterThanEqual, TypeBool(state), upper, lane, ConstantU32(state, 8)}); - state.builder.AddFunction( - {spv::OpSelect, TypeU32(state), selected, upper, ctx.Arg(inst, 2), ctx.Arg(inst, 1)}); - state.builder.AddFunction({spv::OpShiftRightLogical, TypeU32(state), shifted, selected, shift}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), index, shifted, ConstantU32(state, 15)}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, row_value, index}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid, + ConstantU32(state, 15)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane8, lane, + ConstantU32(state, 7)); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), shift, lane8, + ConstantU32(state, 2)); + state.builder.AddFunction(spv::OpUGreaterThanEqual, TypeBool(state), upper, lane, + ConstantU32(state, 8)); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), selected, upper, ctx.Arg(inst, 2), + ctx.Arg(inst, 1)); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), shifted, selected, shift); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), index, shifted, + ConstantU32(state, 15)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, row_value, index); const auto shuffled = ctx.Shuffle(inst, 0, target); uint32_t result = shuffled; if (!flags.fetch_inactive) { const auto source_exec = ctx.Shuffle(inst, 3, target); result = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpSelect, TypeU32(state), result, source_exec, shuffled, ConstantU32(state, 0)}); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), result, source_exec, shuffled, + ConstantU32(state, 0)); } return result; } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterHelpers.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterHelpers.cpp index eddc02c11..6640a5974 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterHelpers.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterHelpers.cpp @@ -9,17 +9,17 @@ DppTargetLane EmitDppQuadPermTargetLane(EmitterState& state, uint32_t subid, uin const auto selected0 = state.builder.AllocateId(); const auto selected = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), quad_base, subid, ConstantU32(state, 0xfffffffcu)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, 3)}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), shift, lane, ConstantU32(state, 1)}); - state.builder.AddFunction( - {spv::OpShiftRightLogical, TypeU32(state), selected0, ConstantU32(state, control), shift}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), selected, selected0, ConstantU32(state, 3)}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, quad_base, selected}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), quad_base, subid, + ConstantU32(state, 0xfffffffcu)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid, + ConstantU32(state, 3)); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), shift, lane, + ConstantU32(state, 1)); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), selected0, + ConstantU32(state, control), shift); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), selected, selected0, + ConstantU32(state, 3)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, quad_base, selected); return {target, ConstantBool(state, true)}; } @@ -30,22 +30,22 @@ DppTargetLane EmitDppRowShiftTargetLane(EmitterState& state, uint32_t subid, uin const auto lane_shifted = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); const auto valid = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), row, subid, ConstantU32(state, 0xfffffff0u)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, 15)}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), row, subid, + ConstantU32(state, 0xfffffff0u)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid, + ConstantU32(state, 15)); if (left) { - state.builder.AddFunction( - {spv::OpIAdd, TypeU32(state), lane_shifted, lane, ConstantU32(state, amount)}); - state.builder.AddFunction( - {spv::OpULessThan, TypeBool(state), valid, lane, ConstantU32(state, 16u - amount)}); + state.builder.AddFunction(spv::OpIAdd, TypeU32(state), lane_shifted, lane, + ConstantU32(state, amount)); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), valid, lane, + ConstantU32(state, 16u - amount)); } else { - state.builder.AddFunction( - {spv::OpISub, TypeU32(state), lane_shifted, lane, ConstantU32(state, amount)}); - state.builder.AddFunction( - {spv::OpUGreaterThanEqual, TypeBool(state), valid, lane, ConstantU32(state, amount)}); + state.builder.AddFunction(spv::OpISub, TypeU32(state), lane_shifted, lane, + ConstantU32(state, amount)); + state.builder.AddFunction(spv::OpUGreaterThanEqual, TypeBool(state), valid, lane, + ConstantU32(state, amount)); } - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, row, lane_shifted}); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, row, lane_shifted); return {target, valid}; } @@ -58,18 +58,17 @@ DppTargetLane EmitDppRowRotateRightTargetLane(EmitterState& state, uint32_t subi const auto plus = state.builder.AllocateId(); const auto selected = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), row, subid, ConstantU32(state, 0xfffffff0u)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, 15)}); - state.builder.AddFunction( - {spv::OpUGreaterThanEqual, TypeBool(state), in_high, lane, ConstantU32(state, amount)}); - state.builder.AddFunction( - {spv::OpISub, TypeU32(state), minus, lane, ConstantU32(state, amount)}); - state.builder.AddFunction( - {spv::OpIAdd, TypeU32(state), plus, lane, ConstantU32(state, 16u - amount)}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), selected, in_high, minus, plus}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, row, selected}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), row, subid, + ConstantU32(state, 0xfffffff0u)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid, + ConstantU32(state, 15)); + state.builder.AddFunction(spv::OpUGreaterThanEqual, TypeBool(state), in_high, lane, + ConstantU32(state, amount)); + state.builder.AddFunction(spv::OpISub, TypeU32(state), minus, lane, ConstantU32(state, amount)); + state.builder.AddFunction(spv::OpIAdd, TypeU32(state), plus, lane, + ConstantU32(state, 16u - amount)); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), selected, in_high, minus, plus); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, row, selected); return {target, ConstantBool(state, true)}; } @@ -80,13 +79,13 @@ DppTargetLane EmitDppMirrorTargetLane(EmitterState& state, uint32_t subid, bool const auto lane = state.builder.AllocateId(); const auto mirrored = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), base, subid, ConstantU32(state, base_mask)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, lane_mask)}); - state.builder.AddFunction( - {spv::OpISub, TypeU32(state), mirrored, ConstantU32(state, lane_mask), lane}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, base, mirrored}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), base, subid, + ConstantU32(state, base_mask)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid, + ConstantU32(state, lane_mask)); + state.builder.AddFunction(spv::OpISub, TypeU32(state), mirrored, ConstantU32(state, lane_mask), + lane); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, base, mirrored); return {target, ConstantBool(state, true)}; } @@ -112,8 +111,8 @@ DppTargetLane EmitDppTargetLane(EmitterState& state, uint32_t control) { } if (control >= 0x160u && control <= 0x16fu) { const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseXor, TypeU32(state), target, subid, ConstantU32(state, control & 0xfu)}); + state.builder.AddFunction(spv::OpBitwiseXor, TypeU32(state), target, subid, + ConstantU32(state, control & 0xfu)); return {target, ConstantBool(state, true)}; } return {subid, ConstantBool(state, true)}; @@ -124,8 +123,8 @@ uint32_t EmitSubgroupLocalInvocationId(EmitterState& state) { EXIT("SubgroupLocalInvocationId was not declared before SPIR-V function emission\n"); } const auto value = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpLoad, TypeU32(state), value, state.subgroup_local_invocation_id_variable}); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, + state.subgroup_local_invocation_id_variable); return state.lane_half == 0 ? value : EmitAddU32(state, value, ConstantU32(state, 32)); } @@ -154,10 +153,10 @@ uint32_t EmitInputComponentU32(EmitterState& state, IR::StageInputKind kind, uin } const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, - TypePointer(state, spv::StorageClassInput, TypeU32(state)), pointer, - variable, ConstantU32(state, component)}); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, pointer}); + state.builder.AddFunction(spv::OpAccessChain, + TypePointer(state, spv::StorageClassInput, TypeU32(state)), pointer, + variable, ConstantU32(state, component)); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer); return value; } @@ -167,7 +166,7 @@ uint32_t EmitLocalInvocationIndex(EmitterState& state) { return ConstantU32(state, 0); } const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, variable}); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, variable); if (state.lane_count == 2) { const auto wave_base = EmitBinaryU32(state, spv::OpBitwiseAnd, value, ConstantU32(state, ~31u)); @@ -184,13 +183,13 @@ uint32_t EmitVertexParameterComponentU32(EmitterState& state, const InputBinding const auto scalar_type = VertexParameterScalarType(state, kind); uint32_t raw = state.builder.AllocateId(); if (count == 1u) { - state.builder.AddFunction({spv::OpLoad, scalar_type, raw, input.variable_id}); + state.builder.AddFunction(spv::OpLoad, scalar_type, raw, input.variable_id); } else { const auto pointer_type = TypePointer(state, spv::StorageClassInput, scalar_type); const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, pointer_type, pointer, input.variable_id, - ConstantU32(state, component)}); - state.builder.AddFunction({spv::OpLoad, scalar_type, raw, pointer}); + state.builder.AddFunction(spv::OpAccessChain, pointer_type, pointer, input.variable_id, + ConstantU32(state, component)); + state.builder.AddFunction(spv::OpLoad, scalar_type, raw, pointer); } if (kind == VertexInputScalarKind::Uint) { @@ -198,49 +197,48 @@ uint32_t EmitVertexParameterComponentU32(EmitterState& state, const InputBinding } const auto bits = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeU32(state), bits, raw}); + state.builder.AddFunction(spv::OpBitcast, TypeU32(state), bits, raw); return bits; } uint32_t EmitSubgroupLaneActiveBool(EmitterState& state, uint32_t lane) { const auto active_ballot = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpGroupNonUniformBallot, TypeU32Vector(state, 4), active_ballot, - ConstantU32(state, spv::ScopeSubgroup), ConstantBool(state, true)}); + state.builder.AddFunction(spv::OpGroupNonUniformBallot, TypeU32Vector(state, 4), active_ballot, + ConstantU32(state, spv::ScopeSubgroup), ConstantBool(state, true)); return EmitBallotLaneActiveBool(state, active_ballot, lane); } uint32_t EmitBallotLaneActiveBool(EmitterState& state, uint32_t active_ballot, uint32_t lane) { const auto low = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), low, active_ballot, 0}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), low, active_ballot, 0); uint32_t mask = low; if (state.program.wave_size == 64u) { const auto high = state.builder.AllocateId(); const auto in_high = state.builder.AllocateId(); const auto selected = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(state), high, active_ballot, 1}); - state.builder.AddFunction( - {spv::OpUGreaterThanEqual, TypeBool(state), in_high, lane, ConstantU32(state, 32)}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), selected, in_high, high, low}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), high, active_ballot, 1); + state.builder.AddFunction(spv::OpUGreaterThanEqual, TypeBool(state), in_high, lane, + ConstantU32(state, 32)); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), selected, in_high, high, low); mask = selected; } const auto lane_low = state.builder.AllocateId(); const auto bit = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane_low, lane, ConstantU32(state, 31)}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), bit, ConstantU32(state, 1), lane_low}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane_low, lane, + ConstantU32(state, 31)); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), bit, ConstantU32(state, 1), + lane_low); const auto hit = state.builder.AllocateId(); const auto active = state.builder.AllocateId(); const auto in_range = state.builder.AllocateId(); const auto ret = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitwiseAnd, TypeU32(state), hit, mask, bit}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), active, hit, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpULessThan, TypeBool(state), in_range, lane, - ConstantU32(state, state.program.wave_size)}); - state.builder.AddFunction({spv::OpLogicalAnd, TypeBool(state), ret, active, in_range}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), hit, mask, bit); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), active, hit, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), in_range, lane, + ConstantU32(state, state.program.wave_size)); + state.builder.AddFunction(spv::OpLogicalAnd, TypeBool(state), ret, active, in_range); return ret; } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterImage.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterImage.cpp index 8952d4b54..daa18b36d 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterImage.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterImage.cpp @@ -90,14 +90,14 @@ uint32_t CubeAxis(EmitterState& state, uint32_t value) { uint32_t CubeLayer(EmitterState& state, uint32_t value) { const auto guest = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertFToU, TypeU32(state), guest, value}); + state.builder.AddFunction(spv::OpConvertFToU, TypeU32(state), guest, value); const auto padding = Binary( state, spv::OpShiftLeftLogical, TypeU32(state), Binary(state, spv::OpShiftRightLogical, TypeU32(state), guest, ConstantU32(state, 3)), ConstantU32(state, 1)); const auto host = Binary(state, spv::OpISub, TypeU32(state), guest, padding); const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertUToF, TypeF32(state), result, host}); + state.builder.AddFunction(spv::OpConvertUToF, TypeF32(state), result, host); return result; } @@ -118,11 +118,11 @@ uint32_t CoordF32(ValueEmitContext& ctx, const IR::MemoryInfo& mem, const IR::In ? AddressF32(ctx, mem, address, first + 2u) : ZeroF32(ctx.state); if (cube) z = CubeLayer(ctx.state, z); - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeF32Vector(ctx.state, 3), result, x, y, z}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(ctx.state, 3), + result, x, y, z); } else { - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeF32Vector(ctx.state, 2), result, x, y}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeF32Vector(ctx.state, 2), + result, x, y); } return result; } @@ -138,11 +138,11 @@ uint32_t CoordU32(ValueEmitContext& ctx, const IR::MemoryInfo& mem, const IR::In if (components == 3u) { const auto z = mem.image_address_components > 2u ? AddressU32(ctx, mem, address, 2) : ConstantU32(ctx.state, 0); - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 3), result, x, y, z}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 3), + result, x, y, z); } else { - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 2), result, x, y}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 2), + result, x, y); } return result; } @@ -193,9 +193,9 @@ uint32_t ResultVector(ValueEmitContext& ctx, uint32_t value, if (dref) return value; const auto component = gather ? index : DmaskComponent(mem.dmask, index); const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeExtract, - ImageScalarType(ctx.state, value_class), result, value, - component}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, + ImageScalarType(ctx.state, value_class), result, value, + component); return result; }; for (uint32_t word = 0; word < mem.data_dwords; word++) { @@ -218,17 +218,16 @@ uint32_t ResultVector(ValueEmitContext& ctx, uint32_t value, ConstantU32(ctx.state, 16u))); } else { const auto pair = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeF32Vector(ctx.state, 2), pair, low, high}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, + TypeF32Vector(ctx.state, 2), pair, low, high); packed[word] = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpExtInst, TypeU32(ctx.state), packed[word], - GlslStd450(ctx.state), GLSLstd450PackHalf2x16, - pair}); + ctx.state.builder.AddFunction(spv::OpExtInst, TypeU32(ctx.state), packed[word], + GlslStd450(ctx.state), GLSLstd450PackHalf2x16, pair); } } const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), - result, packed[0], packed[1], packed[2], packed[3]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), + result, packed[0], packed[1], packed[2], packed[3]); return result; } uint32_t component[4] {}; @@ -238,14 +237,13 @@ uint32_t ResultVector(ValueEmitContext& ctx, uint32_t value, continue; } const auto scalar = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeExtract, - ImageScalarType(ctx.state, value_class), scalar, value, - index}); + ctx.state.builder.AddFunction( + spv::OpCompositeExtract, ImageScalarType(ctx.state, value_class), scalar, value, index); component[index] = SampledComponentBits(ctx, scalar, value_class); } const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, - component[0], component[1], component[2], component[3]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, + component[0], component[1], component[2], component[3]); return result; } @@ -256,12 +254,12 @@ uint32_t QueryDimensions(ValueEmitContext& ctx, const IR::MemoryInfo& mem, const auto image = LoadSampledImageDescriptor(ctx.state, mem.resource); const auto size = ctx.state.builder.AllocateId(); if (info.multisampled != 0u) { - ctx.state.builder.AddFunction( - {spv::OpImageQuerySize, ImageViewSizeType(ctx.state, dimension), size, image}); + ctx.state.builder.AddFunction(spv::OpImageQuerySize, + ImageViewSizeType(ctx.state, dimension), size, image); } else { - ctx.state.builder.AddFunction({spv::OpImageQuerySizeLod, - ImageViewSizeType(ctx.state, dimension), size, image, - AddressU32(ctx, mem, address, 0)}); + ctx.state.builder.AddFunction(spv::OpImageQuerySizeLod, + ImageViewSizeType(ctx.state, dimension), size, image, + AddressU32(ctx, mem, address, 0)); } const auto components = info.coordinate_components; uint32_t result[4] = {ConstantU32(ctx.state, 0), ConstantU32(ctx.state, 0), @@ -271,18 +269,18 @@ uint32_t QueryDimensions(ValueEmitContext& ctx, const IR::MemoryInfo& mem, } else { for (uint32_t index = 0; index < components; index++) { result[index] = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(ctx.state), result[index], size, index}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), + result[index], size, index); } } if (info.multisampled == 0u) { result[3] = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpImageQueryLevels, TypeU32(ctx.state), result[3], image}); + ctx.state.builder.AddFunction(spv::OpImageQueryLevels, TypeU32(ctx.state), result[3], + image); } const auto vector = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), vector, - result[0], result[1], result[2], result[3]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), vector, + result[0], result[1], result[2], result[3]); return vector; } @@ -294,11 +292,11 @@ uint32_t PackedOffset(ValueEmitContext& ctx, const IR::MemoryInfo& mem, const IR if (components == 1u) return zero; const auto result = ctx.state.builder.AllocateId(); if (components == 3u) { - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 3), result, zero, zero, zero}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 3), + result, zero, zero, zero); } else { - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 2), result, zero, zero}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 2), + result, zero, zero); } return result; } @@ -307,18 +305,18 @@ uint32_t PackedOffset(ValueEmitContext& ctx, const IR::MemoryInfo& mem, const IR uint32_t values[3] = {zero, zero, zero}; for (uint32_t index = 0; index < components; index++) { values[index] = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpBitFieldSExtract, TypeI32(ctx.state), values[index], - packed, ConstantU32(ctx.state, index * 8u), - ConstantU32(ctx.state, 6)}); + ctx.state.builder.AddFunction(spv::OpBitFieldSExtract, TypeI32(ctx.state), values[index], + packed, ConstantU32(ctx.state, index * 8u), + ConstantU32(ctx.state, 6)); } if (components == 1u) return values[0]; const auto result = ctx.state.builder.AllocateId(); if (components == 3u) { - ctx.state.builder.AddFunction({spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 3), - result, values[0], values[1], values[2]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 3), + result, values[0], values[1], values[2]); } else { - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 2), result, values[0], values[1]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeI32Vector(ctx.state, 2), + result, values[0], values[1]); } return result; } @@ -327,7 +325,7 @@ uint32_t HorizontalOffsets(EmitterState& state, ImageDimension dimension) { const auto components = ImageDimensionInfoFor(dimension).spatial_components; const auto count = ConstantU32(state, 4); const auto element_type = components == 1u ? TypeI32(state) : TypeI32Vector(state, 2); - const auto array_type = state.builder.Type(spv::OpTypeArray, {element_type, count}); + const auto array_type = state.builder.Type(spv::OpTypeArray, element_type, count); uint32_t offsets[4] {}; for (uint32_t index = 0; index < 4u; index++) { const auto x = ConstantI32(state, static_cast(index) - 1); @@ -335,11 +333,11 @@ uint32_t HorizontalOffsets(EmitterState& state, ImageDimension dimension) { offsets[index] = x; } else { offsets[index] = state.builder.Constant( - spv::OpConstantComposite, TypeI32Vector(state, 2), {x, ConstantI32(state, 0)}); + spv::OpConstantComposite, TypeI32Vector(state, 2), x, ConstantI32(state, 0)); } } - return state.builder.Constant(spv::OpConstantComposite, array_type, - {offsets[0], offsets[1], offsets[2], offsets[3]}); + return state.builder.Constant(spv::OpConstantComposite, array_type, offsets[0], offsets[1], + offsets[2], offsets[3]); } uint32_t InverseSwizzle(uint32_t swizzle, uint32_t component) { @@ -367,15 +365,15 @@ uint32_t UnpackImageTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint if (info.format == Prospero::BufferFormat::kInvalid) return texel; const auto packed = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(ctx.state), packed, texel, 0u}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), packed, texel, 0u); uint32_t components[4] = {ConstantU32(ctx.state, 0), ConstantU32(ctx.state, 0), ConstantU32(ctx.state, 0), ConstantU32(ctx.state, 0)}; for (uint32_t component = 0; component < info.component_count; component++) { components[component] = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpBitFieldUExtract, TypeU32(ctx.state), - components[component], packed, - ConstantU32(ctx.state, info.component_bit_offset[component]), - ConstantU32(ctx.state, info.component_bits[component])}); + ctx.state.builder.AddFunction(spv::OpBitFieldUExtract, TypeU32(ctx.state), + components[component], packed, + ConstantU32(ctx.state, info.component_bit_offset[component]), + ConstantU32(ctx.state, info.component_bits[component])); } for (uint32_t component = info.component_count; component < 4u; component++) { components[component] = components[component % info.component_count]; @@ -394,8 +392,8 @@ uint32_t UnpackImageTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint } } const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, - selected[0], selected[1], selected[2], selected[3]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, + selected[0], selected[1], selected[2], selected[3]); return result; } @@ -409,24 +407,24 @@ uint32_t UnpackImageGather(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uin if (selector < 4u) { const auto value = ConstantU32(ctx.state, selector == 1u ? 1u : 0u); return ctx.state.builder.Constant(spv::OpConstantComposite, TypeU32Vector(ctx.state, 4), - {value, value, value, value}); + value, value, value, value); } uint32_t values[4] {}; for (uint32_t lane = 0; lane < 4u; lane++) { const auto packed = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(ctx.state), packed, gathered, lane}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), packed, gathered, + lane); values[lane] = ctx.state.builder.AllocateId(); const auto physical = (selector - 4u) % info.component_count; - ctx.state.builder.AddFunction({spv::OpBitFieldUExtract, TypeU32(ctx.state), values[lane], - packed, - ConstantU32(ctx.state, info.component_bit_offset[physical]), - ConstantU32(ctx.state, info.component_bits[physical])}); + ctx.state.builder.AddFunction(spv::OpBitFieldUExtract, TypeU32(ctx.state), values[lane], + packed, + ConstantU32(ctx.state, info.component_bit_offset[physical]), + ConstantU32(ctx.state, info.component_bits[physical])); } const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, - values[0], values[1], values[2], values[3]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, + values[0], values[1], values[2], values[3]); return result; } @@ -436,16 +434,16 @@ uint32_t EmitOneDimensionalGatherLz(ValueEmitContext& ctx, const IR::MemoryInfo& state.builder.RequireCapability(spv::CapabilityImageQuery); const auto image = LoadSampledImageDescriptor(state, mem.resource); const auto width = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpImageQuerySizeLod, TypeU32(state), width, image, ConstantU32(state, 0)}); + state.builder.AddFunction(spv::OpImageQuerySizeLod, TypeU32(state), width, image, + ConstantU32(state, 0)); const auto width_f32 = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertUToF, TypeF32(state), width_f32, width}); + state.builder.AddFunction(spv::OpConvertUToF, TypeF32(state), width_f32, width); const auto left = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpExtInst, TypeF32(state), left, GlslStd450(state), - GLSLstd450Floor, - Binary(state, spv::OpFSub, TypeF32(state), - Binary(state, spv::OpFMul, TypeF32(state), coord, width_f32), - ConstantF32(state, 0x3f000000u))}); + state.builder.AddFunction(spv::OpExtInst, TypeF32(state), left, GlslStd450(state), + GLSLstd450Floor, + Binary(state, spv::OpFSub, TypeF32(state), + Binary(state, spv::OpFMul, TypeF32(state), coord, width_f32), + ConstantF32(state, 0x3f000000u))); const auto sampled = MakeSampledImage(state, mem.resource, mem.sampler); const auto vector_type = ImageVectorType(state, numeric_class, 4); @@ -462,15 +460,15 @@ uint32_t EmitOneDimensionalGatherLz(ValueEmitContext& ctx, const IR::MemoryInfo& ConstantF32(state, index == 0u ? 0x3f000000u : 0x3fc00000u)), width_f32); const auto texel = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpImageSampleExplicitLod, vector_type, texel, sampled, - sample_coord, spv::ImageOperandsLodMask, ZeroF32(state)}); + state.builder.AddFunction(spv::OpImageSampleExplicitLod, vector_type, texel, sampled, + sample_coord, spv::ImageOperandsLodMask, ZeroF32(state)); values[index] = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, scalar_type, values[index], texel, component}); + state.builder.AddFunction(spv::OpCompositeExtract, scalar_type, values[index], texel, + component); } const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, vector_type, result, values[0], values[1], - values[1], values[0]}); + state.builder.AddFunction(spv::OpCompositeConstruct, vector_type, result, values[0], values[1], + values[1], values[0]); return result; } @@ -481,8 +479,8 @@ uint32_t PackImageTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint32 auto packed = ConstantU32(ctx.state, 0u); for (uint32_t component = 0; component < info.component_count; component++) { const auto value = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(ctx.state), value, texel, component}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), value, texel, + component); const auto maximum = ConstantU32(ctx.state, info.component_bits[component] == 32u ? UINT32_MAX @@ -490,8 +488,8 @@ uint32_t PackImageTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint32 const auto within = Binary(ctx.state, spv::OpULessThan, TypeBool(ctx.state), value, maximum); const auto clamped = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpSelect, TypeU32(ctx.state), clamped, within, value, maximum}); + ctx.state.builder.AddFunction(spv::OpSelect, TypeU32(ctx.state), clamped, within, value, + maximum); const auto shifted = info.component_bit_offset[component] == 0u ? clamped @@ -501,8 +499,8 @@ uint32_t PackImageTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint32 } const auto zero = ConstantU32(ctx.state, 0u); const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, packed, zero, zero, zero}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(ctx.state, 4), result, + packed, zero, zero, zero); return result; } @@ -516,9 +514,8 @@ uint32_t StoreTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint32_t d if (source < 4u && ((dmask >> source) & 1u) != 0u) { const auto packed_index = DmaskComponentIndex(dmask, source); raw = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(ctx.state), raw, data, - mem.data_bits == 16u ? packed_index / 2u : packed_index}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), raw, data, + mem.data_bits == 16u ? packed_index / 2u : packed_index); if (mem.data_bits == 16u) { if ((packed_index & 1u) != 0u) { raw = Binary(ctx.state, spv::OpShiftRightLogical, TypeU32(ctx.state), raw, @@ -534,14 +531,14 @@ uint32_t StoreTexel(ValueEmitContext& ctx, const IR::MemoryInfo& mem, uint32_t d : Unary(ctx.state, spv::OpBitcast, TypeF32(ctx.state), raw); } const auto texel = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpCompositeConstruct, - integer ? TypeU32Vector(ctx.state, 4) : TypeF32Vector(ctx.state, 4), texel, values[0], - values[1], values[2], values[3]}); + ctx.state.builder.AddFunction(spv::OpCompositeConstruct, + integer ? TypeU32Vector(ctx.state, 4) + : TypeF32Vector(ctx.state, 4), + texel, values[0], values[1], values[2], values[3]); return PackImageTexel(ctx, mem, texel); } -uint32_t ImageAtomicOpcode(IR::ValueOpcode opcode) { +spv::Op ImageAtomicOpcode(IR::ValueOpcode opcode) { switch (opcode) { case IR::ValueOpcode::ImageAtomicSwap32: return spv::OpAtomicExchange; case IR::ValueOpcode::ImageAtomicIAdd32: return spv::OpAtomicIAdd; @@ -550,7 +547,7 @@ uint32_t ImageAtomicOpcode(IR::ValueOpcode opcode) { case IR::ValueOpcode::ImageAtomicAnd32: return spv::OpAtomicAnd; case IR::ValueOpcode::ImageAtomicOr32: return spv::OpAtomicOr; case IR::ValueOpcode::ImageAtomicXor32: return spv::OpAtomicXor; - default: return 0; + default: return spv::OpNop; } } @@ -576,19 +573,19 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { const auto sampled = MakeSampledImage(state, mem.resource, mem.sampler); const auto lod = state.builder.AllocateId(); state.builder.AddFunction( - {spv::OpImageQueryLod, TypeF32Vector(state, 2), lod, sampled, - CoordF32(ctx, mem, *address, 0, ImageDimensionInfoFor(dimension).spatial_components)}); + spv::OpImageQueryLod, TypeF32Vector(state, 2), lod, sampled, + CoordF32(ctx, mem, *address, 0, ImageDimensionInfoFor(dimension).spatial_components)); uint32_t values[4] = {ConstantU32(state, 0), ConstantU32(state, 0), ConstantU32(state, 0), ConstantU32(state, 0)}; for (uint32_t index = 0; index < 2u; index++) { const auto component = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeF32(state), component, lod, index}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeF32(state), component, lod, + index); values[index] = FloatBits(ctx, component); } const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(state, 4), result, - values[0], values[1], values[2], values[3]}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(state, 4), result, + values[0], values[1], values[2], values[3]); ctx.Define(inst, result); return; } @@ -607,14 +604,14 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { const auto coord = CoordU32(ctx, mem, *address, dimension); if (dimension_info.multisampled != 0u) { state.builder.AddFunction( - {spv::OpImageFetch, ImageVectorType(state, numeric_class, 4), color, - descriptor, coord, spv::ImageOperandsSampleMask, - AddressU32(ctx, mem, *address, dimension_info.coordinate_components)}); + spv::OpImageFetch, ImageVectorType(state, numeric_class, 4), color, + descriptor, coord, spv::ImageOperandsSampleMask, + AddressU32(ctx, mem, *address, dimension_info.coordinate_components)); } else { - state.builder.AddFunction({spv::OpImageFetch, - ImageVectorType(state, numeric_class, 4), color, - descriptor, coord, spv::ImageOperandsLodMask, - LodU32(ctx, mem, *address, dimension)}); + state.builder.AddFunction(spv::OpImageFetch, + ImageVectorType(state, numeric_class, 4), color, + descriptor, coord, spv::ImageOperandsLodMask, + LodU32(ctx, mem, *address, dimension)); } return ResultVector(ctx, UnpackImageTexel(ctx, mem, color), numeric_class, false, mem); @@ -711,7 +708,7 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { HasFlag(mem, Decoder::ImageSampleFlagLod) || HasFlag(mem, Decoder::ImageSampleFlagLevelZero) || state.program.stage != ShaderType::Pixel; - uint32_t opcode = spv::OpImageSampleImplicitLod; + auto opcode = spv::OpImageSampleImplicitLod; if (explicit_lod) { opcode = dref ? spv::OpImageSampleDrefExplicitLod : spv::OpImageSampleExplicitLod; } else if (dref) { @@ -748,15 +745,15 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { const auto EmitSample = [&](uint32_t resource) { const auto sampled = MakeSampledImage(state, resource, mem.sampler); const auto sample = state.builder.AllocateId(); - std::vector words {opcode, result_type, sample, sampled, coord}; + std::vector sample_operands {result_type, sample, sampled, coord}; if (dref) { - words.push_back(dref_value); + sample_operands.push_back(dref_value); } if (operand_mask != 0u) { - words.push_back(operand_mask); - words.insert(words.end(), operands.begin(), operands.end()); + sample_operands.push_back(operand_mask); + sample_operands.insert(sample_operands.end(), operands.begin(), operands.end()); } - state.builder.AddFunction(words); + state.builder.AddFunction(opcode, sample_operands); return sample; }; if (image.indirect_root != mem.resource) { @@ -785,11 +782,11 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { } const auto LoadMapping = [&](uint32_t index) { const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypeStorageBufferElementPointer(state), - pointer, state.flattened_srt_variable, ConstantU32(state, 0), - index}); + state.builder.AddFunction(spv::OpAccessChain, TypeStorageBufferElementPointer(state), + pointer, state.flattened_srt_variable, ConstantU32(state, 0), + index); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, pointer}); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer); return value; }; const auto mapping = ConstantU32(state, image.indirect_mapping_offset); @@ -802,9 +799,9 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { const auto mid = Binary(state, spv::OpShiftRightLogical, TypeU32(state), Binary(state, spv::OpIAdd, TypeU32(state), low, high), ConstantU32(state, 1u)); - const auto probe = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpSelect, TypeU32(state), probe, active, mid, ConstantU32(state, 0u)}); + const auto probe = state.builder.AllocateId(); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), probe, active, mid, + ConstantU32(state, 0u)); const auto entry = Binary(state, spv::OpIAdd, TypeU32(state), mapping, Binary(state, spv::OpIAdd, TypeU32(state), Binary(state, spv::OpShiftLeftLogical, TypeU32(state), @@ -816,8 +813,8 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { const auto equal = Binary(state, spv::OpIEqual, TypeBool(state), mapped_key, key); const auto match = Binary(state, spv::OpLogicalAnd, TypeBool(state), active, equal); const auto next_selected = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpSelect, TypeU32(state), next_selected, match, candidate, selected}); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), next_selected, match, + candidate, selected); selected = next_selected; const auto less = Binary(state, spv::OpULessThan, TypeBool(state), mapped_key, key); const auto take_upper = Binary(state, spv::OpLogicalAnd, TypeBool(state), active, less); @@ -825,12 +822,12 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { Unary(state, spv::OpLogicalNot, TypeBool(state), less)); const auto next_low = state.builder.AllocateId(); state.builder.AddFunction( - {spv::OpSelect, TypeU32(state), next_low, take_upper, - Binary(state, spv::OpIAdd, TypeU32(state), mid, ConstantU32(state, 1u)), low}); + spv::OpSelect, TypeU32(state), next_low, take_upper, + Binary(state, spv::OpIAdd, TypeU32(state), mid, ConstantU32(state, 1u)), low); low = next_low; const auto next_high = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpSelect, TypeU32(state), next_high, take_lower, mid, high}); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), next_high, take_lower, mid, + high); high = next_high; } const auto default_label = state.builder.AllocateId(); @@ -842,19 +839,19 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { switch_words.push_back(candidate); switch_words.push_back(labels[candidate - 1u]); } - state.builder.AddFunction( - {spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone}); + state.builder.AddFunction(spv::OpSelectionMerge, merge_label, + spv::SelectionControlMaskNone); state.builder.AddFunction(switch_words); std::vector phi_words {spv::OpPhi, result_type, state.builder.AllocateId()}; EmitLabel(state, default_label); phi_words.push_back(EmitSample(image.indirect_resources[0])); phi_words.push_back(default_label); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); for (uint32_t candidate = 1; candidate < image.indirect_resources.size(); candidate++) { EmitLabel(state, labels[candidate - 1u]); phi_words.push_back(EmitSample(image.indirect_resources[candidate])); phi_words.push_back(labels[candidate - 1u]); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); } EmitLabel(state, merge_label); state.builder.AddFunction(phi_words); @@ -866,21 +863,21 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) { return; } const auto atomic_opcode = ImageAtomicOpcode(op); - if (atomic_opcode != 0u) { + if (atomic_opcode != spv::OpNop) { const auto dimension = image.dimension; ctx.Define(inst, EmitValueOrZeroIfCondition(state, ctx.Arg(inst, 3), [&]() { - const auto pointer = state.builder.AllocateId(); + const auto pointer = state.builder.AllocateId(); const auto pointer_type = state.builder.Type( - spv::OpTypePointer, {spv::StorageClassImage, TypeU32(state)}); - state.builder.AddFunction( - {spv::OpImageTexelPointer, pointer_type, pointer, - StorageImageDescriptorPointer(state, mem.resource), - CoordU32(ctx, mem, *address, dimension), ConstantU32(state, 0)}); + spv::OpTypePointer, spv::StorageClassImage, TypeU32(state)); + state.builder.AddFunction(spv::OpImageTexelPointer, pointer_type, pointer, + StorageImageDescriptorPointer(state, mem.resource), + CoordU32(ctx, mem, *address, dimension), + ConstantU32(state, 0)); const auto old = state.builder.AllocateId(); - state.builder.AddFunction({atomic_opcode, TypeU32(state), old, pointer, - ConstantU32(state, spv::ScopeDevice), - ConstantU32(state, spv::MemorySemanticsMaskNone), - ctx.Arg(inst, 2)}); + state.builder.AddFunction(atomic_opcode, TypeU32(state), old, pointer, + ConstantU32(state, spv::ScopeDevice), + ConstantU32(state, spv::MemorySemanticsMaskNone), + ctx.Arg(inst, 2)); EmitDeviceAtomicMemoryBarrier(state); return old; })); diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h index 5c296c1fd..3b692ca04 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterInternal.h @@ -151,7 +151,7 @@ uint32_t TypeU32ElementPointer(EmitterState& state, spv::StorageClass storage_cl inline void EmitLabel(EmitterState& state, uint32_t label) { state.current_label = label; - state.builder.AddFunction({spv::OpLabel, label}); + state.builder.AddFunction(spv::OpLabel, label); } uint32_t TypeId(EmitterState& state, IR::Type type); @@ -160,7 +160,7 @@ uint32_t TypeId(EmitterState& state, IR::Type type); template uint32_t EmitNative(EmitterState& state, Args... args) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({opcode, TypeId(state, type), result, args...}); + state.builder.AddFunction(opcode, TypeId(state, type), result, args...); return result; } @@ -171,23 +171,23 @@ uint32_t EmitGlsl(EmitterState& state, Args... args) { return EmitNative(state, GlslStd450(state), opcode, args...); } -inline uint32_t Unary(EmitterState& state, uint32_t opcode, uint32_t type, uint32_t value) { +inline uint32_t Unary(EmitterState& state, spv::Op opcode, uint32_t type, uint32_t value) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({opcode, type, result, value}); + state.builder.AddFunction(opcode, type, result, value); return result; } -inline uint32_t Binary(EmitterState& state, uint32_t opcode, uint32_t type, uint32_t lhs, +inline uint32_t Binary(EmitterState& state, spv::Op opcode, uint32_t type, uint32_t lhs, uint32_t rhs) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({opcode, type, result, lhs, rhs}); + state.builder.AddFunction(opcode, type, result, lhs, rhs); return result; } inline uint32_t Select(EmitterState& state, uint32_t type, uint32_t condition, uint32_t true_value, uint32_t false_value) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpSelect, type, result, condition, true_value, false_value}); + state.builder.AddFunction(spv::OpSelect, type, result, condition, true_value, false_value); return result; } @@ -350,7 +350,7 @@ uint32_t EmitSubgroupLaneActiveBool(EmitterState& state, uint32_t lane); inline constexpr auto EmitAddU32 = EmitNative; -uint32_t EmitBinaryU32(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs); +uint32_t EmitBinaryU32(EmitterState& state, spv::Op opcode, uint32_t lhs, uint32_t rhs); uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index); @@ -417,7 +417,7 @@ uint32_t EmitShiftRightConstant(EmitterState& state, uint32_t value, uint32_t sh inline constexpr auto EmitOrU32 = EmitNative; -uint32_t EmitCompareU32Constant(EmitterState& state, uint32_t opcode, uint32_t value, +uint32_t EmitCompareU32Constant(EmitterState& state, spv::Op opcode, uint32_t value, uint32_t constant); uint32_t EmitSubConstantMinusU32(EmitterState& state, uint32_t constant, uint32_t value); @@ -474,11 +474,11 @@ template void EmitIfCondition(EmitterState& state, uint32_t condition, Fn&& fn) { const auto then_label = state.builder.AllocateId(); const auto merge_label = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone}); - state.builder.AddFunction({spv::OpBranchConditional, condition, then_label, merge_label}); + state.builder.AddFunction(spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone); + state.builder.AddFunction(spv::OpBranchConditional, condition, then_label, merge_label); EmitLabel(state, then_label); fn(); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); EmitLabel(state, merge_label); } @@ -489,19 +489,19 @@ uint32_t EmitValueOrDefaultIfCondition(EmitterState& state, uint32_t condition, const auto then_exit = state.builder.AllocateId(); const auto else_label = state.builder.AllocateId(); const auto merge_label = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone}); - state.builder.AddFunction({spv::OpBranchConditional, condition, then_label, else_label}); + state.builder.AddFunction(spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone); + state.builder.AddFunction(spv::OpBranchConditional, condition, then_label, else_label); EmitLabel(state, then_label); const auto then_value = fn(); - state.builder.AddFunction({spv::OpBranch, then_exit}); + state.builder.AddFunction(spv::OpBranch, then_exit); EmitLabel(state, then_exit); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); EmitLabel(state, else_label); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); EmitLabel(state, merge_label); const auto value = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpPhi, type, value, then_value, then_exit, default_value, else_label}); + state.builder.AddFunction(spv::OpPhi, type, value, then_value, then_exit, default_value, + else_label); return value; } @@ -528,30 +528,29 @@ uint32_t AtomicUpdate(EmitterState& state, uint32_t pointer, IR::ResourceKind ki const auto initial = state.builder.AllocateId(); const auto observed = state.builder.AllocateId(); const auto exchanged = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBranch, preheader}); + state.builder.AddFunction(spv::OpBranch, preheader); EmitLabel(state, preheader); - state.builder.AddFunction({spv::OpAtomicLoad, TypeU32(state), initial, pointer, - ConstantU32(state, scope), - ConstantU32(state, spv::MemorySemanticsMaskNone)}); - state.builder.AddFunction({spv::OpBranch, header}); + state.builder.AddFunction(spv::OpAtomicLoad, TypeU32(state), initial, pointer, + ConstantU32(state, scope), + ConstantU32(state, spv::MemorySemanticsMaskNone)); + state.builder.AddFunction(spv::OpBranch, header); EmitLabel(state, header); - state.builder.AddFunction( - {spv::OpPhi, TypeU32(state), observed, initial, preheader, exchanged, cont}); + state.builder.AddFunction(spv::OpPhi, TypeU32(state), observed, initial, preheader, exchanged, + cont); const auto next = desired(observed); - state.builder.AddFunction({spv::OpAtomicCompareExchange, TypeU32(state), exchanged, pointer, - ConstantU32(state, scope), - ConstantU32(state, spv::MemorySemanticsMaskNone), - ConstantU32(state, spv::MemorySemanticsMaskNone), next, observed}); + state.builder.AddFunction(spv::OpAtomicCompareExchange, TypeU32(state), exchanged, pointer, + ConstantU32(state, scope), + ConstantU32(state, spv::MemorySemanticsMaskNone), + ConstantU32(state, spv::MemorySemanticsMaskNone), next, observed); const auto success = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpIEqual, TypeBool(state), success, exchanged, observed}); - state.builder.AddFunction({spv::OpLoopMerge, merge, cont, spv::LoopControlMaskNone}); - state.builder.AddFunction({spv::OpBranchConditional, success, merge, cont}); + state.builder.AddFunction(spv::OpIEqual, TypeBool(state), success, exchanged, observed); + state.builder.AddFunction(spv::OpLoopMerge, merge, cont, spv::LoopControlMaskNone); + state.builder.AddFunction(spv::OpBranchConditional, success, merge, cont); EmitLabel(state, cont); - state.builder.AddFunction({spv::OpBranch, header}); + state.builder.AddFunction(spv::OpBranch, header); EmitLabel(state, merge); - state.builder.AddFunction( - {spv::OpMemoryBarrier, ConstantU32(state, scope), - ConstantU32(state, spv::MemorySemanticsAcquireReleaseMask | memory)}); + state.builder.AddFunction(spv::OpMemoryBarrier, ConstantU32(state, scope), + ConstantU32(state, spv::MemorySemanticsAcquireReleaseMask | memory)); return observed; } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp index 9e0dfa1c2..a1decba73 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemory.cpp @@ -17,11 +17,11 @@ uint32_t EmitDsMaskedLaneRead(EmitterState& state, uint32_t source, uint32_t tar target = Binary(state, spv::OpBitwiseAnd, TypeU32(state), target, ConstantU32(state, 31)); } const auto shuffled = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpGroupNonUniformShuffle, TypeU32(state), shuffled, - ConstantU32(state, spv::ScopeSubgroup), source, target}); + state.builder.AddFunction(spv::OpGroupNonUniformShuffle, TypeU32(state), shuffled, + ConstantU32(state, spv::ScopeSubgroup), source, target); const auto source_exec = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpGroupNonUniformShuffle, TypeBool(state), source_exec, - ConstantU32(state, spv::ScopeSubgroup), exec, target}); + state.builder.AddFunction(spv::OpGroupNonUniformShuffle, TypeBool(state), source_exec, + ConstantU32(state, spv::ScopeSubgroup), exec, target); const auto source_active = AndCondition(state, source_exec, EmitSubgroupLaneActiveBool(state, target)); return Select(state, TypeU32(state), source_active, shuffled, ConstantU32(state, 0)); @@ -107,9 +107,9 @@ uint32_t ScratchByteAddress(ValueEmitContext& ctx, const IR::MemoryInfo& mem, ui } uint32_t ConstantDeviceAddress(EmitterState& state, uint64_t value) { - return state.builder.Constant( - spv::OpConstant, TypeScalarU64(state), - {static_cast(value), static_cast(value >> 32u)}); + return state.builder.Constant(spv::OpConstant, TypeScalarU64(state), + static_cast(value), + static_cast(value >> 32u)); } uint32_t DeviceAddressFromWords(EmitterState& state, uint32_t low, uint32_t high) { @@ -153,8 +153,8 @@ uint32_t GuestAddress(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Mem uint32_t FaultElementPointer(EmitterState& state, uint32_t index) { const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypeStorageBufferElementPointer(state), pointer, - state.fault_buffer_variable, ConstantU32(state, 0), index}); + state.builder.AddFunction(spv::OpAccessChain, TypeStorageBufferElementPointer(state), pointer, + state.fault_buffer_variable, ConstantU32(state, 0), index); return pointer; } @@ -166,16 +166,16 @@ void RecordBdaFault(EmitterState& state, uint32_t page) { Binary(state, spv::OpBitwiseAnd, TypeU32(state), page, ConstantU32(state, 31))); const auto pointer = FaultElementPointer(state, word); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, pointer}); - state.builder.AddFunction( - {spv::OpStore, pointer, Binary(state, spv::OpBitwiseOr, TypeU32(state), value, bit)}); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer); + state.builder.AddFunction(spv::OpStore, pointer, + Binary(state, spv::OpBitwiseOr, TypeU32(state), value, bit)); } uint32_t GetBdaPointer(ValueEmitContext& ctx, uint32_t address) { auto& state = ctx.state; const auto result = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpFunctionCall, TypeScalarU64(state), result, state.bda_pointer_function, address}); + state.builder.AddFunction(spv::OpFunctionCall, TypeScalarU64(state), result, + state.bda_pointer_function, address); return result; } @@ -186,11 +186,12 @@ uint32_t LoadBdaDword(ValueEmitContext& ctx, uint32_t address) { Binary(state, spv::OpINotEqual, TypeBool(state), bda, ConstantDeviceAddress(state, 0)); return EmitValueOrZeroIfCondition(state, present, [&]() { const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpConvertUToPtr, TypePhysicalU32Pointer(state), pointer, bda}); - const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, pointer, - spv::MemoryAccessAlignedMask, sizeof(uint32_t)}); + state.builder.AddFunction(spv::OpConvertUToPtr, TypePhysicalU32Pointer(state), pointer, + bda); + const auto value = state.builder.AllocateId(); + constexpr uint32_t alignment = sizeof(uint32_t); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer, + spv::MemoryAccessAlignedMask, alignment); return value; }); } @@ -306,7 +307,7 @@ uint32_t LoadWordInBounds(ValueEmitContext& ctx, const MemoryResourceAccess& res uint32_t index) { const auto value = ctx.state.builder.AllocateId(); const auto pointer = EmitMemoryElementPointer(ctx.state, resource, index); - ctx.state.builder.AddFunction({spv::OpLoad, TypeU32(ctx.state), value, pointer}); + ctx.state.builder.AddFunction(spv::OpLoad, TypeU32(ctx.state), value, pointer); return value; } @@ -401,11 +402,11 @@ uint32_t LoadFormattedComponent(ValueEmitContext& ctx, const IR::MemoryInfo& mem const auto source_value = type == TypeI32(ctx.state) ? Unary(ctx.state, spv::OpBitcast, type, raw) : raw; const auto extracted = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {IsSignedFormatComponent(info.type) ? spv::OpBitFieldSExtract : spv::OpBitFieldUExtract, - type, extracted, source_value, - ConstantU32(ctx.state, info.component_bit_offset[component]), - ConstantU32(ctx.state, bits)}); + ctx.state.builder.AddFunction(IsSignedFormatComponent(info.type) ? spv::OpBitFieldSExtract + : spv::OpBitFieldUExtract, + type, extracted, source_value, + ConstantU32(ctx.state, info.component_bit_offset[component]), + ConstantU32(ctx.state, bits)); raw = type == TypeI32(ctx.state) ? Unary(ctx.state, spv::OpBitcast, TypeU32(ctx.state), extracted) : extracted; @@ -465,8 +466,8 @@ void StoreSubwordInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem, }; if (mem.kind == IR::ResourceKind::Scratch) { const auto old = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpLoad, TypeU32(ctx.state), old, pointer}); - ctx.state.builder.AddFunction({spv::OpStore, pointer, merge(old)}); + ctx.state.builder.AddFunction(spv::OpLoad, TypeU32(ctx.state), old, pointer); + ctx.state.builder.AddFunction(spv::OpStore, pointer, merge(old)); } else { AtomicUpdate(ctx.state, pointer, mem.kind, merge); } @@ -495,15 +496,15 @@ void StoreWordPrepared(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Me const MemoryResourceAccess& resource, uint32_t data) { const auto index = EmitMemoryElementIndex(ctx.state, resource, DwordIndex(ctx, inst, mem)); EmitIfCondition(ctx.state, EmitMemoryElementInBounds(ctx.state, resource, index), [&]() { - ctx.state.builder.AddFunction( - {spv::OpStore, EmitMemoryElementPointer(ctx.state, resource, index), data}); + ctx.state.builder.AddFunction(spv::OpStore, + EmitMemoryElementPointer(ctx.state, resource, index), data); }); } void StoreWordInBounds(ValueEmitContext& ctx, const MemoryResourceAccess& resource, uint32_t index, uint32_t data) { - ctx.state.builder.AddFunction( - {spv::OpStore, EmitMemoryElementPointer(ctx.state, resource, index), data}); + ctx.state.builder.AddFunction(spv::OpStore, + EmitMemoryElementPointer(ctx.state, resource, index), data); } void StoreWord(ValueEmitContext& ctx, const IR::Inst& inst, IR::MemoryInfo mem) { @@ -538,7 +539,7 @@ void FormattedStore(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Memor }); } -uint32_t SpirvAtomicOpcode(IR::ValueOpcode opcode) { +spv::Op SpirvAtomicOpcode(IR::ValueOpcode opcode) { switch (opcode) { case IR::ValueOpcode::BufferAtomicCmpSwap32: return spv::OpAtomicCompareExchange; case IR::ValueOpcode::BufferAtomicSwap32: @@ -563,7 +564,7 @@ uint32_t SpirvAtomicOpcode(IR::ValueOpcode opcode) { case IR::ValueOpcode::SharedAtomicOr32: return spv::OpAtomicOr; case IR::ValueOpcode::BufferAtomicXor32: case IR::ValueOpcode::SharedAtomicXor32: return spv::OpAtomicXor; - default: return 0; + default: return spv::OpNop; } } @@ -574,15 +575,14 @@ uint32_t EmitAtomicOperation(ValueEmitContext& ctx, const IR::Inst& inst, uint32 const auto desired = ctx.Arg(inst, inst.NumArgs() - 3); const auto comparator = ctx.Arg(inst, inst.NumArgs() - 2); ctx.state.builder.AddFunction( - {spv::OpAtomicCompareExchange, TypeU32(ctx.state), old, pointer, - ConstantU32(ctx.state, scope), ConstantU32(ctx.state, spv::MemorySemanticsMaskNone), - ConstantU32(ctx.state, spv::MemorySemanticsMaskNone), desired, comparator}); + spv::OpAtomicCompareExchange, TypeU32(ctx.state), old, pointer, + ConstantU32(ctx.state, scope), ConstantU32(ctx.state, spv::MemorySemanticsMaskNone), + ConstantU32(ctx.state, spv::MemorySemanticsMaskNone), desired, comparator); } else { const auto value = ctx.Arg(inst, inst.NumArgs() - 2); - ctx.state.builder.AddFunction({SpirvAtomicOpcode(inst.GetOpcode()), TypeU32(ctx.state), old, - pointer, ConstantU32(ctx.state, scope), - ConstantU32(ctx.state, spv::MemorySemanticsMaskNone), - value}); + ctx.state.builder.AddFunction(SpirvAtomicOpcode(inst.GetOpcode()), TypeU32(ctx.state), old, + pointer, ConstantU32(ctx.state, scope), + ConstantU32(ctx.state, spv::MemorySemanticsMaskNone), value); } return old; } @@ -782,8 +782,8 @@ void StoreWideBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t compo EmitIfCondition(state, plan.in_bounds, [&]() { for (uint32_t component = 0; component < components; component++) { const auto data = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(state), data, composite, component}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), data, + composite, component); StoreFormattedInBounds(ctx, mem, plan, component, data); } }); @@ -791,8 +791,8 @@ void StoreWideBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t compo } for (uint32_t component = 0; component < components; component++) { const auto data = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpCompositeExtract, TypeU32(state), data, composite, component}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), data, composite, + component); StoreWordPrepared(ctx, inst, RebaseRawComponent(mem, component), resource, data); } }); @@ -851,49 +851,49 @@ void DefineGetBdaPointer(EmitterState& state) { return; } const auto type = TypeScalarU64(state); - const auto function_type = state.builder.Type(spv::OpTypeFunction, {type, type}); + const auto function_type = state.builder.Type(spv::OpTypeFunction, type, type); state.bda_pointer_function = state.builder.AllocateId(); const auto address = state.builder.AllocateId(); const auto entry_label = state.builder.AllocateId(); state.builder.AddName(state.bda_pointer_function, "get_bda_pointer"); - state.builder.AddFunction({spv::OpFunction, type, state.bda_pointer_function, - spv::FunctionControlMaskNone, function_type}); - state.builder.AddFunction({spv::OpFunctionParameter, type, address}); + state.builder.AddFunction(spv::OpFunction, type, state.bda_pointer_function, + spv::FunctionControlMaskNone, function_type); + state.builder.AddFunction(spv::OpFunctionParameter, type, address); EmitLabel(state, entry_label); const auto page64 = Binary(state, spv::OpShiftRightLogical, type, address, ConstantDeviceAddress(state, BufferCache::CACHING_PAGEBITS)); const auto page = Unary(state, spv::OpUConvert, TypeU32(state), page64); const auto entry_pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypeStorageBufferU64ElementPointer(state), - entry_pointer, state.bda_pagetable_variable, ConstantU32(state, 0), - page}); + state.builder.AddFunction(spv::OpAccessChain, TypeStorageBufferU64ElementPointer(state), + entry_pointer, state.bda_pagetable_variable, ConstantU32(state, 0), + page); const auto base = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, type, base, entry_pointer}); + state.builder.AddFunction(spv::OpLoad, type, base, entry_pointer); const auto missing = Binary(state, spv::OpIEqual, TypeBool(state), base, ConstantDeviceAddress(state, 0)); const auto fault_label = state.builder.AllocateId(); const auto available_label = state.builder.AllocateId(); const auto merge_label = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone}); - state.builder.AddFunction({spv::OpBranchConditional, missing, fault_label, available_label}); + state.builder.AddFunction(spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone); + state.builder.AddFunction(spv::OpBranchConditional, missing, fault_label, available_label); EmitLabel(state, fault_label); RecordBdaFault(state, page); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); EmitLabel(state, available_label); const auto offset = Binary(state, spv::OpBitwiseAnd, type, address, ConstantDeviceAddress(state, BufferCache::CACHING_PAGESIZE - 1)); const auto available = Binary(state, spv::OpIAdd, type, base, offset); - state.builder.AddFunction({spv::OpBranch, merge_label}); + state.builder.AddFunction(spv::OpBranch, merge_label); EmitLabel(state, merge_label); const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpPhi, type, result, ConstantDeviceAddress(state, 0), - fault_label, available, available_label}); - state.builder.AddFunction({spv::OpReturnValue, result}); - state.builder.AddFunction({spv::OpFunctionEnd}); + state.builder.AddFunction(spv::OpPhi, type, result, ConstantDeviceAddress(state, 0), + fault_label, available, available_label); + state.builder.AddFunction(spv::OpReturnValue, result); + state.builder.AddFunction(spv::OpFunctionEnd); } uint32_t EmitAtomic32(ValueEmitContext& ctx, const IR::Inst& inst) { @@ -905,8 +905,8 @@ uint32_t EmitAtomic32(ValueEmitContext& ctx, const IR::Inst& inst) { if (mem.kind == IR::ResourceKind::Lds) { const auto semantics = spv::MemorySemanticsAcquireReleaseMask | spv::MemorySemanticsWorkgroupMemoryMask; - ctx.state.builder.AddFunction({spv::OpMemoryBarrier, ConstantU32(ctx.state, scope), - ConstantU32(ctx.state, semantics)}); + ctx.state.builder.AddFunction(spv::OpMemoryBarrier, ConstantU32(ctx.state, scope), + ConstantU32(ctx.state, semantics)); } else { EmitDeviceAtomicMemoryBarrier(ctx.state); } @@ -932,11 +932,11 @@ uint32_t EmitBufferAtomic64(ValueEmitContext& ctx, const IR::Inst& inst) { ctx.Arg(inst, inst.NumArgs() - 2)); const auto old = state.builder.AllocateId(); state.builder.AddFunction( - {SpirvAtomicOpcode(inst.GetOpcode()), TypeScalarU64(state), old, - EmitStorageBufferElementPointer(state, resource, index, - TypeStorageBufferU64ElementPointer(state)), - ConstantU32(state, spv::ScopeDevice), - ConstantU32(state, spv::MemorySemanticsMaskNone), value}); + SpirvAtomicOpcode(inst.GetOpcode()), TypeScalarU64(state), old, + EmitStorageBufferElementPointer(state, resource, index, + TypeStorageBufferU64ElementPointer(state)), + ConstantU32(state, spv::ScopeDevice), + ConstantU32(state, spv::MemorySemanticsMaskNone), value); EmitDeviceAtomicMemoryBarrier(state); return Unary(state, spv::OpBitcast, TypeU64(state), old); }); @@ -959,11 +959,11 @@ void EmitSharedFloatAtomic(ValueEmitContext& ctx, const IR::Inst& inst) { const auto access = PrepareMemoryElement(ctx, mem, DwordIndex(ctx, inst, mem)); EmitIfCondition( ctx.state, EmitMemoryElementInBounds(ctx.state, access.resource, access.index), [&]() { - ctx.state.builder.AddFunction( - {spv::OpStore, ctx.scratch_u32_variable, ctx.Arg(inst, 1)}); + ctx.state.builder.AddFunction(spv::OpStore, ctx.scratch_u32_variable, + ctx.Arg(inst, 1)); const auto data = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction( - {spv::OpLoad, TypeU32(ctx.state), data, ctx.scratch_u32_variable}); + ctx.state.builder.AddFunction(spv::OpLoad, TypeU32(ctx.state), data, + ctx.scratch_u32_variable); AtomicUpdate( ctx.state, EmitMemoryElementPointer(ctx.state, access.resource, access.index), mem.kind, [&](uint32_t old) { @@ -1006,8 +1006,8 @@ uint32_t EmitAppendConsume(ValueEmitContext& ctx, const IR::Inst& inst) { const auto ballot = ctx.Ballot(inst.Arg(1)); const auto low = state.builder.AllocateId(); const auto high = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), low, ballot, 0}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), high, ballot, 1}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), low, ballot, 0); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), high, ballot, 1); const auto count = Binary(state, spv::OpIAdd, TypeU32(state), Unary(state, spv::OpBitCount, TypeU32(state), low), Unary(state, spv::OpBitCount, TypeU32(state), high)); @@ -1033,17 +1033,17 @@ uint32_t EmitAppendConsume(ValueEmitContext& ctx, const IR::Inst& inst) { AndCondition(state, storage_bounds, m0_bounds))); const auto atomic = EmitValueOrZeroIfCondition(state, condition, [&]() { const auto value = state.builder.AllocateId(); - state.builder.AddFunction( - {append ? spv::OpAtomicIAdd : spv::OpAtomicISub, TypeU32(state), value, - EmitMemoryElementPointer(state, access, index), - ConstantU32(state, mem.kind == IR::ResourceKind::Gds ? spv::ScopeDevice - : spv::ScopeWorkgroup), - ConstantU32(state, spv::MemorySemanticsMaskNone), count}); + state.builder.AddFunction(append ? spv::OpAtomicIAdd : spv::OpAtomicISub, TypeU32(state), + value, EmitMemoryElementPointer(state, access, index), + ConstantU32(state, mem.kind == IR::ResourceKind::Gds + ? spv::ScopeDevice + : spv::ScopeWorkgroup), + ConstantU32(state, spv::MemorySemanticsMaskNone), count); return value; }); const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpGroupNonUniformShuffle, TypeU32(state), result, - ConstantU32(state, spv::ScopeSubgroup), atomic, source_lane}); + state.builder.AddFunction(spv::OpGroupNonUniformShuffle, TypeU32(state), result, + ConstantU32(state, spv::ScopeSubgroup), atomic, source_lane); return result; } @@ -1053,9 +1053,9 @@ uint32_t EmitReadConst(ValueEmitContext& ctx, const IR::Inst& inst) { ctx.Fail(inst, "requires the flattened SRT descriptor"); } const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypeStorageBufferElementPointer(state), pointer, - state.flattened_srt_variable, ConstantU32(state, 0), - ctx.Arg(inst, 1)}); + state.builder.AddFunction(spv::OpAccessChain, TypeStorageBufferElementPointer(state), pointer, + state.flattened_srt_variable, ConstantU32(state, 0), + ctx.Arg(inst, 1)); return EmitNative(state, pointer); } @@ -1131,7 +1131,7 @@ uint32_t EmitSharedIncDec(ValueEmitContext& ctx, const IR::Inst& inst) { uint32_t EmitSwizzleU32(ValueEmitContext& ctx, const IR::Inst& inst) { auto& state = ctx.state; - state.builder.AddFunction({spv::OpStore, ctx.scratch_u32_variable, ctx.Arg(inst, 0)}); + state.builder.AddFunction(spv::OpStore, ctx.scratch_u32_variable, ctx.Arg(inst, 0)); const auto source = EmitNative(state, ctx.scratch_u32_variable); const auto target = EmitDsSwizzleTargetLane(state, EmitSubgroupLocalInvocationId(state), inst.Arg(1).IsImmediate() ? inst.Arg(1).U32() : 0); diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp index 197498743..b7c8b3951 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMemoryHelpers.cpp @@ -7,27 +7,27 @@ uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index) { dword_index += state.program.bindings.push_data_start_dword; const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypePushConstantElementPointer(state), - pointer, state.push_constant_variable, ConstantU32(state, 0), - ConstantU32(state, dword_index)}); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, pointer}); + state.builder.AddFunction(spv::OpAccessChain, TypePushConstantElementPointer(state), + pointer, state.push_constant_variable, ConstantU32(state, 0), + ConstantU32(state, dword_index)); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer); return value; } if (state.shader_data_storage_variable != 0) { const auto pointer = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, TypeStorageBufferElementPointer(state), - pointer, state.shader_data_storage_variable, - ConstantU32(state, 0), ConstantU32(state, dword_index)}); - state.builder.AddFunction({spv::OpLoad, TypeU32(state), value, pointer}); + state.builder.AddFunction(spv::OpAccessChain, TypeStorageBufferElementPointer(state), + pointer, state.shader_data_storage_variable, + ConstantU32(state, 0), ConstantU32(state, dword_index)); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer); return value; } return ConstantU32(state, 0); } -uint32_t EmitBinaryU32(EmitterState& state, uint32_t opcode, uint32_t lhs, uint32_t rhs) { +uint32_t EmitBinaryU32(EmitterState& state, spv::Op opcode, uint32_t lhs, uint32_t rhs) { const auto ret = state.builder.AllocateId(); - state.builder.AddFunction({opcode, TypeU32(state), ret, lhs, rhs}); + state.builder.AddFunction(opcode, TypeU32(state), ret, lhs, rhs); return ret; } @@ -88,12 +88,12 @@ MemoryResourceAccess PrepareStorageBufferResourceAccess(EmitterState& state, ResourceForDescriptor(state, IR::DescriptorBindingKind::Buffers, mem.resource); MemoryResourceAccess access {.kind = mem.kind}; access.object_pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, pointer_type, access.object_pointer, variable, - ConstantU32(state, array_index)}); + state.builder.AddFunction(spv::OpAccessChain, pointer_type, access.object_pointer, variable, + ConstantU32(state, array_index)); access.byte_offset = state.memory_byte_offsets[array_index]; access.length = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpArrayLength, TypeU32(state), access.length, access.object_pointer, 0}); + state.builder.AddFunction(spv::OpArrayLength, TypeU32(state), access.length, + access.object_pointer, 0); return access; } @@ -139,8 +139,8 @@ MemoryResourceAccess PrepareMemoryResourceAccess(EmitterState& state, const IR:: default: EXIT("unsupported memory resource kind: %u\n", static_cast(mem.kind)); } access.length = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpArrayLength, TypeU32(state), access.length, access.object_pointer, 0}); + state.builder.AddFunction(spv::OpArrayLength, TypeU32(state), access.length, + access.object_pointer, 0); return access; } @@ -152,7 +152,7 @@ uint32_t EmitMemoryElementIndex(EmitterState& state, const MemoryResourceAccess& uint32_t EmitMemoryElementInBounds(EmitterState& state, const MemoryResourceAccess& access, uint32_t index) { const auto in_bounds = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpULessThan, TypeBool(state), in_bounds, index, access.length}); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), in_bounds, index, access.length); return in_bounds; } @@ -165,8 +165,8 @@ uint32_t EmitMemoryElementPointer(EmitterState& state, const MemoryResourceAcces : ShaderWorkgroupInput(state.program.stage, state.input_info) != nullptr ? spv::StorageClassWorkgroup : spv::StorageClassFunction; - state.builder.AddFunction({spv::OpAccessChain, TypeU32ElementPointer(state, storage_class), - pointer, access.object_pointer, index}); + state.builder.AddFunction(spv::OpAccessChain, TypeU32ElementPointer(state, storage_class), + pointer, access.object_pointer, index); return pointer; } return EmitStorageBufferElementPointer(state, access, index, @@ -177,14 +177,14 @@ uint32_t EmitStorageBufferElementPointer(EmitterState& state, const MemoryResourceAccess& access, uint32_t index, uint32_t pointer_type) { const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpAccessChain, pointer_type, pointer, access.object_pointer, - ConstantU32(state, 0), index}); + state.builder.AddFunction(spv::OpAccessChain, pointer_type, pointer, access.object_pointer, + ConstantU32(state, 0), index); return pointer; } uint32_t EmitTBufferBitcastU32ToI32(EmitterState& state, uint32_t value) { const auto ret = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitcast, TypeI32(state), ret, value}); + state.builder.AddFunction(spv::OpBitcast, TypeI32(state), ret, value); return ret; } @@ -218,10 +218,10 @@ uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits) { const auto mantissa_f32 = state.builder.AllocateId(); const auto subnormal = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertUToF, TypeF32(state), mantissa_f32, mantissa}); + state.builder.AddFunction(spv::OpConvertUToF, TypeF32(state), mantissa_f32, mantissa); state.builder.AddFunction( - {spv::OpFMul, TypeF32(state), subnormal, mantissa_f32, - ConstantF32Value(state, std::ldexp(1.0f, 1 - 15 - static_cast(mantissa_bits)))}); + spv::OpFMul, TypeF32(state), subnormal, mantissa_f32, + ConstantF32Value(state, std::ldexp(1.0f, 1 - 15 - static_cast(mantissa_bits)))); const auto zero_exp = EmitCompareU32Constant(state, spv::OpIEqual, exponent, 0); const auto special_exp = EmitCompareU32Constant(state, spv::OpIEqual, exponent, 31); @@ -238,22 +238,22 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma case Format::ComponentType::Sint: return raw; case Format::ComponentType::Uscaled: { const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertUToF, TypeF32(state), value, raw}); + state.builder.AddFunction(spv::OpConvertUToF, TypeF32(state), value, raw); return EmitBitcastF32ToU32(state, value); } case Format::ComponentType::Sscaled: { const auto signed_raw = EmitTBufferBitcastU32ToI32(state, raw); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpConvertSToF, TypeF32(state), value, signed_raw}); + state.builder.AddFunction(spv::OpConvertSToF, TypeF32(state), value, signed_raw); return EmitBitcastF32ToU32(state, value); } case Format::ComponentType::Unorm: { const auto value = state.builder.AllocateId(); const auto normalized = state.builder.AllocateId(); const auto max_value = static_cast((1u << bits) - 1u); - state.builder.AddFunction({spv::OpConvertUToF, TypeF32(state), value, raw}); - state.builder.AddFunction({spv::OpFDiv, TypeF32(state), normalized, value, - ConstantF32Value(state, max_value)}); + state.builder.AddFunction(spv::OpConvertUToF, TypeF32(state), value, raw); + state.builder.AddFunction(spv::OpFDiv, TypeF32(state), normalized, value, + ConstantF32Value(state, max_value)); return EmitBitcastF32ToU32(state, normalized); } case Format::ComponentType::Snorm: { @@ -262,11 +262,11 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma const auto normalized = state.builder.AllocateId(); const auto clamped = state.builder.AllocateId(); const auto max_value = static_cast((1u << (bits - 1u)) - 1u); - state.builder.AddFunction({spv::OpConvertSToF, TypeF32(state), value, signed_raw}); - state.builder.AddFunction({spv::OpFDiv, TypeF32(state), normalized, value, - ConstantF32Value(state, max_value)}); - state.builder.AddFunction({spv::OpExtInst, TypeF32(state), clamped, GlslStd450(state), - GLSLstd450FMax, normalized, ConstantF32Value(state, -1.0f)}); + state.builder.AddFunction(spv::OpConvertSToF, TypeF32(state), value, signed_raw); + state.builder.AddFunction(spv::OpFDiv, TypeF32(state), normalized, value, + ConstantF32Value(state, max_value)); + state.builder.AddFunction(spv::OpExtInst, TypeF32(state), clamped, GlslStd450(state), + GLSLstd450FMax, normalized, ConstantF32Value(state, -1.0f)); return EmitBitcastF32ToU32(state, clamped); } case Format::ComponentType::Float: @@ -284,8 +284,8 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma void EmitDeviceAtomicMemoryBarrier(EmitterState& state) { const auto semantics = spv::MemorySemanticsAcquireReleaseMask | spv::MemorySemanticsUniformMemoryMask; - state.builder.AddFunction({spv::OpMemoryBarrier, ConstantU32(state, spv::ScopeDevice), - ConstantU32(state, semantics)}); + state.builder.AddFunction(spv::OpMemoryBarrier, ConstantU32(state, spv::ScopeDevice), + ConstantU32(state, semantics)); } uint32_t EmitFloatAtomicReplacement(EmitterState& state, uint32_t old, uint32_t source, @@ -300,7 +300,7 @@ uint32_t EmitFloatAtomicReplacement(EmitterState& state, uint32_t old, uint32_t const auto negative = EmitCompareU32Constant(state, spv::OpINotEqual, EmitAndConstant(state, bits, 0x80000000u), 0u); const auto negative_key = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpNot, TypeU32(state), negative_key, bits}); + state.builder.AddFunction(spv::OpNot, TypeU32(state), negative_key, bits); const auto positive_key = EmitBinaryU32(state, spv::OpBitwiseXor, bits, ConstantU32(state, 0x80000000u)); return OrderedBits { @@ -313,8 +313,8 @@ uint32_t EmitFloatAtomicReplacement(EmitterState& state, uint32_t old, uint32_t state, EmitLogicalOrBool(state, source_class.nan, old_class.nan), EmitLogicalAndBool(state, source_class.zero, old_class.zero)); const auto compare = state.builder.AllocateId(); - state.builder.AddFunction({max_value ? spv::OpUGreaterThan : spv::OpULessThan, TypeBool(state), - compare, source_class.key, old_class.key}); + state.builder.AddFunction(max_value ? spv::OpUGreaterThan : spv::OpULessThan, TypeBool(state), + compare, source_class.key, old_class.key); return EmitSelectValueU32( state, EmitLogicalAndBool(state, EmitLogicalNotBool(state, unordered), compare), source, old); @@ -342,17 +342,17 @@ uint32_t EmitDsSwizzleTargetLane(EmitterState& state, uint32_t subid, uint32_t c const auto perm = state.builder.AllocateId(); const auto base = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane2, subid, ConstantU32(state, 3)}); - state.builder.AddFunction( - {spv::OpShiftLeftLogical, TypeU32(state), shift, lane2, ConstantU32(state, 1)}); - state.builder.AddFunction( - {spv::OpShiftRightLogical, TypeU32(state), perm0, ConstantU32(state, control), shift}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), perm, perm0, ConstantU32(state, 3)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), base, subid, ConstantU32(state, 0xfffffffcu)}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, base, perm}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane2, subid, + ConstantU32(state, 3)); + state.builder.AddFunction(spv::OpShiftLeftLogical, TypeU32(state), shift, lane2, + ConstantU32(state, 1)); + state.builder.AddFunction(spv::OpShiftRightLogical, TypeU32(state), perm0, + ConstantU32(state, control), shift); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), perm, perm0, + ConstantU32(state, 3)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), base, subid, + ConstantU32(state, 0xfffffffcu)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, base, perm); return target; } @@ -362,17 +362,17 @@ uint32_t EmitDsSwizzleTargetLane(EmitterState& state, uint32_t subid, uint32_t c const auto xored = state.builder.AllocateId(); const auto base = state.builder.AllocateId(); const auto target = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, 31)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), masked, lane, ConstantU32(state, control & 0x1fu)}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), ored, masked, - ConstantU32(state, (control >> 5u) & 0x1fu)}); - state.builder.AddFunction({spv::OpBitwiseXor, TypeU32(state), xored, ored, - ConstantU32(state, (control >> 10u) & 0x1fu)}); - state.builder.AddFunction( - {spv::OpBitwiseAnd, TypeU32(state), base, subid, ConstantU32(state, 0xffffffe0u)}); - state.builder.AddFunction({spv::OpBitwiseOr, TypeU32(state), target, base, xored}); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), lane, subid, + ConstantU32(state, 31)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), masked, lane, + ConstantU32(state, control & 0x1fu)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), ored, masked, + ConstantU32(state, (control >> 5u) & 0x1fu)); + state.builder.AddFunction(spv::OpBitwiseXor, TypeU32(state), xored, ored, + ConstantU32(state, (control >> 10u) & 0x1fu)); + state.builder.AddFunction(spv::OpBitwiseAnd, TypeU32(state), base, subid, + ConstantU32(state, 0xffffffe0u)); + state.builder.AddFunction(spv::OpBitwiseOr, TypeU32(state), target, base, xored); return target; } diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMesh.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMesh.cpp index ba0b47f68..611ee9550 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMesh.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterMesh.cpp @@ -4,15 +4,15 @@ namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter { namespace { uint32_t MeshArray(EmitterState& state, spv::StorageClass storage, uint32_t type, uint32_t count) { - const auto array = state.builder.Type(spv::OpTypeArray, {type, ConstantU32(state, count)}); + const auto array = state.builder.Type(spv::OpTypeArray, type, ConstantU32(state, count)); return state.builder.DefineGlobalVariable(TypePointer(state, storage, array), storage); } uint32_t MeshElement(EmitterState& state, uint32_t variable, spv::StorageClass storage, uint32_t type, uint32_t index) { const auto pointer = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpAccessChain, TypePointer(state, storage, type), pointer, variable, index}); + state.builder.AddFunction(spv::OpAccessChain, TypePointer(state, storage, type), pointer, + variable, index); return pointer; } @@ -20,7 +20,7 @@ uint32_t MeshLoad(EmitterState& state, uint32_t variable, spv::StorageClass stor uint32_t index) { const auto pointer = MeshElement(state, variable, storage, type, index); const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, type, value, pointer}); + state.builder.AddFunction(spv::OpLoad, type, value, pointer); return value; } @@ -50,17 +50,17 @@ void DefineMeshOutputs(EmitterState& state) { state.interface_variables.push_back(output.variable_id); state.builder.AddName(output.variable_id, output.debug_name.c_str()); if (output.kind == IR::StageOutputKind::Parameter) { - state.builder.AddAnnotation( - {spv::OpDecorate, output.variable_id, spv::DecorationLocation, output.location}); + state.builder.AddAnnotation(spv::OpDecorate, output.variable_id, + spv::DecorationLocation, output.location); } else { - state.builder.AddAnnotation( - {spv::OpDecorate, output.variable_id, spv::DecorationBuiltIn, - output.kind == IR::StageOutputKind::Layer ? spv::BuiltInLayer - : spv::BuiltInPosition}); + state.builder.AddAnnotation(spv::OpDecorate, output.variable_id, spv::DecorationBuiltIn, + output.kind == IR::StageOutputKind::Layer + ? spv::BuiltInLayer + : spv::BuiltInPosition); } if (output.kind == IR::StageOutputKind::Layer) { - state.builder.AddAnnotation({spv::OpDecorate, output.variable_id, - spv::DecorationPerPrimitiveEXT}); // PerPrimitiveEXT + state.builder.AddAnnotation(spv::OpDecorate, output.variable_id, + spv::DecorationPerPrimitiveEXT); // PerPrimitiveEXT } } state.mesh_allocation = MeshArray(state, spv::StorageClassWorkgroup, TypeU32(state), 2); @@ -73,11 +73,11 @@ void DefineMeshOutputs(EmitterState& state) { state.interface_variables.push_back(state.mesh_primitives); state.interface_variables.push_back(state.mesh_cull); state.builder.AddAnnotation( - {spv::OpDecorate, state.mesh_primitives, spv::DecorationBuiltIn, - spv::BuiltInPrimitiveTriangleIndicesEXT}); // PrimitiveTriangleIndicesEXT - state.builder.AddAnnotation({spv::OpDecorate, state.mesh_cull, spv::DecorationBuiltIn, - spv::BuiltInCullPrimitiveEXT}); // CullPrimitiveEXT - state.builder.AddAnnotation({spv::OpDecorate, state.mesh_cull, spv::DecorationPerPrimitiveEXT}); + spv::OpDecorate, state.mesh_primitives, spv::DecorationBuiltIn, + spv::BuiltInPrimitiveTriangleIndicesEXT); // PrimitiveTriangleIndicesEXT + state.builder.AddAnnotation(spv::OpDecorate, state.mesh_cull, spv::DecorationBuiltIn, + spv::BuiltInCullPrimitiveEXT); // CullPrimitiveEXT + state.builder.AddAnnotation(spv::OpDecorate, state.mesh_cull, spv::DecorationPerPrimitiveEXT); } uint32_t MeshOutputPointer(EmitterState& state, IR::StageOutputKind kind, uint32_t index) { @@ -103,45 +103,45 @@ uint32_t MeshPrimitivePointer(EmitterState& state) { void EmitMeshAllocate(ValueEmitContext& ctx, const IR::Inst& inst) { auto& state = ctx.state; const auto first = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpIEqual, TypeBool(state), first, - EmitLocalInvocationIndex(state), ConstantU32(state, 0)}); + state.builder.AddFunction(spv::OpIEqual, TypeBool(state), first, + EmitLocalInvocationIndex(state), ConstantU32(state, 0)); EmitIfCondition(state, first, [&] { const auto allocation = ctx.Arg(inst, 0); for (uint32_t field = 0; field < 2; field++) { const auto value = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpBitFieldUExtract, TypeU32(state), value, allocation, - ConstantU32(state, field * 12u), - ConstantU32(state, field == 0 ? 10u : 11u)}); + state.builder.AddFunction(spv::OpBitFieldUExtract, TypeU32(state), value, allocation, + ConstantU32(state, field * 12u), + ConstantU32(state, field == 0 ? 10u : 11u)); const auto pointer = MeshElement(state, state.mesh_allocation, spv::StorageClassWorkgroup, TypeU32(state), ConstantU32(state, field)); - state.builder.AddFunction({spv::OpStore, pointer, value}); + state.builder.AddFunction(spv::OpStore, pointer, value); } }); } void EmitMeshEntryPoint(EmitterState& state) { - state.builder.AddFunction({spv::OpFunction, TypeVoid(state), state.main_func, - spv::FunctionControlMaskNone, TypeFunction(state)}); + state.builder.AddFunction(spv::OpFunction, TypeVoid(state), state.main_func, + spv::FunctionControlMaskNone, TypeFunction(state)); EmitLabel(state, state.builder.AllocateId()); - state.builder.AddFunction( - {spv::OpFunctionCall, TypeVoid(state), state.builder.AllocateId(), state.mesh_guest_func}); + state.builder.AddFunction(spv::OpFunctionCall, TypeVoid(state), state.builder.AllocateId(), + state.mesh_guest_func); // All guest waves finish before the uniform Vulkan allocation and output stores. - state.builder.AddFunction({spv::OpControlBarrier, ConstantU32(state, spv::ScopeWorkgroup), - ConstantU32(state, spv::ScopeWorkgroup), - ConstantU32(state, spv::MemorySemanticsAcquireReleaseMask | - spv::MemorySemanticsWorkgroupMemoryMask)}); + state.builder.AddFunction(spv::OpControlBarrier, ConstantU32(state, spv::ScopeWorkgroup), + ConstantU32(state, spv::ScopeWorkgroup), + ConstantU32(state, spv::MemorySemanticsAcquireReleaseMask | + spv::MemorySemanticsWorkgroupMemoryMask)); const auto vertices = MeshLoad(state, state.mesh_allocation, spv::StorageClassWorkgroup, TypeU32(state), ConstantU32(state, 0)); const auto primitives = MeshLoad(state, state.mesh_allocation, spv::StorageClassWorkgroup, TypeU32(state), ConstantU32(state, 1)); - state.builder.AddFunction( - {spv::OpSetMeshOutputsEXT, vertices, primitives}); // OpSetMeshOutputsEXT + state.builder.AddFunction(spv::OpSetMeshOutputsEXT, vertices, + primitives); // OpSetMeshOutputsEXT for (uint32_t half = 0; half < state.lane_count; half++) { state.lane_half = half; const auto index = EmitLocalInvocationIndex(state); const auto is_vertex = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpULessThan, TypeBool(state), is_vertex, index, vertices}); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), is_vertex, index, vertices); EmitIfCondition(state, is_vertex, [&] { for (const auto& output: state.outputs) { if (output.kind == IR::StageOutputKind::Layer) { @@ -153,12 +153,12 @@ void EmitMeshEntryPoint(EmitterState& state) { ConstantU32(state, half)); const auto pointer = MeshElement(state, output.variable_id, spv::StorageClassOutput, type, index); - state.builder.AddFunction({spv::OpStore, pointer, value}); + state.builder.AddFunction(spv::OpStore, pointer, value); } }); const auto is_primitive = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpULessThan, TypeBool(state), is_primitive, index, primitives}); + state.builder.AddFunction(spv::OpULessThan, TypeBool(state), is_primitive, index, + primitives); EmitIfCondition(state, is_primitive, [&] { const auto packed = MeshLoad(state, state.mesh_primitive_data, spv::StorageClassPrivate, TypeU32(state), ConstantU32(state, half)); @@ -166,25 +166,25 @@ void EmitMeshEntryPoint(EmitterState& state) { for (uint32_t component = 0; component < 3; component++) { vertex[component] = state.builder.AllocateId(); state.builder.AddFunction( - {spv::OpBitFieldUExtract, TypeU32(state), vertex[component], packed, - ConstantU32(state, component * 10u), ConstantU32(state, 10)}); + spv::OpBitFieldUExtract, TypeU32(state), vertex[component], packed, + ConstantU32(state, component * 10u), ConstantU32(state, 10)); } const auto triangle = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeConstruct, TypeU32Vector(state, 3), triangle, - vertex[0], vertex[1], vertex[2]}); + state.builder.AddFunction(spv::OpCompositeConstruct, TypeU32Vector(state, 3), triangle, + vertex[0], vertex[1], vertex[2]); const auto triangle_pointer = MeshElement(state, state.mesh_primitives, spv::StorageClassOutput, TypeU32Vector(state, 3), index); - state.builder.AddFunction({spv::OpStore, triangle_pointer, triangle}); + state.builder.AddFunction(spv::OpStore, triangle_pointer, triangle); const auto null_bit = EmitBinaryU32(state, spv::OpBitwiseAnd, packed, ConstantU32(state, 0x80000000u)); const auto culled = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), culled, null_bit, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpStore, - MeshElement(state, state.mesh_cull, spv::StorageClassOutput, - TypeBool(state), index), - culled}); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), culled, null_bit, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpStore, + MeshElement(state, state.mesh_cull, spv::StorageClassOutput, + TypeBool(state), index), + culled); for (const auto& output: state.outputs) { if (output.kind != IR::StageOutputKind::Layer) { continue; @@ -194,13 +194,13 @@ void EmitMeshEntryPoint(EmitterState& state) { vertex[state.input_info.vertex->mesh.provoking_vertex]); const auto pointer = MeshElement(state, output.variable_id, spv::StorageClassOutput, TypeU32(state), index); - state.builder.AddFunction({spv::OpStore, pointer, layer}); + state.builder.AddFunction(spv::OpStore, pointer, layer); } }); } state.lane_half = 0; - state.builder.AddFunction({spv::OpReturn}); - state.builder.AddFunction({spv::OpFunctionEnd}); + state.builder.AddFunction(spv::OpReturn); + state.builder.AddFunction(spv::OpFunctionEnd); } } // namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp index a0fd6eeb1..375acaf23 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterModule.cpp @@ -13,11 +13,11 @@ uint32_t TypeBool(EmitterState& state) { } uint32_t TypeBoolVector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, {TypeBool(state), components}); + return state.builder.Type(spv::OpTypeVector, TypeBool(state), components); } uint32_t TypeU32(EmitterState& state) { - return state.builder.Type(spv::OpTypeInt, {32, 0}); + return state.builder.Type(spv::OpTypeInt, 32, 0); } uint32_t TypeU64(EmitterState& state) { @@ -25,29 +25,29 @@ uint32_t TypeU64(EmitterState& state) { } uint32_t TypeScalarU64(EmitterState& state) { - return state.builder.Type(spv::OpTypeInt, {64, 0}); + return state.builder.Type(spv::OpTypeInt, 64, 0); } uint32_t TypeU32Pair(EmitterState& state) { const auto element = TypeU32(state); - return state.builder.Type(spv::OpTypeStruct, {element, element}); + return state.builder.Type(spv::OpTypeStruct, element, element); } uint32_t TypeI32(EmitterState& state) { - return state.builder.Type(spv::OpTypeInt, {32, 1}); + return state.builder.Type(spv::OpTypeInt, 32, 1); } uint32_t TypeI32Pair(EmitterState& state) { const auto element = TypeI32(state); - return state.builder.Type(spv::OpTypeStruct, {element, element}); + return state.builder.Type(spv::OpTypeStruct, element, element); } uint32_t TypeF32(EmitterState& state) { - return state.builder.Type(spv::OpTypeFloat, {32}); + return state.builder.Type(spv::OpTypeFloat, 32); } uint32_t TypeU32Vector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, {TypeU32(state), components}); + return state.builder.Type(spv::OpTypeVector, TypeU32(state), components); } uint32_t TypeU32Composite(EmitterState& state, uint32_t components) { @@ -56,31 +56,32 @@ uint32_t TypeU32Composite(EmitterState& state, uint32_t components) { } uint32_t TypeI32Vector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, {TypeI32(state), components}); + return state.builder.Type(spv::OpTypeVector, TypeI32(state), components); } uint32_t TypeF32Vector(EmitterState& state, uint32_t components) { - return state.builder.Type(spv::OpTypeVector, {TypeF32(state), components}); + return state.builder.Type(spv::OpTypeVector, TypeF32(state), components); } uint32_t TypePointer(EmitterState& state, spv::StorageClass storage_class, uint32_t pointee) { - return state.builder.Type(spv::OpTypePointer, {storage_class, pointee}); + return state.builder.Type(spv::OpTypePointer, storage_class, pointee); } uint32_t TypeFunction(EmitterState& state) { - return state.builder.Type(spv::OpTypeFunction, {TypeVoid(state)}); + return state.builder.Type(spv::OpTypeFunction, TypeVoid(state)); } uint32_t StorageRuntimeArrayType(EmitterState& state) { return state.builder.DecoratedType( - spv::OpTypeRuntimeArray, {TypeU32(state)}, - {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint32_t)}}}); + spv::OpTypeRuntimeArray, + {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint32_t)}}}, TypeU32(state)); } uint32_t StorageBufferType(EmitterState& state) { - return state.builder.DecoratedType(spv::OpTypeStruct, {StorageRuntimeArrayType(state)}, + return state.builder.DecoratedType(spv::OpTypeStruct, {{spv::OpMemberDecorate, {0, spv::DecorationOffset, 0}}, - {spv::OpDecorate, {spv::DecorationBlock}}}); + {spv::OpDecorate, {spv::DecorationBlock}}}, + StorageRuntimeArrayType(state)); } uint32_t TypeStorageBufferPointer(EmitterState& state) { @@ -93,14 +94,15 @@ uint32_t TypeStorageBufferElementPointer(EmitterState& state) { uint32_t StorageU64RuntimeArrayType(EmitterState& state) { return state.builder.DecoratedType( - spv::OpTypeRuntimeArray, {TypeScalarU64(state)}, - {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint64_t)}}}); + spv::OpTypeRuntimeArray, + {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint64_t)}}}, TypeScalarU64(state)); } uint32_t StorageBufferU64Type(EmitterState& state) { - return state.builder.DecoratedType(spv::OpTypeStruct, {StorageU64RuntimeArrayType(state)}, + return state.builder.DecoratedType(spv::OpTypeStruct, {{spv::OpMemberDecorate, {0, spv::DecorationOffset, 0}}, - {spv::OpDecorate, {spv::DecorationBlock}}}); + {spv::OpDecorate, {spv::DecorationBlock}}}, + StorageU64RuntimeArrayType(state)); } uint32_t TypeStorageBufferU64Pointer(EmitterState& state) { @@ -122,7 +124,7 @@ uint32_t TypePushConstantElementPointer(EmitterState& state) { uint32_t TypeU32ArrayPointer(EmitterState& state, spv::StorageClass storage_class, uint32_t dwords) { const auto count = ConstantU32(state, std::max(dwords, 1u)); - const auto array = state.builder.Type(spv::OpTypeArray, {TypeU32(state), count}); + const auto array = state.builder.Type(spv::OpTypeArray, TypeU32(state), count); return TypePointer(state, storage_class, array); } @@ -135,29 +137,31 @@ namespace { uint32_t PushConstantArrayType(EmitterState& state) { const auto count = ConstantU32(state, IR::PushData::DwordCount); return state.builder.DecoratedType( - spv::OpTypeArray, {TypeU32(state), count}, - {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint32_t)}}}); + spv::OpTypeArray, {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint32_t)}}}, + TypeU32(state), count); } uint32_t PushConstantBlockType(EmitterState& state) { - return state.builder.DecoratedType(spv::OpTypeStruct, {PushConstantArrayType(state)}, + return state.builder.DecoratedType(spv::OpTypeStruct, {{spv::OpMemberDecorate, {0, spv::DecorationOffset, 0}}, - {spv::OpDecorate, {spv::DecorationBlock}}}); + {spv::OpDecorate, {spv::DecorationBlock}}}, + PushConstantArrayType(state)); } uint32_t PerVertexType(EmitterState& state) { return state.builder.DecoratedType( - spv::OpTypeStruct, {TypeF32Vector(state, 4)}, + spv::OpTypeStruct, {{spv::OpMemberDecorate, {0, spv::DecorationBuiltIn, spv::BuiltInPosition}}, - {spv::OpDecorate, {spv::DecorationBlock}}}); + {spv::OpDecorate, {spv::DecorationBlock}}}, + TypeF32Vector(state, 4)); } uint32_t SampleMaskArrayType(EmitterState& state) { - return state.builder.Type(spv::OpTypeArray, {TypeI32(state), ConstantU32(state, 1)}); + return state.builder.Type(spv::OpTypeArray, TypeI32(state), ConstantU32(state, 1)); } uint32_t F32ArrayType(EmitterState& state, uint32_t count) { - return state.builder.Type(spv::OpTypeArray, {TypeF32(state), ConstantU32(state, count)}); + return state.builder.Type(spv::OpTypeArray, TypeF32(state), ConstantU32(state, count)); } void DefineDescriptors(EmitterState& state) { @@ -174,16 +178,15 @@ void DefineDescriptors(EmitterState& state) { const auto variable = state.builder.DefineGlobalVariable(TypePointer(state, storage, type), storage); state.builder.AddName(variable, name); - state.builder.AddAnnotation( - {spv::OpDecorate, variable, spv::DecorationDescriptorSet, 0}); - state.builder.AddAnnotation({spv::OpDecorate, variable, spv::DecorationBinding, - IR::NativeBinding(state.program.stage, binding.kind)}); + state.builder.AddAnnotation(spv::OpDecorate, variable, spv::DecorationDescriptorSet, 0); + state.builder.AddAnnotation(spv::OpDecorate, variable, spv::DecorationBinding, + IR::NativeBinding(state.program.stage, binding.kind)); return variable; }; const auto ArrayType = [&](uint32_t type) { return state.builder.Type( - spv::OpTypeArray, - {type, ConstantU32(state, static_cast(binding.resources.size()))}); + spv::OpTypeArray, type, + ConstantU32(state, static_cast(binding.resources.size()))); }; switch (binding.kind) { case IR::DescriptorBindingKind::Buffers: @@ -192,10 +195,10 @@ void DefineDescriptors(EmitterState& state) { if (state.requirements.buffer_int64_atomics) { state.storage_buffer_u64_variable = Define(ArrayType(StorageBufferU64Type(state)), "buffers_u64"); - state.builder.AddAnnotation( - {spv::OpDecorate, state.storage_buffer_variable, spv::DecorationAliased}); - state.builder.AddAnnotation({spv::OpDecorate, state.storage_buffer_u64_variable, - spv::DecorationAliased}); + state.builder.AddAnnotation(spv::OpDecorate, state.storage_buffer_variable, + spv::DecorationAliased); + state.builder.AddAnnotation(spv::OpDecorate, state.storage_buffer_u64_variable, + spv::DecorationAliased); } break; case IR::DescriptorBindingKind::BdaPagetable: @@ -242,15 +245,15 @@ void DefineDescriptors(EmitterState& state) { } // namespace uint32_t ConstantU32(EmitterState& state, uint32_t value) { - return state.builder.Constant(spv::OpConstant, TypeU32(state), {value}); + return state.builder.Constant(spv::OpConstant, TypeU32(state), value); } uint32_t ConstantI32(EmitterState& state, int32_t value) { - return state.builder.Constant(spv::OpConstant, TypeI32(state), {static_cast(value)}); + return state.builder.Constant(spv::OpConstant, TypeI32(state), static_cast(value)); } uint32_t ConstantF32(EmitterState& state, uint32_t bits) { - return state.builder.Constant(spv::OpConstant, TypeF32(state), {bits}); + return state.builder.Constant(spv::OpConstant, TypeF32(state), bits); } uint32_t FloatBits(float value) { @@ -270,8 +273,8 @@ uint32_t ConstantBool(EmitterState& state, bool value) { uint32_t ConstantU64(EmitterState& state, uint64_t value) { return state.builder.Constant(spv::OpConstantComposite, TypeU64(state), - {ConstantU32(state, static_cast(value)), - ConstantU32(state, static_cast(value >> 32u))}); + ConstantU32(state, static_cast(value)), + ConstantU32(state, static_cast(value >> 32u))); } uint32_t ConstantU32CompositeZero(EmitterState& state, uint32_t components) { @@ -400,11 +403,11 @@ void DefineInputs(EmitterState& state) { state, VertexParameterScalarKind(state, input.location)); const auto components = VertexParameterComponentCount(input); if (components > 1u) { - type = state.builder.Type(spv::OpTypeVector, {type, components}); + type = state.builder.Type(spv::OpTypeVector, type, components); } } else if (input.per_vertex) { - type = state.builder.Type(spv::OpTypeArray, - {TypeF32Vector(state, 4), ConstantU32(state, 3)}); + type = state.builder.Type(spv::OpTypeArray, TypeF32Vector(state, 4), + ConstantU32(state, 3)); } else { type = TypeF32Vector(state, 4); } @@ -414,38 +417,37 @@ void DefineInputs(EmitterState& state) { input.variable_id = DefineInterfaceVariable(state, type, spv::StorageClassInput, input.debug_name.c_str()); if (input.kind == IR::StageInputKind::Layer || input.kind == IR::StageInputKind::SampleId) { - state.builder.AddAnnotation({spv::OpDecorate, input.variable_id, spv::DecorationFlat}); + state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, spv::DecorationFlat); } if (input.kind == IR::StageInputKind::Parameter) { const auto flat = PixelParameterIsFlat(state, input.location); if (input.per_vertex) { - state.builder.AddAnnotation( - {spv::OpDecorate, input.variable_id, spv::DecorationPerVertexKHR}); + state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, + spv::DecorationPerVertexKHR); } else if (flat) { - state.builder.AddAnnotation( - {spv::OpDecorate, input.variable_id, spv::DecorationFlat}); + state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, + spv::DecorationFlat); } if (state.program.stage == ShaderType::Pixel && state.input_info.pixel->ps_no_perspective && !flat && !input.per_vertex) { - state.builder.AddAnnotation( - {spv::OpDecorate, input.variable_id, spv::DecorationNoPerspective}); + state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, + spv::DecorationNoPerspective); } - state.builder.AddAnnotation({spv::OpDecorate, input.variable_id, - spv::DecorationLocation, - PixelParameterLocation(state, input.location)}); + state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, spv::DecorationLocation, + PixelParameterLocation(state, input.location)); } else if (const auto builtin = BuiltInForInput(input.kind); builtin != UINT32_MAX) { - state.builder.AddAnnotation( - {spv::OpDecorate, input.variable_id, spv::DecorationBuiltIn, builtin}); + state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, spv::DecorationBuiltIn, + builtin); } } if (state.requirements.subgroup_local_invocation_id) { const auto variable = DefineInterfaceVariable(state, TypeU32(state), spv::StorageClassInput, "gl_SubgroupInvocationID"); state.subgroup_local_invocation_id_variable = variable; - state.builder.AddAnnotation({spv::OpDecorate, variable, spv::DecorationBuiltIn, - spv::BuiltInSubgroupLocalInvocationId}); + state.builder.AddAnnotation(spv::OpDecorate, variable, spv::DecorationBuiltIn, + spv::BuiltInSubgroupLocalInvocationId); if (state.program.stage == ShaderType::Pixel) { - state.builder.AddAnnotation({spv::OpDecorate, variable, spv::DecorationFlat}); + state.builder.AddAnnotation(spv::OpDecorate, variable, spv::DecorationFlat); } } } @@ -470,8 +472,7 @@ void DefineOutputs(EmitterState& state) { spv::BuiltIn builtin) { if (variable == 0) { variable = DefineInterfaceVariable(state, type, spv::StorageClassOutput, name); - state.builder.AddAnnotation( - {spv::OpDecorate, variable, spv::DecorationBuiltIn, builtin}); + state.builder.AddAnnotation(spv::OpDecorate, variable, spv::DecorationBuiltIn, builtin); } return variable; }; @@ -527,8 +528,8 @@ void DefineOutputs(EmitterState& state) { const auto type = uint_output ? TypeU32Vector(state, 4) : TypeF32Vector(state, 4); binding.variable_id = DefineInterfaceVariable(state, type, spv::StorageClassOutput, binding.debug_name.c_str()); - state.builder.AddAnnotation({spv::OpDecorate, binding.variable_id, - spv::DecorationLocation, binding.location}); + state.builder.AddAnnotation(spv::OpDecorate, binding.variable_id, + spv::DecorationLocation, binding.location); break; } } @@ -556,12 +557,12 @@ void DefineModule(EmitterState& state) { state.mesh_guest_func = state.builder.AllocateId(); state.builder.RequireCapability(spv::CapabilityMeshShadingEXT); // MeshShadingEXT state.builder.RequireExtension("SPV_EXT_mesh_shader"); - state.builder.AddExecutionMode( - {state.main_func, spv::ExecutionModeOutputTrianglesEXT}); // OutputTrianglesEXT - state.builder.AddExecutionMode({state.main_func, spv::ExecutionModeOutputVertices, - state.input_info.vertex->mesh.max_vertices}); - state.builder.AddExecutionMode({state.main_func, spv::ExecutionModeOutputPrimitivesEXT, - state.input_info.vertex->mesh.max_primitives}); + state.builder.AddExecutionMode(state.main_func, + spv::ExecutionModeOutputTrianglesEXT); // OutputTrianglesEXT + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeOutputVertices, + state.input_info.vertex->mesh.max_vertices); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeOutputPrimitivesEXT, + state.input_info.vertex->mesh.max_primitives); } state.entry_label = state.builder.AllocateId(); @@ -621,14 +622,14 @@ void DefineModule(EmitterState& state) { state.builder.RequireExtension("SPV_KHR_fragment_shader_barycentric"); } state.builder.RequireExtension("SPV_KHR_float_controls"); - state.builder.AddMemoryModel({state.program.info.uses_dma - ? spv::AddressingModelPhysicalStorageBuffer64 - : spv::AddressingModelLogical, - spv::MemoryModelGLSL450}); + state.builder.AddMemoryModel(state.program.info.uses_dma + ? spv::AddressingModelPhysicalStorageBuffer64 + : spv::AddressingModelLogical, + spv::MemoryModelGLSL450); // GCN/RDNA arithmetic preserves 32-bit signed zero, infinity, and NaN. Declaring that // contract prevents host compilers from treating synthesized IEEE values as finite. - state.builder.AddExecutionMode( - {state.main_func, spv::ExecutionModeSignedZeroInfNanPreserve, 32u}); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeSignedZeroInfNanPreserve, + 32u); if (const auto* cs = ShaderWorkgroupInput(state.program.stage, state.input_info)) { uint32_t local_x = state.requirements.compute_derivatives ? 2u : 1u; uint32_t local_y = state.requirements.compute_derivatives ? 2u : 1u; @@ -644,23 +645,22 @@ void DefineModule(EmitterState& state) { local_x = 2u; } } - state.builder.AddExecutionMode( - {state.main_func, spv::ExecutionModeLocalSize, local_x, local_y, local_z}); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeLocalSize, local_x, + local_y, local_z); } if (state.program.stage == ShaderType::Pixel) { - state.builder.AddExecutionMode({state.main_func, spv::ExecutionModeOriginUpperLeft}); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeOriginUpperLeft); if (state.depth_variable != 0) { - state.builder.AddExecutionMode({state.main_func, spv::ExecutionModeDepthReplacing}); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeDepthReplacing); } if (state.input_info.pixel->ps_early_z && !state.input_info.pixel->ps_pixel_kill_enable && !state.input_info.pixel->ps_depth_export_enable && !state.input_info.pixel->ps_sample_mask_export_enable) { - state.builder.AddExecutionMode({state.main_func, spv::ExecutionModeEarlyFragmentTests}); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeEarlyFragmentTests); } } if (state.requirements.compute_derivatives && state.program.stage == ShaderType::Compute) { - state.builder.AddExecutionMode( - {state.main_func, spv::ExecutionModeDerivativeGroupQuadsKHR}); + state.builder.AddExecutionMode(state.main_func, spv::ExecutionModeDerivativeGroupQuadsKHR); } state.builder.AddName(state.main_func, "main"); if (state.requirements.function_lds) { diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp index fc8b77f3a..916aac673 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp @@ -17,11 +17,11 @@ void EmitKillIfBoolFalse(EmitterState& state, uint32_t active) { const auto kill_label = state.builder.AllocateId(); const auto merge_label = state.builder.AllocateId(); const auto inactive = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLogicalNot, TypeBool(state), inactive, active}); - state.builder.AddFunction({spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone}); - state.builder.AddFunction({spv::OpBranchConditional, inactive, kill_label, merge_label}); + state.builder.AddFunction(spv::OpLogicalNot, TypeBool(state), inactive, active); + state.builder.AddFunction(spv::OpSelectionMerge, merge_label, spv::SelectionControlMaskNone); + state.builder.AddFunction(spv::OpBranchConditional, inactive, kill_label, merge_label); EmitLabel(state, kill_label); - state.builder.AddFunction({spv::OpKill}); + state.builder.AddFunction(spv::OpKill); EmitLabel(state, merge_label); } @@ -32,10 +32,10 @@ void EmitKillIfPixelValidMaskInactive(EmitterState& state) { const auto mask_value = state.builder.AllocateId(); const auto active = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpLoad, TypeU32(state), mask_value, state.pixel_valid_mask_variable}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), active, mask_value, ConstantU32(state, 0)}); + state.builder.AddFunction(spv::OpLoad, TypeU32(state), mask_value, + state.pixel_valid_mask_variable); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), active, mask_value, + ConstantU32(state, 0)); EmitKillIfBoolFalse(state, active); } @@ -75,8 +75,8 @@ void StoreDispatcherPhiEdge(ValueEmitContext& ctx, const DispatcherFunctionState } for (size_t index = 0; index < phi.NumArgs(); index++) { if (phi.PhiBlock(index) == from) { - ctx.state.builder.AddFunction( - {spv::OpStore, dispatcher.spills[ctx.half].at(&phi), ctx.Def(phi.Arg(index))}); + ctx.state.builder.AddFunction(spv::OpStore, dispatcher.spills[ctx.half].at(&phi), + ctx.Def(phi.Arg(index))); break; } } @@ -94,7 +94,7 @@ const IR::Block* TargetBlock(const IR::Program& program, uint32_t id) { void EmitReturn(ValueEmitContext& ctx) { EmitKillIfPixelValidMaskInactive(ctx.state); - ctx.state.builder.AddFunction({spv::OpReturn}); + ctx.state.builder.AddFunction(spv::OpReturn); } uint32_t BranchCondition(ValueEmitContext& ctx, const IR::BlockInfo& info) { @@ -108,16 +108,16 @@ uint32_t BranchCondition(ValueEmitContext& ctx, const IR::BlockInfo& info) { const auto low = ctx.state.builder.AllocateId(); const auto high = ctx.state.builder.AllocateId(); const auto result = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(ctx.state), low, ballot, 0}); - ctx.state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(ctx.state), high, ballot, 1}); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), low, ballot, 0); + ctx.state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(ctx.state), high, ballot, 1); const auto kind = info.terminator.condition; const bool zero = kind == CFG::BranchCondition::ExecZero || kind == CFG::BranchCondition::VccZero || kind == CFG::BranchCondition::SccZero; const auto combined = EmitBinaryU32(ctx.state, zero ? spv::OpBitwiseAnd : spv::OpBitwiseOr, low, high); - ctx.state.builder.AddFunction({zero ? spv::OpIEqual : spv::OpINotEqual, TypeBool(ctx.state), - result, combined, ConstantU32(ctx.state, zero ? ~0u : 0u)}); + ctx.state.builder.AddFunction(zero ? spv::OpIEqual : spv::OpINotEqual, TypeBool(ctx.state), + result, combined, ConstantU32(ctx.state, zero ? ~0u : 0u)); return result; } @@ -130,14 +130,14 @@ void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block, const auto* merge = TargetBlock(program, term.merge_block); const auto* cont = TargetBlock(program, term.continue_block); if (merge != nullptr && cont != nullptr) { - ctx.state.builder.AddFunction({spv::OpLoopMerge, ctx.Label(merge), ctx.Label(cont), - spv::LoopControlMaskNone}); + ctx.state.builder.AddFunction(spv::OpLoopMerge, ctx.Label(merge), ctx.Label(cont), + spv::LoopControlMaskNone); } } else if (term.kind == CFG::TerminatorKind::ConditionalBranch && term.merge_block != UINT32_MAX) { if (const auto* merge = TargetBlock(program, term.merge_block); merge != nullptr) { - ctx.state.builder.AddFunction( - {spv::OpSelectionMerge, ctx.Label(merge), spv::SelectionControlMaskNone}); + ctx.state.builder.AddFunction(spv::OpSelectionMerge, ctx.Label(merge), + spv::SelectionControlMaskNone); } } }; @@ -150,7 +150,7 @@ void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block, return; } emit_merge(); - ctx.state.builder.AddFunction({spv::OpBranch, ctx.Label(target)}); + ctx.state.builder.AddFunction(spv::OpBranch, ctx.Label(target)); return; } case CFG::TerminatorKind::ConditionalBranch: { @@ -162,8 +162,8 @@ void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block, } const auto condition = BranchCondition(ctx, info); emit_merge(); - ctx.state.builder.AddFunction({spv::OpBranchConditional, condition, - ctx.Label(true_block), ctx.Label(false_block)}); + ctx.state.builder.AddFunction(spv::OpBranchConditional, condition, + ctx.Label(true_block), ctx.Label(false_block)); return; } default: EmitReturn(ctx); return; @@ -192,10 +192,9 @@ uint32_t EmitDispatcherNextPc(ValueEmitContext& ctx, const DispatcherFunctionSta EmitDispatcherTarget(ctx, dispatcher, block, term.true_block); EmitDispatcherTarget(ctx, dispatcher, block, term.false_block); const auto selected = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpSelect, TypeU32(ctx.state), selected, - BranchCondition(ctx, info), - ConstantU32(ctx.state, term.true_block), - ConstantU32(ctx.state, term.false_block)}); + ctx.state.builder.AddFunction( + spv::OpSelect, TypeU32(ctx.state), selected, BranchCondition(ctx, info), + ConstantU32(ctx.state, term.true_block), ConstantU32(ctx.state, term.false_block)); return selected; } case CFG::TerminatorKind::IndirectBranch: { @@ -214,12 +213,10 @@ uint32_t EmitDispatcherNextPc(ValueEmitContext& ctx, const DispatcherFunctionSta for (size_t index = 0; index < std::min(values.size(), targets.size()); index++) { const auto match = ctx.state.builder.AllocateId(); const auto next = ctx.state.builder.AllocateId(); - ctx.state.builder.AddFunction({spv::OpIEqual, TypeBool(ctx.state), match, - selector, - ConstantU32(ctx.state, values[index])}); - ctx.state.builder.AddFunction({spv::OpSelect, TypeU32(ctx.state), next, match, - ConstantU32(ctx.state, targets[index]), - selected}); + ctx.state.builder.AddFunction(spv::OpIEqual, TypeBool(ctx.state), match, + selector, ConstantU32(ctx.state, values[index])); + ctx.state.builder.AddFunction(spv::OpSelect, TypeU32(ctx.state), next, match, + ConstantU32(ctx.state, targets[index]), selected); selected = next; } } @@ -307,15 +304,15 @@ void EmitDispatcherInstruction(ValueEmitContext& ctx, const DispatcherFunctionSt if (type == 0) { ctx.Fail(inst, "cannot be loaded by the dispatcher"); } - ctx.state.builder.AddFunction( - {spv::OpLoad, type, ctx.Result(inst), dispatcher.spills[ctx.half].at(&inst)}); + ctx.state.builder.AddFunction(spv::OpLoad, type, ctx.Result(inst), + dispatcher.spills[ctx.half].at(&inst)); return; } EmitDirectInstruction(ctx, inst); if (const auto found = dispatcher.spills[ctx.half].find(&inst); found != dispatcher.spills[ctx.half].end()) { - ctx.state.builder.AddFunction( - {spv::OpStore, found->second, ctx.Def(IR::Value(const_cast(&inst)))}); + ctx.state.builder.AddFunction(spv::OpStore, found->second, + ctx.Def(IR::Value(const_cast(&inst)))); } } @@ -362,7 +359,7 @@ void PatchStructuredPhis(ValueEmitContext& ctx, StructuredFunctionState& structu void EmitStructuredFunction(ValueEmitContext& ctx) { const auto& program = ctx.state.program; StructuredFunctionState structured; - ctx.state.builder.AddFunction({spv::OpBranch, ctx.Label(program.blocks.front())}); + ctx.state.builder.AddFunction(spv::OpBranch, ctx.Label(program.blocks.front())); for (size_t index = 0; index < program.blocks.size(); index++) { const auto* block = program.blocks[index]; EmitBlock(ctx, block, [&](ValueEmitContext& lane, const IR::Inst& inst) { @@ -377,31 +374,31 @@ void EmitStructuredFunction(ValueEmitContext& ctx) { void EmitDispatcherFunction(ValueEmitContext& ctx, const DispatcherFunctionState& dispatcher) { auto& state = ctx.state; const auto* entry = state.program.blocks.front(); - state.builder.AddFunction({spv::OpBranch, ctx.Label(entry)}); + state.builder.AddFunction(spv::OpBranch, ctx.Label(entry)); EmitBlock(ctx, entry, [&](ValueEmitContext& lane, const IR::Inst& inst) { EmitDispatcherInstruction(lane, dispatcher, inst); }); const auto initial_pc = EmitDispatcherNextPc(ctx, dispatcher, entry, state.program.block_info.front()); const auto initial_parent = state.current_label; - state.builder.AddFunction({spv::OpBranch, dispatcher.header_label}); + state.builder.AddFunction(spv::OpBranch, dispatcher.header_label); EmitLabel(state, dispatcher.header_label); const auto pc = state.builder.AllocateId(); const auto next_pc = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpPhi, TypeU32(state), pc, initial_pc, initial_parent, next_pc, - dispatcher.continue_label}); + state.builder.AddFunction(spv::OpPhi, TypeU32(state), pc, initial_pc, initial_parent, next_pc, + dispatcher.continue_label); const auto done = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpIEqual, TypeBool(state), done, pc, ConstantU32(ctx.state, UINT32_MAX)}); - state.builder.AddFunction({spv::OpLoopMerge, dispatcher.merge_label, dispatcher.continue_label, - spv::LoopControlMaskNone}); - state.builder.AddFunction( - {spv::OpBranchConditional, done, dispatcher.merge_label, dispatcher.select_label}); + state.builder.AddFunction(spv::OpIEqual, TypeBool(state), done, pc, + ConstantU32(ctx.state, UINT32_MAX)); + state.builder.AddFunction(spv::OpLoopMerge, dispatcher.merge_label, dispatcher.continue_label, + spv::LoopControlMaskNone); + state.builder.AddFunction(spv::OpBranchConditional, done, dispatcher.merge_label, + dispatcher.select_label); EmitLabel(state, dispatcher.select_label); - state.builder.AddFunction( - {spv::OpSelectionMerge, dispatcher.after_switch_label, spv::SelectionControlMaskNone}); + state.builder.AddFunction(spv::OpSelectionMerge, dispatcher.after_switch_label, + spv::SelectionControlMaskNone); std::vector words {spv::OpSwitch, pc, dispatcher.after_switch_label}; for (size_t index = 1; index < state.program.blocks.size(); index++) { words.push_back(state.program.block_info[index].id); @@ -420,13 +417,13 @@ void EmitDispatcherFunction(ValueEmitContext& ctx, const DispatcherFunctionState state.program.block_info[index]); next_pc_words.push_back(selected); next_pc_words.push_back(state.current_label); - state.builder.AddFunction({spv::OpBranch, dispatcher.after_switch_label}); + state.builder.AddFunction(spv::OpBranch, dispatcher.after_switch_label); } EmitLabel(state, dispatcher.after_switch_label); state.builder.AddFunction(next_pc_words); - state.builder.AddFunction({spv::OpBranch, dispatcher.continue_label}); + state.builder.AddFunction(spv::OpBranch, dispatcher.continue_label); EmitLabel(state, dispatcher.continue_label); - state.builder.AddFunction({spv::OpBranch, dispatcher.header_label}); + state.builder.AddFunction(spv::OpBranch, dispatcher.header_label); EmitLabel(state, dispatcher.merge_label); EmitReturn(ctx); } @@ -478,7 +475,8 @@ uint32_t ValueEmitContext::Def(IR::Value value) { return loaded->second.second; } const auto id = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpLoad, TypeId(state, inst->GetType()), id, found->second}); + state.builder.AddFunction(spv::OpLoad, TypeId(state, inst->GetType()), id, + found->second); dispatcher_block_loads.insert_or_assign(inst, std::pair {state.current_label, id}); return id; } @@ -498,9 +496,9 @@ uint32_t ValueEmitContext::Ballot(IR::Value predicate) { const auto ballot_type = TypeU32Vector(state, 4); const auto scope = ConstantU32(state, spv::ScopeSubgroup); const auto low = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpGroupNonUniformBallot, ballot_type, low, scope, - other_half == nullptr || half == 0 ? Def(predicate) : other_half->Def(predicate)}); + state.builder.AddFunction(spv::OpGroupNonUniformBallot, ballot_type, low, scope, + other_half == nullptr || half == 0 ? Def(predicate) + : other_half->Def(predicate)); if (other_half == nullptr) { return low; } @@ -508,20 +506,20 @@ uint32_t ValueEmitContext::Ballot(IR::Value predicate) { const auto low_word = state.builder.AllocateId(); const auto high_word = state.builder.AllocateId(); const auto ballot = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpGroupNonUniformBallot, ballot_type, high, scope, - half == 1 ? Def(predicate) : other_half->Def(predicate)}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), low_word, low, 0}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), high_word, high, 0}); - state.builder.AddFunction({spv::OpCompositeConstruct, ballot_type, ballot, low_word, high_word, - ConstantU32(state, 0), ConstantU32(state, 0)}); + state.builder.AddFunction(spv::OpGroupNonUniformBallot, ballot_type, high, scope, + half == 1 ? Def(predicate) : other_half->Def(predicate)); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), low_word, low, 0); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), high_word, high, 0); + state.builder.AddFunction(spv::OpCompositeConstruct, ballot_type, ballot, low_word, high_word, + ConstantU32(state, 0), ConstantU32(state, 0)); return ballot; } uint32_t ValueEmitContext::FirstLane(uint32_t ballot) { if (other_half == nullptr) { const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpGroupNonUniformBallotFindLSB, TypeU32(state), result, - ConstantU32(state, spv::ScopeSubgroup), ballot}); + state.builder.AddFunction(spv::OpGroupNonUniformBallotFindLSB, TypeU32(state), result, + ConstantU32(state, spv::ScopeSubgroup), ballot); return result; } const auto low = state.builder.AllocateId(); @@ -530,16 +528,16 @@ uint32_t ValueEmitContext::FirstLane(uint32_t ballot) { const auto high_first = state.builder.AllocateId(); const auto low_active = state.builder.AllocateId(); const auto result = state.builder.AllocateId(); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), low, ballot, 0}); - state.builder.AddFunction({spv::OpCompositeExtract, TypeU32(state), high, ballot, 1}); - state.builder.AddFunction( - {spv::OpExtInst, TypeU32(state), low_first, GlslStd450(state), GLSLstd450FindILsb, low}); - state.builder.AddFunction( - {spv::OpExtInst, TypeU32(state), high_first, GlslStd450(state), GLSLstd450FindILsb, high}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), low_active, low, ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpSelect, TypeU32(state), result, low_active, low_first, - EmitAddU32(state, high_first, ConstantU32(state, 32))}); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), low, ballot, 0); + state.builder.AddFunction(spv::OpCompositeExtract, TypeU32(state), high, ballot, 1); + state.builder.AddFunction(spv::OpExtInst, TypeU32(state), low_first, GlslStd450(state), + GLSLstd450FindILsb, low); + state.builder.AddFunction(spv::OpExtInst, TypeU32(state), high_first, GlslStd450(state), + GLSLstd450FindILsb, high); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), low_active, low, + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpSelect, TypeU32(state), result, low_active, low_first, + EmitAddU32(state, high_first, ConstantU32(state, 32))); return result; } @@ -548,8 +546,8 @@ uint32_t ValueEmitContext::Shuffle(const IR::Inst& inst, size_t index, uint32_t const auto scope = ConstantU32(state, spv::ScopeSubgroup); const auto low = state.builder.AllocateId(); if (other_half == nullptr) { - state.builder.AddFunction( - {spv::OpGroupNonUniformShuffle, type, low, scope, Arg(inst, index), lane}); + state.builder.AddFunction(spv::OpGroupNonUniformShuffle, type, low, scope, Arg(inst, index), + lane); return low; } const auto physical_lane = @@ -557,15 +555,14 @@ uint32_t ValueEmitContext::Shuffle(const IR::Inst& inst, size_t index, uint32_t const auto high = state.builder.AllocateId(); const auto in_high = state.builder.AllocateId(); const auto value = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpGroupNonUniformShuffle, type, low, scope, HalfArg(inst, index, 0), physical_lane}); - state.builder.AddFunction( - {spv::OpGroupNonUniformShuffle, type, high, scope, HalfArg(inst, index, 1), physical_lane}); - state.builder.AddFunction( - {spv::OpINotEqual, TypeBool(state), in_high, - EmitBinaryU32(state, spv::OpBitwiseAnd, lane, ConstantU32(state, 32)), - ConstantU32(state, 0)}); - state.builder.AddFunction({spv::OpSelect, type, value, in_high, high, low}); + state.builder.AddFunction(spv::OpGroupNonUniformShuffle, type, low, scope, + HalfArg(inst, index, 0), physical_lane); + state.builder.AddFunction(spv::OpGroupNonUniformShuffle, type, high, scope, + HalfArg(inst, index, 1), physical_lane); + state.builder.AddFunction(spv::OpINotEqual, TypeBool(state), in_high, + EmitBinaryU32(state, spv::OpBitwiseAnd, lane, ConstantU32(state, 32)), + ConstantU32(state, 0)); + state.builder.AddFunction(spv::OpSelect, type, value, in_high, high, low); return value; } @@ -581,8 +578,8 @@ uint32_t ValueEmitContext::Result(const IR::Inst& inst) { uint32_t ValueEmitContext::Define(const IR::Inst& inst, uint32_t value) { if (const auto found = definitions.find(&inst); found != definitions.end()) { if (found->second != value) { - state.builder.AddFunction( - {spv::OpCopyObject, TypeId(state, inst.GetType()), found->second, value}); + state.builder.AddFunction(spv::OpCopyObject, TypeId(state, inst.GetType()), + found->second, value); } return found->second; } @@ -718,28 +715,28 @@ void EmitProgram(EmitterState& state) { break; } } - state.builder.AddFunction({spv::OpFunction, TypeVoid(state), - state.mesh_guest_func != 0 ? state.mesh_guest_func : state.main_func, - spv::FunctionControlMaskNone, TypeFunction(state)}); + state.builder.AddFunction(spv::OpFunction, TypeVoid(state), + state.mesh_guest_func != 0 ? state.mesh_guest_func : state.main_func, + spv::FunctionControlMaskNone, TypeFunction(state)); EmitLabel(state, state.entry_label); if (state.requirements.function_lds) { state.builder.AddFunction( - {spv::OpVariable, - TypeU32ArrayPointer(state, spv::StorageClassFunction, LdsDwordCount(state)), - state.lds_variable, spv::StorageClassFunction}); + spv::OpVariable, + TypeU32ArrayPointer(state, spv::StorageClassFunction, LdsDwordCount(state)), + state.lds_variable, spv::StorageClassFunction); } if (state.requirements.function_scratch) { for (uint32_t half = 0; half < state.lane_count; half++) { - state.builder.AddFunction({spv::OpVariable, - TypeU32ArrayPointer(state, spv::StorageClassFunction, - state.program.scratch_dwords), - state.scratch_variable[half], spv::StorageClassFunction}); + state.builder.AddFunction( + spv::OpVariable, + TypeU32ArrayPointer(state, spv::StorageClassFunction, state.program.scratch_dwords), + state.scratch_variable[half], spv::StorageClassFunction); } } if (state.pixel_valid_mask_variable != 0) { - state.builder.AddFunction({spv::OpVariable, - TypePointer(state, spv::StorageClassFunction, TypeU32(state)), - state.pixel_valid_mask_variable, spv::StorageClassFunction}); + state.builder.AddFunction(spv::OpVariable, + TypePointer(state, spv::StorageClassFunction, TypeU32(state)), + state.pixel_valid_mask_variable, spv::StorageClassFunction); } for (uint32_t half = 0; half < state.lane_count; half++) { auto& lane = half == 0 ? ctx : high; @@ -748,27 +745,27 @@ void EmitProgram(EmitterState& state) { for (const auto& inst: *block) { if (const auto found = dispatcher->spills[half].find(&inst); found != dispatcher->spills[half].end()) { - state.builder.AddFunction({spv::OpVariable, - SpillPointerType(lane, inst.GetType()), - found->second, spv::StorageClassFunction}); + state.builder.AddFunction(spv::OpVariable, + SpillPointerType(lane, inst.GetType()), + found->second, spv::StorageClassFunction); } } } } if (lane.scratch_u32_variable != 0) { - state.builder.AddFunction( - {spv::OpVariable, TypePointer(state, spv::StorageClassFunction, TypeU32(state)), - lane.scratch_u32_variable, spv::StorageClassFunction}); + state.builder.AddFunction(spv::OpVariable, + TypePointer(state, spv::StorageClassFunction, TypeU32(state)), + lane.scratch_u32_variable, spv::StorageClassFunction); } } if (state.gds_variable != 0) { state.gds_length = state.builder.AllocateId(); - state.builder.AddFunction( - {spv::OpArrayLength, TypeU32(state), state.gds_length, state.gds_variable, 0}); + state.builder.AddFunction(spv::OpArrayLength, TypeU32(state), state.gds_length, + state.gds_variable, 0); } if (state.pixel_valid_mask_variable != 0) { - state.builder.AddFunction( - {spv::OpStore, state.pixel_valid_mask_variable, ConstantU32(state, 1)}); + state.builder.AddFunction(spv::OpStore, state.pixel_valid_mask_variable, + ConstantU32(state, 1)); } EmitMemoryOffsets(state); if (program.blocks.empty()) { @@ -778,7 +775,7 @@ void EmitProgram(EmitterState& state) { } else { EmitStructuredFunction(ctx); } - state.builder.AddFunction({spv::OpFunctionEnd}); + state.builder.AddFunction(spv::OpFunctionEnd); if (state.program.stage == ShaderType::Mesh) { EmitMeshEntryPoint(state); } diff --git a/src/graphics/shader/rectListShader.cpp b/src/graphics/shader/rectListShader.cpp index ed6ece214..0d8088493 100644 --- a/src/graphics/shader/rectListShader.cpp +++ b/src/graphics/shader/rectListShader.cpp @@ -55,7 +55,7 @@ class RectListEmitter { public: RectListEmitter(const std::vector& parameters_, spv::ExecutionModel model) : parameters(parameters_) { - builder.AddMemoryModel({spv::AddressingModelLogical, spv::MemoryModelGLSL450}); + builder.AddMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); void_type = Type(spv::OpTypeVoid); uint_type = Type(spv::OpTypeInt, 32u, 0u); @@ -65,9 +65,10 @@ public: function_type = Type(spv::OpTypeFunction, void_type); per_vertex_type = builder.DecoratedType( - spv::OpTypeStruct, {vec4_float_type}, + spv::OpTypeStruct, {{spv::OpMemberDecorate, {0u, spv::DecorationBuiltIn, spv::BuiltInPosition}}, - {spv::OpDecorate, {spv::DecorationBlock}}}); + {spv::OpDecorate, {spv::DecorationBlock}}}, + vec4_float_type); ptr_input_vec4_float = Pointer(spv::StorageClassInput, vec4_float_type); ptr_output_vec4_float = Pointer(spv::StorageClassOutput, vec4_float_type); @@ -188,11 +189,11 @@ public: private: template uint32_t Type(spv::Op opcode, Args... operands) { - return builder.Type(opcode, {operands...}); + return builder.Type(opcode, operands...); } uint32_t Constant(uint32_t type, uint32_t value) { - return builder.Constant(spv::OpConstant, type, {value}); + return builder.Constant(spv::OpConstant, type, value); } uint32_t Pointer(spv::StorageClass storage, uint32_t type) { @@ -206,20 +207,20 @@ private: template uint32_t Result(spv::Op opcode, uint32_t type, Args... operands) { const auto id = builder.AllocateId(); - builder.AddFunction({opcode, type, id, operands...}); + builder.AddFunction(opcode, type, id, operands...); return id; } template uint32_t ResultWithoutType(spv::Op opcode, Args... operands) { const auto id = builder.AllocateId(); - builder.AddFunction({opcode, id, operands...}); + builder.AddFunction(opcode, id, operands...); return id; } template void Emit(spv::Op opcode, Args... operands) { - builder.AddFunction({opcode, operands...}); + builder.AddFunction(opcode, operands...); } template @@ -242,7 +243,7 @@ private: } void Decorate(uint32_t target, spv::Decoration decoration, uint32_t value) { - builder.AddAnnotation({spv::OpDecorate, target, decoration, value}); + builder.AddAnnotation(spv::OpDecorate, target, decoration, value); } void DefineEntry(spv::ExecutionModel model) { @@ -250,11 +251,11 @@ private: builder.RequireCapability(spv::CapabilityTessellation); main = Result(spv::OpFunction, void_type, spv::FunctionControlMaskNone, function_type); if (model == spv::ExecutionModelTessellationControl) { - builder.AddExecutionMode({main, spv::ExecutionModeOutputVertices, 4u}); + builder.AddExecutionMode(main, spv::ExecutionModeOutputVertices, 4u); } else { - builder.AddExecutionMode({main, spv::ExecutionModeQuads}); - builder.AddExecutionMode({main, spv::ExecutionModeSpacingEqual}); - builder.AddExecutionMode({main, spv::ExecutionModeVertexOrderCw}); + builder.AddExecutionMode(main, spv::ExecutionModeQuads); + builder.AddExecutionMode(main, spv::ExecutionModeSpacingEqual); + builder.AddExecutionMode(main, spv::ExecutionModeVertexOrderCw); } DefineInputs(model); DefineOutputs(model); @@ -296,10 +297,10 @@ private: gl_out = AddInterface(spv::StorageClassOutput, Array(per_vertex_type, 4u)); tess_inner = AddInterface(spv::StorageClassOutput, Array(float_type, 2u)); Decorate(tess_inner, spv::DecorationBuiltIn, spv::BuiltInTessLevelInner); - builder.AddAnnotation({spv::OpDecorate, tess_inner, spv::DecorationPatch}); + builder.AddAnnotation(spv::OpDecorate, tess_inner, spv::DecorationPatch); tess_outer = AddInterface(spv::StorageClassOutput, Array(float_type, 4u)); Decorate(tess_outer, spv::DecorationBuiltIn, spv::BuiltInTessLevelOuter); - builder.AddAnnotation({spv::OpDecorate, tess_outer, spv::DecorationPatch}); + builder.AddAnnotation(spv::OpDecorate, tess_outer, spv::DecorationPatch); } else { gl_out = AddInterface(spv::StorageClassOutput, per_vertex_type); } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 223278cba..e16a33237 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -1603,30 +1603,29 @@ std::vector MakePassthroughVertexSpirv(bool layered, float clip_w = 1.0f) { Builder b; const auto void_type = b.Type(spv::OpTypeVoid); - const auto uint_type = b.Type(spv::OpTypeInt, {32, 0}); - const auto int_type = b.Type(spv::OpTypeInt, {32, 1}); - const auto float_type = b.Type(spv::OpTypeFloat, {32}); - const auto vec2_type = b.Type(spv::OpTypeVector, {float_type, 2}); - const auto vec4_type = b.Type(spv::OpTypeVector, {float_type, 4}); + const auto uint_type = b.Type(spv::OpTypeInt, 32, 0); + const auto int_type = b.Type(spv::OpTypeInt, 32, 1); + const auto float_type = b.Type(spv::OpTypeFloat, 32); + const auto vec2_type = b.Type(spv::OpTypeVector, float_type, 2); + const auto vec4_type = b.Type(spv::OpTypeVector, float_type, 4); const auto per_vertex_type = - b.DecoratedType(spv::OpTypeStruct, {vec4_type}, - {{spv::OpDecorate, {spv::DecorationBlock}}, + b.DecoratedType(spv::OpTypeStruct, {{spv::OpDecorate, {spv::DecorationBlock}}, {spv::OpMemberDecorate, - {0, spv::DecorationBuiltIn, spv::BuiltInPosition}}}); + {0, spv::DecorationBuiltIn, spv::BuiltInPosition}}}, vec4_type); const auto ptr_input_vec2 = - b.Type(spv::OpTypePointer, {spv::StorageClassInput, vec2_type}); + b.Type(spv::OpTypePointer, spv::StorageClassInput, vec2_type); const auto ptr_input_vec4 = - b.Type(spv::OpTypePointer, {spv::StorageClassInput, vec4_type}); + b.Type(spv::OpTypePointer, spv::StorageClassInput, vec4_type); const auto ptr_output_vec4 = - b.Type(spv::OpTypePointer, {spv::StorageClassOutput, vec4_type}); + b.Type(spv::OpTypePointer, spv::StorageClassOutput, vec4_type); const auto ptr_output_per_vertex = - b.Type(spv::OpTypePointer, {spv::StorageClassOutput, per_vertex_type}); - const auto func_type = b.Type(spv::OpTypeFunction, {void_type}); - const auto const_u32_0 = b.Constant(spv::OpConstant, uint_type, {0}); + b.Type(spv::OpTypePointer, spv::StorageClassOutput, per_vertex_type); + const auto func_type = b.Type(spv::OpTypeFunction, void_type); + const auto const_u32_0 = b.Constant(spv::OpConstant, uint_type, 0); const auto const_f32_0 = - b.Constant(spv::OpConstant, float_type, {0x00000000u}); + b.Constant(spv::OpConstant, float_type, 0x00000000u); const auto const_f32_w = - b.Constant(spv::OpConstant, float_type, {std::bit_cast(clip_w)}); + b.Constant(spv::OpConstant, float_type, std::bit_cast(clip_w)); const auto in_pos = b.DefineGlobalVariable(ptr_input_vec2, spv::StorageClassInput); const auto in_color = @@ -1640,15 +1639,14 @@ std::vector MakePassthroughVertexSpirv(bool layered, float clip_w = 1.0f) { std::vector interfaces = {in_pos, in_color, per_vertex, out_color}; if (layered) { instance = b.DefineGlobalVariable( - b.Type(spv::OpTypePointer, {spv::StorageClassInput, int_type}), + b.Type(spv::OpTypePointer, spv::StorageClassInput, int_type), spv::StorageClassInput); layer = b.DefineGlobalVariable( - b.Type(spv::OpTypePointer, {spv::StorageClassOutput, int_type}), + b.Type(spv::OpTypePointer, spv::StorageClassOutput, int_type), spv::StorageClassOutput); - b.AddAnnotation({spv::OpDecorate, instance, spv::DecorationBuiltIn, - spv::BuiltInInstanceIndex}); - b.AddAnnotation( - {spv::OpDecorate, layer, spv::DecorationBuiltIn, spv::BuiltInLayer}); + b.AddAnnotation(spv::OpDecorate, instance, spv::DecorationBuiltIn, + spv::BuiltInInstanceIndex); + b.AddAnnotation(spv::OpDecorate, layer, spv::DecorationBuiltIn, spv::BuiltInLayer); b.RequireVersion(0x00010500u); b.RequireCapability(spv::CapabilityShaderLayer); interfaces.insert(interfaces.end(), {instance, layer}); @@ -1663,32 +1661,32 @@ std::vector MakePassthroughVertexSpirv(bool layered, float clip_w = 1.0f) { const auto position_ptr = b.AllocateId(); b.RequireCapability(spv::CapabilityShader); - b.AddMemoryModel({spv::AddressingModelLogical, spv::MemoryModelGLSL450}); + b.AddMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); b.AddEntryPoint(spv::ExecutionModelVertex, main, "main", interfaces); - b.AddAnnotation({spv::OpDecorate, in_pos, spv::DecorationLocation, 0}); - b.AddAnnotation({spv::OpDecorate, in_color, spv::DecorationLocation, 1}); - b.AddAnnotation({spv::OpDecorate, out_color, spv::DecorationLocation, 0}); + b.AddAnnotation(spv::OpDecorate, in_pos, spv::DecorationLocation, 0); + b.AddAnnotation(spv::OpDecorate, in_color, spv::DecorationLocation, 1); + b.AddAnnotation(spv::OpDecorate, out_color, spv::DecorationLocation, 0); - b.AddFunction({spv::OpFunction, void_type, main, spv::FunctionControlMaskNone, - func_type}); - b.AddFunction({spv::OpLabel, label}); - b.AddFunction({spv::OpLoad, vec2_type, pos2, in_pos}); - b.AddFunction({spv::OpLoad, vec4_type, color4, in_color}); - b.AddFunction({spv::OpCompositeExtract, float_type, pos_x, pos2, 0}); - b.AddFunction({spv::OpCompositeExtract, float_type, pos_y, pos2, 1}); - b.AddFunction({spv::OpCompositeConstruct, vec4_type, position, pos_x, pos_y, - const_f32_0, const_f32_w}); - b.AddFunction({spv::OpAccessChain, ptr_output_vec4, position_ptr, per_vertex, - const_u32_0}); - b.AddFunction({spv::OpStore, position_ptr, position}); - b.AddFunction({spv::OpStore, out_color, color4}); + b.AddFunction(spv::OpFunction, void_type, main, spv::FunctionControlMaskNone, + func_type); + b.AddFunction(spv::OpLabel, label); + b.AddFunction(spv::OpLoad, vec2_type, pos2, in_pos); + b.AddFunction(spv::OpLoad, vec4_type, color4, in_color); + b.AddFunction(spv::OpCompositeExtract, float_type, pos_x, pos2, 0); + b.AddFunction(spv::OpCompositeExtract, float_type, pos_y, pos2, 1); + b.AddFunction(spv::OpCompositeConstruct, vec4_type, position, pos_x, pos_y, + const_f32_0, const_f32_w); + b.AddFunction(spv::OpAccessChain, ptr_output_vec4, position_ptr, per_vertex, + const_u32_0); + b.AddFunction(spv::OpStore, position_ptr, position); + b.AddFunction(spv::OpStore, out_color, color4); if (layered) { const auto index = b.AllocateId(); - b.AddFunction({spv::OpLoad, int_type, index, instance}); - b.AddFunction({spv::OpStore, layer, index}); + b.AddFunction(spv::OpLoad, int_type, index, instance); + b.AddFunction(spv::OpStore, layer, index); } - b.AddFunction({spv::OpReturn}); - b.AddFunction({spv::OpFunctionEnd}); + b.AddFunction(spv::OpReturn); + b.AddFunction(spv::OpFunctionEnd); return b.Build(); } diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 6f4ca66ac..c113dea9b 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -10025,11 +10025,120 @@ void TestNewShaderRecompilerAuxPositionExports() { "PA_CL_VS_OUT_CNTL is absent from the vertex shader cache key"); } +void TestTypedSpirvSerialization() { + // Parameters exercise runtime enums, which cannot narrow implicitly to a + // uint32_t initializer list when the enum uses the Windows signed ABI. + const auto check_serialization = [](spv::StorageClass storage_class, + spv::FunctionControlMask control, + spv::Decoration decoration, + GLSLstd450 glsl_opcode, + int32_t signed_literal, + uint32_t high_bit_literal) { + ShaderRecompiler::Spirv::Builder builder; + builder.RequireCapability(spv::CapabilityShader); + const auto glsl = builder.Import("GLSL.std.450"); + builder.AddMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); + const auto void_type = builder.Type(spv::OpTypeVoid); + const std::vector uint_operands{32u, 0u}; + const auto uint_type = builder.Type(spv::OpTypeInt, uint_operands); + Check(uint_type == builder.Type(spv::OpTypeInt, 32u, 0u) && + uint_type == builder.Type(spv::OpTypeInt, + std::span{uint_operands}), + "typed, vector and span type operands produced different declarations"); + const auto float_type = builder.Type(spv::OpTypeFloat, 32u); + const auto vector_type = builder.Type(spv::OpTypeVector, uint_type, 2u); + const auto pointer_type = + builder.Type(spv::OpTypePointer, storage_class, uint_type); + const auto function_type = builder.Type(spv::OpTypeFunction, void_type); + const auto all_bits = + builder.Constant(spv::OpConstant, uint_type, signed_literal); + Check(all_bits == builder.Constant(spv::OpConstant, uint_type, UINT32_MAX), + "signed and unsigned constant operands produced different declarations"); + const auto high_bit = + builder.Constant(spv::OpConstant, uint_type, high_bit_literal); + const auto one = builder.Constant(spv::OpConstant, float_type, 0x3f800000u); + const std::vector components{all_bits, high_bit}; + const auto constant_vector = builder.Constant( + spv::OpConstantComposite, vector_type, + std::span{components}); + Check(constant_vector == builder.Constant(spv::OpConstantComposite, + vector_type, components), + "vector and span constant operands produced different declarations"); + const auto variable = + builder.DefineGlobalVariable(pointer_type, storage_class); + const auto function = builder.AllocateId(); + const auto label = builder.AllocateId(); + const auto absolute = builder.AllocateId(); + const auto constructed = builder.AllocateId(); + const auto shuffled = builder.AllocateId(); + const auto loaded = builder.AllocateId(); + builder.AddEntryPoint(spv::ExecutionModelGLCompute, function, "main", {}); + builder.AddExecutionMode(function, spv::ExecutionModeLocalSize, 1u, 2u, 3u); + builder.AddAnnotation(spv::OpDecorate, one, decoration); + builder.AddFunction(spv::OpFunction, void_type, function, control, + function_type); + const std::vector label_words{248u, label}; + builder.AddFunction(label_words); + builder.AddFunction(spv::OpExtInst, float_type, absolute, glsl, glsl_opcode, + one); + builder.AddFunction(spv::OpCompositeConstruct, vector_type, constructed, + components); + const std::array selectors{1u, 2u}; + builder.AddFunction(spv::OpVectorShuffle, vector_type, shuffled, + constant_vector, constructed, + std::span{selectors}); + builder.AddFunction(spv::OpLoad, uint_type, loaded, variable, + spv::MemoryAccessAlignedMask, 4u); + builder.AddFunction(std::vector{}); + const std::array return_words{253u}; + builder.AddFunction(std::span{return_words}); + builder.AddFunction(spv::OpFunctionEnd); + + // Literal headers and enum values keep this independent of the builder's + // instruction word counts, operand conversion and range flattening. + const std::vector expected{ + 0x07230203u, 0x00010300u, 0u, loaded + 1u, 0u, + 0x00020011u, 1u, // OpCapability Shader + 0x0006000bu, glsl, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0u, + 0x0003000eu, 0u, 1u, // OpMemoryModel Logical GLSL450 + 0x0005000fu, 5u, function, 0x6e69616du, 0u, + 0x00060010u, function, 17u, 1u, 2u, 3u, + 0x00030047u, one, 0u, // OpDecorate RelaxedPrecision + 0x00020013u, void_type, + 0x00040015u, uint_type, 32u, 0u, + 0x00030016u, float_type, 32u, + 0x00040017u, vector_type, uint_type, 2u, + 0x00040020u, pointer_type, 6u, uint_type, + 0x00030021u, function_type, void_type, + 0x0004002bu, uint_type, all_bits, 0xffffffffu, + 0x0004002bu, uint_type, high_bit, 0x80000000u, + 0x0004002bu, float_type, one, 0x3f800000u, + 0x0005002cu, vector_type, constant_vector, all_bits, high_bit, + 0x0004003bu, pointer_type, variable, 6u, + 0x00050036u, void_type, function, 0u, function_type, + 0x000200f8u, label, + 0x0006000cu, float_type, absolute, glsl, 4u, one, + 0x00050050u, vector_type, constructed, all_bits, high_bit, + 0x0007004fu, vector_type, shuffled, constant_vector, constructed, 1u, 2u, + 0x0006003du, uint_type, loaded, variable, 2u, 4u, + 0x000100fdu, + 0x00010038u, + }; + const auto binary = builder.Build(); + Check(binary == expected, + "typed SPIR-V serialization changed instruction words or operand order"); + CheckSpirvBinaryValidates(binary); + }; + check_serialization(spv::StorageClassPrivate, spv::FunctionControlMaskNone, + spv::DecorationRelaxedPrecision, GLSLstd450FAbs, -1, + 0x80000000u); +} + void TestDeferredSpirvPhiPatching() { ShaderRecompiler::Spirv::Builder builder; - const auto type = builder.Type(spv::OpTypeInt, {32u, 0u}); - const auto zero = builder.Constant(spv::OpConstant, type, {0u}); - const auto one = builder.Constant(spv::OpConstant, type, {1u}); + const auto type = builder.Type(spv::OpTypeInt, 32u, 0u); + const auto zero = builder.Constant(spv::OpConstant, type, 0u); + const auto one = builder.Constant(spv::OpConstant, type, 1u); const auto left = builder.AllocateId(); const auto right = builder.AllocateId(); const auto result = builder.AllocateId(); @@ -10080,35 +10189,36 @@ void TestDemandDrivenSpirvDeclarations() { using ShaderRecompiler::Spirv::Builder; Builder declarations; - const auto uint_type = declarations.Type(spv::OpTypeInt, {32u, 0u}); - Check(uint_type == declarations.Type(spv::OpTypeInt, {32u, 0u}), + const auto uint_type = declarations.Type(spv::OpTypeInt, 32u, 0u); + Check(uint_type == declarations.Type(spv::OpTypeInt, 32u, 0u), "structural type interning returned different IDs"); - const auto zero = declarations.Constant(spv::OpConstant, uint_type, {0u}); - Check(zero == declarations.Constant(spv::OpConstant, uint_type, {0u}), + const auto zero = declarations.Constant(spv::OpConstant, uint_type, 0u); + Check(zero == declarations.Constant(spv::OpConstant, uint_type, 0u), "constant interning returned different IDs"); Check(declarations.Import("GLSL.std.450") == declarations.Import("GLSL.std.450"), "extended-instruction import was duplicated"); declarations.RequireCapability(spv::CapabilityShader); declarations.RequireCapability(spv::CapabilityShader); - const auto plain_array = - declarations.Type(spv::OpTypeArray, {uint_type, zero}); + const auto plain_array = declarations.Type(spv::OpTypeArray, uint_type, zero); const auto decorated_array = declarations.DecoratedType( - spv::OpTypeArray, {uint_type, zero}, - {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint32_t)}}}); + spv::OpTypeArray, + {{spv::OpDecorate, {spv::DecorationArrayStride, sizeof(uint32_t)}}}, + uint_type, zero); Check(decorated_array == declarations.DecoratedType( - spv::OpTypeArray, {uint_type, zero}, + spv::OpTypeArray, {{spv::OpDecorate, - {spv::DecorationArrayStride, sizeof(uint32_t)}}}), + {spv::DecorationArrayStride, sizeof(uint32_t)}}}, + uint_type, zero), "decorated type interning returned different IDs"); Check(plain_array != decorated_array, "decorated and undecorated aggregate types were aliased"); - Check(declarations.DecoratedType(spv::OpTypeArray, {uint_type, zero}, {}) == + Check(declarations.DecoratedType(spv::OpTypeArray, {}, uint_type, zero) == plain_array, "empty decorated type request bypassed structural interning"); const auto ptr = declarations.Type(spv::OpTypePointer, - {spv::StorageClassFunction, uint_type}); + spv::StorageClassFunction, uint_type); Check(declarations.DefineGlobalVariable(ptr, spv::StorageClassFunction) != declarations.DefineGlobalVariable(ptr, spv::StorageClassFunction), "distinct variables were structurally interned"); @@ -13020,6 +13130,7 @@ int main() { TestNativeShaderResourceDependencies(); TestNormalizedImageContracts(); TestSpirvRequirementsAnalysis(); + TestTypedSpirvSerialization(); TestDeferredSpirvPhiPatching(); TestCompilerStageInputOwnership(); TestSpirvEmissionOwnsRequirements();