SPV: Implement Vulkan version of GLSL (KHR_vulkan_glsl).
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
@@ -27,8 +27,8 @@
|
||||
#ifndef GLSLstd450_H
|
||||
#define GLSLstd450_H
|
||||
|
||||
const int GLSLstd450Version = 99;
|
||||
const int GLSLstd450Revision = 3;
|
||||
static const int GLSLstd450Version = 100;
|
||||
static const int GLSLstd450Revision = 1;
|
||||
|
||||
enum GLSLstd450 {
|
||||
GLSLstd450Bad = 0, // Don't use
|
||||
@@ -83,7 +83,7 @@ enum GLSLstd450 {
|
||||
GLSLstd450UClamp = 44,
|
||||
GLSLstd450SClamp = 45,
|
||||
GLSLstd450FMix = 46,
|
||||
GLSLstd450IMix = 47,
|
||||
GLSLstd450IMix = 47, // Reserved
|
||||
GLSLstd450Step = 48,
|
||||
GLSLstd450SmoothStep = 49,
|
||||
|
||||
@@ -121,6 +121,10 @@ enum GLSLstd450 {
|
||||
GLSLstd450InterpolateAtSample = 77,
|
||||
GLSLstd450InterpolateAtOffset = 78,
|
||||
|
||||
GLSLstd450NMin = 79,
|
||||
GLSLstd450NMax = 80,
|
||||
GLSLstd450NClamp = 81,
|
||||
|
||||
GLSLstd450Count
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//Copyright (C) 2015-2016 Google, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
@@ -95,6 +96,7 @@ protected:
|
||||
spv::Id getSampledType(const glslang::TSampler&);
|
||||
spv::Id convertGlslangToSpvType(const glslang::TType& type);
|
||||
spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
|
||||
spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim);
|
||||
spv::Id accessChainLoad(const glslang::TType& type);
|
||||
glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
|
||||
int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
|
||||
@@ -195,6 +197,8 @@ spv::StorageClass TranslateStorageClass(const glslang::TType& type)
|
||||
else if (type.getQualifier().isPipeOutput())
|
||||
return spv::StorageClassOutput;
|
||||
else if (type.getQualifier().isUniformOrBuffer()) {
|
||||
if (type.getQualifier().layoutPushConstant)
|
||||
return spv::StorageClassPushConstant;
|
||||
if (type.getBasicType() == glslang::EbtBlock)
|
||||
return spv::StorageClassUniform;
|
||||
else if (type.getBasicType() == glslang::EbtAtomicUint)
|
||||
@@ -225,6 +229,7 @@ spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
|
||||
case glslang::EsdCube: return spv::DimCube;
|
||||
case glslang::EsdRect: return spv::DimRect;
|
||||
case glslang::EsdBuffer: return spv::DimBuffer;
|
||||
case glslang::EsdSubpass: return spv::DimSubpassData;
|
||||
default:
|
||||
assert(0);
|
||||
return spv::Dim2D;
|
||||
@@ -376,6 +381,8 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
||||
case glslang::EbvPosition: return spv::BuiltInPosition;
|
||||
case glslang::EbvVertexId: return spv::BuiltInVertexId;
|
||||
case glslang::EbvInstanceId: return spv::BuiltInInstanceId;
|
||||
case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex;
|
||||
case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex;
|
||||
case glslang::EbvBaseVertex:
|
||||
case glslang::EbvBaseInstance:
|
||||
case glslang::EbvDrawId:
|
||||
@@ -492,6 +499,25 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
|
||||
}
|
||||
}
|
||||
|
||||
// Return whether or not the given type is something that should be tied to a
|
||||
// descriptor set.
|
||||
bool IsDescriptorResource(const glslang::TType& type)
|
||||
{
|
||||
// uniform and buffer blocks are included
|
||||
if (type.getBasicType() == glslang::EbtBlock)
|
||||
return type.getQualifier().isUniformOrBuffer();
|
||||
|
||||
// non block...
|
||||
// basically samplerXXX/subpass/sampler/texture are all included
|
||||
// if they are the global-scope-class, not the function parameter
|
||||
// (or local, if they ever exist) class.
|
||||
if (type.getBasicType() == glslang::EbtSampler)
|
||||
return type.getQualifier().isUniformOrBuffer();
|
||||
|
||||
// None of the above.
|
||||
return false;
|
||||
}
|
||||
|
||||
void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent)
|
||||
{
|
||||
if (child.layoutMatrix == glslang::ElmNone)
|
||||
@@ -708,7 +734,7 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
|
||||
}
|
||||
|
||||
// Only process non-linkage-only nodes for generating actual static uses
|
||||
if (! linkageOnly) {
|
||||
if (! linkageOnly || symbol->getQualifier().isSpecConstant()) {
|
||||
// Prepare to generate code for the access
|
||||
|
||||
// L-value chains will be computed left to right. We're on the symbol now,
|
||||
@@ -717,10 +743,14 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
|
||||
builder.clearAccessChain();
|
||||
|
||||
// For now, we consider all user variables as being in memory, so they are pointers,
|
||||
// except for "const in" arguments to a function, which are an intermediate object.
|
||||
// See comments in handleUserFunctionCall().
|
||||
glslang::TStorageQualifier qualifier = symbol->getQualifier().storage;
|
||||
if (qualifier == glslang::EvqConstReadOnly && constReadOnlyParameters.find(symbol->getId()) != constReadOnlyParameters.end())
|
||||
// except for
|
||||
// A) "const in" arguments to a function, which are an intermediate object.
|
||||
// See comments in handleUserFunctionCall().
|
||||
// B) Specialization constants (normal constant don't even come in as a variable),
|
||||
// These are also pure R-values.
|
||||
glslang::TQualifier qualifier = symbol->getQualifier();
|
||||
if ((qualifier.storage == glslang::EvqConstReadOnly && constReadOnlyParameters.find(symbol->getId()) != constReadOnlyParameters.end()) ||
|
||||
qualifier.isSpecConstant())
|
||||
builder.setAccessChainRValue(id);
|
||||
else
|
||||
builder.setAccessChainLValue(id);
|
||||
@@ -1110,9 +1140,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
{
|
||||
if (node->isUserDefined())
|
||||
result = handleUserFunctionCall(node);
|
||||
assert(result);
|
||||
builder.clearAccessChain();
|
||||
builder.setAccessChainRValue(result);
|
||||
//assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done
|
||||
if (result) {
|
||||
builder.clearAccessChain();
|
||||
builder.setAccessChainRValue(result);
|
||||
} else
|
||||
spv::MissingFunctionality("missing user function; linker needs to catch that");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1157,12 +1190,15 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
case glslang::EOpConstructUVec3:
|
||||
case glslang::EOpConstructUVec4:
|
||||
case glslang::EOpConstructStruct:
|
||||
case glslang::EOpConstructTextureSampler:
|
||||
{
|
||||
std::vector<spv::Id> arguments;
|
||||
translateArguments(*node, arguments);
|
||||
spv::Id resultTypeId = convertGlslangToSpvType(node->getType());
|
||||
spv::Id constructed;
|
||||
if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) {
|
||||
if (node->getOp() == glslang::EOpConstructTextureSampler)
|
||||
constructed = builder.createOp(spv::OpSampledImage, resultTypeId, arguments);
|
||||
else if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) {
|
||||
std::vector<spv::Id> constituents;
|
||||
for (int c = 0; c < (int)arguments.size(); ++c)
|
||||
constituents.push_back(arguments[c]);
|
||||
@@ -1640,11 +1676,17 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
case glslang::EbtSampler:
|
||||
{
|
||||
const glslang::TSampler& sampler = type.getSampler();
|
||||
// an image is present, make its type
|
||||
spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
|
||||
sampler.image ? 2 : 1, TranslateImageFormat(type));
|
||||
if (! sampler.image) {
|
||||
spvType = builder.makeSampledImageType(spvType);
|
||||
if (sampler.sampler) {
|
||||
// pure sampler
|
||||
spvType = builder.makeSamplerType();
|
||||
} else {
|
||||
// an image is present, make its type
|
||||
spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
|
||||
sampler.image ? 2 : 1, TranslateImageFormat(type));
|
||||
if (sampler.combined) {
|
||||
// already has both image and sampler, make the combined type
|
||||
spvType = builder.makeSampledImageType(spvType);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1790,12 +1832,10 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
|
||||
// make the arrays
|
||||
for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
|
||||
int size = type.getArraySizes()->getDimSize(dim);
|
||||
assert(size > 0);
|
||||
spvType = builder.makeArrayType(spvType, size, stride);
|
||||
spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride);
|
||||
if (stride > 0)
|
||||
builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
|
||||
stride *= size;
|
||||
stride *= type.getArraySizes()->getDimSize(dim);
|
||||
}
|
||||
} else {
|
||||
// single-dimensional array, and don't yet have stride
|
||||
@@ -1810,7 +1850,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
spvType = builder.makeRuntimeArray(spvType);
|
||||
} else {
|
||||
assert(type.getOuterArraySize() > 0);
|
||||
spvType = builder.makeArrayType(spvType, type.getOuterArraySize(), stride);
|
||||
spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
|
||||
}
|
||||
if (stride > 0)
|
||||
builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
|
||||
@@ -1819,6 +1859,26 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
return spvType;
|
||||
}
|
||||
|
||||
// Turn the expression forming the array size into an id.
|
||||
// This is not quite trivial, because of specialization constants.
|
||||
// Sometimes, a raw constant is turned into an Id, and sometimes
|
||||
// a specialization constant expression is.
|
||||
spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim)
|
||||
{
|
||||
// First, see if this is sized with a node, meaning a specialization constant:
|
||||
glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim);
|
||||
if (specNode != nullptr) {
|
||||
builder.clearAccessChain();
|
||||
specNode->traverse(this);
|
||||
return accessChainLoad(specNode->getAsTyped()->getType());
|
||||
}
|
||||
|
||||
// Otherwise, need a compile-time (front end) size, get it:
|
||||
int size = arraySizes.getDimSize(dim);
|
||||
assert(size > 0);
|
||||
return builder.makeUintConstant(size);
|
||||
}
|
||||
|
||||
// Wrap the builder's accessChainLoad to:
|
||||
// - localize handling of RelaxedPrecision
|
||||
// - use the SPIR-V inferred type instead of another conversion of the glslang type
|
||||
@@ -1891,7 +1951,7 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl
|
||||
// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
|
||||
// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call.
|
||||
// -1 means a non-forced member offset (no decoration needed).
|
||||
void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
|
||||
void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& /*structType*/, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
|
||||
glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
|
||||
{
|
||||
// this will get a positive value when deemed necessary
|
||||
@@ -2169,6 +2229,24 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
||||
std::vector<spv::Id> operands;
|
||||
auto opIt = arguments.begin();
|
||||
operands.push_back(*(opIt++));
|
||||
|
||||
// Handle subpass operations
|
||||
// TODO: GLSL should change to have the "MS" only on the type rather than the
|
||||
// built-in function.
|
||||
if (cracked.subpass) {
|
||||
// add on the (0,0) coordinate
|
||||
spv::Id zero = builder.makeIntConstant(0);
|
||||
std::vector<spv::Id> comps;
|
||||
comps.push_back(zero);
|
||||
comps.push_back(zero);
|
||||
operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps));
|
||||
if (sampler.ms) {
|
||||
operands.push_back(spv::ImageOperandsSampleMask);
|
||||
operands.push_back(*(opIt++));
|
||||
}
|
||||
return builder.createOp(spv::OpImageRead, convertGlslangToSpvType(node->getType()), operands);
|
||||
}
|
||||
|
||||
operands.push_back(*(opIt++));
|
||||
if (node->getOp() == glslang::EOpImageLoad) {
|
||||
if (sampler.ms) {
|
||||
@@ -3109,7 +3187,7 @@ spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vector
|
||||
}
|
||||
|
||||
// For glslang ops that map to SPV atomic opCodes
|
||||
spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
|
||||
spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
|
||||
{
|
||||
spv::Op opCode = spv::OpNop;
|
||||
|
||||
@@ -3244,8 +3322,10 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
||||
case glslang::EOpMix:
|
||||
if (isFloat)
|
||||
libCall = spv::GLSLstd450FMix;
|
||||
else
|
||||
libCall = spv::GLSLstd450IMix;
|
||||
else {
|
||||
opCode = spv::OpSelect;
|
||||
spv::MissingFunctionality("translating integer mix to OpSelect");
|
||||
}
|
||||
builder.promoteScalar(precision, operands.front(), operands.back());
|
||||
break;
|
||||
case glslang::EOpStep:
|
||||
@@ -3439,6 +3519,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
||||
if (! symbol->getType().isStruct()) {
|
||||
addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
|
||||
addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
|
||||
if (symbol->getType().getQualifier().hasSpecConstantId())
|
||||
addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId);
|
||||
if (symbol->getQualifier().hasLocation())
|
||||
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
|
||||
if (symbol->getQualifier().hasIndex())
|
||||
@@ -3463,8 +3545,14 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
||||
}
|
||||
if (symbol->getQualifier().hasSet())
|
||||
builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet);
|
||||
else if (IsDescriptorResource(symbol->getType())) {
|
||||
// default to 0
|
||||
builder.addDecoration(id, spv::DecorationDescriptorSet, 0);
|
||||
}
|
||||
if (symbol->getQualifier().hasBinding())
|
||||
builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding);
|
||||
if (symbol->getQualifier().hasAttachment())
|
||||
builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment);
|
||||
if (glslangIntermediate->getXfbMode()) {
|
||||
builder.addCapability(spv::CapabilityTransformFeedback);
|
||||
if (symbol->getQualifier().hasXfbStride())
|
||||
@@ -3510,7 +3598,7 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De
|
||||
}
|
||||
|
||||
// Make a full tree of instructions to build a SPIR-V specialization constant,
|
||||
// or regularly constant if possible.
|
||||
// or regular constant if possible.
|
||||
//
|
||||
// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though
|
||||
//
|
||||
@@ -3523,10 +3611,38 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
||||
{
|
||||
assert(node.getQualifier().storage == glslang::EvqConst);
|
||||
|
||||
// hand off to the non-spec-constant path
|
||||
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
|
||||
int nextConst = 0;
|
||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, false);
|
||||
if (! node.getQualifier().specConstant) {
|
||||
// hand off to the non-spec-constant path
|
||||
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
|
||||
int nextConst = 0;
|
||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||
nextConst, false);
|
||||
}
|
||||
|
||||
// We now know we have a specialization constant to build
|
||||
|
||||
if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) {
|
||||
// this is a direct literal assigned to a layout(constant_id=) declaration
|
||||
int nextConst = 0;
|
||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||
nextConst, true);
|
||||
} else {
|
||||
// gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants,
|
||||
// even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ...
|
||||
if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) {
|
||||
std::vector<spv::Id> dimConstId;
|
||||
for (int dim = 0; dim < 3; ++dim) {
|
||||
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
|
||||
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
|
||||
if (specConst)
|
||||
addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
|
||||
}
|
||||
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
|
||||
} else {
|
||||
spv::MissingFunctionality("specialization-constant expression trees");
|
||||
return spv::NoResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use 'consts' as the flattened glslang source of scalar constants to recursively
|
||||
|
||||
@@ -437,7 +437,7 @@ namespace spv {
|
||||
}
|
||||
|
||||
// Store IDs from instruction in our map
|
||||
for (int op = 0; op < spv::InstructionDesc[opCode].operands.getNum(); ++op, --numOperands) {
|
||||
for (int op = 0; numOperands > 0; ++op, --numOperands) {
|
||||
switch (spv::InstructionDesc[opCode].operands.getClass(op)) {
|
||||
case spv::OperandId:
|
||||
idFn(asId(word++));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//Copyright (C) 2015-2016 Google, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
@@ -308,11 +309,9 @@ Id Builder::makeMatrixType(Id component, int cols, int rows)
|
||||
// TODO: performance: track arrays per stride
|
||||
// If a stride is supplied (non-zero) make an array.
|
||||
// If no stride (0), reuse previous array types.
|
||||
Id Builder::makeArrayType(Id element, unsigned size, int stride)
|
||||
// 'size' is an Id of a constant or specialization constant of the array size
|
||||
Id Builder::makeArrayType(Id element, Id sizeId, int stride)
|
||||
{
|
||||
// First, we need a constant instruction for the size
|
||||
Id sizeId = makeUintConstant(size);
|
||||
|
||||
Instruction* type;
|
||||
if (stride == 0) {
|
||||
// try to find existing type
|
||||
@@ -518,8 +517,12 @@ int Builder::getNumTypeConstituents(Id typeId) const
|
||||
return 1;
|
||||
case OpTypeVector:
|
||||
case OpTypeMatrix:
|
||||
case OpTypeArray:
|
||||
return instr->getImmediateOperand(1);
|
||||
case OpTypeArray:
|
||||
{
|
||||
Id lengthId = instr->getImmediateOperand(1);
|
||||
return module.getInstruction(lengthId)->getImmediateOperand(0);
|
||||
}
|
||||
case OpTypeStruct:
|
||||
return instr->getNumOperands();
|
||||
default:
|
||||
@@ -647,16 +650,19 @@ Id Builder::makeBoolConstant(bool b, bool specConstant)
|
||||
Instruction* constant;
|
||||
Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse);
|
||||
|
||||
// See if we already made it
|
||||
Id existing = 0;
|
||||
for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
|
||||
constant = groupedConstants[OpTypeBool][i];
|
||||
if (constant->getTypeId() == typeId && constant->getOpCode() == opcode)
|
||||
existing = constant->getResultId();
|
||||
}
|
||||
// See if we already made it. Applies only to regular constants, because specialization constants
|
||||
// must remain distinct for the purpose of applying a SpecId decoration.
|
||||
if (! specConstant) {
|
||||
Id existing = 0;
|
||||
for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
|
||||
constant = groupedConstants[OpTypeBool][i];
|
||||
if (constant->getTypeId() == typeId && constant->getOpCode() == opcode)
|
||||
existing = constant->getResultId();
|
||||
}
|
||||
|
||||
if (existing)
|
||||
return existing;
|
||||
if (existing)
|
||||
return existing;
|
||||
}
|
||||
|
||||
// Make it
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
@@ -670,9 +676,14 @@ Id Builder::makeBoolConstant(bool b, bool specConstant)
|
||||
Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
|
||||
{
|
||||
Op opcode = specConstant ? OpSpecConstant : OpConstant;
|
||||
Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value);
|
||||
if (existing)
|
||||
return existing;
|
||||
|
||||
// See if we already made it. Applies only to regular constants, because specialization constants
|
||||
// must remain distinct for the purpose of applying a SpecId decoration.
|
||||
if (! specConstant) {
|
||||
Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value);
|
||||
if (existing)
|
||||
return existing;
|
||||
}
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(value);
|
||||
@@ -688,9 +699,14 @@ Id Builder::makeFloatConstant(float f, bool specConstant)
|
||||
Op opcode = specConstant ? OpSpecConstant : OpConstant;
|
||||
Id typeId = makeFloatType(32);
|
||||
unsigned value = *(unsigned int*)&f;
|
||||
Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
|
||||
if (existing)
|
||||
return existing;
|
||||
|
||||
// See if we already made it. Applies only to regular constants, because specialization constants
|
||||
// must remain distinct for the purpose of applying a SpecId decoration.
|
||||
if (! specConstant) {
|
||||
Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
|
||||
if (existing)
|
||||
return existing;
|
||||
}
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(value);
|
||||
@@ -708,9 +724,14 @@ Id Builder::makeDoubleConstant(double d, bool specConstant)
|
||||
unsigned long long value = *(unsigned long long*)&d;
|
||||
unsigned op1 = value & 0xFFFFFFFF;
|
||||
unsigned op2 = value >> 32;
|
||||
Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2);
|
||||
if (existing)
|
||||
return existing;
|
||||
|
||||
// See if we already made it. Applies only to regular constants, because specialization constants
|
||||
// must remain distinct for the purpose of applying a SpecId decoration.
|
||||
if (! specConstant) {
|
||||
Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2);
|
||||
if (existing)
|
||||
return existing;
|
||||
}
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
c->addImmediateOperand(op1);
|
||||
@@ -751,8 +772,9 @@ Id Builder::findCompositeConstant(Op typeClass, std::vector<Id>& comps) const
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
|
||||
Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members, bool specConstant)
|
||||
{
|
||||
Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite;
|
||||
assert(typeId);
|
||||
Op typeClass = getTypeClass(typeId);
|
||||
|
||||
@@ -767,11 +789,13 @@ Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
|
||||
return makeFloatConstant(0.0);
|
||||
}
|
||||
|
||||
Id existing = findCompositeConstant(typeClass, members);
|
||||
if (existing)
|
||||
return existing;
|
||||
if (! specConstant) {
|
||||
Id existing = findCompositeConstant(typeClass, members);
|
||||
if (existing)
|
||||
return existing;
|
||||
}
|
||||
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantComposite);
|
||||
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
|
||||
for (int op = 0; op < (int)members.size(); ++op)
|
||||
c->addIdOperand(members[op]);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//Copyright (C) 2015-2016 Google, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
@@ -104,7 +105,7 @@ public:
|
||||
Id makeStructResultType(Id type0, Id type1);
|
||||
Id makeVectorType(Id component, int size);
|
||||
Id makeMatrixType(Id component, int cols, int rows);
|
||||
Id makeArrayType(Id element, unsigned size, int stride); // 0 means no stride decoration
|
||||
Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration
|
||||
Id makeRuntimeArray(Id element);
|
||||
Id makeFunctionType(Id returnType, const std::vector<Id>& paramTypes);
|
||||
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
|
||||
@@ -189,7 +190,7 @@ public:
|
||||
Id makeDoubleConstant(double d, bool specConstant = false);
|
||||
|
||||
// Turn the array of constants into a proper spv constant of the requested type.
|
||||
Id makeCompositeConstant(Id type, std::vector<Id>& comps);
|
||||
Id makeCompositeConstant(Id type, std::vector<Id>& comps, bool specConst = false);
|
||||
|
||||
// Methods for adding information outside the CFG.
|
||||
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
|
||||
|
||||
@@ -473,6 +473,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
||||
else
|
||||
out << OperandClassParams[operandClass].getName(stream[word++]);
|
||||
--numOperands;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -531,7 +532,6 @@ void GLSLstd450GetDebugNames(const char** names)
|
||||
names[GLSLstd450SClamp] = "SClamp";
|
||||
names[GLSLstd450UClamp] = "UClamp";
|
||||
names[GLSLstd450FMix] = "FMix";
|
||||
names[GLSLstd450IMix] = "IMix";
|
||||
names[GLSLstd450Step] = "Step";
|
||||
names[GLSLstd450SmoothStep] = "SmoothStep";
|
||||
names[GLSLstd450Fma] = "Fma";
|
||||
|
||||
@@ -712,7 +712,7 @@ const char* KernelProfilingInfoString(int info)
|
||||
}
|
||||
}
|
||||
|
||||
const int CapabilityCeiling = 57;
|
||||
const int CapabilityCeiling = 58;
|
||||
|
||||
const char* CapabilityString(int info)
|
||||
{
|
||||
@@ -775,6 +775,7 @@ const char* CapabilityString(int info)
|
||||
case 54: return "GeometryStreams";
|
||||
case 55: return "StorageImageReadWithoutFormat";
|
||||
case 56: return "StorageImageWriteWithoutFormat";
|
||||
case 57: return "MultiViewport";
|
||||
|
||||
case CapabilityCeiling:
|
||||
default: return "Bad";
|
||||
@@ -1104,6 +1105,7 @@ const char* OpcodeString(int op)
|
||||
case 317: return "OpNoLine";
|
||||
case 318: return "OpAtomicFlagTestAndSet";
|
||||
case 319: return "OpAtomicFlagClear";
|
||||
case 320: return "OpImageSparseRead";
|
||||
|
||||
case OpcodeCeiling:
|
||||
default:
|
||||
@@ -1311,7 +1313,6 @@ void Parameterize()
|
||||
CapabilityParams[CapabilityTessellation].caps.push_back(CapabilityShader);
|
||||
CapabilityParams[CapabilityVector16].caps.push_back(CapabilityKernel);
|
||||
CapabilityParams[CapabilityFloat16Buffer].caps.push_back(CapabilityKernel);
|
||||
CapabilityParams[CapabilityFloat16].caps.push_back(CapabilityFloat16Buffer);
|
||||
CapabilityParams[CapabilityInt64Atomics].caps.push_back(CapabilityInt64);
|
||||
CapabilityParams[CapabilityImageBasic].caps.push_back(CapabilityKernel);
|
||||
CapabilityParams[CapabilityImageReadWrite].caps.push_back(CapabilityImageBasic);
|
||||
@@ -1353,6 +1354,7 @@ void Parameterize()
|
||||
CapabilityParams[CapabilityGeometryStreams].caps.push_back(CapabilityGeometry);
|
||||
CapabilityParams[CapabilityStorageImageReadWithoutFormat].caps.push_back(CapabilityShader);
|
||||
CapabilityParams[CapabilityStorageImageWriteWithoutFormat].caps.push_back(CapabilityShader);
|
||||
CapabilityParams[CapabilityMultiViewport].caps.push_back(CapabilityGeometry);
|
||||
|
||||
AddressingParams[AddressingModelPhysical32].caps.push_back(CapabilityAddresses);
|
||||
AddressingParams[AddressingModelPhysical64].caps.push_back(CapabilityAddresses);
|
||||
@@ -1362,7 +1364,7 @@ void Parameterize()
|
||||
MemoryParams[MemoryModelOpenCL].caps.push_back(CapabilityKernel);
|
||||
|
||||
MemorySemanticsParams[MemorySemanticsUniformMemoryShift].caps.push_back(CapabilityShader);
|
||||
MemorySemanticsParams[MemorySemanticsAtomicCounterMemoryShift].caps.push_back(CapabilityShader);
|
||||
MemorySemanticsParams[MemorySemanticsAtomicCounterMemoryShift].caps.push_back(CapabilityAtomicStorage);
|
||||
|
||||
ExecutionModelParams[ExecutionModelVertex].caps.push_back(CapabilityShader);
|
||||
ExecutionModelParams[ExecutionModelTessellationControl].caps.push_back(CapabilityTessellation);
|
||||
@@ -1528,7 +1530,7 @@ void Parameterize()
|
||||
DecorationParams[DecorationFlat].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationPatch].caps.push_back(CapabilityTessellation);
|
||||
DecorationParams[DecorationCentroid].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationSample].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationSample].caps.push_back(CapabilitySampleRateShading);
|
||||
DecorationParams[DecorationInvariant].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationConstant].caps.push_back(CapabilityKernel);
|
||||
DecorationParams[DecorationUniform].caps.push_back(CapabilityShader);
|
||||
@@ -1537,14 +1539,14 @@ void Parameterize()
|
||||
DecorationParams[DecorationStream].caps.push_back(CapabilityGeometryStreams);
|
||||
DecorationParams[DecorationLocation].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationComponent].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationOffset].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationIndex].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationBinding].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationDescriptorSet].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationXfbBuffer].caps.push_back(CapabilityTransformFeedback);
|
||||
DecorationParams[DecorationXfbStride].caps.push_back(CapabilityTransformFeedback);
|
||||
DecorationParams[DecorationArrayStride].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationMatrixStride].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationBuiltIn].caps.push_back(CapabilityShader);
|
||||
DecorationParams[DecorationMatrixStride].caps.push_back(CapabilityMatrix);
|
||||
DecorationParams[DecorationFuncParamAttr].caps.push_back(CapabilityKernel);
|
||||
DecorationParams[DecorationFPRoundingMode].caps.push_back(CapabilityKernel);
|
||||
DecorationParams[DecorationFPFastMathMode].caps.push_back(CapabilityKernel);
|
||||
@@ -1556,8 +1558,8 @@ void Parameterize()
|
||||
|
||||
BuiltInParams[BuiltInPosition].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInPointSize].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInClipDistance].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInCullDistance].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInClipDistance].caps.push_back(CapabilityClipDistance);
|
||||
BuiltInParams[BuiltInCullDistance].caps.push_back(CapabilityCullDistance);
|
||||
|
||||
BuiltInParams[BuiltInVertexId].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInVertexId].desc = "Vertex ID, which takes on values 0, 1, 2, . . . .";
|
||||
@@ -1576,7 +1578,7 @@ void Parameterize()
|
||||
BuiltInParams[BuiltInInvocationId].caps.push_back(CapabilityGeometry);
|
||||
BuiltInParams[BuiltInInvocationId].caps.push_back(CapabilityTessellation);
|
||||
BuiltInParams[BuiltInLayer].caps.push_back(CapabilityGeometry);
|
||||
BuiltInParams[BuiltInViewportIndex].caps.push_back(CapabilityGeometry);
|
||||
BuiltInParams[BuiltInViewportIndex].caps.push_back(CapabilityMultiViewport);
|
||||
BuiltInParams[BuiltInTessLevelOuter].caps.push_back(CapabilityTessellation);
|
||||
BuiltInParams[BuiltInTessLevelInner].caps.push_back(CapabilityTessellation);
|
||||
BuiltInParams[BuiltInTessCoord].caps.push_back(CapabilityTessellation);
|
||||
@@ -1584,9 +1586,9 @@ void Parameterize()
|
||||
BuiltInParams[BuiltInFragCoord].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInPointCoord].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInFrontFacing].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInSampleId].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInSamplePosition].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInSampleMask].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInSampleId].caps.push_back(CapabilitySampleRateShading);
|
||||
BuiltInParams[BuiltInSamplePosition].caps.push_back(CapabilitySampleRateShading);
|
||||
BuiltInParams[BuiltInSampleMask].caps.push_back(CapabilitySampleRateShading);
|
||||
BuiltInParams[BuiltInFragDepth].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInHelperInvocation].caps.push_back(CapabilityShader);
|
||||
BuiltInParams[BuiltInWorkDim].caps.push_back(CapabilityKernel);
|
||||
@@ -1962,6 +1964,12 @@ void Parameterize()
|
||||
InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true);
|
||||
InstructionDesc[OpImageSparseDrefGather].capabilities.push_back(CapabilitySparseResidency);
|
||||
|
||||
InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Image'");
|
||||
InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Coordinate'");
|
||||
InstructionDesc[OpImageSparseRead].operands.push(OperandImageOperands, "", true);
|
||||
InstructionDesc[OpImageSparseRead].operands.push(OperandVariableIds, "", true);
|
||||
InstructionDesc[OpImageSparseRead].capabilities.push_back(CapabilitySparseResidency);
|
||||
|
||||
InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'");
|
||||
InstructionDesc[OpImageSparseTexelsResident].capabilities.push_back(CapabilitySparseResidency);
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ protected:
|
||||
int resultPresent : 1;
|
||||
};
|
||||
|
||||
const int OpcodeCeiling = 320;
|
||||
const int OpcodeCeiling = 321;
|
||||
|
||||
// The set of objects that hold all the instruction/operand
|
||||
// parameterization information.
|
||||
|
||||
1756
SPIRV/spirv.hpp
1756
SPIRV/spirv.hpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user