mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
update glslang
This commit is contained in:
@@ -41,5 +41,6 @@ static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader
|
||||
static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
|
||||
static const char* const E_SPV_EXT_shader_tile_image = "SPV_EXT_shader_tile_image";
|
||||
static const char* const E_SPV_EXT_mesh_shader = "SPV_EXT_mesh_shader";
|
||||
static const char* const E_SPV_ARM_cooperative_matrix_layouts = "SPV_ARM_cooperative_matrix_layouts";
|
||||
|
||||
#endif // #ifndef GLSLextEXT_H
|
||||
|
||||
@@ -61,5 +61,7 @@ static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_coope
|
||||
static const char* const E_SPV_KHR_maximal_reconvergence = "SPV_KHR_maximal_reconvergence";
|
||||
static const char* const E_SPV_KHR_subgroup_rotate = "SPV_KHR_subgroup_rotate";
|
||||
static const char* const E_SPV_KHR_expect_assume = "SPV_KHR_expect_assume";
|
||||
static const char* const E_SPV_EXT_replicated_composites = "SPV_EXT_replicated_composites";
|
||||
static const char* const E_SPV_KHR_relaxed_extended_instruction = "SPV_KHR_relaxed_extended_instruction";
|
||||
|
||||
#endif // #ifndef GLSLextKHR_H
|
||||
|
||||
@@ -227,6 +227,7 @@ protected:
|
||||
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);
|
||||
bool hasQCOMImageProceessingDecoration(spv::Id id, spv::Decoration decor);
|
||||
void addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor);
|
||||
void addImageProcessing2QCOMDecoration(spv::Id id, bool isForGather);
|
||||
spv::Id createSpvConstant(const glslang::TIntermTyped&);
|
||||
@@ -283,6 +284,7 @@ protected:
|
||||
spv::Id taskPayloadID;
|
||||
// Used later for generating OpTraceKHR/OpExecuteCallableKHR/OpHitObjectRecordHit*/OpHitObjectGetShaderBindingTableData
|
||||
std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[4];
|
||||
std::unordered_map<spv::Id, std::vector<spv::Decoration> > idToQCOMDecorations;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -398,11 +400,11 @@ void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector
|
||||
bool useVulkanMemoryModel)
|
||||
{
|
||||
if (!useVulkanMemoryModel) {
|
||||
if (qualifier.isCoherent())
|
||||
memory.push_back(spv::DecorationCoherent);
|
||||
if (qualifier.isVolatile()) {
|
||||
memory.push_back(spv::DecorationVolatile);
|
||||
memory.push_back(spv::DecorationCoherent);
|
||||
} else if (qualifier.isCoherent()) {
|
||||
memory.push_back(spv::DecorationCoherent);
|
||||
}
|
||||
}
|
||||
if (qualifier.isRestrict())
|
||||
@@ -987,18 +989,6 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
||||
return spv::BuiltInHitTriangleVertexPositionsKHR;
|
||||
case glslang::EbvInstanceCustomIndex:
|
||||
return spv::BuiltInInstanceCustomIndexKHR;
|
||||
case glslang::EbvHitT:
|
||||
{
|
||||
// this is a GLSL alias of RayTmax
|
||||
// in SPV_NV_ray_tracing it has a dedicated builtin
|
||||
// but in SPV_KHR_ray_tracing it gets mapped to RayTmax
|
||||
auto& extensions = glslangIntermediate->getRequestedExtensions();
|
||||
if (extensions.find("GL_NV_ray_tracing") != extensions.end()) {
|
||||
return spv::BuiltInHitTNV;
|
||||
} else {
|
||||
return spv::BuiltInRayTmaxKHR;
|
||||
}
|
||||
}
|
||||
case glslang::EbvHitKind:
|
||||
return spv::BuiltInHitKindKHR;
|
||||
case glslang::EbvObjectToWorld:
|
||||
@@ -1593,6 +1583,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
||||
builder.addInclude(iItr->first, iItr->second);
|
||||
}
|
||||
|
||||
builder.setUseReplicatedComposites(glslangIntermediate->usingReplicatedComposites());
|
||||
|
||||
stdBuiltins = builder.import("GLSL.std.450");
|
||||
|
||||
spv::AddressingModel addressingModel = spv::AddressingModelLogical;
|
||||
@@ -2007,8 +1999,9 @@ void TGlslangToSpvTraverser::finishSpv(bool compileOnly)
|
||||
}
|
||||
|
||||
// finish off the entry-point SPV instruction by adding the Input/Output <id>
|
||||
for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it)
|
||||
entryPoint->addIdOperand(*it);
|
||||
entryPoint->reserveOperands(iOSet.size());
|
||||
for (auto id : iOSet)
|
||||
entryPoint->addIdOperand(id);
|
||||
}
|
||||
|
||||
// Add capabilities, extensions, remove unneeded decorations, etc.,
|
||||
@@ -3381,6 +3374,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
|
||||
case glslang::EOpImageBlockMatchGatherSSDQCOM:
|
||||
case glslang::EOpImageBlockMatchGatherSADQCOM:
|
||||
builder.addCapability(spv::CapabilityTextureBlockMatchQCOM);
|
||||
builder.addExtension(spv::E_SPV_QCOM_image_processing);
|
||||
builder.addCapability(spv::CapabilityTextureBlockMatch2QCOM);
|
||||
builder.addExtension(spv::E_SPV_QCOM_image_processing2);
|
||||
break;
|
||||
@@ -3710,6 +3705,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf
|
||||
if (node->getOp() == glslang::EOpCooperativeMatrixLoad) {
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[3])); // matrixLayout
|
||||
auto layout = builder.getConstantScalar(operands[3]);
|
||||
if (layout == spv::CooperativeMatrixLayoutRowBlockedInterleavedARM ||
|
||||
layout == spv::CooperativeMatrixLayoutColumnBlockedInterleavedARM) {
|
||||
builder.addExtension(spv::E_SPV_ARM_cooperative_matrix_layouts);
|
||||
builder.addCapability(spv::CapabilityCooperativeMatrixLayoutsARM);
|
||||
}
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride
|
||||
} else {
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride
|
||||
@@ -3734,6 +3735,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[0])); // object
|
||||
if (node->getOp() == glslang::EOpCooperativeMatrixStore) {
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[3])); // matrixLayout
|
||||
auto layout = builder.getConstantScalar(operands[3]);
|
||||
if (layout == spv::CooperativeMatrixLayoutRowBlockedInterleavedARM ||
|
||||
layout == spv::CooperativeMatrixLayoutColumnBlockedInterleavedARM) {
|
||||
builder.addExtension(spv::E_SPV_ARM_cooperative_matrix_layouts);
|
||||
builder.addCapability(spv::CapabilityCooperativeMatrixLayoutsARM);
|
||||
}
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride
|
||||
} else {
|
||||
idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride
|
||||
@@ -5376,17 +5383,37 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
|
||||
int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout,
|
||||
matrixLayout == glslang::ElmRowMajor);
|
||||
|
||||
bool isVectorLike = memberType.isVector();
|
||||
if (memberType.isMatrix()) {
|
||||
if (matrixLayout == glslang::ElmRowMajor)
|
||||
isVectorLike = memberType.getMatrixRows() == 1;
|
||||
else
|
||||
isVectorLike = memberType.getMatrixCols() == 1;
|
||||
}
|
||||
|
||||
// Adjust alignment for HLSL rules
|
||||
// TODO: make this consistent in early phases of code:
|
||||
// adjusting this late means inconsistencies with earlier code, which for reflection is an issue
|
||||
// Until reflection is brought in sync with these adjustments, don't apply to $Global,
|
||||
// which is the most likely to rely on reflection, and least likely to rely implicit layouts
|
||||
if (glslangIntermediate->usingHlslOffsets() &&
|
||||
! memberType.isArray() && memberType.isVector() && structType.getTypeName().compare("$Global") != 0) {
|
||||
int dummySize;
|
||||
int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize);
|
||||
if (componentAlignment <= 4)
|
||||
! memberType.isStruct() && structType.getTypeName().compare("$Global") != 0) {
|
||||
int componentSize;
|
||||
int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, componentSize);
|
||||
if (! memberType.isArray() && isVectorLike && componentAlignment <= 4)
|
||||
memberAlignment = componentAlignment;
|
||||
|
||||
// Don't add unnecessary padding after this member
|
||||
// (undo std140 bumping size to a mutliple of vec4)
|
||||
if (explicitLayout == glslang::ElpStd140) {
|
||||
if (memberType.isMatrix()) {
|
||||
if (matrixLayout == glslang::ElmRowMajor)
|
||||
memberSize -= componentSize * (4 - memberType.getMatrixCols());
|
||||
else
|
||||
memberSize -= componentSize * (4 - memberType.getMatrixRows());
|
||||
} else if (memberType.isArray())
|
||||
memberSize -= componentSize * (4 - memberType.getVectorSize());
|
||||
}
|
||||
}
|
||||
|
||||
// Bump up to member alignment
|
||||
@@ -5394,7 +5421,7 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType
|
||||
|
||||
// Bump up to vec4 if there is a bad straddle
|
||||
if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize,
|
||||
currentOffset))
|
||||
currentOffset, isVectorLike))
|
||||
glslang::RoundToPow2(currentOffset, 16);
|
||||
|
||||
nextOffset = currentOffset + memberSize;
|
||||
@@ -5479,8 +5506,10 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
|
||||
// memory and use RestrictPointer/AliasedPointer.
|
||||
if (originalParam(type.getQualifier().storage, type, false) ||
|
||||
!writableParam(type.getQualifier().storage)) {
|
||||
decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrict :
|
||||
spv::DecorationAliased);
|
||||
// TranslateMemoryDecoration added Restrict decoration already.
|
||||
if (!type.getQualifier().isRestrict()) {
|
||||
decorations.push_back(spv::DecorationAliased);
|
||||
}
|
||||
} else {
|
||||
decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrictPointerEXT :
|
||||
spv::DecorationAliasedPointerEXT);
|
||||
@@ -5492,12 +5521,16 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
|
||||
glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate();
|
||||
if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction)
|
||||
continue;
|
||||
|
||||
builder.setDebugSourceLocation(glslFunction->getLoc().line, glslFunction->getLoc().getFilename());
|
||||
|
||||
if (isShaderEntryPoint(glslFunction)) {
|
||||
// For HLSL, the entry function is actually a compiler generated function to resolve the difference of
|
||||
// entry function signature between HLSL and SPIR-V. So we don't emit debug information for that.
|
||||
if (glslangIntermediate->getSource() != glslang::EShSourceHlsl) {
|
||||
builder.setupDebugFunctionEntry(shaderEntry, glslangIntermediate->getEntryPointMangledName().c_str(),
|
||||
glslFunction->getLoc().line,
|
||||
std::vector<spv::Id>(), // main function has no param
|
||||
std::vector<char const*>());
|
||||
builder.setupFunctionDebugInfo(shaderEntry, glslangIntermediate->getEntryPointMangledName().c_str(),
|
||||
std::vector<spv::Id>(), // main function has no param
|
||||
std::vector<char const*>());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -5550,8 +5583,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
|
||||
TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()),
|
||||
glslFunction->getName().c_str(), convertGlslangLinkageToSpv(glslFunction->getLinkType()), paramTypes,
|
||||
paramDecorations, &functionBlock);
|
||||
builder.setupDebugFunctionEntry(function, glslFunction->getName().c_str(), glslFunction->getLoc().line,
|
||||
paramTypes, paramNames);
|
||||
builder.setupFunctionDebugInfo(function, glslFunction->getName().c_str(), paramTypes, paramNames);
|
||||
if (implicitThis)
|
||||
function->setImplicitThis();
|
||||
|
||||
@@ -5775,8 +5807,16 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
|
||||
lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
|
||||
builder.addDecoration(lvalue_id, TranslateNonUniformDecoration(lvalueCoherentFlags));
|
||||
lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
|
||||
} else
|
||||
arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType()));
|
||||
} else {
|
||||
if (i > 0 &&
|
||||
glslangArguments[i]->getAsSymbolNode() && glslangArguments[i-1]->getAsSymbolNode() &&
|
||||
glslangArguments[i]->getAsSymbolNode()->getId() == glslangArguments[i-1]->getAsSymbolNode()->getId()) {
|
||||
// Reuse the id if possible
|
||||
arguments.push_back(arguments[i-1]);
|
||||
} else {
|
||||
arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6407,6 +6447,9 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
||||
}
|
||||
}
|
||||
|
||||
// Reset source location to the function call location after argument evaluation
|
||||
builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
|
||||
|
||||
// 2. Allocate space for anything needing a copy, and if it's "in" or "inout"
|
||||
// copy the original into that space.
|
||||
//
|
||||
@@ -8055,6 +8098,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
||||
}
|
||||
|
||||
std::vector<spv::Id> spvAtomicOperands; // hold the spv operands
|
||||
spvAtomicOperands.reserve(6);
|
||||
spvAtomicOperands.push_back(pointerId);
|
||||
spvAtomicOperands.push_back(scopeId);
|
||||
spvAtomicOperands.push_back(semanticsId);
|
||||
@@ -9813,6 +9857,16 @@ void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const g
|
||||
}
|
||||
}
|
||||
|
||||
bool TGlslangToSpvTraverser::hasQCOMImageProceessingDecoration(spv::Id id, spv::Decoration decor)
|
||||
{
|
||||
std::vector<spv::Decoration> &decoVec = idToQCOMDecorations[id];
|
||||
for ( auto d : decoVec ) {
|
||||
if ( d == decor )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TGlslangToSpvTraverser::addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor)
|
||||
{
|
||||
spv::Op opc = builder.getOpCode(id);
|
||||
@@ -9823,7 +9877,10 @@ void TGlslangToSpvTraverser::addImageProcessingQCOMDecoration(spv::Id id, spv::D
|
||||
|
||||
if (opc == spv::OpLoad) {
|
||||
spv::Id texid = builder.getIdOperand(id, 0);
|
||||
builder.addDecoration(texid, decor);
|
||||
if (!hasQCOMImageProceessingDecoration(texid, decor)) {//
|
||||
builder.addDecoration(texid, decor);
|
||||
idToQCOMDecorations[texid].push_back(decor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9841,7 +9898,10 @@ void TGlslangToSpvTraverser::addImageProcessing2QCOMDecoration(spv::Id id, bool
|
||||
if (this->glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) {
|
||||
assert(iOSet.count(tsid) > 0);
|
||||
}
|
||||
this->builder.addDecoration(tsid, decor);
|
||||
if (!hasQCOMImageProceessingDecoration(tsid, decor)) {
|
||||
this->builder.addDecoration(tsid, decor);
|
||||
idToQCOMDecorations[tsid].push_back(decor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10183,6 +10243,7 @@ spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslan
|
||||
|
||||
// Operands to accumulate OpPhi operands
|
||||
std::vector<spv::Id> phiOperands;
|
||||
phiOperands.reserve(4);
|
||||
// accumulate left operand's phi information
|
||||
phiOperands.push_back(leftId);
|
||||
phiOperands.push_back(builder.getBuildPoint()->getId());
|
||||
|
||||
@@ -53,6 +53,7 @@ struct SpvOptions {
|
||||
bool emitNonSemanticShaderDebugInfo {false};
|
||||
bool emitNonSemanticShaderDebugSource{ false };
|
||||
bool compileOnly{false};
|
||||
bool optimizerAllowExpandedIDBound{false};
|
||||
};
|
||||
|
||||
void GetSpirvVersion(std::string&);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -235,6 +235,7 @@ public:
|
||||
Id makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name,
|
||||
NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType = false);
|
||||
Id makePointerDebugType(StorageClass storageClass, Id const baseType);
|
||||
Id makeForwardPointerDebugType(StorageClass storageClass);
|
||||
Id makeDebugSource(const Id fileName);
|
||||
Id makeDebugCompilationUnit();
|
||||
Id createDebugGlobalVariable(Id const type, char const*const name, Id const variable);
|
||||
@@ -246,9 +247,12 @@ public:
|
||||
Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId);
|
||||
Id makeDebugLexicalBlock(uint32_t line);
|
||||
std::string unmangleFunctionName(std::string const& name) const;
|
||||
void setupDebugFunctionEntry(Function* function, const char* name, int line,
|
||||
const std::vector<Id>& paramTypes,
|
||||
const std::vector<char const*>& paramNames);
|
||||
|
||||
// Initialize non-semantic debug information for a function, including those of:
|
||||
// - The function definition
|
||||
// - The function parameters
|
||||
void setupFunctionDebugInfo(Function* function, const char* name, const std::vector<Id>& paramTypes,
|
||||
const std::vector<char const*>& paramNames);
|
||||
|
||||
// accelerationStructureNV type
|
||||
Id makeAccelerationStructureType();
|
||||
@@ -263,9 +267,9 @@ public:
|
||||
Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
|
||||
Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
|
||||
Op getMostBasicTypeClass(Id typeId) const;
|
||||
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
||||
int getNumTypeConstituents(Id typeId) const;
|
||||
int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
|
||||
unsigned int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
||||
unsigned int getNumTypeConstituents(Id typeId) const;
|
||||
unsigned int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
|
||||
Id getScalarTypeId(Id typeId) const;
|
||||
Id getContainedTypeId(Id typeId) const;
|
||||
Id getContainedTypeId(Id typeId, int) const;
|
||||
@@ -333,18 +337,18 @@ public:
|
||||
return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
|
||||
}
|
||||
|
||||
int getTypeNumColumns(Id typeId) const
|
||||
unsigned int getTypeNumColumns(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
return getNumTypeConstituents(typeId);
|
||||
}
|
||||
int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
|
||||
int getTypeNumRows(Id typeId) const
|
||||
unsigned int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
|
||||
unsigned int getTypeNumRows(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
return getNumTypeComponents(getContainedTypeId(typeId));
|
||||
}
|
||||
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
||||
unsigned int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
||||
|
||||
Dim getTypeDimensionality(Id typeId) const
|
||||
{
|
||||
@@ -855,6 +859,8 @@ public:
|
||||
void postProcess(Instruction&);
|
||||
// Hook to visit each non-32-bit sized float/int operation in a block.
|
||||
void postProcessType(const Instruction&, spv::Id typeId);
|
||||
// move OpSampledImage instructions to be next to their users.
|
||||
void postProcessSamplers();
|
||||
|
||||
void dump(std::vector<unsigned int>&) const;
|
||||
|
||||
@@ -870,6 +876,8 @@ public:
|
||||
// Check if the builder is generating code for spec constants.
|
||||
bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
|
||||
|
||||
void setUseReplicatedComposites(bool use) { useReplicatedComposites = use; }
|
||||
|
||||
protected:
|
||||
Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
|
||||
Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
|
||||
@@ -885,10 +893,13 @@ public:
|
||||
void createSelectionMerge(Block* mergeBlock, unsigned int control);
|
||||
void dumpSourceInstructions(std::vector<unsigned int>&) const;
|
||||
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;
|
||||
template <class Range> void dumpInstructions(std::vector<unsigned int>& out, const Range& instructions) const;
|
||||
void dumpModuleProcesses(std::vector<unsigned int>&) const;
|
||||
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
|
||||
const;
|
||||
struct DecorationInstructionLessThan {
|
||||
bool operator()(const std::unique_ptr<Instruction>& lhs, const std::unique_ptr<Instruction>& rhs) const;
|
||||
};
|
||||
|
||||
unsigned int spvVersion; // the version of SPIR-V to emit in the header
|
||||
SourceLanguage sourceLang;
|
||||
@@ -936,6 +947,7 @@ public:
|
||||
Id uniqueId;
|
||||
Function* entryPointFunction;
|
||||
bool generatingOpCodeForSpecConst;
|
||||
bool useReplicatedComposites { false };
|
||||
AccessChain accessChain;
|
||||
|
||||
// special blocks of instructions for output
|
||||
@@ -944,7 +956,7 @@ public:
|
||||
std::vector<std::unique_ptr<Instruction> > entryPoints;
|
||||
std::vector<std::unique_ptr<Instruction> > executionModes;
|
||||
std::vector<std::unique_ptr<Instruction> > names;
|
||||
std::vector<std::unique_ptr<Instruction> > decorations;
|
||||
std::set<std::unique_ptr<Instruction>, DecorationInstructionLessThan> decorations;
|
||||
std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
|
||||
std::vector<std::unique_ptr<Instruction> > externals;
|
||||
std::vector<std::unique_ptr<Function> > functions;
|
||||
|
||||
@@ -387,12 +387,14 @@ void Builder::postProcessCFG()
|
||||
}
|
||||
|
||||
// Remove unneeded decorations, for unreachable instructions
|
||||
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
|
||||
[&unreachableDefinitions](std::unique_ptr<Instruction>& I) -> bool {
|
||||
Id decoration_id = I.get()->getIdOperand(0);
|
||||
return unreachableDefinitions.count(decoration_id) != 0;
|
||||
}),
|
||||
decorations.end());
|
||||
for (auto decorationIter = decorations.begin(); decorationIter != decorations.end();) {
|
||||
Id decorationId = (*decorationIter)->getIdOperand(0);
|
||||
if (unreachableDefinitions.count(decorationId) != 0) {
|
||||
decorationIter = decorations.erase(decorationIter);
|
||||
} else {
|
||||
++decorationIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// comment in header
|
||||
@@ -483,6 +485,58 @@ void Builder::postProcessFeatures() {
|
||||
}
|
||||
}
|
||||
|
||||
// SPIR-V requires that any instruction consuming the result of an OpSampledImage
|
||||
// be in the same block as the OpSampledImage instruction. This pass goes finds
|
||||
// uses of OpSampledImage where that is not the case and duplicates the
|
||||
// OpSampledImage to be immediately before the instruction that consumes it.
|
||||
// The old OpSampledImage is left in place, potentially with no users.
|
||||
void Builder::postProcessSamplers()
|
||||
{
|
||||
// first, find all OpSampledImage instructions and store them in a map.
|
||||
std::map<Id, Instruction*> sampledImageInstrs;
|
||||
for (auto f: module.getFunctions()) {
|
||||
for (auto b: f->getBlocks()) {
|
||||
for (auto &i: b->getInstructions()) {
|
||||
if (i->getOpCode() == spv::OpSampledImage) {
|
||||
sampledImageInstrs[i->getResultId()] = i.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// next find all uses of the given ids and rewrite them if needed.
|
||||
for (auto f: module.getFunctions()) {
|
||||
for (auto b: f->getBlocks()) {
|
||||
auto &instrs = b->getInstructions();
|
||||
for (size_t idx = 0; idx < instrs.size(); idx++) {
|
||||
Instruction *i = instrs[idx].get();
|
||||
for (int opnum = 0; opnum < i->getNumOperands(); opnum++) {
|
||||
// Is this operand of the current instruction the result of an OpSampledImage?
|
||||
if (i->isIdOperand(opnum) &&
|
||||
sampledImageInstrs.count(i->getIdOperand(opnum)))
|
||||
{
|
||||
Instruction *opSampImg = sampledImageInstrs[i->getIdOperand(opnum)];
|
||||
if (i->getBlock() != opSampImg->getBlock()) {
|
||||
Instruction *newInstr = new Instruction(getUniqueId(),
|
||||
opSampImg->getTypeId(),
|
||||
spv::OpSampledImage);
|
||||
newInstr->addIdOperand(opSampImg->getIdOperand(0));
|
||||
newInstr->addIdOperand(opSampImg->getIdOperand(1));
|
||||
newInstr->setBlock(b);
|
||||
|
||||
// rewrite the user of the OpSampledImage to use the new instruction.
|
||||
i->setIdOperand(opnum, newInstr->getResultId());
|
||||
// insert the new OpSampledImage right before the current instruction.
|
||||
instrs.insert(instrs.begin() + idx,
|
||||
std::unique_ptr<Instruction>(newInstr));
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// comment in header
|
||||
void Builder::postProcess(bool compileOnly)
|
||||
{
|
||||
@@ -491,6 +545,7 @@ void Builder::postProcess(bool compileOnly)
|
||||
postProcessCFG();
|
||||
|
||||
postProcessFeatures();
|
||||
postProcessSamplers();
|
||||
}
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "SpvTools.h"
|
||||
#include "spirv-tools/optimizer.hpp"
|
||||
#include "../glslang/MachineIndependent/localintermediate.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
@@ -218,9 +219,20 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
|
||||
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
|
||||
|
||||
spvtools::OptimizerOptions spvOptOptions;
|
||||
if (options->optimizerAllowExpandedIDBound)
|
||||
spvOptOptions.set_max_id_bound(0x3FFFFFFF);
|
||||
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);
|
||||
|
||||
if (options->optimizerAllowExpandedIDBound) {
|
||||
if (spirv.size() > 3 && spirv[3] > kDefaultMaxIdBound) {
|
||||
spvtools::Optimizer optimizer2(target_env);
|
||||
optimizer2.SetMessageConsumer(OptimizerMesssageConsumer);
|
||||
optimizer2.RegisterPass(spvtools::CreateCompactIdsPass());
|
||||
optimizer2.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector<unsigned int>& spirv,
|
||||
|
||||
@@ -44,10 +44,11 @@
|
||||
#if ENABLE_OPT
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <unordered_set>
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#endif
|
||||
|
||||
#include "../glslang/MachineIndependent/localintermediate.h"
|
||||
#include "../glslang/MachineIndependent/Versions.h"
|
||||
#include "GlslangToSpv.h"
|
||||
#include "Logger.h"
|
||||
|
||||
@@ -55,6 +56,8 @@ namespace glslang {
|
||||
|
||||
#if ENABLE_OPT
|
||||
|
||||
class TIntermediate;
|
||||
|
||||
// Translate glslang's view of target versioning to what SPIRV-Tools uses.
|
||||
spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger);
|
||||
|
||||
|
||||
@@ -1035,6 +1035,8 @@ const char* CapabilityString(int info)
|
||||
case CapabilityTileImageDepthReadAccessEXT: return "TileImageDepthReadAccessEXT";
|
||||
case CapabilityTileImageStencilReadAccessEXT: return "TileImageStencilReadAccessEXT";
|
||||
|
||||
case CapabilityCooperativeMatrixLayoutsARM: return "CooperativeMatrixLayoutsARM";
|
||||
|
||||
case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR";
|
||||
|
||||
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
|
||||
@@ -1064,6 +1066,9 @@ const char* CapabilityString(int info)
|
||||
case CapabilityTextureSampleWeightedQCOM: return "TextureSampleWeightedQCOM";
|
||||
case CapabilityTextureBoxFilterQCOM: return "TextureBoxFilterQCOM";
|
||||
case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM";
|
||||
case CapabilityTextureBlockMatch2QCOM: return "TextureBlockMatch2QCOM";
|
||||
|
||||
case CapabilityReplicatedCompositesEXT: return "CapabilityReplicatedCompositesEXT";
|
||||
|
||||
default: return "Bad";
|
||||
}
|
||||
@@ -1442,6 +1447,7 @@ const char* OpcodeString(int op)
|
||||
case 4429: return "OpSubgroupAnyKHR";
|
||||
case 4430: return "OpSubgroupAllEqualKHR";
|
||||
case 4432: return "OpSubgroupReadInvocationKHR";
|
||||
case 4433: return "OpExtInstWithForwardRefsKHR";
|
||||
|
||||
case OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR";
|
||||
case OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR";
|
||||
@@ -1583,6 +1589,10 @@ const char* OpcodeString(int op)
|
||||
case OpImageBlockMatchGatherSSDQCOM: return "OpImageBlockMatchGatherSSDQCOM";
|
||||
case OpImageBlockMatchGatherSADQCOM: return "OpImageBlockMatchGatherSADQCOM";
|
||||
|
||||
case OpConstantCompositeReplicateEXT: return "OpConstantCompositeReplicateEXT";
|
||||
case OpSpecConstantCompositeReplicateEXT: return "OpSpecConstantCompositeReplicateEXT";
|
||||
case OpCompositeConstructReplicateEXT: return "OpCompositeConstructReplicateEXT";
|
||||
|
||||
default:
|
||||
return "Bad";
|
||||
}
|
||||
@@ -1889,6 +1899,10 @@ void Parameterize()
|
||||
InstructionDesc[OpExtInst].operands.push(OperandLiteralNumber, "'Instruction'");
|
||||
InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n...");
|
||||
|
||||
InstructionDesc[OpExtInstWithForwardRefsKHR].operands.push(OperandId, "'Set'");
|
||||
InstructionDesc[OpExtInstWithForwardRefsKHR].operands.push(OperandLiteralNumber, "'Instruction'");
|
||||
InstructionDesc[OpExtInstWithForwardRefsKHR].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n...");
|
||||
|
||||
InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'");
|
||||
InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true);
|
||||
InstructionDesc[OpLoad].operands.push(OperandLiteralNumber, "", true);
|
||||
@@ -3470,6 +3484,10 @@ void Parameterize()
|
||||
InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'block size'");
|
||||
InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandImageOperands, "", true);
|
||||
InstructionDesc[OpImageBlockMatchGatherSADQCOM].setResultAndType(true, true);
|
||||
|
||||
InstructionDesc[OpConstantCompositeReplicateEXT].operands.push(OperandId, "'Value'");
|
||||
InstructionDesc[OpSpecConstantCompositeReplicateEXT].operands.push(OperandId, "'Value'");
|
||||
InstructionDesc[OpCompositeConstructReplicateEXT].operands.push(OperandId, "'Value'");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -385,7 +385,7 @@ enum ImageOperandsShift {
|
||||
ImageOperandsMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum ImageOperandsMask {
|
||||
enum ImageOperandsMask : unsigned {
|
||||
ImageOperandsMaskNone = 0,
|
||||
ImageOperandsBiasMask = 0x00000001,
|
||||
ImageOperandsLodMask = 0x00000002,
|
||||
@@ -420,7 +420,7 @@ enum FPFastMathModeShift {
|
||||
FPFastMathModeMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum FPFastMathModeMask {
|
||||
enum FPFastMathModeMask : unsigned {
|
||||
FPFastMathModeMaskNone = 0,
|
||||
FPFastMathModeNotNaNMask = 0x00000001,
|
||||
FPFastMathModeNotInfMask = 0x00000002,
|
||||
@@ -745,7 +745,7 @@ enum SelectionControlShift {
|
||||
SelectionControlMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum SelectionControlMask {
|
||||
enum SelectionControlMask : unsigned {
|
||||
SelectionControlMaskNone = 0,
|
||||
SelectionControlFlattenMask = 0x00000001,
|
||||
SelectionControlDontFlattenMask = 0x00000002,
|
||||
@@ -774,7 +774,7 @@ enum LoopControlShift {
|
||||
LoopControlMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum LoopControlMask {
|
||||
enum LoopControlMask : unsigned {
|
||||
LoopControlMaskNone = 0,
|
||||
LoopControlUnrollMask = 0x00000001,
|
||||
LoopControlDontUnrollMask = 0x00000002,
|
||||
@@ -806,7 +806,7 @@ enum FunctionControlShift {
|
||||
FunctionControlMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum FunctionControlMask {
|
||||
enum FunctionControlMask : unsigned {
|
||||
FunctionControlMaskNone = 0,
|
||||
FunctionControlInlineMask = 0x00000001,
|
||||
FunctionControlDontInlineMask = 0x00000002,
|
||||
@@ -836,7 +836,7 @@ enum MemorySemanticsShift {
|
||||
MemorySemanticsMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum MemorySemanticsMask {
|
||||
enum MemorySemanticsMask : unsigned {
|
||||
MemorySemanticsMaskNone = 0,
|
||||
MemorySemanticsAcquireMask = 0x00000002,
|
||||
MemorySemanticsReleaseMask = 0x00000004,
|
||||
@@ -872,7 +872,7 @@ enum MemoryAccessShift {
|
||||
MemoryAccessMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum MemoryAccessMask {
|
||||
enum MemoryAccessMask : unsigned {
|
||||
MemoryAccessMaskNone = 0,
|
||||
MemoryAccessVolatileMask = 0x00000001,
|
||||
MemoryAccessAlignedMask = 0x00000002,
|
||||
@@ -922,7 +922,7 @@ enum KernelProfilingInfoShift {
|
||||
KernelProfilingInfoMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum KernelProfilingInfoMask {
|
||||
enum KernelProfilingInfoMask : unsigned {
|
||||
KernelProfilingInfoMaskNone = 0,
|
||||
KernelProfilingInfoCmdExecTimeMask = 0x00000001,
|
||||
};
|
||||
@@ -1002,6 +1002,7 @@ enum Capability {
|
||||
CapabilityTileImageColorReadAccessEXT = 4166,
|
||||
CapabilityTileImageDepthReadAccessEXT = 4167,
|
||||
CapabilityTileImageStencilReadAccessEXT = 4168,
|
||||
CapabilityCooperativeMatrixLayoutsARM = 4201,
|
||||
CapabilityFragmentShadingRateKHR = 4422,
|
||||
CapabilitySubgroupBallotKHR = 4423,
|
||||
CapabilityDrawParameters = 4427,
|
||||
@@ -1163,6 +1164,7 @@ enum Capability {
|
||||
CapabilityDotProductKHR = 6019,
|
||||
CapabilityRayCullMaskKHR = 6020,
|
||||
CapabilityCooperativeMatrixKHR = 6022,
|
||||
CapabilityReplicatedCompositesEXT = 6024,
|
||||
CapabilityBitInstructions = 6025,
|
||||
CapabilityGroupNonUniformRotateKHR = 6026,
|
||||
CapabilityAtomicFloat32AddEXT = 6033,
|
||||
@@ -1192,7 +1194,7 @@ enum RayFlagsShift {
|
||||
RayFlagsMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum RayFlagsMask {
|
||||
enum RayFlagsMask : unsigned {
|
||||
RayFlagsMaskNone = 0,
|
||||
RayFlagsOpaqueKHRMask = 0x00000001,
|
||||
RayFlagsNoOpaqueKHRMask = 0x00000002,
|
||||
@@ -1234,7 +1236,7 @@ enum FragmentShadingRateShift {
|
||||
FragmentShadingRateMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum FragmentShadingRateMask {
|
||||
enum FragmentShadingRateMask : unsigned {
|
||||
FragmentShadingRateMaskNone = 0,
|
||||
FragmentShadingRateVertical2PixelsMask = 0x00000001,
|
||||
FragmentShadingRateVertical4PixelsMask = 0x00000002,
|
||||
@@ -1289,7 +1291,7 @@ enum CooperativeMatrixOperandsShift {
|
||||
CooperativeMatrixOperandsMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum CooperativeMatrixOperandsMask {
|
||||
enum CooperativeMatrixOperandsMask : unsigned {
|
||||
CooperativeMatrixOperandsMaskNone = 0,
|
||||
CooperativeMatrixOperandsMatrixASignedComponentsKHRMask = 0x00000001,
|
||||
CooperativeMatrixOperandsMatrixBSignedComponentsKHRMask = 0x00000002,
|
||||
@@ -1301,6 +1303,8 @@ enum CooperativeMatrixOperandsMask {
|
||||
enum CooperativeMatrixLayout {
|
||||
CooperativeMatrixLayoutRowMajorKHR = 0,
|
||||
CooperativeMatrixLayoutColumnMajorKHR = 1,
|
||||
CooperativeMatrixLayoutRowBlockedInterleavedARM = 4202,
|
||||
CooperativeMatrixLayoutColumnBlockedInterleavedARM = 4203,
|
||||
CooperativeMatrixLayoutMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -1667,6 +1671,7 @@ enum Op {
|
||||
OpSubgroupAllEqualKHR = 4430,
|
||||
OpGroupNonUniformRotateKHR = 4431,
|
||||
OpSubgroupReadInvocationKHR = 4432,
|
||||
OpExtInstWithForwardRefsKHR = 4433,
|
||||
OpTraceRayKHR = 4445,
|
||||
OpExecuteCallableKHR = 4446,
|
||||
OpConvertUToAccelerationStructureKHR = 4447,
|
||||
@@ -1689,6 +1694,9 @@ enum Op {
|
||||
OpCooperativeMatrixStoreKHR = 4458,
|
||||
OpCooperativeMatrixMulAddKHR = 4459,
|
||||
OpCooperativeMatrixLengthKHR = 4460,
|
||||
OpConstantCompositeReplicateEXT = 4461,
|
||||
OpSpecConstantCompositeReplicateEXT = 4462,
|
||||
OpCompositeConstructReplicateEXT = 4463,
|
||||
OpTypeRayQueryKHR = 4472,
|
||||
OpRayQueryInitializeKHR = 4473,
|
||||
OpRayQueryTerminateKHR = 4474,
|
||||
@@ -2391,6 +2399,7 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
|
||||
case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
|
||||
case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
|
||||
case OpExtInstWithForwardRefsKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpColorAttachmentReadEXT: *hasResult = true; *hasResultType = true; break;
|
||||
case OpDepthAttachmentReadEXT: *hasResult = true; *hasResultType = true; break;
|
||||
case OpStencilAttachmentReadEXT: *hasResult = true; *hasResultType = true; break;
|
||||
@@ -2418,6 +2427,9 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpCooperativeMatrixStoreKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpCooperativeMatrixMulAddKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSpecConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break;
|
||||
case OpCompositeConstructReplicateEXT: *hasResult = true; *hasResultType = true; break;
|
||||
case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
|
||||
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
|
||||
|
||||
@@ -97,12 +97,24 @@ public:
|
||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
|
||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
|
||||
virtual ~Instruction() {}
|
||||
void reserveOperands(size_t count) {
|
||||
operands.reserve(count);
|
||||
idOperand.reserve(count);
|
||||
}
|
||||
void addIdOperand(Id id) {
|
||||
// ids can't be 0
|
||||
assert(id);
|
||||
operands.push_back(id);
|
||||
idOperand.push_back(true);
|
||||
}
|
||||
// This method is potentially dangerous as it can break assumptions
|
||||
// about SSA and lack of forward references.
|
||||
void setIdOperand(unsigned idx, Id id) {
|
||||
assert(id);
|
||||
assert(idOperand[idx]);
|
||||
operands[idx] = id;
|
||||
}
|
||||
|
||||
void addImmediateOperand(unsigned int immediate) {
|
||||
operands.push_back(immediate);
|
||||
idOperand.push_back(false);
|
||||
@@ -234,7 +246,7 @@ public:
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
|
||||
const std::vector<Block*>& getPredecessors() const { return predecessors; }
|
||||
const std::vector<Block*>& getSuccessors() const { return successors; }
|
||||
const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
|
||||
std::vector<std::unique_ptr<Instruction> >& getInstructions() {
|
||||
return instructions;
|
||||
}
|
||||
const std::vector<std::unique_ptr<Instruction> >& getLocalVariables() const { return localVariables; }
|
||||
@@ -398,6 +410,7 @@ public:
|
||||
|
||||
void setDebugLineInfo(Id fileName, int line, int column) {
|
||||
lineInstruction = std::unique_ptr<Instruction>{new Instruction(OpLine)};
|
||||
lineInstruction->reserveOperands(3);
|
||||
lineInstruction->addIdOperand(fileName);
|
||||
lineInstruction->addImmediateOperand(line);
|
||||
lineInstruction->addImmediateOperand(column);
|
||||
@@ -521,6 +534,7 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam
|
||||
linkType(linkage)
|
||||
{
|
||||
// OpFunction
|
||||
functionInstruction.reserveOperands(2);
|
||||
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
||||
functionInstruction.addIdOperand(functionType);
|
||||
parent.mapInstruction(&functionInstruction);
|
||||
|
||||
@@ -268,7 +268,6 @@ enum TBuiltInVariable {
|
||||
EbvRayTmin,
|
||||
EbvRayTmax,
|
||||
EbvCullMask,
|
||||
EbvHitT,
|
||||
EbvHitKind,
|
||||
EbvObjectToWorld,
|
||||
EbvObjectToWorld3x4,
|
||||
@@ -495,7 +494,6 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
|
||||
case EbvObjectRayDirection: return "ObjectRayDirectionNV";
|
||||
case EbvRayTmin: return "ObjectRayTminNV";
|
||||
case EbvRayTmax: return "ObjectRayTmaxNV";
|
||||
case EbvHitT: return "HitTNV";
|
||||
case EbvHitKind: return "HitKindNV";
|
||||
case EbvIncomingRayFlags: return "IncomingRayFlagsNV";
|
||||
case EbvObjectToWorld: return "ObjectToWorldNV";
|
||||
|
||||
@@ -94,6 +94,11 @@ std::string to_string(const T& val) {
|
||||
#pragma warning(disable : 4201) // nameless union
|
||||
#endif
|
||||
|
||||
// Allow compilation to WASI which does not support threads yet.
|
||||
#ifdef __wasi__
|
||||
#define DISABLE_THREAD_SUPPORT
|
||||
#endif
|
||||
|
||||
#include "PoolAlloc.h"
|
||||
|
||||
//
|
||||
|
||||
@@ -95,10 +95,14 @@ public:
|
||||
default: append("UNKNOWN ERROR: "); break;
|
||||
}
|
||||
}
|
||||
void location(const TSourceLoc& loc, bool absolute = false) {
|
||||
void location(const TSourceLoc& loc, bool absolute = false, bool displayColumn = false) {
|
||||
const int maxSize = 24;
|
||||
char locText[maxSize];
|
||||
snprintf(locText, maxSize, ":%d", loc.line);
|
||||
if (displayColumn) {
|
||||
snprintf(locText, maxSize, ":%d:%d", loc.line, loc.column);
|
||||
} else {
|
||||
snprintf(locText, maxSize, ":%d", loc.line);
|
||||
}
|
||||
|
||||
if(loc.getFilename() == nullptr && shaderFileName != nullptr && absolute) {
|
||||
append(std::filesystem::absolute(shaderFileName).string());
|
||||
@@ -119,9 +123,11 @@ public:
|
||||
append(s);
|
||||
append("\n");
|
||||
}
|
||||
void message(TPrefixType message, const char* s, const TSourceLoc& loc) {
|
||||
void message(TPrefixType message, const char* s, const TSourceLoc& loc, bool absolute = false,
|
||||
bool displayColumn = false)
|
||||
{
|
||||
prefix(message);
|
||||
location(loc);
|
||||
location(loc, absolute, displayColumn);
|
||||
append(s);
|
||||
append("\n");
|
||||
}
|
||||
|
||||
@@ -507,7 +507,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
|
||||
case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
|
||||
case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
|
||||
case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
|
||||
case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
|
||||
case EbtInt64: {
|
||||
int64_t i64val = unionArray[i].getI64Const();
|
||||
newConstArray[i].setI64Const(i64val == INT64_MIN ? INT64_MIN : -i64val);
|
||||
break;
|
||||
}
|
||||
case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
|
||||
default:
|
||||
return nullptr;
|
||||
@@ -1009,6 +1013,12 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
|
||||
objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
|
||||
children[2]->getAsTyped()->getType().getVectorSize());
|
||||
break;
|
||||
case EOpMul:
|
||||
{
|
||||
TIntermConstantUnion* left = children[0]->getAsConstantUnion();
|
||||
TIntermConstantUnion* right = children[1]->getAsConstantUnion();
|
||||
return left->fold(EOpMul, right);
|
||||
}
|
||||
default:
|
||||
return aggrNode;
|
||||
}
|
||||
|
||||
@@ -1707,9 +1707,6 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
||||
|
||||
"vec4 textureCube(samplerCube, vec3);"
|
||||
|
||||
"vec4 texture2DArray(sampler2DArray, vec3);" // GL_EXT_texture_array
|
||||
"vec4 texture2DArray(sampler2DArray, vec3, float);" // GL_EXT_texture_array
|
||||
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
@@ -1736,9 +1733,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
||||
"vec4 shadow2DRectProj(sampler2DRectShadow, vec4);" // GL_ARB_texture_rectangle, caught by keyword check
|
||||
|
||||
"vec4 texture1DArray(sampler1DArray, vec2);" // GL_EXT_texture_array
|
||||
"vec4 texture2DArray(sampler2DArray, vec3);" // GL_EXT_texture_array
|
||||
"vec4 shadow1DArray(sampler1DArrayShadow, vec3);" // GL_EXT_texture_array
|
||||
"vec4 shadow2DArray(sampler2DArrayShadow, vec4);" // GL_EXT_texture_array
|
||||
"vec4 texture1DArray(sampler1DArray, vec2, float);" // GL_EXT_texture_array
|
||||
"vec4 texture2DArray(sampler2DArray, vec3, float);" // GL_EXT_texture_array
|
||||
"vec4 shadow1DArray(sampler1DArrayShadow, vec3, float);" // GL_EXT_texture_array
|
||||
"vec4 texture1DArrayLod(sampler1DArray, vec2, float);" // GL_EXT_texture_array
|
||||
"vec4 texture2DArrayLod(sampler2DArray, vec3, float);" // GL_EXT_texture_array
|
||||
@@ -4559,6 +4558,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
||||
"const int gl_MatrixOperandsSaturatingAccumulation = 0x10;\n"
|
||||
"const int gl_CooperativeMatrixLayoutRowMajor = 0;\n"
|
||||
"const int gl_CooperativeMatrixLayoutColumnMajor = 1;\n"
|
||||
"const int gl_CooperativeMatrixLayoutRowBlockedInterleavedARM = 4202;\n"
|
||||
"const int gl_CooperativeMatrixLayoutColumnBlockedInterleavedARM = 4203;\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
@@ -8122,11 +8123,9 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
||||
}
|
||||
|
||||
// E_GL_EXT_texture_array
|
||||
if (spvVersion.spv == 0) {
|
||||
symbolTable.setFunctionExtensions("texture2DArray", 1, &E_GL_EXT_texture_array);
|
||||
}
|
||||
if (profile != EEsProfile && spvVersion.spv == 0) {
|
||||
symbolTable.setFunctionExtensions("texture1DArray", 1, &E_GL_EXT_texture_array);
|
||||
symbolTable.setFunctionExtensions("texture2DArray", 1, &E_GL_EXT_texture_array);
|
||||
symbolTable.setFunctionExtensions("shadow1DArray", 1, &E_GL_EXT_texture_array);
|
||||
symbolTable.setFunctionExtensions("shadow2DArray", 1, &E_GL_EXT_texture_array);
|
||||
|
||||
@@ -9212,8 +9211,6 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
||||
BuiltInVariable("gl_RayTmaxNV", EbvRayTmax, symbolTable);
|
||||
BuiltInVariable("gl_RayTmaxEXT", EbvRayTmax, symbolTable);
|
||||
BuiltInVariable("gl_CullMaskEXT", EbvCullMask, symbolTable);
|
||||
BuiltInVariable("gl_HitTNV", EbvHitT, symbolTable);
|
||||
BuiltInVariable("gl_HitTEXT", EbvHitT, symbolTable);
|
||||
BuiltInVariable("gl_HitKindNV", EbvHitKind, symbolTable);
|
||||
BuiltInVariable("gl_HitKindEXT", EbvHitKind, symbolTable);
|
||||
BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorld, symbolTable);
|
||||
@@ -9232,6 +9229,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
||||
BuiltInVariable("gl_HitKindFrontFacingMicroTriangleNV", EbvHitKindFrontFacingMicroTriangleNV, symbolTable);
|
||||
BuiltInVariable("gl_HitKindBackFacingMicroTriangleNV", EbvHitKindBackFacingMicroTriangleNV, symbolTable);
|
||||
|
||||
// gl_HitT variables are aliases of their gl_RayTmax counterparts.
|
||||
RetargetVariable("gl_HitTNV", "gl_RayTmaxNV", symbolTable);
|
||||
RetargetVariable("gl_HitTEXT", "gl_RayTmaxEXT", symbolTable);
|
||||
|
||||
// GL_ARB_shader_ballot
|
||||
symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot);
|
||||
symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot);
|
||||
@@ -10138,11 +10139,9 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
||||
symbolTable.relateToOperator("textureBlockMatchGatherSADQCOM", EOpImageBlockMatchGatherSADQCOM);
|
||||
}
|
||||
|
||||
if (spvVersion.spv == 0) {
|
||||
symbolTable.relateToOperator("texture2DArray", EOpTexture);
|
||||
}
|
||||
if (profile != EEsProfile && spvVersion.spv == 0) {
|
||||
symbolTable.relateToOperator("texture1DArray", EOpTexture);
|
||||
symbolTable.relateToOperator("texture2DArray", EOpTexture);
|
||||
symbolTable.relateToOperator("shadow1DArray", EOpTexture);
|
||||
symbolTable.relateToOperator("shadow2DArray", EOpTexture);
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReaso
|
||||
safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
|
||||
|
||||
infoSink.info.prefix(prefix);
|
||||
infoSink.info.location(loc, messages & EShMsgAbsolutePath);
|
||||
infoSink.info.location(loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
|
||||
infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
|
||||
|
||||
if (prefix == EPrefixError) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// Copyright (C) 2015-2018 Google, Inc.
|
||||
// Copyright (C) 2017, 2019 ARM Limited.
|
||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
||||
// Modifications Copyright (C) 2024 Ravi Prakash Singh.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -399,6 +400,10 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
|
||||
if (spvVersion.spv < glslang::EShTargetSpv_1_3)
|
||||
error(loc, "requires SPIR-V 1.3", "#pragma use_variable_pointers", "");
|
||||
intermediate.setUseVariablePointers();
|
||||
} else if (spvVersion.spv > 0 && tokens[0].compare("use_replicated_composites") == 0) {
|
||||
if (tokens.size() != 1)
|
||||
error(loc, "extra tokens", "#pragma", "");
|
||||
intermediate.setReplicatedComposites();
|
||||
} else if (tokens[0].compare("once") == 0) {
|
||||
warn(loc, "not implemented", "#pragma once", "");
|
||||
} else if (tokens[0].compare("glslang_binary_double_output") == 0) {
|
||||
@@ -492,7 +497,7 @@ TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symb
|
||||
if ((variable->getMangledName() == "gl_PrimitiveTriangleIndicesEXT" && primitiveType != ElgTriangles) ||
|
||||
(variable->getMangledName() == "gl_PrimitiveLineIndicesEXT" && primitiveType != ElgLines) ||
|
||||
(variable->getMangledName() == "gl_PrimitivePointIndicesEXT" && primitiveType != ElgPoints)) {
|
||||
error(loc, "cannot be used (ouput primitive type mismatch)", string->c_str(), "");
|
||||
error(loc, "cannot be used (output primitive type mismatch)", string->c_str(), "");
|
||||
variable = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -598,6 +603,10 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
||||
indexValue >= resources.maxCullDistances) {
|
||||
error(loc, "gl_CullDistance", "[", "array index out of range '%d'", indexValue);
|
||||
}
|
||||
else if (base->getQualifier().builtIn == EbvSampleMask &&
|
||||
indexValue >= (resources.maxSamples + 31) / 32) {
|
||||
error(loc, "gl_SampleMask", "[", "array index out of range '%d'", indexValue);
|
||||
}
|
||||
// For 2D per-view builtin arrays, update the inner dimension size in parent type
|
||||
if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) {
|
||||
TIntermBinary* binaryNode = base->getAsBinaryNode();
|
||||
@@ -2700,7 +2709,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
||||
case EOpEmitStreamVertex:
|
||||
case EOpEndStreamPrimitive:
|
||||
if (version == 150)
|
||||
requireExtensions(loc, 1, &E_GL_ARB_gpu_shader5, "if the verison is 150 , the EmitStreamVertex and EndStreamPrimitive only support at extension GL_ARB_gpu_shader5");
|
||||
requireExtensions(loc, 1, &E_GL_ARB_gpu_shader5, "if the version is 150 , the EmitStreamVertex and EndStreamPrimitive only support at extension GL_ARB_gpu_shader5");
|
||||
intermediate.setMultiStream();
|
||||
break;
|
||||
|
||||
@@ -3609,6 +3618,19 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
||||
makeSpecConst = ! intArgument && !type.isArray();
|
||||
break;
|
||||
|
||||
case EOpConstructCooperativeMatrixNV:
|
||||
case EOpConstructCooperativeMatrixKHR:
|
||||
case EOpConstructStruct:
|
||||
{
|
||||
const char *specConstantCompositeExt[] = { E_GL_EXT_spec_constant_composites };
|
||||
if (checkExtensionsRequested(loc, 1, specConstantCompositeExt, "spec constant aggregate constructor")) {
|
||||
makeSpecConst = true;
|
||||
} else {
|
||||
makeSpecConst = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// anything else wasn't white-listed in the spec as a conversion
|
||||
makeSpecConst = false;
|
||||
@@ -6564,10 +6586,10 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
||||
int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision);
|
||||
if (repeated >= 0 && ! typeCollision)
|
||||
error(loc, "overlapping use of location", "location", "%d", repeated);
|
||||
// "fragment-shader outputs/tileImageEXT ... if two variables are placed within the same
|
||||
// location, they must have the same underlying type (floating-point or integer)"
|
||||
if (typeCollision && language == EShLangFragment && (qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT))
|
||||
error(loc, "fragment outputs or tileImageEXTs sharing the same location", "location", "%d must be the same basic type", repeated);
|
||||
// When location aliasing, the aliases sharing the location must have the same underlying numerical type and bit width(
|
||||
// floating - point or integer, 32 - bit versus 64 - bit,etc.)
|
||||
if (typeCollision && (qualifier.isPipeInput() || qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT))
|
||||
error(loc, "the aliases sharing the location", "location", "%d must be the same basic type and interpolation qualification", repeated);
|
||||
}
|
||||
|
||||
if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) {
|
||||
@@ -7365,7 +7387,7 @@ TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, T
|
||||
}
|
||||
} else if (function->getName() == "atomicCounter") {
|
||||
// change atomicCounter into a direct read of the variable
|
||||
if (arguments->getAsTyped()) {
|
||||
if (arguments && arguments->getAsTyped()) {
|
||||
result = arguments->getAsTyped();
|
||||
}
|
||||
}
|
||||
@@ -8351,6 +8373,11 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
|
||||
|
||||
int paramCount = 0; // keeps track of the constructor parameter number being checked
|
||||
|
||||
// We don't know "top down" whether type is a specialization constant,
|
||||
// but a const becomes a specialization constant if any of its children are.
|
||||
bool hasSpecConst = false;
|
||||
bool isConstConstructor = true;
|
||||
|
||||
// for each parameter to the constructor call, check to see if the right type is passed or convert them
|
||||
// to the right type if possible (and allowed).
|
||||
// for structure constructors, just check if the right type is passed, no conversion is allowed.
|
||||
@@ -8363,13 +8390,24 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
|
||||
else
|
||||
newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
|
||||
|
||||
if (newNode)
|
||||
if (newNode) {
|
||||
*p = newNode;
|
||||
else
|
||||
if (!newNode->getType().getQualifier().isConstant())
|
||||
isConstConstructor = false;
|
||||
if (newNode->getType().getQualifier().isSpecConstant())
|
||||
hasSpecConst = true;
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TIntermTyped *ret_node = intermediate.setAggregateOperator(aggrNode, op, type, loc);
|
||||
TIntermTyped* ret_node = intermediate.setAggregateOperator(aggrNode, op, type, loc);
|
||||
|
||||
const char *specConstantCompositeExt[] = { E_GL_EXT_spec_constant_composites };
|
||||
if (checkExtensionsRequested(loc, 1, specConstantCompositeExt, "spec constant aggregate constructor")) {
|
||||
if (isConstConstructor && hasSpecConst) {
|
||||
ret_node->getWritableType().getQualifier().makeSpecConstant();
|
||||
}
|
||||
}
|
||||
|
||||
TIntermAggregate *agg_node = ret_node->getAsAggregate();
|
||||
if (agg_node && (agg_node->isVector() || agg_node->isArray() || agg_node->isMatrix()))
|
||||
@@ -8503,7 +8541,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
||||
basicOp = EOpConstructFloat16;
|
||||
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
|
||||
// so construct a 32-bit type and convert
|
||||
if (!intermediate.getArithemeticFloat16Enabled()) {
|
||||
// and do not generate any conversion if it is an identity conversion, i.e. float16_t(<float16_t> var)
|
||||
if (!intermediate.getArithemeticFloat16Enabled() && (node->getBasicType() != EbtFloat16)) {
|
||||
TType tempType(EbtFloat, EvqTemporary, type.getVectorSize());
|
||||
newNode = node;
|
||||
if (tempType != newNode->getType()) {
|
||||
@@ -8526,7 +8565,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
||||
basicOp = EOpConstructInt8;
|
||||
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
|
||||
// so construct a 32-bit type and convert
|
||||
if (!intermediate.getArithemeticInt8Enabled()) {
|
||||
// and do not generate any conversion if it is an identity conversion, i.e. int8_t(<int8_t> var)
|
||||
if (!intermediate.getArithemeticInt8Enabled() && (node->getBasicType() != EbtInt8)) {
|
||||
TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
|
||||
newNode = node;
|
||||
if (tempType != newNode->getType()) {
|
||||
@@ -8549,7 +8589,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
||||
basicOp = EOpConstructUint8;
|
||||
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
|
||||
// so construct a 32-bit type and convert
|
||||
if (!intermediate.getArithemeticInt8Enabled()) {
|
||||
// and do not generate any conversion if it is an identity conversion, i.e. uint8_t(<uint8_t> var)
|
||||
if (!intermediate.getArithemeticInt8Enabled() && (node->getBasicType() != EbtUint8)) {
|
||||
TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
|
||||
newNode = node;
|
||||
if (tempType != newNode->getType()) {
|
||||
@@ -8572,7 +8613,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
||||
basicOp = EOpConstructInt16;
|
||||
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
|
||||
// so construct a 32-bit type and convert
|
||||
if (!intermediate.getArithemeticInt16Enabled()) {
|
||||
// and do not generate any conversion if it is an identity conversion, i.e. int16_t(<int16_t> var)
|
||||
if (!intermediate.getArithemeticInt16Enabled() && (node->getBasicType() != EbtInt16)) {
|
||||
TType tempType(EbtInt, EvqTemporary, type.getVectorSize());
|
||||
newNode = node;
|
||||
if (tempType != newNode->getType()) {
|
||||
@@ -8595,7 +8637,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
||||
basicOp = EOpConstructUint16;
|
||||
// 8/16-bit storage extensions don't support constructing composites of 8/16-bit types,
|
||||
// so construct a 32-bit type and convert
|
||||
if (!intermediate.getArithemeticInt16Enabled()) {
|
||||
// and do not generate any conversion if it is an identity conversion, i.e. uint16_t(<uint16_t> var)
|
||||
if (!intermediate.getArithemeticInt16Enabled() && (node->getBasicType() != EbtUint16)) {
|
||||
TType tempType(EbtUint, EvqTemporary, type.getVectorSize());
|
||||
newNode = node;
|
||||
if (tempType != newNode->getType()) {
|
||||
|
||||
@@ -35,14 +35,21 @@
|
||||
#include "../Include/Common.h"
|
||||
#include "../Include/PoolAlloc.h"
|
||||
|
||||
// Mostly here for target that do not support threads such as WASI.
|
||||
#ifdef DISABLE_THREAD_SUPPORT
|
||||
#define THREAD_LOCAL
|
||||
#else
|
||||
#define THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
namespace glslang {
|
||||
|
||||
namespace {
|
||||
thread_local TPoolAllocator* threadPoolAllocator = nullptr;
|
||||
THREAD_LOCAL TPoolAllocator* threadPoolAllocator = nullptr;
|
||||
|
||||
TPoolAllocator* GetDefaultThreadPoolAllocator()
|
||||
{
|
||||
thread_local TPoolAllocator defaultAllocator;
|
||||
THREAD_LOCAL TPoolAllocator defaultAllocator;
|
||||
return &defaultAllocator;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -1497,7 +1497,7 @@ int TScanContext::tokenizeIdentifier()
|
||||
case USAMPLER2DARRAY:
|
||||
afterType = true;
|
||||
if (keyword == SAMPLER2DARRAY || keyword == SAMPLER2DARRAYSHADOW) {
|
||||
if ((keyword == SAMPLER2DARRAY || !parseContext.isEsProfile()) &&
|
||||
if (!parseContext.isEsProfile() &&
|
||||
(parseContext.extensionTurnedOn(E_GL_EXT_texture_array) || parseContext.symbolTable.atBuiltInLevel())) {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,10 @@ namespace { // anonymous namespace for file-local functions and symbols
|
||||
int NumberOfClients = 0;
|
||||
|
||||
// global initialization lock
|
||||
#ifndef DISABLE_THREAD_SUPPORT
|
||||
std::mutex init_lock;
|
||||
#endif
|
||||
|
||||
|
||||
using namespace glslang;
|
||||
|
||||
@@ -420,7 +423,9 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
|
||||
TInfoSink infoSink;
|
||||
|
||||
// Make sure only one thread tries to do this at a time
|
||||
#ifndef DISABLE_THREAD_SUPPORT
|
||||
const std::lock_guard<std::mutex> lock(init_lock);
|
||||
#endif
|
||||
|
||||
// See if it's already been done for this version/profile combination
|
||||
int versionIndex = MapVersionToIndex(version);
|
||||
@@ -788,7 +793,7 @@ bool ProcessDeferred(
|
||||
// set version/profile to defaultVersion/defaultProfile regardless of the #version
|
||||
// directive in the source code
|
||||
bool forceDefaultVersionAndProfile,
|
||||
int overrideVersion, // overrides version specified by #verison or default version
|
||||
int overrideVersion, // overrides version specified by #version or default version
|
||||
bool forwardCompatible, // give errors for use of deprecated features
|
||||
EShMessages messages, // warnings/errors/AST; things to print out
|
||||
TIntermediate& intermediate, // returned tree, etc.
|
||||
@@ -1311,7 +1316,9 @@ bool CompileDeferred(
|
||||
//
|
||||
int ShInitialize()
|
||||
{
|
||||
#ifndef DISABLE_THREAD_SUPPORT
|
||||
const std::lock_guard<std::mutex> lock(init_lock);
|
||||
#endif
|
||||
++NumberOfClients;
|
||||
|
||||
if (PerProcessGPA == nullptr)
|
||||
@@ -1371,7 +1378,9 @@ void ShDestruct(ShHandle handle)
|
||||
//
|
||||
int ShFinalize()
|
||||
{
|
||||
#ifndef DISABLE_THREAD_SUPPORT
|
||||
const std::lock_guard<std::mutex> lock(init_lock);
|
||||
#endif
|
||||
--NumberOfClients;
|
||||
assert(NumberOfClients >= 0);
|
||||
if (NumberOfClients > 0)
|
||||
@@ -2033,7 +2042,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
|
||||
//
|
||||
// Return true if no errors.
|
||||
//
|
||||
bool TProgram::crossStageCheck(EShMessages) {
|
||||
bool TProgram::crossStageCheck(EShMessages messages) {
|
||||
|
||||
// make temporary intermediates to hold the linkage symbols for each linking interface
|
||||
// while we do the checks
|
||||
@@ -2084,7 +2093,7 @@ bool TProgram::crossStageCheck(EShMessages) {
|
||||
|
||||
// compare cross stage symbols for each stage boundary
|
||||
for (unsigned int i = 1; i < activeStages.size(); ++i) {
|
||||
activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]);
|
||||
activeStages[i - 1]->checkStageIO(messages, *infoSink, *activeStages[i]);
|
||||
error |= (activeStages[i - 1]->getNumErrors() != 0);
|
||||
}
|
||||
|
||||
@@ -2105,11 +2114,15 @@ const char* TProgram::getInfoDebugLog()
|
||||
// Reflection implementation.
|
||||
//
|
||||
|
||||
unsigned int TObjectReflection::layoutLocation() const { return type->getQualifier().layoutLocation; }
|
||||
|
||||
bool TProgram::buildReflection(int opts)
|
||||
{
|
||||
if (! linked || reflection != nullptr)
|
||||
return false;
|
||||
|
||||
SetThreadPoolAllocator(pool);
|
||||
|
||||
int firstStage = EShLangVertex, lastStage = EShLangFragment;
|
||||
|
||||
if (opts & EShReflectionIntermediateIO) {
|
||||
@@ -2165,6 +2178,9 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
|
||||
{
|
||||
if (! linked)
|
||||
return false;
|
||||
|
||||
SetThreadPoolAllocator(pool);
|
||||
|
||||
TIoMapper* ioMapper = nullptr;
|
||||
TIoMapper defaultIOMapper;
|
||||
if (pIoMapper == nullptr)
|
||||
|
||||
@@ -265,6 +265,7 @@ void TParseVersions::initializeExtensionBehavior()
|
||||
extensionBehavior[E_GL_EXT_expect_assume] = EBhDisable;
|
||||
|
||||
extensionBehavior[E_GL_EXT_control_flow_attributes2] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_spec_constant_composites] = EBhDisable;
|
||||
|
||||
extensionBehavior[E_GL_KHR_cooperative_matrix] = EBhDisable;
|
||||
|
||||
@@ -414,7 +415,6 @@ void TParseVersions::getPreamble(std::string& preamble)
|
||||
"#define GL_EXT_shader_texture_lod 1\n"
|
||||
"#define GL_EXT_shadow_samplers 1\n"
|
||||
"#define GL_EXT_fragment_shading_rate 1\n"
|
||||
"#define GL_EXT_texture_array 1\n"
|
||||
|
||||
// AEP
|
||||
"#define GL_ANDROID_extension_pack_es31a 1\n"
|
||||
@@ -520,6 +520,7 @@ void TParseVersions::getPreamble(std::string& preamble)
|
||||
"#define GL_EXT_fragment_shading_rate 1\n"
|
||||
"#define GL_EXT_shared_memory_block 1\n"
|
||||
"#define GL_EXT_shader_integer_mix 1\n"
|
||||
"#define GL_EXT_spec_constant_composites 1\n"
|
||||
|
||||
// GL_KHR_shader_subgroup
|
||||
"#define GL_KHR_shader_subgroup_basic 1\n"
|
||||
@@ -774,7 +775,7 @@ void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int
|
||||
for (int i = 0; i < numExtensions; ++i) {
|
||||
switch (getExtensionBehavior(extensions[i])) {
|
||||
case EBhWarn:
|
||||
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
|
||||
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
|
||||
[[fallthrough]];
|
||||
case EBhRequire:
|
||||
case EBhEnable:
|
||||
@@ -812,7 +813,8 @@ void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int
|
||||
error(loc, "deprecated, may be removed in future release", featureDesc, "");
|
||||
else if (! suppressWarnings())
|
||||
infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
|
||||
String(depVersion) + "; may be removed in future release").c_str(), loc);
|
||||
String(depVersion) + "; may be removed in future release").c_str(),
|
||||
loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -849,11 +851,14 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
|
||||
for (int i = 0; i < numExtensions; ++i) {
|
||||
TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
|
||||
if (behavior == EBhDisable && relaxedErrors()) {
|
||||
infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
|
||||
infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc,
|
||||
messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
|
||||
behavior = EBhWarn;
|
||||
}
|
||||
if (behavior == EBhWarn) {
|
||||
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
|
||||
infoSink.info.message(EPrefixWarning,
|
||||
("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(),
|
||||
loc, messages & EShMsgAbsolutePath, messages & EShMsgDisplayErrorColumn);
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +222,7 @@ const char* const E_GL_EXT_texture_array = "GL_EXT_texture_ar
|
||||
const char* const E_GL_EXT_maximal_reconvergence = "GL_EXT_maximal_reconvergence";
|
||||
const char* const E_GL_EXT_expect_assume = "GL_EXT_expect_assume";
|
||||
const char* const E_GL_EXT_control_flow_attributes2 = "GL_EXT_control_flow_attributes2";
|
||||
const char* const E_GL_EXT_spec_constant_composites = "GL_EXT_spec_constant_composites";
|
||||
|
||||
// Arrays of extensions for the above viewportEXTs duplications
|
||||
|
||||
|
||||
@@ -113,10 +113,32 @@ void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit
|
||||
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
|
||||
}
|
||||
|
||||
static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
|
||||
return // 1) same stage and same shader interface
|
||||
(stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
|
||||
// 2) accross stages and both are uniform or buffer
|
||||
(symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) ||
|
||||
(symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) ||
|
||||
// 3) in/out matched across stage boundary
|
||||
(stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
|
||||
(unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
|
||||
}
|
||||
|
||||
static bool isSameSymbol(TIntermSymbol* symbol1, EShLanguage stage1, TIntermSymbol* symbol2, EShLanguage stage2) {
|
||||
// If they are both blocks in the same shader interface,
|
||||
// match by the block-name, not the identifier name.
|
||||
if (symbol1->getType().getBasicType() == EbtBlock && symbol2->getType().getBasicType() == EbtBlock) {
|
||||
if (isSameInterface(symbol1, stage1, symbol2, stage2)) {
|
||||
return symbol1->getType().getTypeName() == symbol2->getType().getTypeName();
|
||||
}
|
||||
} else if (symbol1->getName() == symbol2->getName())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// do error checking on the shader boundary in / out vars
|
||||
//
|
||||
void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) {
|
||||
void TIntermediate::checkStageIO(EShMessages messages, TInfoSink& infoSink, TIntermediate& unit) {
|
||||
if (unit.treeRoot == nullptr || treeRoot == nullptr)
|
||||
return;
|
||||
|
||||
@@ -137,7 +159,32 @@ void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) {
|
||||
// do matching and error checking
|
||||
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
|
||||
|
||||
// TODO: final check; make sure that any statically used `in` have matching `out` written to
|
||||
// Check that all of our inputs have matching outputs from the previous stage.
|
||||
// Only do this for Vulkan, since GL_ARB_separate_shader_objects allows for
|
||||
// the in/out to not match
|
||||
if (spvVersion.vulkan > 0 || (messages & EshMsgCrossStageIO)) {
|
||||
for (auto& nextStageInterm : unitLinkerObjects) {
|
||||
auto* nextStageSymbol = nextStageInterm->getAsSymbolNode();
|
||||
bool found = false;
|
||||
for (auto& curStageInterm : linkerObjects) {
|
||||
if (isSameSymbol(curStageInterm->getAsSymbolNode(), getStage(), nextStageSymbol, unit.getStage())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
TString errmsg;
|
||||
errmsg.append("Input '");
|
||||
if (nextStageSymbol->getType().getBasicType() == EbtBlock)
|
||||
errmsg.append(nextStageSymbol->getType().getTypeName());
|
||||
else
|
||||
errmsg.append(nextStageSymbol->getName());
|
||||
errmsg.append("' in ").append(StageName(unit.getStage()));
|
||||
errmsg.append(" shader has no corresponding output in ").append(StageName(getStage())).append(" shader.");
|
||||
error(infoSink, errmsg.c_str(), unit.getStage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
|
||||
@@ -511,17 +558,6 @@ void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, c
|
||||
globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
|
||||
}
|
||||
|
||||
static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
|
||||
return // 1) same stage and same shader interface
|
||||
(stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
|
||||
// 2) accross stages and both are uniform or buffer
|
||||
(symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) ||
|
||||
(symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) ||
|
||||
// 3) in/out matched across stage boundary
|
||||
(stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
|
||||
(unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
|
||||
}
|
||||
|
||||
//
|
||||
// Global Unfiform block stores any default uniforms (i.e. uniforms without a block)
|
||||
// If two linked stages declare the same member, they are meant to be the same uniform
|
||||
@@ -707,24 +743,18 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
|
||||
// Error check and merge the linker objects (duplicates should not be created)
|
||||
std::size_t initialNumLinkerObjects = linkerObjects.size();
|
||||
for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) {
|
||||
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
|
||||
bool merge = true;
|
||||
|
||||
// Don't merge inputs backwards into previous stages
|
||||
if (getStage() != unitStage && unitSymbol->getQualifier().storage == EvqVaryingIn)
|
||||
merge = false;
|
||||
|
||||
for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
|
||||
TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
|
||||
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
|
||||
assert(symbol && unitSymbol);
|
||||
|
||||
bool isSameSymbol = false;
|
||||
// If they are both blocks in the same shader interface,
|
||||
// match by the block-name, not the identifier name.
|
||||
if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
|
||||
if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
|
||||
isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
|
||||
}
|
||||
}
|
||||
else if (symbol->getName() == unitSymbol->getName())
|
||||
isSameSymbol = true;
|
||||
|
||||
if (isSameSymbol) {
|
||||
if (isSameSymbol(symbol, getStage(), unitSymbol, unitStage)) {
|
||||
// filter out copy
|
||||
merge = false;
|
||||
|
||||
@@ -1689,7 +1719,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
||||
// First range:
|
||||
TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation);
|
||||
TRange componentRange(0, 3);
|
||||
TIoRange range(locationRange, componentRange, type.getBasicType(), 0);
|
||||
TIoRange range(locationRange, componentRange, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat, qualifier.sample, qualifier.patch);
|
||||
|
||||
// check for collisions
|
||||
collision = checkLocationRange(set, range, type, typeCollision);
|
||||
@@ -1699,7 +1729,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
||||
// Second range:
|
||||
TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1);
|
||||
TRange componentRange2(0, 1);
|
||||
TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0);
|
||||
TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0, qualifier.centroid, qualifier.smooth, qualifier.flat, qualifier.sample, qualifier.patch);
|
||||
|
||||
// check for collisions
|
||||
collision = checkLocationRange(set, range2, type, typeCollision);
|
||||
@@ -1725,7 +1755,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
||||
TBasicType basicTy = type.getBasicType();
|
||||
if (basicTy == EbtSampler && type.getSampler().isAttachmentEXT())
|
||||
basicTy = type.getSampler().type;
|
||||
TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0);
|
||||
TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0, qualifier.centroid, qualifier.smooth, qualifier.flat, qualifier.sample, qualifier.patch);
|
||||
|
||||
// check for collisions, except for vertex inputs on desktop targeting OpenGL
|
||||
if (! (!isEsProfile() && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0)
|
||||
@@ -1737,6 +1767,24 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
||||
return collision;
|
||||
}
|
||||
|
||||
// Check that two types can be stored in different components in the same location.
|
||||
// They must be the same type, except signed/unsigned integers are considered compatible.
|
||||
static bool checkCompatibleTypes(TBasicType t1, TBasicType t2) {
|
||||
if (t1 != t2) {
|
||||
if ((t1 == EbtInt8 && t2 == EbtUint8) ||
|
||||
(t2 == EbtInt8 && t1 == EbtUint8) ||
|
||||
(t1 == EbtInt16 && t2 == EbtUint16) ||
|
||||
(t2 == EbtInt16 && t1 == EbtUint16)||
|
||||
(t1 == EbtInt && t2 == EbtUint) ||
|
||||
(t2 == EbtInt && t1 == EbtUint)||
|
||||
(t1 == EbtInt64 && t2 == EbtUint64) ||
|
||||
(t2 == EbtInt64 && t1 == EbtUint64)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return t1 == t2;
|
||||
}
|
||||
|
||||
// Compare a new (the passed in) 'range' against the existing set, and see
|
||||
// if there are any collisions.
|
||||
//
|
||||
@@ -1748,7 +1796,13 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
|
||||
if (range.overlap(usedIo[set][r])) {
|
||||
// there is a collision; pick one
|
||||
return std::max(range.location.start, usedIo[set][r].location.start);
|
||||
} else if (range.location.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) {
|
||||
} else if (range.location.overlap(usedIo[set][r].location) &&
|
||||
(!checkCompatibleTypes(type.getBasicType(), usedIo[set][r].basicType) ||
|
||||
type.getQualifier().centroid != usedIo[set][r].centroid ||
|
||||
type.getQualifier().smooth != usedIo[set][r].smooth ||
|
||||
type.getQualifier().flat != usedIo[set][r].flat ||
|
||||
type.getQualifier().sample != usedIo[set][r].sample ||
|
||||
type.getQualifier().patch != usedIo[set][r].patch)) {
|
||||
// aliased-type mismatch
|
||||
typeCollision = true;
|
||||
return std::max(range.location.start, usedIo[set][r].location.start);
|
||||
@@ -2217,9 +2271,9 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
|
||||
}
|
||||
|
||||
// To aid the basic HLSL rule about crossing vec4 boundaries.
|
||||
bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
|
||||
bool TIntermediate::improperStraddle(const TType& type, int size, int offset, bool vectorLike)
|
||||
{
|
||||
if (! type.isVector() || type.isArray())
|
||||
if (! vectorLike || type.isArray())
|
||||
return false;
|
||||
|
||||
return size <= 16 ? offset / 16 != (offset + size - 1) / 16
|
||||
|
||||
@@ -99,7 +99,8 @@ private:
|
||||
// A "call" is a pair: <caller, callee>.
|
||||
// There can be duplicates. General assumption is the list is small.
|
||||
struct TCall {
|
||||
TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
|
||||
TCall(const TString& pCaller, const TString& pCallee)
|
||||
: caller(pCaller), callee(pCallee), visited(false), currentPath(false), errorGiven(false) { }
|
||||
TString caller;
|
||||
TString callee;
|
||||
bool visited;
|
||||
@@ -123,8 +124,10 @@ struct TRange {
|
||||
// within the same location range, component range, and index value. Locations don't alias unless
|
||||
// all other dimensions of their range overlap.
|
||||
struct TIoRange {
|
||||
TIoRange(TRange location, TRange component, TBasicType basicType, int index)
|
||||
: location(location), component(component), basicType(basicType), index(index) { }
|
||||
TIoRange(TRange location, TRange component, TBasicType basicType, int index, bool centroid, bool smooth, bool flat, bool sample, bool patch)
|
||||
: location(location), component(component), basicType(basicType), index(index), centroid(centroid), smooth(smooth), flat(flat), sample(sample), patch(patch)
|
||||
{
|
||||
}
|
||||
bool overlap(const TIoRange& rhs) const
|
||||
{
|
||||
return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
|
||||
@@ -133,6 +136,11 @@ struct TIoRange {
|
||||
TRange component;
|
||||
TBasicType basicType;
|
||||
int index;
|
||||
bool centroid;
|
||||
bool smooth;
|
||||
bool flat;
|
||||
bool sample;
|
||||
bool patch;
|
||||
};
|
||||
|
||||
// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
|
||||
@@ -724,6 +732,11 @@ public:
|
||||
usePhysicalStorageBuffer = true;
|
||||
}
|
||||
bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
|
||||
void setReplicatedComposites()
|
||||
{
|
||||
useReplicatedComposites = true;
|
||||
}
|
||||
bool usingReplicatedComposites() const { return useReplicatedComposites; }
|
||||
void setUseVariablePointers()
|
||||
{
|
||||
useVariablePointers = true;
|
||||
@@ -1037,7 +1050,7 @@ public:
|
||||
|
||||
void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
|
||||
void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
|
||||
void checkStageIO(TInfoSink&, TIntermediate&);
|
||||
void checkStageIO(EShMessages, TInfoSink&, TIntermediate&);
|
||||
|
||||
bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
|
||||
TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
|
||||
@@ -1057,7 +1070,7 @@ public:
|
||||
static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
|
||||
static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
|
||||
static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
|
||||
static bool improperStraddle(const TType& type, int size, int offset);
|
||||
static bool improperStraddle(const TType& type, int size, int offset, bool vectorLike);
|
||||
static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
|
||||
static int getOffset(const TType& type, int index);
|
||||
static int getBlockSize(const TType& blockType);
|
||||
@@ -1237,6 +1250,7 @@ protected:
|
||||
bool subgroupUniformControlFlow;
|
||||
bool maximallyReconverges;
|
||||
bool usePhysicalStorageBuffer;
|
||||
bool useReplicatedComposites { false };
|
||||
|
||||
TSpirvRequirement* spirvRequirement;
|
||||
TSpirvExecutionMode* spirvExecutionMode;
|
||||
@@ -1251,7 +1265,7 @@ protected:
|
||||
|
||||
std::unordered_set<int> usedConstantId; // specialization constant ids used
|
||||
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
|
||||
std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
|
||||
std::vector<TIoRange> usedIo[5]; // sets of used locations, one for each of in, out, uniform, and buffers
|
||||
std::vector<TRange> usedIoRT[4]; // sets of used location, one for rayPayload/rayPayloadIN,
|
||||
// one for callableData/callableDataIn, one for hitObjectAttributeNV and
|
||||
// one for shaderrecordhitobjectNV
|
||||
|
||||
@@ -374,7 +374,7 @@ namespace {
|
||||
int op_div(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a / b; }
|
||||
int op_mod(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a % b; }
|
||||
int op_pos(int a) { return a; }
|
||||
int op_neg(int a) { return -a; }
|
||||
int op_neg(int a) { return a == INT_MIN ? INT_MIN : -a; }
|
||||
int op_cmpl(int a) { return ~a; }
|
||||
int op_not(int a) { return !a; }
|
||||
|
||||
|
||||
@@ -220,7 +220,9 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
|
||||
}
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
exponent = exponent * 10 + (ch - '0');
|
||||
if (exponent < 500) {
|
||||
exponent = exponent * 10 + (ch - '0');
|
||||
}
|
||||
saveName(ch);
|
||||
ch = getChar();
|
||||
}
|
||||
|
||||
@@ -271,6 +271,8 @@ enum EShMessages : unsigned {
|
||||
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
|
||||
EShMsgEnhanced = (1 << 15), // enhanced message readability
|
||||
EShMsgAbsolutePath = (1 << 16), // Output Absolute path for messages
|
||||
EShMsgDisplayErrorColumn = (1 << 17), // Display error message column aswell as line
|
||||
EshMsgCrossStageIO = (1 << 30), // Always validate cross-stage IO
|
||||
LAST_ELEMENT_MARKER(EShMsgCount),
|
||||
};
|
||||
|
||||
@@ -747,6 +749,8 @@ public:
|
||||
GLSLANG_EXPORT void dump() const;
|
||||
static TObjectReflection badReflection() { return TObjectReflection(); }
|
||||
|
||||
GLSLANG_EXPORT unsigned int layoutLocation() const;
|
||||
|
||||
std::string name;
|
||||
int offset;
|
||||
int glDefineType;
|
||||
|
||||
Reference in New Issue
Block a user