Updated glslang.

This commit is contained in:
Бранимир Караџић 2020-03-14 12:58:54 -07:00
parent 52ce62fe25
commit 4b57cdc595
34 changed files with 4581 additions and 3974 deletions

3
3rdparty/glslang/SPIRV/CMakeLists.txt vendored Executable file → Normal file
View File

@ -27,7 +27,8 @@ set(HEADERS
SpvTools.h
disassemble.h
GLSL.ext.AMD.h
GLSL.ext.NV.h)
GLSL.ext.NV.h
NonSemanticDebugPrintf.h)
set(SPVREMAP_HEADERS
SPVRemapper.h

View File

@ -44,5 +44,6 @@ static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physi
static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer";
static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock";
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
#endif // #ifndef GLSLextKHR_H

319
3rdparty/glslang/SPIRV/GlslangToSpv.cpp vendored Executable file → Normal file
View File

@ -1,6 +1,6 @@
//
// Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.
@ -48,6 +48,7 @@ namespace spv {
#include "GLSL.ext.EXT.h"
#include "GLSL.ext.AMD.h"
#include "GLSL.ext.NV.h"
#include "NonSemanticDebugPrintf.h"
}
// Glslang includes
@ -187,7 +188,8 @@ protected:
void makeGlobalInitializers(const glslang::TIntermSequence&);
void visitFunctions(const glslang::TIntermSequence&);
void handleFunctionEntry(const glslang::TIntermAggregate* node);
void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
@ -196,23 +198,31 @@ protected:
glslang::TBasicType typeProxy, bool reduceComparison = true);
spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right);
spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand,
glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
glslang::TBasicType typeProxy,
const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand,
glslang::TBasicType typeProxy);
spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand,
glslang::TBasicType typeProxy);
spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize);
spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands);
spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId,
std::vector<spv::Id>& operands, glslang::TBasicType typeProxy,
const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags);
spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands,
glslang::TBasicType typeProxy);
spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation,
spv::Id typeId, std::vector<spv::Id>& operands);
spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands,
glslang::TBasicType typeProxy);
spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId,
std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
spv::Id getSymbolId(const glslang::TIntermSymbol* node);
void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier);
spv::Id createSpvConstant(const glslang::TIntermTyped&);
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&,
int& nextConst, bool specConstant);
bool isTrivialLeaf(const glslang::TIntermTyped* node);
bool isTrivial(const glslang::TIntermTyped* node);
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
@ -233,15 +243,18 @@ protected:
spv::Builder builder;
bool inEntryPoint;
bool entryPointTerminated;
bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used
bool linkageOnly; // true when visiting the set of objects in the AST present only for
// establishing interface, whether or not they were statically used
std::set<spv::Id> iOSet; // all input/output variables from either static use or declaration of interface
const glslang::TIntermediate* glslangIntermediate;
bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
spv::Id stdBuiltins;
spv::Id nonSemanticDebugPrintf;
std::unordered_map<const char*, spv::Id> extBuiltinMap;
std::unordered_map<int, spv::Id> symbolValues;
std::unordered_set<int> rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer
std::unordered_set<int> rValueParameters; // set of formal function parameters passed as rValues,
// rather than a pointer
std::unordered_map<std::string, spv::Function*> functionMap;
std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
// for mapping glslang block indices to spv indices (e.g., due to hidden members):
@ -374,7 +387,8 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto
}
// Translate glslang type to SPIR-V memory decorations.
void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory, bool useVulkanMemoryModel)
void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory,
bool useVulkanMemoryModel)
{
if (!useVulkanMemoryModel) {
if (qualifier.isCoherent())
@ -640,7 +654,8 @@ spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope(
// is generated only when using the variable in an executable instruction, but not when
// just declaring a struct member variable with it. This is true for PointSize,
// ClipDistance, and CullDistance.
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration)
spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn,
bool memberDeclaration)
{
switch (builtIn) {
case glslang::EbvPointSize:
@ -1106,7 +1121,8 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
}
}
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(
const glslang::TIntermSelection& selectionNode) const
{
if (selectionNode.getFlatten())
return spv::SelectionControlFlattenMask;
@ -1115,7 +1131,8 @@ spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(cons
return spv::SelectionControlMaskNone;
}
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode)
const
{
if (switchNode.getFlatten())
return spv::SelectionControlFlattenMask;
@ -1350,16 +1367,18 @@ bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifie
// Implement the TGlslangToSpvTraverser class.
//
TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate,
spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options)
: TIntermTraverser(true, false, true),
TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
const glslang::TIntermediate* glslangIntermediate,
spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) :
TIntermTraverser(true, false, true),
options(options),
shaderEntry(nullptr), currentFunction(nullptr),
sequenceDepth(0), logger(buildLogger),
builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger),
inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
glslangIntermediate(glslangIntermediate),
nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp())
nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()),
nonSemanticDebugPrintf(0)
{
spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
@ -1402,7 +1421,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5);
builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
};
}
if (glslangIntermediate->usingVulkanMemoryModel()) {
memoryModel = spv::MemoryModelVulkanKHR;
builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
@ -1520,7 +1539,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
glslang::TLayoutGeometry primitive;
if (glslangIntermediate->getStage() == EShLangTessControl) {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
glslangIntermediate->getVertices());
primitive = glslangIntermediate->getOutputPrimitive();
} else {
primitive = glslangIntermediate->getInputPrimitive();
@ -1599,8 +1619,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
if (glslangIntermediate->getStage() == EShLangMeshNV) {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, glslangIntermediate->getPrimitives());
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
glslangIntermediate->getVertices());
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV,
glslangIntermediate->getPrimitives());
switch (glslangIntermediate->getOutputPrimitive()) {
case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break;
@ -1847,7 +1869,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
int dummySize;
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
TranslateCoherent(node->getLeft()->getType()),
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
glslangIntermediate->getBaseAlignmentScalar(
node->getLeft()->getType(), dummySize));
} else {
// Load through a block reference is performed with a dot operator that
@ -1877,7 +1900,9 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
}
// normal case for indexing array or structure or block
builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
builder.accessChainPush(builder.makeIntConstant(spvIndex),
TranslateCoherent(node->getLeft()->getType()),
node->getLeft()->getType().getBufferReferenceAlignment());
// Add capabilities here for accessing PointSize and clip/cull distance.
// We have deferred generation of associated capabilities until now.
@ -1914,9 +1939,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
int dummySize;
builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
TranslateCoherent(node->getLeft()->getType()),
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
dummySize));
} else
builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), node->getLeft()->getType().getBufferReferenceAlignment());
builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()),
node->getLeft()->getType().getBufferReferenceAlignment());
}
return false;
case glslang::EOpVectorSwizzle:
@ -1927,7 +1954,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
int dummySize;
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
TranslateCoherent(node->getLeft()->getType()),
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
dummySize));
}
return false;
case glslang::EOpMatrixSwizzle:
@ -1943,7 +1971,8 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
if (isTrivial(node->getRight()->getAsTyped()))
break; // handle below as a normal binary operation
// otherwise, we need to do dynamic short circuiting on the right operand
spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped());
spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(),
*node->getRight()->getAsTyped());
builder.clearAccessChain();
builder.setAccessChainRValue(result);
}
@ -2091,7 +2120,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
} else {
glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
block->traverse(this);
unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()
->getConstArray()[0].getUConst();
length = builder.createArrayLength(builder.accessChainGetLValue(), member);
}
@ -2117,7 +2147,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
// Does it need a swizzle inversion? If so, evaluation is inverted;
// operate first on the swizzle base, then apply the swizzle.
spv::Id invertedType = spv::NoType;
auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
invertedType : convertGlslangToSpvType(node->getType()); };
if (node->getOp() == glslang::EOpInterpolateAtCentroid)
invertedType = getInvertedSwizzleType(*node->getOperand());
@ -2154,11 +2185,13 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
// it could be a conversion
if (! result)
result = createConversion(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType());
result = createConversion(node->getOp(), decorations, resultType(), operand,
node->getOperand()->getBasicType());
// if not, then possibly an operation
if (! result)
result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, node->getOperand()->getBasicType(), lvalueCoherentFlags);
result = createUnaryOperation(node->getOp(), decorations, resultType(), operand,
node->getOperand()->getBasicType(), lvalueCoherentFlags);
if (result) {
if (invertedType) {
@ -2251,7 +2284,8 @@ spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, s
std::vector<spv::Id> rTypeConstituents;
int numrTypeConstituents = builder.getNumTypeConstituents(rType);
for (int i = 0; i < numrTypeConstituents; ++i) {
rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i));
rTypeConstituents.push_back(builder.createCompositeExtract(constituent,
builder.getContainedTypeId(rType, i), i));
}
constituents[c] = createCompositeConstruct(lType, rTypeConstituents);
} else {
@ -2278,7 +2312,13 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
spv::Id result = spv::NoResult;
spv::Id invertedType = spv::NoType; // to use to override the natural type of the node
auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
spv::Builder::AccessChain complexLvalue; // for holding swizzling l-values too complex for SPIR-V,
// for at out parameter
spv::Id temporaryLvalue = spv::NoResult; // temporary to pass, as proxy for complexLValue
auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
invertedType :
convertGlslangToSpvType(node->getType()); };
// try texturing
result = createImageTextureFunctionCall(node);
@ -2382,7 +2422,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
if (node->isUserDefined())
result = handleUserFunctionCall(node);
// 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);
@ -2651,6 +2690,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
break;
#endif
case glslang::EOpDebugPrintf:
noReturnValue = true;
break;
default:
break;
}
@ -2727,9 +2770,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
// Does it need a swizzle inversion? If so, evaluation is inverted;
// operate first on the swizzle base, then apply the swizzle.
// That is, we transform
//
// interpolate(v.zy) -> interpolate(v).zy
//
if (glslangOperands[0]->getAsOperator() &&
glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
invertedType = convertGlslangToSpvType(
glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
}
break;
case glslang::EOpAtomicLoad:
@ -2789,7 +2837,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.setAccessChain(save);
// Point to the first element of the array.
builder.accessChainPush(elementId, TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
builder.accessChainPush(elementId,
TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()),
glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment());
spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
@ -2800,7 +2849,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask;
if (node->getOp() == glslang::EOpCooperativeMatrixStore)
memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask;
if (builder.getStorageClass(builder.getAccessChain().base) == spv::StorageClassPhysicalStorageBufferEXT) {
if (builder.getStorageClass(builder.getAccessChain().base) ==
spv::StorageClassPhysicalStorageBufferEXT) {
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
}
@ -2810,8 +2860,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
memoryAccessOperands.push_back(spv::IdImmediate(false, alignment));
}
if (memoryAccess & (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
memoryAccessOperands.push_back(spv::IdImmediate(true, builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
if (memoryAccess &
(spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) {
memoryAccessOperands.push_back(spv::IdImmediate(true,
builder.makeUintConstant(TranslateMemoryScope(coherentFlags))));
}
} else if (arg == 2) {
continue;
@ -2819,8 +2871,20 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
}
#endif
// for l-values, pass the address, for r-values, pass the value
if (lvalue) {
if (invertedType == spv::NoType && !builder.isSpvLvalue()) {
// SPIR-V cannot represent an l-value containing a swizzle that doesn't
// reduce to a simple access chain. So, we need a temporary vector to
// receive the result, and must later swizzle that into the original
// l-value.
complexLvalue = builder.getAccessChain();
temporaryLvalue = builder.createVariable(spv::StorageClassFunction,
builder.accessChainGetInferredType(), "swizzleTemp");
operands.push_back(temporaryLvalue);
} else {
operands.push_back(builder.accessChainGetLValue());
}
lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
} else {
@ -2861,7 +2925,14 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
#endif
if (atomic) {
// Handle all atomics
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags);
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
lvalueCoherentFlags);
} else if (node->getOp() == glslang::EOpDebugPrintf) {
if (!nonSemanticDebugPrintf) {
nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf");
}
result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands);
builder.addExtension(spv::E_SPV_KHR_non_semantic_info);
} else {
// Pass through to generic operations.
switch (glslangOperands.size()) {
@ -2883,8 +2954,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
break;
}
if (invertedType)
if (invertedType != spv::NoResult)
result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
else if (temporaryLvalue != spv::NoResult) {
builder.setAccessChain(complexLvalue);
builder.accessChainStore(builder.createLoad(temporaryLvalue));
}
}
if (noReturnValue)
@ -3091,7 +3166,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
defaultSegment = (int)codeSegments.size();
else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) {
valueIndexToSegment[caseValues.size()] = (int)codeSegments.size();
caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst());
caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()
->getConstArray()[0].getIConst());
} else
codeSegments.push_back(child);
}
@ -3104,7 +3180,8 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
// make the switch statement
std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment,
segmentBlocks);
// emit all the code in the segments
breakForLoop.push(false);
@ -3361,7 +3438,8 @@ spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyp
// When inverting a swizzle with a parent op, this function
// will apply the swizzle operation to a completed parent operation.
spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult)
spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node,
spv::Id parentResult)
{
std::vector<unsigned> swizzle;
convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle);
@ -3501,6 +3579,9 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
}
break;
case glslang::EbtString:
// no type used for OpString
return 0;
default:
assert(0);
break;
@ -3626,7 +3707,8 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
{
// Create a vector of struct types for SPIR-V to consume
std::vector<spv::Id> spvMembers;
int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0,
// except sometimes for blocks
std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
for (int i = 0; i < (int)glslangMembers->size(); i++) {
glslang::TType& glslangMember = *(*glslangMembers)[i].type;
@ -3662,10 +3744,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
}
spvMembers.push_back(
convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true));
convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
true));
} else {
spvMembers.push_back(
convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false));
convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember,
false));
}
}
}
@ -3871,7 +3955,8 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
int vecSize = builder.getNumTypeComponents(nominalTypeId);
spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
if (nominalTypeId != bvecType)
loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize));
loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId,
makeSmearedConstant(builder.makeUintConstant(0), vecSize));
}
}
@ -3920,7 +4005,8 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
alignment |= type.getBufferReferenceAlignment();
builder.accessChainStore(rvalue,
spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask),
spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
~spv::MemoryAccessMakePointerVisibleKHRMask),
TranslateMemoryScope(coherentFlags), alignment);
}
@ -3981,7 +4067,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id
// set up the target storage
builder.clearAccessChain();
builder.setAccessChainLValue(lValue);
builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), type.getBufferReferenceAlignment());
builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type),
type.getBufferReferenceAlignment());
// store the member
multiTypeStore(glslangElementType, elementRValue);
@ -4001,7 +4088,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id
// set up the target storage
builder.clearAccessChain();
builder.setAccessChainLValue(lValue);
builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), type.getBufferReferenceAlignment());
builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type),
type.getBufferReferenceAlignment());
// store the member
multiTypeStore(glslangMemberType, memberRValue);
@ -4036,18 +4124,21 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang:
}
// Given an array type, returns the integer stride required for that array
int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout,
glslang::TLayoutMatrix matrixLayout)
{
int size;
int stride;
glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout,
matrixLayout == glslang::ElmRowMajor);
return stride;
}
// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix
// when used as a member of an interface block
int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout,
glslang::TLayoutMatrix matrixLayout)
{
glslang::TType elementType;
elementType.shallowCopy(matrixType);
@ -4055,7 +4146,8 @@ int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, gl
int size;
int stride;
glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout,
matrixLayout == glslang::ElmRowMajor);
return stride;
}
@ -4066,8 +4158,8 @@ 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,
glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
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
nextOffset = -1;
@ -4097,7 +4189,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
int memberSize;
int dummyStride;
int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, matrixLayout == glslang::ElmRowMajor);
int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout,
matrixLayout == glslang::ElmRowMajor);
// Adjust alignment for HLSL rules
// TODO: make this consistent in early phases of code:
@ -4116,7 +4209,8 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
glslang::RoundToPow2(currentOffset, memberAlignment);
// Bump up to vec4 if there is a bad straddle
if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize,
currentOffset))
glslang::RoundToPow2(currentOffset, 16);
nextOffset = currentOffset + memberSize;
@ -4188,7 +4282,8 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier,
// Make all the functions, skeletally, without actually visiting their bodies.
void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
{
const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type, bool useVulkanMemoryModel) {
const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type,
bool useVulkanMemoryModel) {
spv::Decoration paramPrecision = TranslatePrecisionDecoration(type);
if (paramPrecision != spv::NoPrecision)
decorations.push_back(paramPrecision);
@ -4286,7 +4381,8 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen
builder.setBuildPoint(shaderEntry->getLastBlock());
for (int i = 0; i < (int)initializers.size(); ++i) {
glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate();
if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) {
if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() !=
glslang::EOpLinkerObjects) {
// We're on a top-level node that's not a function. Treat as an initializer, whose
// code goes into the beginning of the entry point.
@ -4314,7 +4410,8 @@ void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate
builder.setBuildPoint(functionBlock);
}
void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments, spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
{
const glslang::TIntermSequence& glslangArguments = node.getSequence();
@ -4327,7 +4424,8 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
#ifndef GLSLANG_WEB
f16ShadowCompare = sampler.shadow && glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
f16ShadowCompare = sampler.shadow &&
glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16;
#endif
}
@ -4703,7 +4801,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
operands.push_back(imageOperand);
}
if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) {
spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) };
spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope(
TranslateCoherent(imageType))) };
operands.push_back(imageOperand);
}
@ -4736,13 +4835,17 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
}
spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
if (imageType.getQualifier().nonUniform) {
builder.addDecoration(pointer, spv::DecorationNonUniformEXT);
}
std::vector<spv::Id> operands;
operands.push_back(pointer);
for (; opIt != arguments.end(); ++opIt)
operands.push_back(*opIt);
return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(), lvalueCoherentFlags);
return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
lvalueCoherentFlags);
}
}
@ -4767,7 +4870,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
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));
operands.push_back(builder.makeCompositeConstant(
builder.makeVectorType(builder.makeIntType(32), 2), comps));
}
for (; opIt != arguments.end(); ++opIt)
@ -4856,7 +4960,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
else
dRefComp = builder.getNumComponents(params.coords) - 1;
indexes.push_back(dRefComp);
params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
params.Dref = builder.createCompositeExtract(params.coords,
builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
}
// lod
@ -4981,7 +5086,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
flags.clear();
builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1));
builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
i+1));
}
return builder.createCompositeExtract(res, resultType(), 0);
}
@ -5004,8 +5110,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
// copy the projective coordinate if we have to
if (projTargetComp != projSourceComp) {
spv::Id projComp = builder.createCompositeExtract(params.coords,
builder.getScalarTypeId(builder.getTypeId(params.coords)),
projSourceComp);
builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp);
params.coords = builder.createCompositeInsert(projComp, params.coords,
builder.getTypeId(params.coords), projTargetComp);
}
@ -5087,7 +5192,8 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
++lValueCount;
} else if (writableParam(qualifiers[a])) {
// need space to hold the copy
arg = builder.createVariable(spv::StorageClassFunction, builder.getContainedTypeId(function->getParamType(a)), "param");
arg = builder.createVariable(spv::StorageClassFunction,
builder.getContainedTypeId(function->getParamType(a)), "param");
if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
// need to copy the input into output space
builder.setAccessChain(lValues[lValueCount]);
@ -6395,7 +6501,9 @@ 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, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/,
spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy,
const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags)
{
spv::Op opCode = spv::OpNop;
@ -6411,12 +6519,14 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
case glslang::EOpAtomicMin:
case glslang::EOpImageAtomicMin:
case glslang::EOpAtomicCounterMin:
opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin;
opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
spv::OpAtomicUMin : spv::OpAtomicSMin;
break;
case glslang::EOpAtomicMax:
case glslang::EOpImageAtomicMax:
case glslang::EOpAtomicCounterMax:
opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax;
opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ?
spv::OpAtomicUMax : spv::OpAtomicSMax;
break;
case glslang::EOpAtomicAnd:
case glslang::EOpImageAtomicAnd:
@ -6481,7 +6591,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
scopeId = builder.makeUintConstant(spv::ScopeDevice);
}
// semantics default to relaxed
spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ?
spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() &&
glslangIntermediate->usingVulkanMemoryModel() ?
spv::MemorySemanticsVolatileMask :
spv::MemorySemanticsMaskNone);
spv::Id semanticsId2 = semanticsId;
@ -6494,20 +6605,24 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
valueId = operands[2];
if (operands.size() > 3) {
scopeId = operands[3];
semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
semanticsId2 = builder.makeUintConstant(builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
semanticsId = builder.makeUintConstant(
builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5]));
semanticsId2 = builder.makeUintConstant(
builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7]));
}
} else if (opCode == spv::OpAtomicLoad) {
if (operands.size() > 1) {
scopeId = operands[1];
semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
semanticsId = builder.makeUintConstant(
builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]));
}
} else {
// atomic store or RMW
valueId = operands[1];
if (operands.size() > 2) {
scopeId = operands[2];
semanticsId = builder.makeUintConstant(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
semanticsId = builder.makeUintConstant
(builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4]));
}
}
@ -6552,7 +6667,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
}
// Create group invocation operations.
spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId,
std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
{
bool isUnsigned = isTypeUnsignedInt(typeProxy);
bool isFloat = isTypeFloat(typeProxy);
@ -6766,8 +6882,10 @@ spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv
op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
op == spv::OpSubgroupReadInvocationKHR ||
op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD ||
op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD ||
op == spv::OpGroupSMinNonUniformAMD ||
op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD ||
op == spv::OpGroupSMaxNonUniformAMD ||
op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD);
// Handle group invocation operations scalar by scalar.
@ -7156,7 +7274,8 @@ spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, s
return builder.createOp(opCode, typeId, spvGroupOperands);
}
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision,
spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
{
bool isUnsigned = isTypeUnsignedInt(typeProxy);
bool isFloat = isTypeFloat(typeProxy);
@ -7258,14 +7377,16 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
unsigned int executionScope = builder.getConstantScalar(operands[0]);
unsigned int memoryScope = builder.getConstantScalar(operands[1]);
unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]);
builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics);
builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope,
(spv::MemorySemanticsMask)semantics);
if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask |
spv::MemorySemanticsMakeVisibleKHRMask |
spv::MemorySemanticsOutputMemoryKHRMask |
spv::MemorySemanticsVolatileMask)) {
builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
}
if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || memoryScope == spv::ScopeDevice)) {
if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice ||
memoryScope == spv::ScopeDevice)) {
builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
}
return 0;
@ -7348,7 +7469,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
if (builder.getNumComponents(operands[0]) == 1)
frexpIntType = builder.makeIntegerType(width, true);
else
frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0]));
frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true),
builder.getNumComponents(operands[0]));
typeId = builder.makeStructResultType(typeId0, frexpIntType);
consumedOperands = 1;
}
@ -7558,7 +7680,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId)
{
// GLSL memory barriers use queuefamily scope in new model, device scope in old model
spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ?
spv::ScopeQueueFamilyKHR : spv::ScopeDevice;
switch (op) {
case glslang::EOpBarrier:
@ -7787,7 +7910,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
#ifndef GLSLANG_WEB
if (symbol->getType().isImage()) {
std::vector<spv::Decoration> memory;
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, glslangIntermediate->usingVulkanMemoryModel());
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
glslangIntermediate->usingVulkanMemoryModel());
for (unsigned int i = 0; i < memory.size(); ++i)
builder.addDecoration(id, memory[i]);
}
@ -7841,7 +7965,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
}
if (symbol->isReference()) {
builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
builder.addDecoration(id, symbol->getType().getQualifier().restrict ?
spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
}
#endif
@ -7903,7 +8028,8 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
// hand off to the non-spec-constant path
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
int nextConst = 0;
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ?
node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
nextConst, false);
}
@ -7957,7 +8083,8 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
// If there are not enough elements present in 'consts', 0 will be substituted;
// an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
//
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType,
const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
{
// vector of constants for SPIR-V
std::vector<spv::Id> spvConsts;
@ -8075,6 +8202,9 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar);
break;
#endif
case glslang::EbtString:
scalar = builder.getStringId(consts[nextConst].getSConst()->c_str());
break;
default:
assert(0);
break;
@ -8175,7 +8305,8 @@ bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node)
// Emit short-circuiting code, where 'right' is never evaluated unless
// the left side is true (for &&) or false (for ||).
spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right)
spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left,
glslang::TIntermTyped& right)
{
spv::Id boolTypeId = builder.makeBoolType();

View File

@ -0,0 +1,50 @@
// Copyright (c) 2020 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"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
// https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
//
#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
#ifdef __cplusplus
extern "C" {
#endif
enum {
NonSemanticDebugPrintfRevision = 1,
NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
};
enum NonSemanticDebugPrintfInstructions {
NonSemanticDebugPrintfDebugPrintf = 1,
NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
};
#ifdef __cplusplus
}
#endif
#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_

View File

@ -496,7 +496,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
return type->getResultId();
}
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
ImageFormat format)
{
assert(sampled == 1 || sampled == 2);
@ -1270,7 +1271,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
// Comments in header
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& decorations, Block **entry)
{
// Make the function and initial instructions in it
Id typeId = makeFunctionType(returnType, paramTypes);
@ -1373,7 +1375,8 @@ Id Builder::createUndefined(Id type)
}
// av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const
{
switch (sc) {
case spv::StorageClassUniform:
@ -1392,7 +1395,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
}
// Comments in header
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
unsigned int alignment)
{
Instruction* store = new Instruction(OpStore);
store->addIdOperand(lValue);
@ -1495,7 +1499,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
std::vector<Id>(1, index));
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite);
@ -1697,7 +1702,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
return op->getResultId();
}
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
const std::vector<unsigned>& literals)
{
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
op->addImmediateOperand((unsigned) opCode);
@ -2187,7 +2193,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (constituent == 0)
resultId = subResultId;
else
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
precision);
}
return resultId;
@ -2196,7 +2203,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == (int)constituents.size()));
if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be
@ -2609,7 +2617,8 @@ void Builder::clearAccessChain()
}
// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
@ -2663,7 +2672,8 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
}
// Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType,
spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
Id id;
@ -2721,7 +2731,13 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
}
// load through the access chain
id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
id = collapseAccessChain();
// Apply nonuniform both to the access chain and the loaded value.
// Buffer accesses need the access chain decorated, and this is where
// loaded image types get decorated. TODO: This should maybe move to
// createImageTextureFunctionCall.
addDecoration(id, nonUniform);
id = createLoad(id, memoryAccess, scope, alignment);
setPrecision(id, precision);
addDecoration(id, nonUniform);
}
@ -3075,7 +3091,8 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
dumpSourceInstructions(iItr->first, *iItr->second, out);
}
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
void Builder::dumpInstructions(std::vector<unsigned int>& out,
const std::vector<std::unique_ptr<Instruction> >& instructions) const
{
for (int i = 0; i < (int)instructions.size(); ++i) {
instructions[i]->dump(out);

View File

@ -1,6 +1,6 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.
@ -94,6 +94,7 @@ public:
const char* file_c_str = str.c_str();
fileString->addStringOperand(file_c_str);
strings.push_back(std::unique_ptr<Instruction>(fileString));
module.mapInstruction(fileString);
stringIds[file_c_str] = strId;
return strId;
}
@ -196,7 +197,8 @@ public:
Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const;
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
ImageFormat getImageTypeFormat(Id typeId) const
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
@ -206,12 +208,17 @@ public:
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isBoolType(Id typeId)
{ return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isIntType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
bool isUintType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
bool isScalarType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
getTypeClass(typeId) == OpTypeBool; }
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
@ -221,7 +228,8 @@ public:
#else
bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
#endif
bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isAggregateType(Id typeId) const
{ return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@ -233,7 +241,8 @@ public:
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
unsigned int getConstantScalar(Id resultId) const
{ return module.getInstruction(resultId)->getImmediateOperand(0); }
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
int getScalarTypeWidth(Id typeId) const
@ -275,14 +284,22 @@ public:
// For making new constants (will return old constant if the requested one was already made).
Id makeBoolConstant(bool b, bool specConstant = false);
Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeInt8Constant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeUint8Constant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeUint16Constant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(16), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false)
{ return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false)
{ return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false);
Id makeFloat16Constant(float f16, bool specConstant = false);
@ -313,8 +330,8 @@ public:
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
@ -333,10 +350,12 @@ public:
Id createUndefined(Id type);
// Store into an Id and return the l-value
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Load from an Id and return it
Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Create an OpAccessChain instruction
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@ -495,7 +514,7 @@ public:
// recursion stack can hold the memory for it.
//
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
// Add a branch to the innermost switch's merge block.
void addSwitchBreak();
@ -569,10 +588,13 @@ public:
std::vector<Id> indexChain;
Id instr; // cache the instruction that generates this access chain
std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
Id component; // a dynamic component index, can coexist with a swizzle,
// done after the swizzle, NoResult if not present
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied;
// NoType unless a swizzle or component is present
bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment.
// Only tracks base and (optional) component selection alignment.
// Accumulate whether anything in the chain of structures has coherent decorations.
struct CoherentFlags {
@ -655,11 +677,13 @@ public:
}
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
// push a dynamic component selection onto the access chain, only applicable with a
// non-trivial swizzle or no swizzle
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
unsigned int alignment)
{
if (accessChain.swizzle.size() != 1) {
accessChain.component = component;
@ -671,10 +695,18 @@ public:
}
// use accessChain and swizzle to store value
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
unsigned int alignment = 0);
// Return whether or not the access chain can be represented in SPIR-V
// as an l-value.
// E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
// get the direct pointer for an l-value
Id accessChainGetLValue();
@ -703,7 +735,8 @@ public:
void createBranch(Block* block);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
const std::vector<unsigned int>& operands);
// Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@ -729,7 +762,8 @@ public:
void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
void dumpModuleProcesses(std::vector<unsigned int>&) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const;
unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage source;
@ -765,9 +799,13 @@ public:
std::vector<std::unique_ptr<Function> > functions;
// not output, internally used for quick & dirty canonical (unique) creation
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants; // map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes; // map type opcodes to type instructions
// map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
// map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
// map type opcodes to type instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
// stack of switches
std::stack<Block*> switchMerges;

View File

@ -1,6 +1,6 @@
//
// Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2018 Google, Inc.
// Copyright (C) 2018-2020 Google, Inc.
//
// All rights reserved.
//
@ -130,8 +130,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
// legalizing HLSL SPIR-V.
void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions* options)
void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, const SpvOptions* options)
{
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
@ -207,7 +207,8 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
}
spvtools::OptimizerOptions spvOptOptions;
spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}

View File

@ -75,6 +75,7 @@ enum ExtInstSet {
GLSLextAMDInst,
GLSLextNVInst,
OpenCLExtInst,
NonSemanticDebugPrintfExtInst,
};
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@ -480,8 +481,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
if (opCode == OpExtInst) {
ExtInstSet extInstSet = GLSL450Inst;
const char* name = idDescriptor[stream[word - 2]].c_str();
if (0 == memcmp("OpenCL", name, 6)) {
if (strcmp("OpenCL.std", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
extInstSet = NonSemanticDebugPrintfExtInst;
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
@ -505,6 +510,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
}
else if (extInstSet == GLSLextNVInst) {
out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
} else if (extInstSet == NonSemanticDebugPrintfExtInst) {
out << "(DebugPrintf)";
}
}
break;

View File

@ -1,5 +1,6 @@
add_library(glslang-default-resource-limits
${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp)
${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp
${CMAKE_CURRENT_SOURCE_DIR}/resource_limits_c.cpp)
set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang)
set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON)

View File

@ -1,6 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2016-2020 Google, Inc.
//
// All rights reserved.
//

View File

@ -0,0 +1,51 @@
/**
BSD 2-Clause License
Copyright (c) 2020, Travis Fort
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/
#include "resource_limits_c.h"
#include "ResourceLimits.h"
#include <stdlib.h>
#include <string.h>
#include <string>
const glslang_resource_t* glslang_default_resource(void)
{
return reinterpret_cast<const glslang_resource_t*>(&glslang::DefaultTBuiltInResource);
}
const char* glslang_default_resource_string()
{
std::string cpp_str = glslang::GetDefaultTBuiltInResourceString();
char* c_str = (char*)malloc(cpp_str.length() + 1);
strcpy(c_str, cpp_str.c_str());
return c_str;
}
void glslang_decode_resource_limits(glslang_resource_t* resources, char* config)
{
glslang::DecodeResourceLimits(reinterpret_cast<TBuiltInResource*>(resources), config);
}

View File

@ -0,0 +1,54 @@
/**
BSD 2-Clause License
Copyright (c) 2020, Travis Fort
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/
#ifndef _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
#define _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
#include "../glslang/Include/glslang_c_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
// These are the default resources for TBuiltInResources, used for both
// - parsing this string for the case where the user didn't supply one,
// - dumping out a template for user construction of a config file.
const glslang_resource_t* glslang_default_resource(void);
// Returns the DefaultTBuiltInResource as a human-readable string.
// NOTE: User is responsible for freeing this string.
const char* glslang_default_resource_string();
// Decodes the resource limits from |config| to |resources|.
void glslang_decode_resource_limits(glslang_resource_t* resources, char* config);
#ifdef __cplusplus
}
#endif
#endif // _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_

View File

@ -54,6 +54,8 @@ static_assert(int(GLSLANG_TEX_SAMP_TRANS_COUNT) == EShTexSampTransCount, "");
static_assert(int(GLSLANG_MSG_COUNT) == EShMsgCount, "");
static_assert(int(GLSLANG_REFLECTION_COUNT) == EShReflectionCount, "");
static_assert(int(GLSLANG_PROFILE_COUNT) == EProfileCount, "");
static_assert(sizeof(glslang_limits_t) == sizeof(TLimits), "");
static_assert(sizeof(glslang_resource_t) == sizeof(TBuiltInResource), "");
typedef struct glslang_shader_s {
glslang::TShader* shader;
@ -350,15 +352,19 @@ const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader)
return shader->preprocessedGLSL.c_str();
}
int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* i)
int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input)
{
DirStackFileIncluder Includer;
/* TODO: use custom callbacks if they are available in 'i->callbacks' */
return shader->shader->preprocess(
/* No user-defined resources limit */
&glslang::DefaultTBuiltInResource, i->default_version, c_shader_profile(i->default_profile),
i->force_default_version_and_profile != 0, i->forward_compatible != 0,
(EShMessages)c_shader_messages(i->messages), &shader->preprocessedGLSL, Includer
reinterpret_cast<const TBuiltInResource*>(input->resource),
input->default_version,
c_shader_profile(input->default_profile),
input->force_default_version_and_profile != 0,
input->forward_compatible != 0,
(EShMessages)c_shader_messages(input->messages),
&shader->preprocessedGLSL,
Includer
);
}
@ -368,9 +374,11 @@ int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input)
shader->shader->setStrings(&preprocessedCStr, 1);
return shader->shader->parse(
/* No user-defined resource limits for now */
&glslang::DefaultTBuiltInResource, input->default_version, input->forward_compatible != 0,
(EShMessages)c_shader_messages(input->messages));
reinterpret_cast<const TBuiltInResource*>(input->resource),
input->default_version,
input->forward_compatible != 0,
(EShMessages)c_shader_messages(input->messages)
);
}
const char* glslang_shader_get_info_log(glslang_shader_t* shader) { return shader->shader->getInfoLog(); }

View File

@ -553,6 +553,7 @@ public:
// having a constant_id is not sufficient: expressions have no id, but are still specConstant
bool specConstant : 1;
bool nonUniform : 1;
bool explicitOffset : 1;
#ifdef GLSLANG_WEB
bool isWriteOnly() const { return false; }

View File

@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GLSLANG_C_IFACE_H_INCLUDED
#define GLSLANG_C_IFACE_H_INCLUDED
#include <stdbool.h>
#include <stdlib.h>
#include "glslang_c_shader_types.h"
@ -40,6 +41,117 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef struct glslang_shader_s glslang_shader_t;
typedef struct glslang_program_s glslang_program_t;
/* TLimits counterpart */
typedef struct glslang_limits_s {
bool non_inductive_for_loops;
bool while_loops;
bool do_while_loops;
bool general_uniform_indexing;
bool general_attribute_matrix_vector_indexing;
bool general_varying_indexing;
bool general_sampler_indexing;
bool general_variable_indexing;
bool general_constant_matrix_vector_indexing;
} glslang_limits_t;
/* TBuiltInResource counterpart */
typedef struct glslang_resource_s {
int max_lights;
int max_clip_planes;
int max_texture_units;
int max_texture_coords;
int max_vertex_attribs;
int max_vertex_uniform_components;
int max_varying_floats;
int max_vertex_texture_image_units;
int max_combined_texture_image_units;
int max_texture_image_units;
int max_fragment_uniform_components;
int max_draw_buffers;
int max_vertex_uniform_vectors;
int max_varying_vectors;
int max_fragment_uniform_vectors;
int max_vertex_output_vectors;
int max_fragment_input_vectors;
int min_program_texel_offset;
int max_program_texel_offset;
int max_clip_distances;
int max_compute_work_group_count_x;
int max_compute_work_group_count_y;
int max_compute_work_group_count_z;
int max_compute_work_group_size_x;
int max_compute_work_group_size_y;
int max_compute_work_group_size_z;
int max_compute_uniform_components;
int max_compute_texture_image_units;
int max_compute_image_uniforms;
int max_compute_atomic_counters;
int max_compute_atomic_counter_buffers;
int max_varying_components;
int max_vertex_output_components;
int max_geometry_input_components;
int max_geometry_output_components;
int max_fragment_input_components;
int max_image_units;
int max_combined_image_units_and_fragment_outputs;
int max_combined_shader_output_resources;
int max_image_samples;
int max_vertex_image_uniforms;
int max_tess_control_image_uniforms;
int max_tess_evaluation_image_uniforms;
int max_geometry_image_uniforms;
int max_fragment_image_uniforms;
int max_combined_image_uniforms;
int max_geometry_texture_image_units;
int max_geometry_output_vertices;
int max_geometry_total_output_components;
int max_geometry_uniform_components;
int max_geometry_varying_components;
int max_tess_control_input_components;
int max_tess_control_output_components;
int max_tess_control_texture_image_units;
int max_tess_control_uniform_components;
int max_tess_control_total_output_components;
int max_tess_evaluation_input_components;
int max_tess_evaluation_output_components;
int max_tess_evaluation_texture_image_units;
int max_tess_evaluation_uniform_components;
int max_tess_patch_components;
int max_patch_vertices;
int max_tess_gen_level;
int max_viewports;
int max_vertex_atomic_counters;
int max_tess_control_atomic_counters;
int max_tess_evaluation_atomic_counters;
int max_geometry_atomic_counters;
int max_fragment_atomic_counters;
int max_combined_atomic_counters;
int max_atomic_counter_bindings;
int max_vertex_atomic_counter_buffers;
int max_tess_control_atomic_counter_buffers;
int max_tess_evaluation_atomic_counter_buffers;
int max_geometry_atomic_counter_buffers;
int max_fragment_atomic_counter_buffers;
int max_combined_atomic_counter_buffers;
int max_atomic_counter_buffer_size;
int max_transform_feedback_buffers;
int max_transform_feedback_interleaved_components;
int max_cull_distances;
int max_combined_clip_and_cull_distances;
int max_samples;
int max_mesh_output_vertices_nv;
int max_mesh_output_primitives_nv;
int max_mesh_work_group_size_x_nv;
int max_mesh_work_group_size_y_nv;
int max_mesh_work_group_size_z_nv;
int max_task_work_group_size_x_nv;
int max_task_work_group_size_y_nv;
int max_task_work_group_size_z_nv;
int max_mesh_view_count_nv;
glslang_limits_t limits;
} glslang_resource_t;
typedef struct glslang_input_s {
glslang_source_t language;
glslang_stage_t stage;
@ -54,6 +166,7 @@ typedef struct glslang_input_s {
int force_default_version_and_profile;
int forward_compatible;
glslang_messages_t messages;
const glslang_resource_t* resource;
} glslang_input_t;
/* Inclusion result structure allocated by C include_local/include_system callbacks */

View File

@ -621,6 +621,8 @@ enum TOperator {
EOpIsHelperInvocation,
EOpDebugPrintf,
//
// Branch
//

View File

@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2018 Google, Inc.
// Copyright (C) 2018-2020 Google, Inc.
//
// All rights reserved.
//
@ -1079,7 +1079,6 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
{
double arg0 = childConstUnions[0][arg0comp].getDConst();
double arg1 = childConstUnions[1][arg1comp].getDConst();
assert(arg1 != 0.0);
double result = arg0 - arg1 * floor(arg0 / arg1);
newConstArray[comp].setDConst(result);
break;

View File

@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.
@ -4086,6 +4086,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
commonBuiltins.append("void controlBarrier(int, int, int, int);\n"
"void memoryBarrier(int, int, int);\n");
commonBuiltins.append("void debugPrintfEXT();\n");
if (profile != EEsProfile && version >= 450) {
// coopMatStoreNV perhaps ought to have "out" on the buf parameter, but
// adding it introduces undesirable tempArgs on the stack. What we want
@ -7903,6 +7905,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
}
symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics);
symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf);
// GL_ARB_shader_ballot
if (profile != EEsProfile) {
@ -8451,6 +8454,8 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("average", EOpAverage);
symbolTable.relateToOperator("averageRounded", EOpAverageRounded);
symbolTable.relateToOperator("multiply32x16", EOpMul32x16);
symbolTable.relateToOperator("debugPrintfEXT", EOpDebugPrintf);
if (PureOperatorBuiltins) {
symbolTable.relateToOperator("imageSize", EOpImageQuerySize);

View File

@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.

View File

@ -1353,6 +1353,9 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction
case EOpInterpolateAtSample:
numArgs = 1;
break;
case EOpDebugPrintf:
numArgs = 0;
break;
default:
break;
}
@ -3086,7 +3089,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
error(loc, "constructor argument does not have a type", "constructor", "");
return true;
}
if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) {
if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
error(loc, "cannot convert a sampler", "constructor", "");
return true;
}
@ -5138,6 +5141,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
profileRequires(loc, EEsProfile, 310, nullptr, feature);
}
publicType.qualifier.layoutOffset = value;
publicType.qualifier.explicitOffset = true;
if (nonLiteral)
error(loc, "needs a literal integer", "offset", "");
return;
@ -6082,6 +6086,15 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
#endif
const TFunction* function = nullptr;
// debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()",
// mangled to "debugPrintfEXT("
if (call.getName() == "debugPrintfEXT") {
TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn);
if (symbol)
return symbol->getAsFunction();
}
bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||

