#include "spirv_module.h" namespace dxvk { SpirvModule:: SpirvModule() { this->instImportGlsl450(); } SpirvModule::~SpirvModule() { } SpirvCodeBuffer SpirvModule::compile() const { SpirvCodeBuffer result; result.putHeader(m_id); result.append(m_capabilities); result.append(m_extensions); result.append(m_instExt); result.append(m_memoryModel); result.append(m_entryPoints); result.append(m_execModeInfo); result.append(m_debugNames); result.append(m_annotations); result.append(m_typeConstDefs); result.append(m_variables); result.append(m_code); return result; } uint32_t SpirvModule::allocateId() { return m_id++; } void SpirvModule::enableCapability( spv::Capability capability) { // Scan the generated instructions to check // whether we already enabled the capability. for (auto ins : m_capabilities) { if (ins.opCode() == spv::OpCapability && ins.arg(1) == capability) return; } m_capabilities.putIns (spv::OpCapability, 2); m_capabilities.putWord(capability); } void SpirvModule::enableExtension( const char* extensionName) { m_extensions.putIns (spv::OpExtension, 1 + m_extensions.strLen(extensionName)); m_extensions.putStr (extensionName); } void SpirvModule::addEntryPoint( uint32_t entryPointId, spv::ExecutionModel executionModel, const char* name, uint32_t interfaceCount, const uint32_t* interfaceIds) { m_entryPoints.putIns (spv::OpEntryPoint, 3 + m_entryPoints.strLen(name) + interfaceCount); m_entryPoints.putWord (executionModel); m_entryPoints.putWord (entryPointId); m_entryPoints.putStr (name); for (uint32_t i = 0; i < interfaceCount; i++) m_entryPoints.putWord(interfaceIds[i]); } void SpirvModule::setMemoryModel( spv::AddressingModel addressModel, spv::MemoryModel memoryModel) { m_memoryModel.putIns (spv::OpMemoryModel, 3); m_memoryModel.putWord (addressModel); m_memoryModel.putWord (memoryModel); } void SpirvModule::setExecutionMode( uint32_t entryPointId, spv::ExecutionMode executionMode) { m_execModeInfo.putIns (spv::OpExecutionMode, 3); m_execModeInfo.putWord(entryPointId); m_execModeInfo.putWord(executionMode); } void SpirvModule::setLocalSize( uint32_t entryPointId, uint32_t x, uint32_t y, uint32_t z) { m_execModeInfo.putIns (spv::OpExecutionMode, 6); m_execModeInfo.putWord (entryPointId); m_execModeInfo.putWord (spv::ExecutionModeLocalSize); m_execModeInfo.putInt32(x); m_execModeInfo.putInt32(y); m_execModeInfo.putInt32(z); } void SpirvModule::setOutputVertices( uint32_t entryPointId, uint32_t vertexCount) { m_execModeInfo.putIns (spv::OpExecutionMode, 4); m_execModeInfo.putWord(entryPointId); m_execModeInfo.putWord(spv::ExecutionModeOutputVertices); m_execModeInfo.putWord(vertexCount); } void SpirvModule::setDebugName( uint32_t expressionId, const char* debugName) { m_debugNames.putIns (spv::OpName, 2 + m_debugNames.strLen(debugName)); m_debugNames.putWord(expressionId); m_debugNames.putStr (debugName); } void SpirvModule::setDebugMemberName( uint32_t structId, uint32_t memberId, const char* debugName) { m_debugNames.putIns (spv::OpMemberName, 3 + m_debugNames.strLen(debugName)); m_debugNames.putWord(structId); m_debugNames.putWord(memberId); m_debugNames.putStr (debugName); } uint32_t SpirvModule::constBool( bool v) { uint32_t typeId = this->defBoolType(); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (v ? spv::OpConstantTrue : spv::OpConstantFalse, 3); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); return resultId; } uint32_t SpirvModule::consti32( int32_t v) { uint32_t typeId = this->defIntType(32, 1); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstant, 4); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); m_typeConstDefs.putInt32(v); return resultId; } uint32_t SpirvModule::consti64( int64_t v) { uint32_t typeId = this->defIntType(64, 1); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstant, 5); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); m_typeConstDefs.putInt64(v); return resultId; } uint32_t SpirvModule::constu32( uint32_t v) { uint32_t typeId = this->defIntType(32, 0); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstant, 4); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); m_typeConstDefs.putInt32(v); return resultId; } uint32_t SpirvModule::constu64( uint64_t v) { uint32_t typeId = this->defIntType(64, 0); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstant, 5); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); m_typeConstDefs.putInt64(v); return resultId; } uint32_t SpirvModule::constf32( float v) { uint32_t typeId = this->defFloatType(32); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstant, 4); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); m_typeConstDefs.putFloat32(v); return resultId; } uint32_t SpirvModule::constf64( double v) { uint32_t typeId = this->defFloatType(64); uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstant, 5); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); m_typeConstDefs.putFloat64(v); return resultId; } uint32_t SpirvModule::constComposite( uint32_t typeId, uint32_t constCount, const uint32_t* constIds) { uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpConstantComposite, 3 + constCount); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); for (uint32_t i = 0; i < constCount; i++) m_typeConstDefs.putWord(constIds[i]); return resultId; } uint32_t SpirvModule::specConstBool( bool v) { uint32_t typeId = this->defBoolType(); uint32_t resultId = this->allocateId(); const spv::Op op = v ? spv::OpSpecConstantTrue : spv::OpSpecConstantFalse; m_typeConstDefs.putIns (op, 3); m_typeConstDefs.putWord (typeId); m_typeConstDefs.putWord (resultId); return resultId; } void SpirvModule::decorate( uint32_t object, spv::Decoration decoration) { m_annotations.putIns (spv::OpDecorate, 3); m_annotations.putWord (object); m_annotations.putWord (decoration); } void SpirvModule::decorateArrayStride( uint32_t object, uint32_t stride) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationArrayStride); m_annotations.putInt32(stride); } void SpirvModule::decorateBinding( uint32_t object, uint32_t binding) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationBinding); m_annotations.putInt32(binding); } void SpirvModule::decorateBlock(uint32_t object) { m_annotations.putIns (spv::OpDecorate, 3); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationBlock); } void SpirvModule::decorateBuiltIn( uint32_t object, spv::BuiltIn builtIn) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationBuiltIn); m_annotations.putWord (builtIn); } void SpirvModule::decorateComponent( uint32_t object, uint32_t location) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationComponent); m_annotations.putInt32(location); } void SpirvModule::decorateDescriptorSet( uint32_t object, uint32_t set) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationDescriptorSet); m_annotations.putInt32(set); } void SpirvModule::decorateLocation( uint32_t object, uint32_t location) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationLocation); m_annotations.putInt32(location); } void SpirvModule::decorateSpecId( uint32_t object, uint32_t specId) { m_annotations.putIns (spv::OpDecorate, 4); m_annotations.putWord (object); m_annotations.putWord (spv::DecorationSpecId); m_annotations.putInt32(specId); } void SpirvModule::memberDecorateBuiltIn( uint32_t structId, uint32_t memberId, spv::BuiltIn builtIn) { m_annotations.putIns (spv::OpMemberDecorate, 5); m_annotations.putWord (structId); m_annotations.putWord (memberId); m_annotations.putWord (spv::DecorationBuiltIn); m_annotations.putWord (builtIn); } void SpirvModule::memberDecorateOffset( uint32_t structId, uint32_t memberId, uint32_t offset) { m_annotations.putIns (spv::OpMemberDecorate, 5); m_annotations.putWord (structId); m_annotations.putWord (memberId); m_annotations.putWord (spv::DecorationOffset); m_annotations.putWord (offset); } uint32_t SpirvModule::defVoidType() { return this->defType(spv::OpTypeVoid, 0, nullptr); } uint32_t SpirvModule::defBoolType() { return this->defType(spv::OpTypeBool, 0, nullptr); } uint32_t SpirvModule::defIntType( uint32_t width, uint32_t isSigned) { std::array args = { width, isSigned }; return this->defType(spv::OpTypeInt, args.size(), args.data()); } uint32_t SpirvModule::defFloatType( uint32_t width) { std::array args = { width }; return this->defType(spv::OpTypeFloat, args.size(), args.data()); } uint32_t SpirvModule::defVectorType( uint32_t elementType, uint32_t elementCount) { std::array args = { elementType, elementCount }; return this->defType(spv::OpTypeVector, args.size(), args.data()); } uint32_t SpirvModule::defMatrixType( uint32_t columnType, uint32_t columnCount) { std::array args = { columnType, columnCount }; return this->defType(spv::OpTypeMatrix, args.size(), args.data()); } uint32_t SpirvModule::defArrayType( uint32_t typeId, uint32_t length) { std::array args = { typeId, length }; return this->defType(spv::OpTypeArray, args.size(), args.data()); } uint32_t SpirvModule::defArrayTypeUnique( uint32_t typeId, uint32_t length) { uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpTypeArray, 4); m_typeConstDefs.putWord(resultId); m_typeConstDefs.putWord(typeId); m_typeConstDefs.putWord(length); return resultId; } uint32_t SpirvModule::defRuntimeArrayType( uint32_t typeId) { std::array args = { typeId }; return this->defType(spv::OpTypeRuntimeArray, args.size(), args.data()); } uint32_t SpirvModule::defRuntimeArrayTypeUnique( uint32_t typeId) { uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpTypeRuntimeArray, 3); m_typeConstDefs.putWord(resultId); m_typeConstDefs.putWord(typeId); return resultId; } uint32_t SpirvModule::defFunctionType( uint32_t returnType, uint32_t argCount, const uint32_t* argTypes) { std::vector args; args.push_back(returnType); for (uint32_t i = 0; i < argCount; i++) args.push_back(argTypes[i]); return this->defType(spv::OpTypeFunction, args.size(), args.data()); } uint32_t SpirvModule::defStructType( uint32_t memberCount, const uint32_t* memberTypes) { return this->defType(spv::OpTypeStruct, memberCount, memberTypes); } uint32_t SpirvModule::defStructTypeUnique( uint32_t memberCount, const uint32_t* memberTypes) { uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (spv::OpTypeStruct, 2 + memberCount); m_typeConstDefs.putWord(resultId); for (uint32_t i = 0; i < memberCount; i++) m_typeConstDefs.putWord(memberTypes[i]); return resultId; } uint32_t SpirvModule::defPointerType( uint32_t variableType, spv::StorageClass storageClass) { std::array args = { storageClass, variableType, }; return this->defType(spv::OpTypePointer, args.size(), args.data()); } uint32_t SpirvModule::defSamplerType() { return this->defType(spv::OpTypeSampler, 0, nullptr); } uint32_t SpirvModule::defImageType( uint32_t sampledType, spv::Dim dimensionality, uint32_t depth, uint32_t arrayed, uint32_t multisample, uint32_t sampled, spv::ImageFormat format) { std::array args = { sampledType, dimensionality, depth, arrayed, multisample, sampled, format }; return this->defType(spv::OpTypeImage, args.size(), args.data()); } uint32_t SpirvModule::defSampledImageType( uint32_t imageType) { return this->defType(spv::OpTypeSampledImage, 1, &imageType); } uint32_t SpirvModule::newVar( uint32_t pointerType, spv::StorageClass storageClass) { uint32_t resultId = this->allocateId(); m_variables.putIns (spv::OpVariable, 4); m_variables.putWord (pointerType); m_variables.putWord (resultId); m_variables.putWord (storageClass); return resultId; } uint32_t SpirvModule::newVarInit( uint32_t pointerType, spv::StorageClass storageClass, uint32_t initialValue) { uint32_t resultId = this->allocateId(); m_variables.putIns (spv::OpVariable, 5); m_variables.putWord (pointerType); m_variables.putWord (resultId); m_variables.putWord (storageClass); m_variables.putWord (initialValue); return resultId; } void SpirvModule::functionBegin( uint32_t returnType, uint32_t functionId, uint32_t functionType, spv::FunctionControlMask functionControl) { m_code.putIns (spv::OpFunction, 5); m_code.putWord(returnType); m_code.putWord(functionId); m_code.putWord(functionControl); m_code.putWord(functionType); } uint32_t SpirvModule::functionParameter( uint32_t parameterType) { uint32_t parameterId = this->allocateId(); m_code.putIns (spv::OpFunctionParameter, 3); m_code.putWord(parameterType); m_code.putWord(parameterId); return parameterId; } void SpirvModule::functionEnd() { m_code.putIns (spv::OpFunctionEnd, 1); } uint32_t SpirvModule::opAccessChain( uint32_t resultType, uint32_t composite, uint32_t indexCount, const uint32_t* indexArray) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAccessChain, 4 + indexCount); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(composite); for (uint32_t i = 0; i < indexCount; i++) m_code.putInt32(indexArray[i]); return resultId; } uint32_t SpirvModule::opAny( uint32_t resultType, uint32_t vector) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAny, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector); return resultId; } uint32_t SpirvModule::opAll( uint32_t resultType, uint32_t vector) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAll, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector); return resultId; } uint32_t SpirvModule::opAtomicLoad( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicLoad, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); return resultId; } void SpirvModule::opAtomicStore( uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { m_code.putIns (spv::OpAtomicStore, 5); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); } uint32_t SpirvModule::opAtomicExchange( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicExchange, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicCompareExchange( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t equal, uint32_t unequal, uint32_t value, uint32_t comparator) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicCompareExchange, 9); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(equal); m_code.putWord(unequal); m_code.putWord(value); m_code.putWord(comparator); return resultId; } uint32_t SpirvModule::opAtomicIIncrement( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicIIncrement, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); return resultId; } uint32_t SpirvModule::opAtomicIDecrement( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicIDecrement, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); return resultId; } uint32_t SpirvModule::opAtomicIAdd( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicIAdd, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicISub( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicISub, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicSMin( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicSMin, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicSMax( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicSMax, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicUMin( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicUMin, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicUMax( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicUMax, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicAnd( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicAnd, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicOr( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicOr, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opAtomicXor( uint32_t resultType, uint32_t pointer, uint32_t scope, uint32_t semantics, uint32_t value) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpAtomicXor, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(pointer); m_code.putWord(scope); m_code.putWord(semantics); m_code.putWord(value); return resultId; } uint32_t SpirvModule::opBitcast( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitcast, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opBitCount( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitCount, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opBitReverse( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitReverse, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFindILsb( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FindILsb); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFindUMsb( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FindUMsb); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFindSMsb( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FindSMsb); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opBitFieldInsert( uint32_t resultType, uint32_t base, uint32_t insert, uint32_t offset, uint32_t count) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitFieldInsert, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(base); m_code.putWord(insert); m_code.putWord(offset); m_code.putWord(count); return resultId; } uint32_t SpirvModule::opBitFieldSExtract( uint32_t resultType, uint32_t base, uint32_t offset, uint32_t count) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitFieldSExtract, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(base); m_code.putWord(offset); m_code.putWord(count); return resultId; } uint32_t SpirvModule::opBitFieldUExtract( uint32_t resultType, uint32_t base, uint32_t offset, uint32_t count) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitFieldUExtract, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(base); m_code.putWord(offset); m_code.putWord(count); return resultId; } uint32_t SpirvModule::opBitwiseAnd( uint32_t resultType, uint32_t operand1, uint32_t operand2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitwiseAnd, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand1); m_code.putWord(operand2); return resultId; } uint32_t SpirvModule::opBitwiseOr( uint32_t resultType, uint32_t operand1, uint32_t operand2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitwiseOr, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand1); m_code.putWord(operand2); return resultId; } uint32_t SpirvModule::opBitwiseXor( uint32_t resultType, uint32_t operand1, uint32_t operand2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpBitwiseXor, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand1); m_code.putWord(operand2); return resultId; } uint32_t SpirvModule::opNot( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpNot, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opShiftLeftLogical( uint32_t resultType, uint32_t base, uint32_t shift) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpShiftLeftLogical, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(base); m_code.putWord(shift); return resultId; } uint32_t SpirvModule::opShiftRightArithmetic( uint32_t resultType, uint32_t base, uint32_t shift) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpShiftRightArithmetic, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(base); m_code.putWord(shift); return resultId; } uint32_t SpirvModule::opShiftRightLogical( uint32_t resultType, uint32_t base, uint32_t shift) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpShiftRightLogical, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(base); m_code.putWord(shift); return resultId; } uint32_t SpirvModule::opConvertFtoS( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpConvertFToS, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opConvertFtoU( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpConvertFToU, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opConvertStoF( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpConvertSToF, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opConvertUtoF( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpConvertUToF, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opCompositeConstruct( uint32_t resultType, uint32_t valueCount, const uint32_t* valueArray) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpCompositeConstruct, 3 + valueCount); m_code.putWord(resultType); m_code.putWord(resultId); for (uint32_t i = 0; i < valueCount; i++) m_code.putWord(valueArray[i]); return resultId; } uint32_t SpirvModule::opCompositeExtract( uint32_t resultType, uint32_t composite, uint32_t indexCount, const uint32_t* indexArray) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpCompositeExtract, 4 + indexCount); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(composite); for (uint32_t i = 0; i < indexCount; i++) m_code.putInt32(indexArray[i]); return resultId; } uint32_t SpirvModule::opCompositeInsert( uint32_t resultType, uint32_t object, uint32_t composite, uint32_t indexCount, const uint32_t* indexArray) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpCompositeInsert, 5 + indexCount); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(object); m_code.putWord(composite); for (uint32_t i = 0; i < indexCount; i++) m_code.putInt32(indexArray[i]); return resultId; } uint32_t SpirvModule::opDpdx( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDPdx, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opDpdy( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDPdy, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opDpdxCoarse( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDPdxCoarse, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opDpdyCoarse( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDPdyCoarse, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opDpdxFine( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDPdxFine, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opDpdyFine( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDPdyFine, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opVectorShuffle( uint32_t resultType, uint32_t vectorLeft, uint32_t vectorRight, uint32_t indexCount, const uint32_t* indexArray) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpVectorShuffle, 5 + indexCount); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vectorLeft); m_code.putWord(vectorRight); for (uint32_t i = 0; i < indexCount; i++) m_code.putInt32(indexArray[i]); return resultId; } uint32_t SpirvModule::opSNegate( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSNegate, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFNegate( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFNegate, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opSAbs( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450SAbs); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFAbs( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FAbs); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opIAdd( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpIAdd, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opISub( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpISub, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFAdd( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFAdd, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFSub( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFSub, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opSDiv( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSDiv, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opUDiv( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpUDiv, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opSRem( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSRem, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opUMod( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpUMod, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFDiv( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFDiv, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opIMul( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpIMul, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFMul( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFMul, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFFma( uint32_t resultType, uint32_t a, uint32_t b, uint32_t c) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 8); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Fma); m_code.putWord(a); m_code.putWord(b); m_code.putWord(c); return resultId; } uint32_t SpirvModule::opFMax( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FMax); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFMin( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FMin); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opNMax( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450NMax); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opNMin( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450NMin); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opSMax( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450SMax); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opSMin( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450SMin); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opUMax( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450UMax); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opUMin( uint32_t resultType, uint32_t a, uint32_t b) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 7); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450UMin); m_code.putWord(a); m_code.putWord(b); return resultId; } uint32_t SpirvModule::opFClamp( uint32_t resultType, uint32_t x, uint32_t minVal, uint32_t maxVal) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 8); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450FClamp); m_code.putWord(x); m_code.putWord(minVal); m_code.putWord(maxVal); return resultId; } uint32_t SpirvModule::opNClamp( uint32_t resultType, uint32_t x, uint32_t minVal, uint32_t maxVal) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 8); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450NClamp); m_code.putWord(x); m_code.putWord(minVal); m_code.putWord(maxVal); return resultId; } uint32_t SpirvModule::opIEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpIEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opINotEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpINotEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opSLessThan( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSLessThan, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opSLessThanEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSLessThanEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opSGreaterThan( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSGreaterThan, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opSGreaterThanEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSGreaterThanEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opULessThan( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpULessThan, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opULessThanEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpULessThanEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opUGreaterThan( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpUGreaterThan, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opUGreaterThanEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpUGreaterThanEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opFOrdEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFOrdEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opFOrdNotEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFOrdNotEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opFOrdLessThan( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFOrdLessThan, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opFOrdLessThanEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFOrdLessThanEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opFOrdGreaterThan( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFOrdGreaterThan, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opFOrdGreaterThanEqual( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFOrdGreaterThanEqual, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opDot( uint32_t resultType, uint32_t vector1, uint32_t vector2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpDot, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(vector1); m_code.putWord(vector2); return resultId; } uint32_t SpirvModule::opSin( uint32_t resultType, uint32_t vector) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Sin); m_code.putWord(vector); return resultId; } uint32_t SpirvModule::opCos( uint32_t resultType, uint32_t vector) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Cos); m_code.putWord(vector); return resultId; } uint32_t SpirvModule::opSqrt( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Sqrt); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opInverseSqrt( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450InverseSqrt); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opExp2( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Exp2); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opLog2( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Log2); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFract( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Fract); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opCeil( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Ceil); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opFloor( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Floor); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opRound( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Round); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opRoundEven( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450RoundEven); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opTrunc( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450Trunc); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opPackHalf2x16( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450PackHalf2x16); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opUnpackHalf2x16( uint32_t resultType, uint32_t operand) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpExtInst, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(m_instExtGlsl450); m_code.putWord(spv::GLSLstd450UnpackHalf2x16); m_code.putWord(operand); return resultId; } uint32_t SpirvModule::opSelect( uint32_t resultType, uint32_t condition, uint32_t operand1, uint32_t operand2) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSelect, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(condition); m_code.putWord(operand1); m_code.putWord(operand2); return resultId; } uint32_t SpirvModule::opFunctionCall( uint32_t resultType, uint32_t functionId, uint32_t argCount, const uint32_t* argIds) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpFunctionCall, 4 + argCount); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(functionId); for (uint32_t i = 0; i < argCount; i++) m_code.putWord(argIds[i]); return resultId; } void SpirvModule::opLabel(uint32_t labelId) { m_code.putIns (spv::OpLabel, 2); m_code.putWord(labelId); } uint32_t SpirvModule::opLoad( uint32_t typeId, uint32_t pointerId) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpLoad, 4); m_code.putWord(typeId); m_code.putWord(resultId); m_code.putWord(pointerId); return resultId; } void SpirvModule::opStore( uint32_t pointerId, uint32_t valueId) { m_code.putIns (spv::OpStore, 3); m_code.putWord(pointerId); m_code.putWord(valueId); } uint32_t SpirvModule::opImageRead( uint32_t resultType, uint32_t image, uint32_t coordinates, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageRead, 5 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); m_code.putWord(coordinates); putImageOperands(operands); return resultId; } void SpirvModule::opImageWrite( uint32_t image, uint32_t coordinates, uint32_t texel, const SpirvImageOperands& operands) { m_code.putIns (spv::OpImageWrite, 4 + getImageOperandWordCount(operands)); m_code.putWord(image); m_code.putWord(coordinates); m_code.putWord(texel); putImageOperands(operands); } uint32_t SpirvModule::opSampledImage( uint32_t resultType, uint32_t image, uint32_t sampler) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpSampledImage, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); m_code.putWord(sampler); return resultId; } uint32_t SpirvModule::opImageTexelPointer( uint32_t resultType, uint32_t image, uint32_t coordinates, uint32_t sample) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageTexelPointer, 6); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); m_code.putWord(coordinates); m_code.putWord(sample); return resultId; } uint32_t SpirvModule::opImageQuerySizeLod( uint32_t resultType, uint32_t image, uint32_t lod) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageQuerySizeLod, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); m_code.putWord(lod); return resultId; } uint32_t SpirvModule::opImageQuerySize( uint32_t resultType, uint32_t image) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageQuerySize, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); return resultId; } uint32_t SpirvModule::opImageQueryLevels( uint32_t resultType, uint32_t image) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageQueryLevels, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); return resultId; } uint32_t SpirvModule::opImageQueryLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageQueryLod, 5); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); return resultId; } uint32_t SpirvModule::opImageQuerySamples( uint32_t resultType, uint32_t image) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpImageQuerySamples, 4); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); return resultId; } uint32_t SpirvModule::opImageFetch( uint32_t resultType, uint32_t image, uint32_t coordinates, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageFetch, 5 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(image); m_code.putWord(coordinates); putImageOperands(operands); return resultId; } uint32_t SpirvModule::opImageGather( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, uint32_t component, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageGather, 6 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); m_code.putWord(component); putImageOperands(operands); return resultId; } uint32_t SpirvModule::opImageDrefGather( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, uint32_t reference, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageDrefGather, 6 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); m_code.putWord(reference); putImageOperands(operands); return resultId; } uint32_t SpirvModule::opImageSampleImplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageSampleImplicitLod, 5 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); putImageOperands(operands); return resultId; } uint32_t SpirvModule::opImageSampleExplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageSampleExplicitLod, 5 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); putImageOperands(operands); return resultId; } uint32_t SpirvModule::opImageSampleDrefImplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, uint32_t reference, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageSampleDrefImplicitLod, 6 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); m_code.putWord(reference); putImageOperands(operands); return resultId; } uint32_t SpirvModule::opImageSampleDrefExplicitLod( uint32_t resultType, uint32_t sampledImage, uint32_t coordinates, uint32_t reference, const SpirvImageOperands& operands) { uint32_t resultId = this->allocateId(); m_code.putIns(spv::OpImageSampleDrefExplicitLod, 6 + getImageOperandWordCount(operands)); m_code.putWord(resultType); m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); m_code.putWord(reference); putImageOperands(operands); return resultId; } void SpirvModule::opControlBarrier( uint32_t execution, uint32_t memory, uint32_t semantics) { m_code.putIns (spv::OpControlBarrier, 4); m_code.putWord(execution); m_code.putWord(memory); m_code.putWord(semantics); } void SpirvModule::opMemoryBarrier( uint32_t memory, uint32_t semantics) { m_code.putIns (spv::OpMemoryBarrier, 3); m_code.putWord(memory); m_code.putWord(semantics); } void SpirvModule::opLoopMerge( uint32_t mergeBlock, uint32_t continueTarget, uint32_t loopControl) { m_code.putIns (spv::OpLoopMerge, 4); m_code.putWord(mergeBlock); m_code.putWord(continueTarget); m_code.putWord(loopControl); } void SpirvModule::opSelectionMerge( uint32_t mergeBlock, uint32_t selectionControl) { m_code.putIns (spv::OpSelectionMerge, 3); m_code.putWord(mergeBlock); m_code.putWord(selectionControl); } void SpirvModule::opBranch( uint32_t label) { m_code.putIns (spv::OpBranch, 2); m_code.putWord(label); } void SpirvModule::opBranchConditional( uint32_t condition, uint32_t trueLabel, uint32_t falseLabel) { m_code.putIns (spv::OpBranchConditional, 4); m_code.putWord(condition); m_code.putWord(trueLabel); m_code.putWord(falseLabel); } void SpirvModule::opSwitch( uint32_t selector, uint32_t jumpDefault, uint32_t caseCount, const SpirvSwitchCaseLabel* caseLabels) { m_code.putIns (spv::OpSwitch, 3 + 2 * caseCount); m_code.putWord(selector); m_code.putWord(jumpDefault); for (uint32_t i = 0; i < caseCount; i++) { m_code.putWord(caseLabels[i].literal); m_code.putWord(caseLabels[i].labelId); } } uint32_t SpirvModule::opPhi( uint32_t resultType, uint32_t sourceCount, const SpirvPhiLabel* sourceLabels) { uint32_t resultId = this->allocateId(); m_code.putIns (spv::OpPhi, 3 + 2 * sourceCount); m_code.putWord(resultType); m_code.putWord(resultId); for (uint32_t i = 0; i < sourceCount; i++) { m_code.putWord(sourceLabels[i].varId); m_code.putWord(sourceLabels[i].labelId); } return resultId; } void SpirvModule::opReturn() { m_code.putIns (spv::OpReturn, 1); } void SpirvModule::opKill() { m_code.putIns (spv::OpKill, 1); } void SpirvModule::opEmitVertex() { m_code.putIns (spv::OpEmitVertex, 1); } void SpirvModule::opEndPrimitive() { m_code.putIns (spv::OpEndPrimitive, 1); } uint32_t SpirvModule::defType( spv::Op op, uint32_t argCount, const uint32_t* argIds) { // Since the type info is stored in the code buffer, // we can use the code buffer to look up type IDs as // well. Result IDs are always stored as argument 1. for (auto ins : m_typeConstDefs) { bool match = ins.opCode() == op; for (uint32_t i = 0; i < argCount && match; i++) match &= ins.arg(2 + i) == argIds[i]; if (match) return ins.arg(1); } // Type not yet declared, create a new one. uint32_t resultId = this->allocateId(); m_typeConstDefs.putIns (op, 2 + argCount); m_typeConstDefs.putWord(resultId); for (uint32_t i = 0; i < argCount; i++) m_typeConstDefs.putWord(argIds[i]); return resultId; } void SpirvModule::instImportGlsl450() { m_instExtGlsl450 = this->allocateId(); const char* name = "GLSL.std.450"; m_instExt.putIns (spv::OpExtInstImport, 2 + m_instExt.strLen(name)); m_instExt.putWord(m_instExtGlsl450); m_instExt.putStr (name); } uint32_t SpirvModule::getImageOperandWordCount(const SpirvImageOperands& op) const { // Each flag may add one or more operands const uint32_t result = ((op.flags & spv::ImageOperandsBiasMask) ? 1 : 0) + ((op.flags & spv::ImageOperandsLodMask) ? 1 : 0) + ((op.flags & spv::ImageOperandsConstOffsetMask) ? 1 : 0) + ((op.flags & spv::ImageOperandsGradMask) ? 2 : 0) + ((op.flags & spv::ImageOperandsOffsetMask) ? 1 : 0) + ((op.flags & spv::ImageOperandsConstOffsetsMask)? 1 : 0) + ((op.flags & spv::ImageOperandsSampleMask) ? 1 : 0) + ((op.flags & spv::ImageOperandsMinLodMask) ? 1 : 0); // Add a DWORD for the operand mask if it is non-zero return result != 0 ? result + 1 : 0; } void SpirvModule::putImageOperands(const SpirvImageOperands& op) { if (op.flags != 0) { m_code.putWord(op.flags); if (op.flags & spv::ImageOperandsBiasMask) m_code.putWord(op.sLodBias); if (op.flags & spv::ImageOperandsLodMask) m_code.putWord(op.sLod); if (op.flags & spv::ImageOperandsConstOffsetMask) m_code.putWord(op.sConstOffset); if (op.flags & spv::ImageOperandsGradMask) { m_code.putWord(op.sGradX); m_code.putWord(op.sGradY); } if (op.flags & spv::ImageOperandsOffsetMask) m_code.putWord(op.gOffset); if (op.flags & spv::ImageOperandsConstOffsetsMask) m_code.putWord(op.gConstOffsets); if (op.flags & spv::ImageOperandsSampleMask) m_code.putWord(op.sSampleId); if (op.flags & spv::ImageOperandsMinLodMask) m_code.putWord(op.sMinLod); } } }