[glslang][EXT] Support extension ARB_bindless_texture.
Add missing callgraph clean for bindless status flag. Add test cases. Add support to check special extensions not be available for Vulkan when using GLSL.
This commit is contained in:
parent
2b2523fb95
commit
16526fd9d2
19 changed files with 608 additions and 35 deletions
|
|
@ -751,6 +751,11 @@ bool TIntermediate::buildConvertOp(TBasicType dst, TBasicType src, TOperator& ne
|
|||
case EbtInt64: newOp = EOpConvInt64ToUint; break;
|
||||
case EbtUint64: newOp = EOpConvUint64ToUint; break;
|
||||
#endif
|
||||
// For bindless texture type conversion, add a dummy convert op, just
|
||||
// to generate a new TIntermTyped
|
||||
// uvec2(any sampler type)
|
||||
// uvec2(any image type)
|
||||
case EbtSampler: newOp = EOpConvIntToUint; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
|
|||
//
|
||||
switch (node->getBasicType()) {
|
||||
case EbtSampler:
|
||||
message = "can't modify a sampler";
|
||||
if (extensionTurnedOn(E_GL_ARB_bindless_texture) == false)
|
||||
message = "can't modify a sampler";
|
||||
break;
|
||||
case EbtVoid:
|
||||
message = "can't modify void";
|
||||
|
|
|
|||
|
|
@ -1389,7 +1389,8 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
|
|||
#endif
|
||||
const TType& argType = arg->getAsTyped()->getType();
|
||||
const TQualifier& argQualifier = argType.getQualifier();
|
||||
if (argQualifier.isMemory() && (argType.containsOpaque() || argType.isReference())) {
|
||||
bool containsBindlessSampler = intermediate.getBindlessMode() && argType.containsSampler();
|
||||
if (argQualifier.isMemory() && !containsBindlessSampler && (argType.containsOpaque() || argType.isReference())) {
|
||||
const char* message = "argument cannot drop memory qualifier when passed to formal parameter";
|
||||
#ifndef GLSLANG_WEB
|
||||
if (argQualifier.volatil && ! formalQualifier.volatil)
|
||||
|
|
@ -1675,9 +1676,13 @@ TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermType
|
|||
error(loc, "type does not match, or is not convertible to, the function's return type", "return", "");
|
||||
branch = intermediate.addBranch(EOpReturn, value, loc);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
if (value->getType().isTexture() || value->getType().isImage()) {
|
||||
if (!extensionTurnedOn(E_GL_ARB_bindless_texture))
|
||||
error(loc, "sampler or image can be used as return type only when the extension GL_ARB_bindless_texture enabled", "return", "");
|
||||
}
|
||||
branch = intermediate.addBranch(EOpReturn, value, loc);
|
||||
|
||||
}
|
||||
branch->updatePrecision(currentFunctionType->getQualifier().precision);
|
||||
return branch;
|
||||
}
|
||||
|
|
@ -1928,6 +1933,9 @@ TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TInt
|
|||
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference())
|
||||
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference");
|
||||
|
||||
if (op == EOpAssign && left->getBasicType() == EbtSampler && right->getBasicType() == EbtSampler)
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "sampler assignment for bindless texture");
|
||||
|
||||
return intermediate.addAssign(op, left, right, loc);
|
||||
}
|
||||
|
||||
|
|
@ -2811,6 +2819,14 @@ TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPu
|
|||
profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor");
|
||||
}
|
||||
|
||||
// Reuse EOpConstructTextureSampler for bindless image constructor
|
||||
// uvec2 imgHandle;
|
||||
// imageLoad(image1D(imgHandle), 0);
|
||||
if (type.isImage() && extensionTurnedOn(E_GL_ARB_bindless_texture))
|
||||
{
|
||||
intermediate.setBindlessImageMode(currentCaller, AstRefTypeFunc);
|
||||
}
|
||||
|
||||
TOperator op = intermediate.mapTypeToConstructorOp(type);
|
||||
|
||||
if (op == EOpNull) {
|
||||
|
|
@ -3544,8 +3560,13 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
return true;
|
||||
}
|
||||
if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
|
||||
error(loc, "cannot convert a sampler", constructorString.c_str(), "");
|
||||
return true;
|
||||
if (op == EOpConstructUVec2 && extensionTurnedOn(E_GL_ARB_bindless_texture)) {
|
||||
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeFunc);
|
||||
}
|
||||
else {
|
||||
error(loc, "cannot convert a sampler", constructorString.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (op != EOpConstructStruct && typed->isAtomic()) {
|
||||
error(loc, "cannot convert an atomic_uint", constructorString.c_str(), "");
|
||||
|
|
@ -3565,6 +3586,26 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
|
|||
{
|
||||
TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change
|
||||
const char* token = constructorName.c_str();
|
||||
// verify the constructor for bindless texture, the input must be ivec2 or uvec2
|
||||
if (function.getParamCount() == 1) {
|
||||
TType* pType = function[0].type;
|
||||
TBasicType basicType = pType->getBasicType();
|
||||
bool isIntegerVec2 = ((basicType == EbtUint || basicType == EbtInt) && pType->getVectorSize() == 2);
|
||||
bool bindlessMode = extensionTurnedOn(E_GL_ARB_bindless_texture);
|
||||
if (isIntegerVec2 && bindlessMode) {
|
||||
if (pType->getSampler().isImage())
|
||||
intermediate.setBindlessImageMode(currentCaller, AstRefTypeFunc);
|
||||
else
|
||||
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeFunc);
|
||||
return false;
|
||||
} else {
|
||||
if (!bindlessMode)
|
||||
error(loc, "sampler-constructor requires the extension GL_ARB_bindless_texture enabled", token, "");
|
||||
else
|
||||
error(loc, "sampler-constructor requires the input to be ivec2 or uvec2", token, "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// exactly two arguments needed
|
||||
if (function.getParamCount() != 2) {
|
||||
|
|
@ -3660,13 +3701,32 @@ void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const
|
|||
if (type.getQualifier().storage == EvqUniform)
|
||||
return;
|
||||
|
||||
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler))
|
||||
error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
|
||||
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler)) {
|
||||
// For bindless texture, sampler can be declared as an struct member
|
||||
if (extensionTurnedOn(E_GL_ARB_bindless_texture)) {
|
||||
if (type.getSampler().isImage())
|
||||
intermediate.setBindlessImageMode(currentCaller, AstRefTypeVar);
|
||||
else
|
||||
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeVar);
|
||||
}
|
||||
else {
|
||||
error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str());
|
||||
}
|
||||
}
|
||||
else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) {
|
||||
// non-uniform sampler
|
||||
// not yet: okay if it has an initializer
|
||||
// if (! initializer)
|
||||
error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
|
||||
// For bindless texture, sampler can be declared as an input/output/block member
|
||||
if (extensionTurnedOn(E_GL_ARB_bindless_texture)) {
|
||||
if (type.getSampler().isImage())
|
||||
intermediate.setBindlessImageMode(currentCaller, AstRefTypeVar);
|
||||
else
|
||||
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeVar);
|
||||
}
|
||||
else {
|
||||
// non-uniform sampler
|
||||
// not yet: okay if it has an initializer
|
||||
// if (! initializer)
|
||||
error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3732,7 +3792,7 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
|
|||
//
|
||||
// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
|
||||
//
|
||||
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck)
|
||||
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck, const TPublicType* publicType)
|
||||
{
|
||||
bool nonuniformOkay = false;
|
||||
|
||||
|
|
@ -3768,6 +3828,11 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
|
|||
{
|
||||
requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "default std430 layout for uniform");
|
||||
}
|
||||
|
||||
if (publicType != nullptr && publicType->isImage() &&
|
||||
(qualifier.layoutFormat > ElfExtSizeGuard && qualifier.layoutFormat < ElfCount))
|
||||
qualifier.layoutFormat = mapLegacyLayoutFormat(qualifier.layoutFormat, publicType->sampler.getBasicType());
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -4172,7 +4237,7 @@ void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType ba
|
|||
|
||||
void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type)
|
||||
{
|
||||
if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque())
|
||||
if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque() && !intermediate.getBindlessMode())
|
||||
error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), "");
|
||||
if (!parsingBuiltins && type.contains16BitFloat())
|
||||
requireFloat16Arithmetic(loc, type.getBasicTypeString().c_str(), "float16 types can only be in uniform block or buffer storage");
|
||||
|
|
@ -5105,7 +5170,7 @@ void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, c
|
|||
|
||||
void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op)
|
||||
{
|
||||
if (containsFieldWithBasicType(type, EbtSampler))
|
||||
if (containsFieldWithBasicType(type, EbtSampler) && !extensionTurnedOn(E_GL_ARB_bindless_texture))
|
||||
error(loc, "can't use with samplers or structs containing samplers", op, "");
|
||||
}
|
||||
|
||||
|
|
@ -5480,6 +5545,28 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
|
|||
intermediate.setUsePhysicalStorageBuffer();
|
||||
return;
|
||||
}
|
||||
if (id == "bindless_sampler") {
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bindless_sampler");
|
||||
publicType.qualifier.layoutBindlessSampler = true;
|
||||
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeLayout);
|
||||
return;
|
||||
}
|
||||
if (id == "bindless_image") {
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bindless_image");
|
||||
publicType.qualifier.layoutBindlessImage = true;
|
||||
intermediate.setBindlessImageMode(currentCaller, AstRefTypeLayout);
|
||||
return;
|
||||
}
|
||||
if (id == "bound_sampler") {
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bound_sampler");
|
||||
publicType.qualifier.layoutBindlessSampler = false;
|
||||
return;
|
||||
}
|
||||
if (id == "bound_image") {
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bound_image");
|
||||
publicType.qualifier.layoutBindlessImage = false;
|
||||
return;
|
||||
}
|
||||
if (language == EShLangGeometry || language == EShLangTessEvaluation || language == EShLangMesh) {
|
||||
if (id == TQualifier::getGeometryString(ElgTriangles)) {
|
||||
publicType.shaderQualifiers.geometry = ElgTriangles;
|
||||
|
|
@ -6137,6 +6224,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
|
|||
dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
|
||||
if (src.layoutShaderRecord)
|
||||
dst.layoutShaderRecord = true;
|
||||
if (src.layoutBindlessSampler)
|
||||
dst.layoutBindlessSampler = true;
|
||||
if (src.layoutBindlessImage)
|
||||
dst.layoutBindlessImage = true;
|
||||
if (src.pervertexNV)
|
||||
dst.pervertexNV = true;
|
||||
if (src.pervertexEXT)
|
||||
|
|
@ -6418,7 +6509,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
|||
|
||||
// Image format
|
||||
if (qualifier.hasFormat()) {
|
||||
if (! type.isImage())
|
||||
if (! type.isImage() && !intermediate.getBindlessImageMode())
|
||||
error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.getFormat()), "");
|
||||
else {
|
||||
if (type.getSampler().type == EbtFloat && qualifier.getFormat() > ElfFloatGuard)
|
||||
|
|
@ -6437,7 +6528,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (type.isImage() && ! qualifier.isWriteOnly()) {
|
||||
} else if (type.isImage() && ! qualifier.isWriteOnly() && !intermediate.getBindlessImageMode()) {
|
||||
const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier";
|
||||
requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation);
|
||||
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
|
||||
|
|
@ -7745,12 +7836,14 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode*
|
|||
// Combined texture-sampler constructors are completely semantic checked
|
||||
// in constructorTextureSamplerError()
|
||||
if (op == EOpConstructTextureSampler) {
|
||||
if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) {
|
||||
// Transfer depth into the texture (SPIR-V image) type, as a hint
|
||||
// for tools to know this texture/image is a depth image.
|
||||
aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true;
|
||||
if (aggrNode != nullptr) {
|
||||
if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) {
|
||||
// Transfer depth into the texture (SPIR-V image) type, as a hint
|
||||
// for tools to know this texture/image is a depth image.
|
||||
aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true;
|
||||
}
|
||||
return intermediate.setAggregateOperator(aggrNode, op, type, loc);
|
||||
}
|
||||
return intermediate.setAggregateOperator(aggrNode, op, type, loc);
|
||||
}
|
||||
|
||||
TTypeList::const_iterator memberTypes;
|
||||
|
|
@ -7885,6 +7978,16 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUvec2, true, node,
|
||||
type);
|
||||
return newNode;
|
||||
} else if (node->getType().getBasicType() == EbtSampler) {
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "sampler conversion to uvec2");
|
||||
// force the basic type of the constructor param to uvec2, otherwise spv builder will
|
||||
// report some errors
|
||||
TIntermTyped* newSrcNode = intermediate.createConversion(EbtUint, node);
|
||||
newSrcNode->getAsTyped()->getWritableType().setVectorSize(2);
|
||||
|
||||
TIntermTyped* newNode =
|
||||
intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructUVec2, false, newSrcNode, type);
|
||||
return newNode;
|
||||
}
|
||||
case EOpConstructUVec3:
|
||||
case EOpConstructUVec4:
|
||||
|
|
@ -7898,7 +8001,15 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||
case EOpConstructBool:
|
||||
basicOp = EOpConstructBool;
|
||||
break;
|
||||
|
||||
case EOpConstructTextureSampler:
|
||||
if ((node->getType().getBasicType() == EbtUint || node->getType().getBasicType() == EbtInt) &&
|
||||
node->getType().getVectorSize() == 2) {
|
||||
requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "ivec2/uvec2 convert to texture handle");
|
||||
// No matter ivec2 or uvec2, Set EOpPackUint2x32 just to generate an opBitcast op code
|
||||
TIntermTyped* newNode =
|
||||
intermediate.addBuiltInFunctionCall(node->getLoc(), EOpPackUint2x32, true, node, type);
|
||||
return newNode;
|
||||
}
|
||||
#ifndef GLSLANG_WEB
|
||||
|
||||
case EOpConstructDVec2:
|
||||
|
|
@ -8245,6 +8356,30 @@ void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier&
|
|||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Update qualifier layoutBindlessImage & layoutBindlessSampler on block member
|
||||
//
|
||||
void TParseContext::updateBindlessQualifier(TType& memberType)
|
||||
{
|
||||
if (memberType.containsSampler()) {
|
||||
if (memberType.isStruct()) {
|
||||
TTypeList* typeList = memberType.getWritableStruct();
|
||||
for (unsigned int member = 0; member < typeList->size(); ++member) {
|
||||
TType* subMemberType = (*typeList)[member].type;
|
||||
updateBindlessQualifier(*subMemberType);
|
||||
}
|
||||
}
|
||||
else if (memberType.getSampler().isImage()) {
|
||||
intermediate.setBindlessImageMode(currentCaller, AstRefTypeLayout);
|
||||
memberType.getQualifier().layoutBindlessImage = true;
|
||||
}
|
||||
else {
|
||||
intermediate.setBindlessTextureMode(currentCaller, AstRefTypeLayout);
|
||||
memberType.getQualifier().layoutBindlessSampler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Do everything needed to add an interface block.
|
||||
//
|
||||
|
|
@ -8297,8 +8432,13 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
|
|||
}
|
||||
}
|
||||
|
||||
if (memberType.containsOpaque())
|
||||
error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
|
||||
// For bindless texture, sampler can be declared as uniform/storage block member,
|
||||
if (memberType.containsOpaque()) {
|
||||
if (memberType.containsSampler() && extensionTurnedOn(E_GL_ARB_bindless_texture))
|
||||
updateBindlessQualifier(memberType);
|
||||
else
|
||||
error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
|
||||
}
|
||||
|
||||
if (memberType.containsCoopMat())
|
||||
error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), "");
|
||||
|
|
@ -9472,4 +9612,38 @@ const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TT
|
|||
return originStruct;
|
||||
}
|
||||
|
||||
TLayoutFormat TParseContext::mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType)
|
||||
{
|
||||
TLayoutFormat layoutFormat = ElfNone;
|
||||
if (imageType == EbtFloat) {
|
||||
switch (legacyLayoutFormat) {
|
||||
case ElfSize1x16: layoutFormat = ElfR16f; break;
|
||||
case ElfSize1x32: layoutFormat = ElfR32f; break;
|
||||
case ElfSize2x32: layoutFormat = ElfRg32f; break;
|
||||
case ElfSize4x32: layoutFormat = ElfRgba32f; break;
|
||||
default: break;
|
||||
}
|
||||
} else if (imageType == EbtUint) {
|
||||
switch (legacyLayoutFormat) {
|
||||
case ElfSize1x8: layoutFormat = ElfR8ui; break;
|
||||
case ElfSize1x16: layoutFormat = ElfR16ui; break;
|
||||
case ElfSize1x32: layoutFormat = ElfR32ui; break;
|
||||
case ElfSize2x32: layoutFormat = ElfRg32ui; break;
|
||||
case ElfSize4x32: layoutFormat = ElfRgba32ui; break;
|
||||
default: break;
|
||||
}
|
||||
} else if (imageType == EbtInt) {
|
||||
switch (legacyLayoutFormat) {
|
||||
case ElfSize1x8: layoutFormat = ElfR8i; break;
|
||||
case ElfSize1x16: layoutFormat = ElfR16i; break;
|
||||
case ElfSize1x32: layoutFormat = ElfR32i; break;
|
||||
case ElfSize2x32: layoutFormat = ElfRg32i; break;
|
||||
case ElfSize4x32: layoutFormat = ElfRgba32i; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return layoutFormat;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ public:
|
|||
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
|
||||
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
||||
void memberQualifierCheck(glslang::TPublicType&);
|
||||
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
|
||||
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false, const TPublicType* publicType = nullptr);
|
||||
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
|
||||
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
||||
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
|
||||
|
|
@ -456,9 +456,11 @@ public:
|
|||
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
||||
void invariantCheck(const TSourceLoc&, const TQualifier&);
|
||||
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
||||
void updateBindlessQualifier(TType& memberType);
|
||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
||||
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
|
||||
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
|
||||
TLayoutFormat mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType);
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
TAttributeType attributeFromName(const TString& name) const;
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ public:
|
|||
|
||||
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
|
||||
virtual const TParameter& operator[](int i) const { return parameters[i]; }
|
||||
const TQualifier& getQualifier() const { return returnType.getQualifier(); }
|
||||
|
||||
#ifndef GLSLANG_WEB
|
||||
virtual void setSpirvInstruction(const TSpirvInstruction& inst)
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ void TParseVersions::initializeExtensionBehavior()
|
|||
extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable;
|
||||
extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable;
|
||||
extensionBehavior[E_GL_ARB_draw_instanced] = EBhDisable;
|
||||
extensionBehavior[E_GL_ARB_bindless_texture] = EBhDisable;
|
||||
extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable;
|
||||
|
||||
|
||||
|
|
@ -370,6 +371,9 @@ void TParseVersions::initializeExtensionBehavior()
|
|||
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_shader_atomic_float] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_shader_atomic_float2] = EBhDisable;
|
||||
|
||||
// Record extensions not for spv.
|
||||
spvUnsupportedExt.push_back(E_GL_ARB_bindless_texture);
|
||||
}
|
||||
|
||||
#endif // GLSLANG_WEB
|
||||
|
|
@ -437,7 +441,6 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||
|
||||
} else { // !isEsProfile()
|
||||
preamble =
|
||||
"#define GL_FRAGMENT_PRECISION_HIGH 1\n"
|
||||
"#define GL_ARB_texture_rectangle 1\n"
|
||||
"#define GL_ARB_shading_language_420pack 1\n"
|
||||
"#define GL_ARB_texture_gather 1\n"
|
||||
|
|
@ -477,6 +480,7 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||
"#define GL_ARB_vertex_attrib_64bit 1\n"
|
||||
"#define GL_ARB_draw_instanced 1\n"
|
||||
"#define GL_ARB_fragment_coord_conventions 1\n"
|
||||
"#define GL_ARB_bindless_texture 1\n"
|
||||
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
|
||||
"#define GL_EXT_shader_image_load_formatted 1\n"
|
||||
"#define GL_EXT_post_depth_coverage 1\n"
|
||||
|
|
@ -576,6 +580,10 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||
preamble += "#define GL_EXT_null_initializer 1\n";
|
||||
preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n";
|
||||
}
|
||||
if (version >= 130) {
|
||||
preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n";
|
||||
}
|
||||
|
||||
#endif // GLSLANG_WEB
|
||||
}
|
||||
|
||||
|
|
@ -1099,6 +1107,13 @@ void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const
|
|||
minSpvVersion = iter->second;
|
||||
requireSpv(loc, extension, minSpvVersion);
|
||||
}
|
||||
|
||||
if (spvVersion.spv != 0){
|
||||
for (auto ext : spvUnsupportedExt){
|
||||
if (strcmp(extension, ext.c_str()) == 0)
|
||||
error(loc, "not allowed when using generating SPIR-V codes", extension, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call for any operation needing full GLSL integer data-type support.
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_
|
|||
const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit";
|
||||
const char* const E_GL_ARB_draw_instanced = "GL_ARB_draw_instanced";
|
||||
const char* const E_GL_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions";
|
||||
const char* const E_GL_ARB_bindless_texture = "GL_ARB_bindless_texture";
|
||||
|
||||
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
|
||||
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
|
||||
|
|
|
|||
|
|
@ -1218,7 +1218,7 @@ fully_specified_type
|
|||
parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier);
|
||||
}
|
||||
| type_qualifier type_specifier {
|
||||
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
|
||||
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier, false, &$2);
|
||||
parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2);
|
||||
|
||||
if ($2.arraySizes) {
|
||||
|
|
|
|||
|
|
@ -1218,7 +1218,7 @@ fully_specified_type
|
|||
parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier);
|
||||
}
|
||||
| type_qualifier type_specifier {
|
||||
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
|
||||
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier, false, &$2);
|
||||
parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2);
|
||||
|
||||
if ($2.arraySizes) {
|
||||
|
|
|
|||
|
|
@ -6551,7 +6551,7 @@ yyreduce:
|
|||
case 136: /* fully_specified_type: type_qualifier type_specifier */
|
||||
#line 1220 "MachineIndependent/glslang.y"
|
||||
{
|
||||
parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
|
||||
parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, false, &(yyvsp[0].interm.type));
|
||||
parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type));
|
||||
|
||||
if ((yyvsp[0].interm.type).arraySizes) {
|
||||
|
|
|
|||
|
|
@ -1517,7 +1517,10 @@ void TIntermediate::checkCallGraphBodies(TInfoSink& infoSink, bool keepUncalled)
|
|||
if (! keepUncalled) {
|
||||
for (int f = 0; f < (int)functionSequence.size(); ++f) {
|
||||
if (! reachable[f])
|
||||
{
|
||||
resetTopLevelUncalledStatus(functionSequence[f]->getAsAggregate()->getName());
|
||||
functionSequence[f] = nullptr;
|
||||
}
|
||||
}
|
||||
functionSequence.erase(std::remove(functionSequence.begin(), functionSequence.end(), nullptr), functionSequence.end());
|
||||
}
|
||||
|
|
@ -2012,6 +2015,15 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
|
|||
case EbtInt16:
|
||||
case EbtUint16: size = 2; return 2;
|
||||
case EbtReference: size = 8; return 8;
|
||||
case EbtSampler:
|
||||
{
|
||||
if (type.isBindlessImage() || type.isBindlessTexture()) {
|
||||
size = 8; return 8;
|
||||
}
|
||||
else {
|
||||
size = 4; return 4;
|
||||
}
|
||||
}
|
||||
default: size = 4; return 4;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,6 +225,16 @@ enum ComputeDerivativeMode {
|
|||
LayoutDerivativeGroupLinear, // derivative_group_linearNV
|
||||
};
|
||||
|
||||
//
|
||||
// Status type on AST level. Some uncalled status or functions would be reset in call graph.
|
||||
// Currently we will keep status set by explicitly declared layout or variable decl.
|
||||
//
|
||||
enum AstRefType {
|
||||
AstRefTypeVar, // Status set by variable decl
|
||||
AstRefTypeFunc, // Status set by function decl
|
||||
AstRefTypeLayout, // Status set by layout decl
|
||||
};
|
||||
|
||||
class TIdMaps {
|
||||
public:
|
||||
TMap<TString, long long>& operator[](long long i) { return maps[i]; }
|
||||
|
|
@ -744,6 +754,65 @@ public:
|
|||
useVariablePointers = true;
|
||||
processes.addProcess("use-variable-pointers");
|
||||
}
|
||||
// Set the global flag for bindless texture
|
||||
void setBindlessTextureMode(const TString& currentCaller, AstRefType type)
|
||||
{
|
||||
// When type is not func, currentCaller should be "" (empty string)
|
||||
bindlessTextureModeCaller[currentCaller] = type;
|
||||
}
|
||||
|
||||
// Get the global flag for bindless texture
|
||||
bool getBindlessTextureMode() const
|
||||
{
|
||||
return (bindlessTextureModeCaller.size() > 0);
|
||||
}
|
||||
|
||||
// Set the global flag for bindless image
|
||||
void setBindlessImageMode(const TString& currentCaller, AstRefType type)
|
||||
{
|
||||
// When type is not func, currentCaller should be "" (empty string)
|
||||
bindlessImageModeCaller[currentCaller] = type;
|
||||
}
|
||||
|
||||
// Get the global flag for bindless image
|
||||
bool getBindlessImageMode() const
|
||||
{
|
||||
return (bindlessImageModeCaller.size() > 0);
|
||||
}
|
||||
|
||||
// Get the global flag for bindless texture
|
||||
bool resetTopLevelUncalledStatus(const TString& deadCaller)
|
||||
{
|
||||
// For reflection collection purpose, currently uniform layout setting and some
|
||||
// flags introduced by variables (IO, global, etc,.) won't be reset here.
|
||||
// Remove each global status (AST top level) introduced by uncalled functions.
|
||||
// If a status is set by several functions, keep those which in call graph.
|
||||
bool result = false;
|
||||
|
||||
// For two types of bindless mode flag, we would only reset which is set by an uncalled function.
|
||||
// If one status flag's key in caller vec is empty, it should be come from a non-function setting.
|
||||
if (!bindlessTextureModeCaller.empty()) {
|
||||
auto caller = bindlessTextureModeCaller.find(deadCaller);
|
||||
if (caller != bindlessTextureModeCaller.end() && bindlessTextureModeCaller[deadCaller] == AstRefTypeFunc) {
|
||||
bindlessTextureModeCaller.erase(caller);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
if (!bindlessImageModeCaller.empty()) {
|
||||
auto caller = bindlessImageModeCaller.find(deadCaller);
|
||||
if (caller != bindlessImageModeCaller.end() && bindlessImageModeCaller[deadCaller] == AstRefTypeFunc) {
|
||||
bindlessImageModeCaller.erase(caller);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool getBindlessMode() const
|
||||
{
|
||||
return getBindlessTextureMode() || getBindlessImageMode();
|
||||
}
|
||||
|
||||
bool usingVariablePointers() const { return useVariablePointers; }
|
||||
|
||||
#ifdef ENABLE_HLSL
|
||||
|
|
@ -1188,7 +1257,8 @@ protected:
|
|||
|
||||
TSpirvRequirement* spirvRequirement;
|
||||
TSpirvExecutionMode* spirvExecutionMode;
|
||||
|
||||
std::map<TString, AstRefType> bindlessTextureModeCaller;
|
||||
std::map<TString, AstRefType> bindlessImageModeCaller;
|
||||
std::unordered_map<std::string, int> uniformLocationOverrides;
|
||||
int uniformLocationBase;
|
||||
TNumericFeatures numericFeatures;
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ public:
|
|||
protected:
|
||||
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is
|
||||
TMap<TString, unsigned int> extensionMinSpv; // for each extension string, store minimum spirv required
|
||||
TVector<TString> spvUnsupportedExt; // for extensions reserved for spv usage.
|
||||
EShMessages messages; // errors/warnings/rule-sets
|
||||
int numErrors; // number of compile-time errors encountered
|
||||
TInputScanner* currentScanner;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue