mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-14 18:23:52 +01:00
47347e38da
Major rewrite of the entire shader decoder to generate easy to parse data structures for the compiler, which ultimately allows new instructions to be implemented more easily.
1312 lines
36 KiB
C++
1312 lines
36 KiB
C++
#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_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::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::enableEarlyFragmentTests(
|
|
uint32_t entryPointId) {
|
|
m_execModeInfo.putIns (spv::OpExecutionMode, 3);
|
|
m_execModeInfo.putWord(entryPointId);
|
|
m_execModeInfo.putWord(spv::ExecutionModeEarlyFragmentTests);
|
|
}
|
|
|
|
|
|
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::setOriginUpperLeft(
|
|
uint32_t entryPointId) {
|
|
m_execModeInfo.putIns (spv::OpExecutionMode, 3);
|
|
m_execModeInfo.putWord(entryPointId);
|
|
m_execModeInfo.putWord(spv::ExecutionModeOriginUpperLeft);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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::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<uint32_t, 2> args = { width, isSigned };
|
|
return this->defType(spv::OpTypeInt,
|
|
args.size(), args.data());
|
|
}
|
|
|
|
|
|
uint32_t SpirvModule::defFloatType(
|
|
uint32_t width) {
|
|
std::array<uint32_t, 1> args = { width };
|
|
return this->defType(spv::OpTypeFloat,
|
|
args.size(), args.data());
|
|
}
|
|
|
|
|
|
uint32_t SpirvModule::defVectorType(
|
|
uint32_t elementType,
|
|
uint32_t elementCount) {
|
|
std::array<uint32_t, 2> args = {
|
|
elementType,
|
|
elementCount
|
|
};
|
|
|
|
return this->defType(spv::OpTypeVector,
|
|
args.size(), args.data());
|
|
}
|
|
|
|
|
|
uint32_t SpirvModule::defMatrixType(
|
|
uint32_t columnType,
|
|
uint32_t columnCount) {
|
|
std::array<uint32_t, 2> args = {
|
|
columnType,
|
|
columnCount
|
|
};
|
|
|
|
return this->defType(spv::OpTypeMatrix,
|
|
args.size(), args.data());
|
|
}
|
|
|
|
|
|
uint32_t SpirvModule::defArrayType(
|
|
uint32_t typeId,
|
|
uint32_t length) {
|
|
std::array<uint32_t, 2> 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<uint32_t, 1> 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<uint32_t> 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<uint32_t, 2> 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<uint32_t, 7> 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;
|
|
}
|
|
|
|
|
|
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::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::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::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::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::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::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::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::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::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::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::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::opImageSampleImplicitLod(
|
|
uint32_t resultType,
|
|
uint32_t sampledImage,
|
|
uint32_t coordinates) {
|
|
uint32_t resultId = this->allocateId();
|
|
|
|
m_code.putIns (spv::OpImageSampleImplicitLod, 5);
|
|
m_code.putWord(resultType);
|
|
m_code.putWord(resultId);
|
|
m_code.putWord(sampledImage);
|
|
m_code.putWord(coordinates);
|
|
return resultId;
|
|
}
|
|
|
|
|
|
void SpirvModule::opReturn() {
|
|
m_code.putIns (spv::OpReturn, 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);
|
|
}
|
|
|
|
} |