View File

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2020 Google, Inc.
//
// All rights reserved.
//
@ -187,13 +188,11 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
if (lookingInMiddle) {
notFirstToken = true;
// make forward progress by finishing off the current line plus extra new lines
if (peek() == '\n' || peek() == '\r') {
while (peek() == '\n' || peek() == '\r')
get();
} else
if (peek() != '\n' && peek() != '\r') {
do {
c = get();
} while (c != EndOfInput && c != '\n' && c != '\r');
}
while (peek() == '\n' || peek() == '\r')
get();
if (peek() == EndOfInput)
@ -843,6 +842,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
parseContext.error(loc, "not supported", "::", "");
break;
case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL;
case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;

View File

@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
//
// All rights reserved.
//

View File

@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
//
// All rights reserved.
//
@ -221,6 +221,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable;
extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable;
extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable;
extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
@ -418,6 +419,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_buffer_reference2 1\n"
"#define GL_EXT_buffer_reference_uvec2 1\n"
"#define GL_EXT_demote_to_helper_invocation 1\n"
"#define GL_EXT_debug_printf 1\n"
// GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n"

View File

@ -185,6 +185,7 @@ const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_ref
const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2";
const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation";
const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock";
const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf";
// Arrays of extensions for the above viewportEXTs duplications

View File

@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2019 Google, Inc.
//
// All rights reserved.
//
@ -263,6 +263,7 @@ GLSLANG_WEB_EXCLUDE_OFF
%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
%token <lex> SUB_ASSIGN
%token <lex> STRING_LITERAL
%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@ -377,6 +378,9 @@ primary_expression
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
}
GLSLANG_WEB_EXCLUDE_ON
| STRING_LITERAL {
$$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
}
| INT32CONSTANT {
parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
$$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);

