Updated glslang.

This commit is contained in:
Бранимир Караџић 2024-05-27 21:09:28 -07:00
parent 887dbc8ffe
commit 3e2188c27d
15 changed files with 166 additions and 56 deletions

View File

@ -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:
@ -3382,6 +3372,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;
@ -5377,17 +5369,34 @@ 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
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
@ -5395,7 +5404,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;
@ -5480,8 +5489,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);
@ -8056,6 +8067,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);
@ -9814,6 +9826,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);
@ -9824,7 +9846,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);
}
}
}
@ -9842,7 +9867,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);
}
}
};
@ -10184,6 +10212,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());

View File

@ -3409,10 +3409,13 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
}
// If the result is a vector, make it from the gathered constituents.
if (constituents.size() > 0)
if (constituents.size() > 0) {
result = createCompositeConstruct(resultTypeId, constituents);
return setPrecision(result, precision);
return setPrecision(result, precision);
} else {
// Precision was set when generating this component.
return result;
}
}
// Comments in header

View File

@ -855,6 +855,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;

View File

@ -483,6 +483,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 +543,7 @@ void Builder::postProcess(bool compileOnly)
postProcessCFG();
postProcessFeatures();
postProcessSamplers();
}
}; // end spv namespace

View File

@ -1064,6 +1064,7 @@ const char* CapabilityString(int info)
case CapabilityTextureSampleWeightedQCOM: return "TextureSampleWeightedQCOM";
case CapabilityTextureBoxFilterQCOM: return "TextureBoxFilterQCOM";
case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM";
case CapabilityTextureBlockMatch2QCOM: return "TextureBlockMatch2QCOM";
default: return "Bad";
}

View File

@ -107,6 +107,14 @@ public:
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);
@ -238,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; }

View File

@ -35,7 +35,7 @@
#define GLSLANG_BUILD_INFO
#define GLSLANG_VERSION_MAJOR 14
#define GLSLANG_VERSION_MINOR 1
#define GLSLANG_VERSION_MINOR 2
#define GLSLANG_VERSION_PATCH 0
#define GLSLANG_VERSION_FLAVOR ""

View File

@ -962,14 +962,11 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
return addConstructor(loc, base, type);
}
}
if (base->getVectorSize() == 1) {
// Use EOpIndexDirect (below) with vec1.x so that it remains l-value (Test/hlsl.swizzle.vec1.comp)
if (base->getVectorSize() == 1 && selectors.size() > 1) {
TType scalarType(base->getBasicType(), EvqTemporary, 1);
if (selectors.size() == 1)
return addConstructor(loc, base, scalarType);
else {
TType vectorType(base->getBasicType(), EvqTemporary, selectors.size());
return addConstructor(loc, addConstructor(loc, base, scalarType), vectorType);
}
TType vectorType(base->getBasicType(), EvqTemporary, selectors.size());
return addConstructor(loc, addConstructor(loc, base, scalarType), vectorType);
}
if (base->getType().getQualifier().isFrontEndConstant())

View File

@ -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";

View File

@ -9209,8 +9209,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);
@ -9229,6 +9227,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);

View File

@ -492,7 +492,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 +598,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 +2704,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;
@ -6564,10 +6568,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()) {

View File

@ -788,7 +788,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.
@ -2105,6 +2105,8 @@ const char* TProgram::getInfoDebugLog()
// Reflection implementation.
//
unsigned int TObjectReflection::layoutLocation() const { return type->getQualifier().layoutLocation; }
bool TProgram::buildReflection(int opts)
{
if (! linked || reflection != nullptr)

View File

@ -1689,7 +1689,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);
// check for collisions
collision = checkLocationRange(set, range, type, typeCollision);
@ -1699,7 +1699,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);
// check for collisions
collision = checkLocationRange(set, range2, type, typeCollision);
@ -1725,7 +1725,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);
// check for collisions, except for vertex inputs on desktop targeting OpenGL
if (! (!isEsProfile() && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0)
@ -1748,7 +1748,11 @@ 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) &&
(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)) {
// aliased-type mismatch
typeCollision = true;
return std::max(range.location.start, usedIo[set][r].location.start);
@ -2217,9 +2221,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

View File

@ -123,8 +123,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)
: location(location), component(component), basicType(basicType), index(index), centroid(centroid), smooth(smooth), flat(flat)
{
}
bool overlap(const TIoRange& rhs) const
{
return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
@ -133,6 +135,9 @@ struct TIoRange {
TRange component;
TBasicType basicType;
int index;
bool centroid;
bool smooth;
bool flat;
};
// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
@ -1057,7 +1062,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);
@ -1251,7 +1256,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

View File

@ -745,6 +745,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;