View File

@ -263,6 +263,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
%token <lex> SUB_ASSIGN
%token <lex> STRING_LITERAL
%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@ -377,6 +378,9 @@ primary_expression
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
}
| STRING_LITERAL {
$$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
}
| INT32CONSTANT {
parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
$$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);

File diff suppressed because it is too large Load Diff

View File

@ -356,103 +356,104 @@ extern int yydebug;
XOR_ASSIGN = 566,
OR_ASSIGN = 567,
SUB_ASSIGN = 568,
LEFT_PAREN = 569,
RIGHT_PAREN = 570,
LEFT_BRACKET = 571,
RIGHT_BRACKET = 572,
LEFT_BRACE = 573,
RIGHT_BRACE = 574,
DOT = 575,
COMMA = 576,
COLON = 577,
EQUAL = 578,
SEMICOLON = 579,
BANG = 580,
DASH = 581,
TILDE = 582,
PLUS = 583,
STAR = 584,
SLASH = 585,
PERCENT = 586,
LEFT_ANGLE = 587,
RIGHT_ANGLE = 588,
VERTICAL_BAR = 589,
CARET = 590,
AMPERSAND = 591,
QUESTION = 592,
INVARIANT = 593,
HIGH_PRECISION = 594,
MEDIUM_PRECISION = 595,
LOW_PRECISION = 596,
PRECISION = 597,
PACKED = 598,
RESOURCE = 599,
SUPERP = 600,
FLOATCONSTANT = 601,
INTCONSTANT = 602,
UINTCONSTANT = 603,
BOOLCONSTANT = 604,
IDENTIFIER = 605,
TYPE_NAME = 606,
CENTROID = 607,
IN = 608,
OUT = 609,
INOUT = 610,
STRUCT = 611,
VOID = 612,
WHILE = 613,
BREAK = 614,
CONTINUE = 615,
DO = 616,
ELSE = 617,
FOR = 618,
IF = 619,
DISCARD = 620,
RETURN = 621,
SWITCH = 622,
CASE = 623,
DEFAULT = 624,
UNIFORM = 625,
SHARED = 626,
BUFFER = 627,
FLAT = 628,
SMOOTH = 629,
LAYOUT = 630,
DOUBLECONSTANT = 631,
INT16CONSTANT = 632,
UINT16CONSTANT = 633,
FLOAT16CONSTANT = 634,
INT32CONSTANT = 635,
UINT32CONSTANT = 636,
INT64CONSTANT = 637,
UINT64CONSTANT = 638,
SUBROUTINE = 639,
DEMOTE = 640,
PAYLOADNV = 641,
PAYLOADINNV = 642,
HITATTRNV = 643,
CALLDATANV = 644,
CALLDATAINNV = 645,
PATCH = 646,
SAMPLE = 647,
NONUNIFORM = 648,
COHERENT = 649,
VOLATILE = 650,
RESTRICT = 651,
READONLY = 652,
WRITEONLY = 653,
DEVICECOHERENT = 654,
QUEUEFAMILYCOHERENT = 655,
WORKGROUPCOHERENT = 656,
SUBGROUPCOHERENT = 657,
NONPRIVATE = 658,
NOPERSPECTIVE = 659,
EXPLICITINTERPAMD = 660,
PERVERTEXNV = 661,
PERPRIMITIVENV = 662,
PERVIEWNV = 663,
PERTASKNV = 664,
PRECISE = 665
STRING_LITERAL = 569,
LEFT_PAREN = 570,
RIGHT_PAREN = 571,
LEFT_BRACKET = 572,
RIGHT_BRACKET = 573,
LEFT_BRACE = 574,
RIGHT_BRACE = 575,
DOT = 576,
COMMA = 577,
COLON = 578,
EQUAL = 579,
SEMICOLON = 580,
BANG = 581,
DASH = 582,
TILDE = 583,
PLUS = 584,
STAR = 585,
SLASH = 586,
PERCENT = 587,
LEFT_ANGLE = 588,
RIGHT_ANGLE = 589,
VERTICAL_BAR = 590,
CARET = 591,
AMPERSAND = 592,
QUESTION = 593,
INVARIANT = 594,
HIGH_PRECISION = 595,
MEDIUM_PRECISION = 596,
LOW_PRECISION = 597,
PRECISION = 598,
PACKED = 599,
RESOURCE = 600,
SUPERP = 601,
FLOATCONSTANT = 602,
INTCONSTANT = 603,
UINTCONSTANT = 604,
BOOLCONSTANT = 605,
IDENTIFIER = 606,
TYPE_NAME = 607,
CENTROID = 608,
IN = 609,
OUT = 610,
INOUT = 611,
STRUCT = 612,
VOID = 613,
WHILE = 614,
BREAK = 615,
CONTINUE = 616,
DO = 617,
ELSE = 618,
FOR = 619,
IF = 620,
DISCARD = 621,
RETURN = 622,
SWITCH = 623,
CASE = 624,
DEFAULT = 625,
UNIFORM = 626,
SHARED = 627,
BUFFER = 628,
FLAT = 629,
SMOOTH = 630,
LAYOUT = 631,
DOUBLECONSTANT = 632,
INT16CONSTANT = 633,
UINT16CONSTANT = 634,
FLOAT16CONSTANT = 635,
INT32CONSTANT = 636,
UINT32CONSTANT = 637,
INT64CONSTANT = 638,
UINT64CONSTANT = 639,
SUBROUTINE = 640,
DEMOTE = 641,
PAYLOADNV = 642,
PAYLOADINNV = 643,
HITATTRNV = 644,
CALLDATANV = 645,
CALLDATAINNV = 646,
PATCH = 647,
SAMPLE = 648,
NONUNIFORM = 649,
COHERENT = 650,
VOLATILE = 651,
RESTRICT = 652,
READONLY = 653,
WRITEONLY = 654,
DEVICECOHERENT = 655,
QUEUEFAMILYCOHERENT = 656,
WORKGROUPCOHERENT = 657,
SUBGROUPCOHERENT = 658,
NONPRIVATE = 659,
NOPERSPECTIVE = 660,
EXPLICITINTERPAMD = 661,
PERVERTEXNV = 662,
PERPRIMITIVENV = 663,
PERVIEWNV = 664,
PERTASKNV = 665,
PRECISE = 666
};
#endif
@ -497,7 +498,7 @@ union YYSTYPE
glslang::TArraySizes* typeParameters;
} interm;
#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
#line 502 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View File

@ -1090,6 +1090,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
case EOpDebugPrintf: out.debug << "Debug printf"; break;
default: out.debug.message(EPrefixError, "Bad aggregation op");
}

23
3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp vendored Executable file → Normal file
View File

@ -621,14 +621,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
{
const TSourceLoc directiveLoc = ppToken->loc;
bool startWithLocalSearch = true; // to additionally include the extra "" paths
int token = scanToken(ppToken);
int token;
// handle <header-name>-style #include
if (token == '<') {
// Find the first non-whitespace char after #include
int ch = getChar();
while (ch == ' ' || ch == '\t') {
ch = getChar();
}
if (ch == '<') {
// <header-name> style
startWithLocalSearch = false;
token = scanHeaderName(ppToken, '>');
} else if (ch == '"') {
// "header-name" style
token = scanHeaderName(ppToken, '"');
} else {
// unexpected, get the full token to generate the error
ungetChar();
token = scanToken(ppToken);
}
// otherwise ppToken already has the header name and it was "header-name" style
if (token != PpAtomConstString) {
parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
@ -711,7 +722,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
const char* sourceName = nullptr; // Optional source file name.
bool lineErr = false;
bool fileErr = false;
disableEscapeSequences = true;
token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
disableEscapeSequences = false;
if (! lineErr) {
lineToken = lineRes;
if (token == '\n')
@ -754,7 +767,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
// Handle #error
int TPpContext::CPPerror(TPpToken* ppToken)
{
disableEscapeSequences = true;
int token = scanToken(ppToken);
disableEscapeSequences = false;
std::string message;
TSourceLoc loc = ppToken->loc;

View File

@ -87,7 +87,8 @@ namespace glslang {
TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false),
rootFileName(rootFileName),
currentSourceFile(rootFileName)
currentSourceFile(rootFileName),
disableEscapeSequences(false)
{
ifdepth = 0;
for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)

View File

@ -695,6 +695,7 @@ protected:
std::string currentSourceFile;
std::istringstream strtodStream;
bool disableEscapeSequences;
};
} // end namespace glslang

View File

@ -1026,12 +1026,80 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
case '\'':
return pp->characterLiteral(ppToken);
case '"':
// TODO: If this gets enhanced to handle escape sequences, or
// anything that is different than what #include needs, then
// #include needs to use scanHeaderName() for this.
// #include uses scanHeaderName() to ignore these escape sequences.
ch = getch();
while (ch != '"' && ch != '\n' && ch != EndOfInput) {
if (len < MaxTokenLength) {
if (ch == '\\' && !pp->disableEscapeSequences) {
int nextCh = getch();
switch (nextCh) {
case '\'': ch = 0x27; break;
case '"': ch = 0x22; break;
case '?': ch = 0x3f; break;
case '\\': ch = 0x5c; break;
case 'a': ch = 0x07; break;
case 'b': ch = 0x08; break;
case 'f': ch = 0x0c; break;
case 'n': ch = 0x0a; break;
case 'r': ch = 0x0d; break;
case 't': ch = 0x09; break;
case 'v': ch = 0x0b; break;
case 'x':
// Hex value, arbitrary number of characters. Terminated by the first
// non-hex digit
{
int numDigits = 0;
ch = 0;
while (true) {
nextCh = getch();
if (nextCh >= '0' && nextCh <= '9')
nextCh -= '0';
else if (nextCh >= 'A' && nextCh <= 'F')
nextCh -= 'A' - 10;
else if (nextCh >= 'a' && nextCh <= 'f')
nextCh -= 'a' - 10;
else {
ungetch();
break;
}
numDigits++;
ch = ch * 0x10 + nextCh;
}
if (numDigits == 0) {
pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", "");
}
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
// Octal value, up to three octal digits
{
int numDigits = 1;
ch = nextCh - '0';
while (numDigits < 3) {
nextCh = getch();
if (nextCh >= '0' && nextCh <= '7')
nextCh -= '0';
else {
ungetch();
break;
}
numDigits++;
ch = ch * 8 + nextCh;
}
break;
}
default:
pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", "");
break;
}
}
ppToken->name[len] = (char)ch;
len++;
ch = getch();
@ -1120,9 +1188,11 @@ int TPpContext::tokenize(TPpToken& ppToken)
continue;
break;
case PpAtomConstString:
if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
// HLSL allows string literals.
parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
// GLSL allows string literals with GL_EXT_debug_printf.
if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
parseContext.requireExtensions(ppToken.loc, 1, &E_GL_EXT_debug_printf, "string literal");
if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf))
continue;
}
break;

View File

@ -17,7 +17,7 @@ if(ENABLE_GLSLANG_JS)
target_link_options(glslang.js PRIVATE "SHELL: -s FILESYSTEM=0")
if(ENABLE_EMSCRIPTEN_SINGLE_FILE)
target_link_options(glslang.js "SHELL: -s SINGLE_FILE=1")
target_link_options(glslang.js PRIVATE "SHELL: -s SINGLE_FILE=1")
endif(ENABLE_EMSCRIPTEN_SINGLE_FILE)
if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)