Updated glslang.

This commit is contained in:
Бранимир Караџић
2026-01-30 16:25:32 -08:00
committed by Branimir Karadžić
parent 85d0b7ad3f
commit 21e71a6141
36 changed files with 7998 additions and 5899 deletions

View File

@@ -44,5 +44,6 @@ static const char* const E_SPV_EXT_mesh_shader = "SPV_EXT_mesh_shader";
static const char* const E_SPV_EXT_float8 = "SPV_EXT_float8"; static const char* const E_SPV_EXT_float8 = "SPV_EXT_float8";
static const char* const E_SPV_EXT_shader_64bit_indexing = "SPV_EXT_shader_64bit_indexing"; static const char* const E_SPV_EXT_shader_64bit_indexing = "SPV_EXT_shader_64bit_indexing";
static const char* const E_SPV_EXT_shader_invocation_reorder = "SPV_EXT_shader_invocation_reorder"; static const char* const E_SPV_EXT_shader_invocation_reorder = "SPV_EXT_shader_invocation_reorder";
static const char* const E_SPV_EXT_long_vector = "SPV_EXT_long_vector";
#endif // #ifndef GLSLextEXT_H #endif // #ifndef GLSLextEXT_H

View File

@@ -66,5 +66,6 @@ static const char* const E_SPV_KHR_relaxed_extended_instruction = "SPV_KHR_relax
static const char* const E_SPV_KHR_integer_dot_product = "SPV_KHR_integer_dot_product"; static const char* const E_SPV_KHR_integer_dot_product = "SPV_KHR_integer_dot_product";
static const char* const E_SPV_NV_cooperative_vector = "SPV_NV_cooperative_vector"; static const char* const E_SPV_NV_cooperative_vector = "SPV_NV_cooperative_vector";
static const char* const E_SPV_KHR_bfloat16 = "SPV_KHR_bfloat16"; static const char* const E_SPV_KHR_bfloat16 = "SPV_KHR_bfloat16";
static const char* const E_SPV_EXT_descriptor_heap = "SPV_EXT_descriptor_heap";
static const char* const E_SPV_KHR_untyped_pointers = "SPV_KHR_untyped_pointers";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H

View File

@@ -101,4 +101,8 @@ const char* const E_SPV_NV_cluster_acceleration_structure = "SPV_NV_cluster_acce
//SPV_NV_linear_swept_spheres //SPV_NV_linear_swept_spheres
const char* const E_SPV_NV_linear_swept_spheres = "SPV_NV_linear_swept_spheres"; const char* const E_SPV_NV_linear_swept_spheres = "SPV_NV_linear_swept_spheres";
//SPV_NV_push_constant_bank
const char* const E_SPV_NV_push_constant_bank = "SPV_NV_push_constant_bank";
#endif // #ifndef GLSLextNV_H #endif // #ifndef GLSLextNV_H

View File

@@ -174,6 +174,8 @@ protected:
spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
glslang::TLayoutPacking, const glslang::TQualifier&); glslang::TLayoutPacking, const glslang::TQualifier&);
spv::LinkageType convertGlslangLinkageToSpv(glslang::TLinkType glslangLinkType); spv::LinkageType convertGlslangLinkageToSpv(glslang::TLinkType glslangLinkType);
spv::Id decorateDescHeapType(const glslang::TType& type, spv::Id& memberBaseOffset, spv::Id& alignment,
int& maxPlainDataAlignment);
void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking,
const glslang::TQualifier&, spv::Id, const std::vector<spv::Id>& spvMembers); const glslang::TQualifier&, spv::Id, const std::vector<spv::Id>& spvMembers);
spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim, bool allowZero = false, bool boolType = false); spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim, bool allowZero = false, bool boolType = false);
@@ -243,6 +245,7 @@ protected:
std::pair<spv::Id, spv::Id> getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&); std::pair<spv::Id, spv::Id> getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&);
spv::Id translateForcedType(spv::Id object); spv::Id translateForcedType(spv::Id object);
spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents); spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents);
void recordDescHeapAccessChainInfo(glslang::TIntermBinary* node);
glslang::SpvOptions& options; glslang::SpvOptions& options;
spv::Function* shaderEntry; spv::Function* shaderEntry;
@@ -288,6 +291,15 @@ protected:
// Used later for generating OpTraceKHR/OpExecuteCallableKHR/OpHitObjectRecordHit*/OpHitObjectGetShaderBindingTableData // Used later for generating OpTraceKHR/OpExecuteCallableKHR/OpHitObjectRecordHit*/OpHitObjectGetShaderBindingTableData
std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[4]; std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[4];
std::unordered_map<spv::Id, std::vector<spv::Decoration> > idToQCOMDecorations; std::unordered_map<spv::Id, std::vector<spv::Decoration> > idToQCOMDecorations;
// For nested or inner resource heap structure's alignment and offset records.
typedef struct heapMetaData {
spv::Id typeStride;
spv::Id maxRsrcTypeAlignment;
int maxPlainDataAlignment;
} HeapMetaData;
std::unordered_map<const glslang::TType*, HeapMetaData> heapStructureTypeMetaData;
std::unordered_map<spv::Id, spv::Id> heapStructureTypeSize;
std::vector<spv::Id> heapStructureMemberOffsets;
}; };
// //
@@ -391,6 +403,8 @@ spv::Decoration TranslateBlockDecoration(const glslang::TStorageQualifier storag
case glslang::EvqCallableDataIn: return spv::Decoration::Block; case glslang::EvqCallableDataIn: return spv::Decoration::Block;
case glslang::EvqHitObjectAttrNV: return spv::Decoration::Block; case glslang::EvqHitObjectAttrNV: return spv::Decoration::Block;
case glslang::EvqHitObjectAttrEXT: return spv::Decoration::Block; case glslang::EvqHitObjectAttrEXT: return spv::Decoration::Block;
case glslang::EvqResourceHeap: return spv::Decoration::Block;
case glslang::EvqSamplerHeap: return spv::Decoration::Block;
default: default:
assert(0); assert(0);
break; break;
@@ -467,6 +481,8 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
case glslang::EvqCallableDataIn: case glslang::EvqCallableDataIn:
case glslang::EvqHitObjectAttrNV: case glslang::EvqHitObjectAttrNV:
case glslang::EvqHitObjectAttrEXT: case glslang::EvqHitObjectAttrEXT:
case glslang::EvqResourceHeap:
case glslang::EvqSamplerHeap:
return spv::Decoration::Max; return spv::Decoration::Max;
default: default:
assert(0); assert(0);
@@ -1160,6 +1176,38 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
builder.addExtension(spv::E_SPV_QCOM_tile_shading); builder.addExtension(spv::E_SPV_QCOM_tile_shading);
return spv::BuiltIn::TileApronSizeQCOM; return spv::BuiltIn::TileApronSizeQCOM;
// SPV_EXT_descriptor_heap
case glslang::EbvSamplerHeapEXT:
builder.addExtension(spv::E_SPV_EXT_descriptor_heap);
builder.addExtension(spv::E_SPV_KHR_untyped_pointers);
builder.addCapability(spv::Capability::DescriptorHeapEXT);
builder.addCapability(spv::Capability::UntypedPointersKHR);
// Add SamplerHeapEXT Symbol for spv level.
if (builtInVariableIds.find(uint32_t(spv::BuiltIn::SamplerHeapEXT)) == builtInVariableIds.end()) {
spv::Id samplerHeapEXT =
builder.createUntypedVariable(spv::NoPrecision, spv::StorageClass::UniformConstant, "sampler_heap");
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4)
entryPoint->addIdOperand(samplerHeapEXT);
builder.addDecoration(samplerHeapEXT, spv::Decoration::BuiltIn, (int)spv::BuiltIn::SamplerHeapEXT);
builtInVariableIds.insert({uint32_t(spv::BuiltIn::SamplerHeapEXT), samplerHeapEXT});
}
return spv::BuiltIn::SamplerHeapEXT;
case glslang::EbvResourceHeapEXT:
builder.addExtension(spv::E_SPV_EXT_descriptor_heap);
builder.addExtension(spv::E_SPV_KHR_untyped_pointers);
builder.addCapability(spv::Capability::DescriptorHeapEXT);
builder.addCapability(spv::Capability::UntypedPointersKHR);
// Add ResourceHeapEXT Symbol for spv level.
if (builtInVariableIds.find(uint32_t(spv::BuiltIn::ResourceHeapEXT)) == builtInVariableIds.end()) {
spv::Id resourceHeapEXT =
builder.createUntypedVariable(spv::NoPrecision, spv::StorageClass::UniformConstant, "resource_heap");
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4)
entryPoint->addIdOperand(resourceHeapEXT);
builder.addDecoration(resourceHeapEXT, spv::Decoration::BuiltIn, (int)spv::BuiltIn::ResourceHeapEXT);
builtInVariableIds.insert({uint32_t(spv::BuiltIn::ResourceHeapEXT), resourceHeapEXT});
}
return spv::BuiltIn::ResourceHeapEXT;
default: default:
return spv::BuiltIn::Max; return spv::BuiltIn::Max;
} }
@@ -1352,8 +1400,13 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
type.getQualifier().storage == glslang::EvqUniform) { type.getQualifier().storage == glslang::EvqUniform) {
if (type.isAtomic()) if (type.isAtomic())
return spv::StorageClass::AtomicCounter; return spv::StorageClass::AtomicCounter;
if (type.containsOpaque() && !glslangIntermediate->getBindlessMode()) if (type.containsOpaque() && !glslangIntermediate->getBindlessMode()) {
return spv::StorageClass::UniformConstant; if (type.getQualifier().storage == glslang::EvqResourceHeap ||
type.getQualifier().storage == glslang::EvqSamplerHeap)
return spv::StorageClass::Uniform;
else
return spv::StorageClass::UniformConstant;
}
} }
if (type.getQualifier().isUniformOrBuffer() && if (type.getQualifier().isUniformOrBuffer() &&
@@ -1369,7 +1422,8 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
if (type.getQualifier().isUniformOrBuffer()) { if (type.getQualifier().isUniformOrBuffer()) {
if (type.getQualifier().isPushConstant()) if (type.getQualifier().isPushConstant())
return spv::StorageClass::PushConstant; return spv::StorageClass::PushConstant;
if (type.getBasicType() == glslang::EbtBlock) if (type.getBasicType() == glslang::EbtBlock ||
type.getQualifier().layoutDescriptorHeap)
return spv::StorageClass::Uniform; return spv::StorageClass::Uniform;
return spv::StorageClass::UniformConstant; return spv::StorageClass::UniformConstant;
} }
@@ -2207,7 +2261,7 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
// C) R-Values from type translation, see above call to translateForcedType() // C) R-Values from type translation, see above call to translateForcedType()
glslang::TQualifier qualifier = symbol->getQualifier(); glslang::TQualifier qualifier = symbol->getQualifier();
if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() || if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() ||
!builder.isPointerType(builder.getTypeId(id))) (!builder.isPointerType(builder.getTypeId(id)) && !builder.isUntypedPointer(id)))
builder.setAccessChainRValue(id); builder.setAccessChainRValue(id);
else else
builder.setAccessChainLValue(id); builder.setAccessChainLValue(id);
@@ -2248,6 +2302,28 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
#endif #endif
} }
// Create new untyped access chain instruction to descriptor heap, based on EXT_descriptor_heap extension.
void TGlslangToSpvTraverser::recordDescHeapAccessChainInfo(glslang::TIntermBinary* node)
{
// EXT_descriptor_heap
glslang::TType* nodeTy = node->getWritableType().clone();
// For buffer/structure type, using its basic structure type:
// data ptr will be first loaded into a BufferPointerType before finally gets chained accessed.
if (node->getLeft()->getQualifier().isUniformOrBuffer())
nodeTy = node->getLeft()->getType().clone();
if (nodeTy->isArray())
nodeTy->clearArraySizes();
spv::BuiltIn bt = spv::BuiltIn::Max;
unsigned int firstArrIndex = 0;
auto rsrcOffsetIdx = builder.isStructureHeapMember(builder.getTypeId(builder.getAccessChain().base),
builder.getAccessChain().indexChain, 0, &bt, &firstArrIndex);
spv::Id remappedBuiltin = bt == spv::BuiltIn::Max ? 0 : builtInVariableIds[unsigned(bt)];
nodeTy->getQualifier().layoutDescriptorInnerBlock = false;
// Extra dimension is not needed when translate storage and type. Real loading type is based on orignal AST nodes.
builder.setAccessChainDescHeapInfo(TranslateStorageClass(*nodeTy), convertGlslangToSpvType(*nodeTy),
nodeTy->getQualifier().layoutDescriptorStride, rsrcOffsetIdx, remappedBuiltin, firstArrIndex);
}
bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
{ {
builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename());
@@ -2402,6 +2478,14 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// We have deferred generation of associated capabilities until now. // We have deferred generation of associated capabilities until now.
if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray()) if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray())
declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex); declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex);
// EXT_descriptor_heap
// Record untyped descriptor heap access info.
if (node->getLeft()->getType().isBuiltIn() &&
(node->getLeft()->getQualifier().builtIn == glslang::EbvResourceHeapEXT ||
node->getLeft()->getQualifier().builtIn == glslang::EbvSamplerHeapEXT)) {
recordDescHeapAccessChainInfo(node);
}
} }
} }
return false; return false;
@@ -2459,6 +2543,14 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
builder.accessChainPush(index, coherent_flags, builder.accessChainPush(index, coherent_flags,
node->getLeft()->getType().getBufferReferenceAlignment()); node->getLeft()->getType().getBufferReferenceAlignment());
} }
// EXT_descriptor_heap
// Record untyped descriptor heap access info.
if (node->getLeft()->getType().isBuiltIn() &&
(node->getLeft()->getQualifier().builtIn == glslang::EbvResourceHeapEXT ||
node->getLeft()->getQualifier().builtIn == glslang::EbvSamplerHeapEXT)) {
recordDescHeapAccessChainInfo(node);
}
} }
return false; return false;
case glslang::EOpVectorSwizzle: case glslang::EOpVectorSwizzle:
@@ -2698,9 +2790,13 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
length = builder.createCooperativeMatrixLengthNV(typeId); length = builder.createCooperativeMatrixLengthNV(typeId);
} }
} else if (node->getOperand()->getType().isCoopVecNV()) { } else if (node->getOperand()->getType().isCoopVecOrLongVector()) {
spv::Id typeId = convertGlslangToSpvType(node->getOperand()->getType()); spv::Id typeId = convertGlslangToSpvType(node->getOperand()->getType());
length = builder.getCooperativeVectorNumComponents(typeId); if (builder.isCooperativeVectorType(typeId)) {
length = builder.getCooperativeVectorNumComponents(typeId);
} else {
length = builder.makeIntConstant(builder.getNumTypeConstituents(typeId));
}
} else { } else {
glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
block->traverse(this); block->traverse(this);
@@ -3351,7 +3447,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.addCapability(spv::Capability::CooperativeMatrixConversionsNV); builder.addCapability(spv::Capability::CooperativeMatrixConversionsNV);
builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); builder.addExtension(spv::E_SPV_NV_cooperative_matrix2);
constructed = builder.createCooperativeMatrixConversion(resultType(), arguments[0]); constructed = builder.createCooperativeMatrixConversion(resultType(), arguments[0]);
} else if (node->getOp() == glslang::EOpConstructCooperativeVectorNV && } else if (node->getType().isCoopVecOrLongVector() &&
arguments.size() == 1 && arguments.size() == 1 &&
builder.getTypeId(arguments[0]) == resultType()) { builder.getTypeId(arguments[0]) == resultType()) {
constructed = arguments[0]; constructed = arguments[0];
@@ -3361,7 +3457,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
node->getType().isArray() || node->getType().isArray() ||
// Handle constructing coopvec from one component here, to avoid the component // Handle constructing coopvec from one component here, to avoid the component
// getting smeared // getting smeared
(node->getOp() == glslang::EOpConstructCooperativeVectorNV && arguments.size() == 1 && builder.isScalar(arguments[0]))) { (node->getType().hasSpecConstantVectorComponents() && arguments.size() == 1 && builder.isScalar(arguments[0]))) {
std::vector<spv::Id> constituents; std::vector<spv::Id> constituents;
for (int c = 0; c < (int)arguments.size(); ++c) for (int c = 0; c < (int)arguments.size(); ++c)
constituents.push_back(arguments[c]); constituents.push_back(arguments[c]);
@@ -3423,7 +3519,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
{ {
// for scalar dot product, use multiply // for scalar dot product, use multiply
glslang::TIntermSequence& glslangOperands = node->getSequence(); glslang::TIntermSequence& glslangOperands = node->getSequence();
if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1) if (!glslangOperands[0]->getAsTyped()->getType().isLongVector() &&
glslangOperands[0]->getAsTyped()->getVectorSize() == 1)
binOp = glslang::EOpMul; binOp = glslang::EOpMul;
break; break;
} }
@@ -5430,6 +5527,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
case glslang::EbtStruct: case glslang::EbtStruct:
case glslang::EbtBlock: case glslang::EbtBlock:
{ {
// If it's an inner declared heap buffer or uniform block, using OpTypeBufferEXT
// to convert it to an untyped type.
if (type.getQualifier().isUniformOrBuffer() &&
type.getQualifier().layoutDescriptorHeap && type.getQualifier().layoutDescriptorInnerBlock) {
spvType = builder.makeUntypedPointer(TranslateStorageClass(type), true);
break;
}
// If we've seen this struct type, return it // If we've seen this struct type, return it
const glslang::TTypeList* glslangMembers = type.getStruct(); const glslang::TTypeList* glslangMembers = type.getStruct();
@@ -5647,6 +5752,24 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spvType = builder.makeCooperativeVectorTypeNV(spvType, components); spvType = builder.makeCooperativeVectorTypeNV(spvType, components);
} }
if (type.isLongVector()) {
builder.addCapability(spv::Capability::LongVectorEXT);
builder.addExtension(spv::E_SPV_EXT_long_vector);
if (type.getBasicType() == glslang::EbtFloat16)
builder.addCapability(spv::Capability::Float16);
if (type.getBasicType() == glslang::EbtUint8 || type.getBasicType() == glslang::EbtInt8) {
builder.addCapability(spv::Capability::Int8);
}
if (type.hasSpecConstantVectorComponents()) {
spv::Id components = makeArraySizeId(*type.getTypeParameters()->arraySizes, 0);
spvType = builder.makeCooperativeVectorTypeNV(spvType, components);
} else {
spvType = builder.makeVectorType(spvType, type.getTypeParameters()->arraySizes->getDimSize(0));
}
}
if (type.isArray()) { if (type.isArray()) {
int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride
@@ -5680,9 +5803,15 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix); stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
} }
if (type.getQualifier().storage == glslang::EvqResourceHeap ||
type.getQualifier().storage == glslang::EvqSamplerHeap) {
auto structSize = heapStructureTypeSize[spvType];
spvType = builder.makeRuntimeArray(spvType);
builder.addDecorationId(spvType, spv::Decoration::ArrayStrideIdEXT, structSize);
}
// Do the outer dimension, which might not be known for a runtime-sized array. // Do the outer dimension, which might not be known for a runtime-sized array.
// (Unsized arrays that survive through linking will be runtime-sized arrays) // (Unsized arrays that survive through linking will be runtime-sized arrays)
if (type.isSizedArray()) else if (type.isSizedArray())
spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
else { else {
// If we see an runtime array in a buffer_reference, it is not a descriptor // If we see an runtime array in a buffer_reference, it is not a descriptor
@@ -5888,11 +6017,41 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
} }
} }
// For those whose storage is ResourceHeap or SamplerHeap, we needs to recursively add
// member decorator for inner structure member declaration with spec Constant.
spv::Id heapStructSize = 0;
if (qualifier.storage == glslang::EvqResourceHeap || qualifier.storage == glslang::EvqSamplerHeap ||
qualifier.layoutDescriptorInnerBlock) {
auto memberBaseOffset = builder.makeUintConstant(0);
int maxPlainDataTypeAlignment = 0;
spv::Id descTypeMaxAlignment = 0;
auto structLastMemberSize =
decorateDescHeapType(type, memberBaseOffset, descTypeMaxAlignment, maxPlainDataTypeAlignment);
auto structureUnaligned = builder.createSpecConstantOp(
spv::Op::OpIAdd, builder.makeUintType(32), {memberBaseOffset, structLastMemberSize}, {});
auto structurePadding = builder.createSpecConstantOp(
spv::Op::OpUMod, builder.makeUintType(32), {descTypeMaxAlignment, structureUnaligned}, {});
heapStructSize = builder.createSpecConstantOp(
spv::Op::OpIAdd, builder.makeUintType(32), {structureUnaligned, structurePadding}, {});
HeapMetaData meta = {heapStructSize, descTypeMaxAlignment, maxPlainDataTypeAlignment};
heapStructureTypeMetaData[&type] = meta;
}
// Make the SPIR-V type // Make the SPIR-V type
spv::Id spvType = builder.makeStructType(spvMembers, memberDebugInfo, type.getTypeName().c_str(), false); spv::Id spvType = builder.makeStructType(spvMembers, memberDebugInfo, type.getTypeName().c_str(), false);
if (! HasNonLayoutQualifiers(type, qualifier)) if (! HasNonLayoutQualifiers(type, qualifier))
structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType;
// Keep decoration data order after spv structure type.
if (qualifier.storage == glslang::EvqResourceHeap || qualifier.storage == glslang::EvqSamplerHeap ||
qualifier.layoutDescriptorInnerBlock) {
heapStructureTypeSize[spvType] = heapStructSize;
for (unsigned int i = 0; i < spvMembers.size(); i++) {
builder.addMemberDecorationIdEXT(spvType, i, spv::Decoration::OffsetIdEXT, {heapStructureMemberOffsets[i]});
}
heapStructureMemberOffsets.clear();
}
// Decorate it // Decorate it
decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType, spvMembers); decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType, spvMembers);
@@ -5904,6 +6063,126 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
return spvType; return spvType;
} }
// Return not aligned size of current type.
spv::Id TGlslangToSpvTraverser::decorateDescHeapType(
const glslang::TType& type,
spv::Id &memberBaseOffset,
spv::Id &descTypeAlignment,
int& maxPlainDataAlignment)
{
glslang::TLayoutPacking explicitLayout = glslang::ElpScalar;
auto selectMaxRsrcTyAlign = [&](spv::Id typeSize) {
if (descTypeAlignment != 0) {
auto compareInst = builder.createSpecConstantOp(spv::Op::OpUGreaterThan, builder.makeBoolType(),
{descTypeAlignment, typeSize}, {});
auto selectMaxAlign = builder.createSpecConstantOp(spv::Op::OpSelect, builder.makeUintType(32),
{compareInst, descTypeAlignment, typeSize}, {});
descTypeAlignment = selectMaxAlign;
} else
descTypeAlignment = typeSize;
};
// Get or calculate following info ordered.
// Member Type | Type size | Type alignment within current structure | Type offset.
// PS. resource blocks declared within a structure will not be processed as a normal declaration before,
// and its' size is dependent on constantSizeOfEXT op, so we won't trigger it as a normal structure here.
bool isArray = type.isArray();
if (type.isStruct() && !type.getQualifier().layoutDescriptorInnerBlock) {
// 1. Structure type is processed from inner to higher level.
// If member is a sturcture, it will be processed earlier,
// parent structure could just load early results.
if (heapStructureTypeMetaData.find(&type) != heapStructureTypeMetaData.end()) {
auto metadata = heapStructureTypeMetaData[&type];
selectMaxRsrcTyAlign(metadata.maxRsrcTypeAlignment);
maxPlainDataAlignment = std::max(metadata.maxPlainDataAlignment, maxPlainDataAlignment);
return metadata.typeStride;
}
// For other nested structure, it would be declared before its parent,
// so it should be directly returned a result in above check.
const glslang::TTypeList* structTyList = type.getStruct();
spv::Id previousTypeSize = 0;
auto currentOffset = memberBaseOffset;
for (int i = 0; i < (int)structTyList->size(); i++) {
// Get offset :
// OffsetsBase = default ? 0 : OffsetInLayout;
// OffsetsBase = OffsetsBase + previousOffset + previousPadding.
const glslang::TType& memberTy = *(*structTyList)[i].type;
spv::Id typeSize = decorateDescHeapType(memberTy, currentOffset, descTypeAlignment, maxPlainDataAlignment);
// 2. Get each member's unaligned offset, padding and aligned offset.
// As this function is processed recursively, from bottom to upper, so in here,
// non-structure member's alignment should have been known.
if (i != 0) {
auto offsetNotAligned = builder.createSpecConstantOp(spv::Op::OpIAdd, builder.makeUintType(32),
{currentOffset, previousTypeSize}, {});
auto offsetPadding = builder.createSpecConstantOp(spv::Op::OpUMod, builder.makeUintType(32),
{typeSize, offsetNotAligned}, {});
currentOffset = builder.createSpecConstantOp(spv::Op::OpIAdd, builder.makeUintType(32),
{offsetNotAligned, offsetPadding}, {});
}
heapStructureMemberOffsets.push_back(currentOffset);
previousTypeSize = typeSize;
}
// 3. Structure level, get max resource type's alignment, max plain data alignment and final
// structure inner alignment.
// Get compared result for alignment within whole structure.
spv::Id maxPlainAlignmentSize = builder.makeIntConstant(maxPlainDataAlignment);
// Select biggest alignemnt size between desc types and plain old types.
selectMaxRsrcTyAlign(maxPlainAlignmentSize);
memberBaseOffset = currentOffset;
// Now, return generates size of the MaterialData type
// Get structure level unaligned offset, padding and final offset outside.
return previousTypeSize;
}
// Following are normal types, structures/blocks have been processed in above part.
// Normal type or member type within a structure.
bool useConstantSizeOf =
((type.getQualifier().isUniformOrBuffer() && type.getQualifier().layoutDescriptorHeap) ||
type.isImage() || type.isTexture() || type.isTensorARM() || type.getBasicType() == glslang::EbtAccStruct);
// Get single type and layout info.
int elemCurrentOffset, elemAlignedSize;
int memberSize, dummyStride, typeAlignment;
spv::Id spvType = 0;
if (isArray) {
glslang::TType elemTy(type, 0);
elemTy.clearArraySizes();
if (!useConstantSizeOf) {
typeAlignment = glslangIntermediate->getMemberAlignment(
elemTy, memberSize, dummyStride, glslang::ElpScalar, elemTy.getQualifier().layoutMatrix == glslang::ElmRowMajor);
updateMemberOffset(elemTy, elemTy, elemCurrentOffset, elemAlignedSize, explicitLayout, elemTy.getQualifier().layoutMatrix);
elemAlignedSize *= type.getCumulativeArraySize();
}
spvType = convertGlslangToSpvType(elemTy);
} else {
if (!useConstantSizeOf) {
typeAlignment = glslangIntermediate->getMemberAlignment(
type, memberSize, dummyStride, glslang::ElpScalar, type.getQualifier().layoutMatrix == glslang::ElmRowMajor);
updateMemberOffset(type, type, elemCurrentOffset, elemAlignedSize, explicitLayout, type.getQualifier().layoutMatrix);
}
spvType = convertGlslangToSpvType(type);
}
// Get alignment and type size.
spv::Id typeSize = 0;
if (useConstantSizeOf) {
typeSize = builder.createConstantSizeOfEXT(spvType);
// For resource type, needs to check current's largest alignment to select.
// New parent structure's alignment is equal to:
// maxInnerAlignment = currentAlignment > maxInnerAlignment
// ? currentAlignment
// : maxInnerAlignment;
selectMaxRsrcTyAlign(typeSize);
} else {
typeSize = builder.makeIntConstant(elemAlignedSize);
maxPlainDataAlignment = std::max(typeAlignment, maxPlainDataAlignment);
}
return typeSize;
}
void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
const glslang::TTypeList* glslangMembers, const glslang::TTypeList* glslangMembers,
glslang::TLayoutPacking explicitLayout, glslang::TLayoutPacking explicitLayout,
@@ -5972,7 +6251,12 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
if (glslangMember.getQualifier().hasXfbOffset()) if (glslangMember.getQualifier().hasXfbOffset())
builder.addMemberDecoration(spvType, member, spv::Decoration::Offset, builder.addMemberDecoration(spvType, member, spv::Decoration::Offset,
glslangMember.getQualifier().layoutXfbOffset); glslangMember.getQualifier().layoutXfbOffset);
else if (explicitLayout != glslang::ElpNone) { else if (glslangMember.getQualifier().hasMemberOffset()) {
builder.addExtension(spv::E_SPV_NV_push_constant_bank);
builder.addCapability(spv::Capability::PushConstantBanksNV);
builder.addMemberDecoration(spvType, member, spv::Decoration::MemberOffsetNV,
glslangMember.getQualifier().layoutMemberOffset);
} else if (explicitLayout != glslang::ElpNone) {
// figure out what to do with offset, which is accumulating // figure out what to do with offset, which is accumulating
int nextOffset; int nextOffset;
updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix);
@@ -5987,7 +6271,9 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
// built-in variable decorations // built-in variable decorations
spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true);
if (builtIn != spv::BuiltIn::Max) // built-in decoration is used to detect AST nodes, but won't be decorated on member variables.
if (builtIn != spv::BuiltIn::Max &&
builtIn != spv::BuiltIn::ResourceHeapEXT && builtIn != spv::BuiltIn::SamplerHeapEXT)
builder.addMemberDecoration(spvType, member, spv::Decoration::BuiltIn, (int)builtIn); builder.addMemberDecoration(spvType, member, spv::Decoration::BuiltIn, (int)builtIn);
// nonuniform // nonuniform
@@ -6040,6 +6326,13 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
if (qualifier.hasHitObjectShaderRecordNV()) if (qualifier.hasHitObjectShaderRecordNV())
builder.addDecoration(spvType, spv::Decoration::HitObjectShaderRecordBufferNV); builder.addDecoration(spvType, spv::Decoration::HitObjectShaderRecordBufferNV);
if (qualifier.hasBank()) {
builder.addExtension(spv::E_SPV_NV_push_constant_bank);
builder.addCapability(spv::Capability::PushConstantBanksNV);
builder.addDecoration(spvType, spv::Decoration::BankNV, qualifier.layoutBank);
}
if (qualifier.hasHitObjectShaderRecordEXT()) if (qualifier.hasHitObjectShaderRecordEXT())
builder.addDecoration(spvType, spv::Decoration::HitObjectShaderRecordBufferEXT); builder.addDecoration(spvType, spv::Decoration::HitObjectShaderRecordBufferEXT);
} }
@@ -6111,6 +6404,12 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId); loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId);
} }
if (!builder.getAccessChain().descHeapInfo.descHeapInstId.empty()) {
for (auto heapInst : builder.getAccessChain().descHeapInfo.descHeapInstId)
heapInst->setTypeId(convertGlslangToSpvType(type));
builder.clearAccessChain();
}
return loadedId; return loadedId;
} }
@@ -7082,7 +7381,18 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
} else { } else {
resultTypeId = builder.makePointer(spv::StorageClass::Image, resultType()); resultTypeId = builder.makePointer(spv::StorageClass::Image, resultType());
} }
spv::Id pointer = builder.createOp(spv::Op::OpImageTexelPointer, resultTypeId, operands);
// EXT_descriptor_heap
// For image atomic parameter, using untyped image texel pointer to carry on type metadata.
spv::Op imgTexelOp = spv::Op::OpImageTexelPointer;
if (node->getQualifier().isUsedByAtomic() &&
imageType.getQualifier().builtIn == glslang::EbvResourceHeapEXT) {
operands.insert(operands.begin(), {true, convertGlslangToSpvType(imageType)});
imgTexelOp = spv::Op::OpUntypedImageTexelPointerEXT;
resultTypeId = builder.makeUntypedPointer(spv::StorageClass::Image);
}
spv::Id pointer = builder.createOp(imgTexelOp, resultTypeId, operands);
if (imageType.getQualifier().nonUniform) { if (imageType.getQualifier().nonUniform) {
builder.addDecoration(pointer, spv::Decoration::NonUniformEXT); builder.addDecoration(pointer, spv::Decoration::NonUniformEXT);
} }
@@ -9843,9 +10153,12 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16);
if (builder.getNumComponents(operands[0]) == 1) if (builder.getNumComponents(operands[0]) == 1)
frexpIntType = builder.makeIntegerType(width, true); frexpIntType = builder.makeIntegerType(width, true);
else if (builder.isCooperativeVector(operands[0]))
frexpIntType = builder.makeCooperativeVectorTypeNV(builder.makeIntegerType(width, true),
builder.getCooperativeVectorNumComponents(builder.getTypeId(operands[0])));
else else
frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true),
builder.getNumComponents(operands[0])); builder.getNumComponents(operands[0]));
typeId = builder.makeStructResultType(typeId0, frexpIntType); typeId = builder.makeStructResultType(typeId0, frexpIntType);
consumedOperands = 1; consumedOperands = 1;
} }
@@ -10755,7 +11068,11 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
builtIn == spv::BuiltIn::ObjectToWorldKHR || builtIn == spv::BuiltIn::ObjectToWorldKHR ||
builtIn == spv::BuiltIn::WorldToObjectKHR; builtIn == spv::BuiltIn::WorldToObjectKHR;
if (mayNeedToReuseBuiltIn) { // EXT_descriptor_heap
const bool needToRemapDescHeap =
builtIn == spv::BuiltIn::ResourceHeapEXT || builtIn == spv::BuiltIn::SamplerHeapEXT;
if (mayNeedToReuseBuiltIn || needToRemapDescHeap) {
auto iter = builtInVariableIds.find(uint32_t(builtIn)); auto iter = builtInVariableIds.find(uint32_t(builtIn));
if (builtInVariableIds.end() != iter) { if (builtInVariableIds.end() != iter) {
id = iter->second; id = iter->second;
@@ -10929,6 +11246,18 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
if (symbol->getType().getQualifier().hasSpirvDecorate()) if (symbol->getType().getQualifier().hasSpirvDecorate())
applySpirvDecorate(symbol->getType(), id, {}); applySpirvDecorate(symbol->getType(), id, {});
if (symbol->getQualifier().hasBank()) {
builder.addExtension(spv::E_SPV_NV_push_constant_bank);
builder.addCapability(spv::Capability::PushConstantBanksNV);
builder.addDecoration(id, spv::Decoration::BankNV, symbol->getQualifier().layoutBank);
}
if (symbol->getQualifier().hasMemberOffset()) {
builder.addExtension(spv::E_SPV_NV_push_constant_bank);
builder.addCapability(spv::Capability::PushConstantBanksNV);
builder.addDecoration(id, spv::Decoration::MemberOffsetNV, symbol->getQualifier().layoutMemberOffset);
}
return id; return id;
} }
@@ -11149,8 +11478,8 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla
glslang::TVector<glslang::TTypeLoc>::const_iterator iter; glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false));
} else if (glslangType.getVectorSize() > 1 || glslangType.isCoopVecNV()) { } else if (glslangType.getVectorSize() > 1 || glslangType.isCoopVecOrLongVector()) {
unsigned int numComponents = glslangType.isCoopVecNV() ? glslangType.getTypeParameters()->arraySizes->getDimSize(0) : glslangType.getVectorSize(); unsigned int numComponents = glslangType.isCoopVecOrLongVector() ? glslangType.getTypeParameters()->arraySizes->getDimSize(0) : glslangType.getVectorSize();
for (unsigned int i = 0; i < numComponents; ++i) { for (unsigned int i = 0; i < numComponents; ++i) {
bool zero = nextConst >= consts.size(); bool zero = nextConst >= consts.size();
switch (glslangType.getBasicType()) { switch (glslangType.getBasicType()) {

View File

@@ -190,6 +190,27 @@ Id Builder::makeForwardPointer(StorageClass storageClass)
return type->getResultId(); return type->getResultId();
} }
Id Builder::makeUntypedPointer(StorageClass storageClass, bool setBufferPointer)
{
// try to find it
Instruction* type;
// both typeBufferEXT and UntypedPointer only contains storage class info.
spv::Op typeOp = setBufferPointer ? Op::OpTypeBufferEXT : Op::OpTypeUntypedPointerKHR;
for (int t = 0; t < (int)groupedTypes[enumCast(typeOp)].size(); ++t) {
type = groupedTypes[enumCast(typeOp)][t];
if (type->getImmediateOperand(0) == (unsigned)storageClass)
return type->getResultId();
}
// not found, make it
type = new Instruction(getUniqueId(), NoType, typeOp);
type->addImmediateOperand(storageClass);
groupedTypes[enumCast(typeOp)].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee) Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
{ {
// try to find it // try to find it
@@ -1767,6 +1788,7 @@ bool Builder::isConstantOpCode(Op opcode) const
case Op::OpSpecConstantComposite: case Op::OpSpecConstantComposite:
case Op::OpSpecConstantCompositeReplicateEXT: case Op::OpSpecConstantCompositeReplicateEXT:
case Op::OpSpecConstantOp: case Op::OpSpecConstantOp:
case Op::OpConstantSizeOfEXT:
return true; return true;
default: default:
return false; return false;
@@ -2429,6 +2451,23 @@ void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id
decorations.insert(std::unique_ptr<Instruction>(dec)); decorations.insert(std::unique_ptr<Instruction>(dec));
} }
void Builder::addMemberDecorationIdEXT(Id id, unsigned int member, Decoration decoration,
const std::vector<unsigned>& operands)
{
if (decoration == spv::Decoration::Max)
return;
Instruction* dec = new Instruction(Op::OpMemberDecorateIdEXT);
dec->reserveOperands(operands.size() + 3);
dec->addIdOperand(id);
dec->addImmediateOperand(member);
dec->addImmediateOperand(decoration);
for (auto operand : operands)
dec->addIdOperand(operand);
decorations.insert(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{ {
if (decoration == spv::Decoration::Max) if (decoration == spv::Decoration::Max)
@@ -2844,6 +2883,38 @@ void Builder::createConstVariable(Id type, const char* name, Id constant, bool i
} }
} }
// Comments in header
Id Builder::createUntypedVariable(Decoration precision, StorageClass storageClass, const char* name, Id dataType,
Id initializer)
{
Id resultUntypedPointerType = makeUntypedPointer(storageClass);
Instruction* inst = new Instruction(getUniqueId(), resultUntypedPointerType, Op::OpUntypedVariableKHR);
inst->addImmediateOperand(storageClass);
if (dataType != NoResult) {
Id dataPointerType = makePointer(storageClass, dataType);
inst->addIdOperand(dataPointerType);
}
if (initializer != NoResult)
inst->addIdOperand(initializer);
switch (storageClass) {
case StorageClass::Function:
// Validation rules require the declaration in the entry block
buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst));
break;
default:
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
module.mapInstruction(inst);
break;
}
if (name)
addName(inst->getResultId(), name);
setPrecision(inst->getResultId(), precision);
return inst->getResultId();
}
// Comments in header // Comments in header
Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer, Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer,
bool const compilerGenerated) bool const compilerGenerated)
@@ -2916,9 +2987,14 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
unsigned int alignment) unsigned int alignment)
{ {
Instruction* store = new Instruction(Op::OpStore); Instruction* store = nullptr;
store->reserveOperands(2); if (isUntypedPointer(lValue))
store->addIdOperand(lValue); store = createDescHeapLoadStoreBaseRemap(lValue, Op::OpStore);
else {
store = new Instruction(Op::OpStore);
store->reserveOperands(2);
store->addIdOperand(lValue);
}
store->addIdOperand(rValue); store->addIdOperand(rValue);
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
@@ -2940,8 +3016,13 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess, Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess,
spv::Scope scope, unsigned int alignment) spv::Scope scope, unsigned int alignment)
{ {
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), Op::OpLoad); Instruction* load = nullptr;
load->addIdOperand(lValue); if (isUntypedPointer(lValue))
load = createDescHeapLoadStoreBaseRemap(lValue, Op::OpLoad);
else {
load = new Instruction(getUniqueId(), getDerefTypeId(lValue), Op::OpLoad);
load->addIdOperand(lValue);
}
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
@@ -2961,6 +3042,172 @@ Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMa
return load->getResultId(); return load->getResultId();
} }
Instruction* Builder::createDescHeapLoadStoreBaseRemap(Id baseId, Op op)
{
// could only be untypedAccessChain or BufferPointerEXT op.
spv::Op instOp = module.getInstruction(baseId)->getOpCode();
spv::Id baseVal = baseId;
// base type (from run time array)
spv::Id resultTy = getIdOperand(baseId, 0);
// Descriptor heap using run time array.
if (accessChain.descHeapInfo.descHeapStorageClass != StorageClass::Max)
resultTy = getIdOperand(resultTy, 0);
if (instOp == Op::OpBufferPointerEXT) {
// get base structure type from run time array of buffer structure type.
// create an extra untyped access chain for buffer pointer.
resultTy = accessChain.descHeapInfo.descHeapBaseTy;
Instruction* chain = new Instruction(getUniqueId(), getTypeId(baseId), Op::OpUntypedAccessChainKHR);
// base type.
chain->addIdOperand(resultTy);
// base
chain->addIdOperand(baseId);
// index
for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
chain->addIdOperand(accessChain.indexChain[i]);
}
addInstruction(std::unique_ptr<Instruction>(chain));
baseVal = chain->getResultId();
clearAccessChain();
} else if (instOp != Op::OpUntypedAccessChainKHR) {
assert("Not a untyped load type");
}
Instruction* inst = nullptr;
if (op == Op::OpStore)
inst = new Instruction(Op::OpStore);
else {
inst = new Instruction(getUniqueId(), resultTy, Op::OpLoad);
accessChain.descHeapInfo.descHeapInstId.push_back(inst);
}
inst->addIdOperand(baseVal);
return inst;
}
uint32_t Builder::isStructureHeapMember(Id id, std::vector<Id> indexChain,
unsigned int idx, spv::BuiltIn* bt, uint32_t* firstArrIndex)
{
unsigned currentIdx = idx;
// Process types, only array types could contain no constant id operands.
Id baseId = id;
if (baseId == NoType)
return 0;
if (isPointerType(baseId))
baseId = getContainedTypeId(baseId);
auto baseInst = module.getInstruction(baseId);
if (baseInst->getOpCode() == spv::Op::OpTypeArray ||
baseInst->getOpCode() == spv::Op::OpTypeRuntimeArray) {
if (firstArrIndex)
*firstArrIndex = currentIdx;
baseId = getContainedTypeId(baseId);
baseInst = module.getInstruction(baseId);
currentIdx++;
}
if (currentIdx >= indexChain.size())
return 0;
// Process index op.
auto indexInst = module.getInstruction(indexChain[currentIdx]);
if (indexInst->getOpCode() != spv::Op::OpConstant)
return 0;
auto index = indexInst->getImmediateOperand(0);
for (auto dec = decorations.begin(); dec != decorations.end(); dec++) {
if (dec->get()->getOpCode() == spv::Op::OpMemberDecorate && dec->get()->getIdOperand(0) == baseId &&
dec->get()->getImmediateOperand(1) == index &&
dec->get()->getImmediateOperand(2) == spv::Decoration::BuiltIn &&
(dec->get()->getImmediateOperand(3) == (unsigned)spv::BuiltIn::ResourceHeapEXT ||
dec->get()->getImmediateOperand(3) == (unsigned)spv::BuiltIn::SamplerHeapEXT)) {
if (bt)
*bt = (spv::BuiltIn)dec->get()->getImmediateOperand(3);
return currentIdx;
}
}
// New base.
if (baseInst->getOpCode() == spv::Op::OpTypeStruct) {
if (!baseInst->isIdOperand(index) || idx == indexChain.size() - 1)
return 0;
return isStructureHeapMember(baseInst->getIdOperand(index), indexChain, currentIdx + 1, bt, firstArrIndex);
}
return 0;
}
// Comments in header
Id Builder::createDescHeapAccessChain()
{
uint32_t rsrcOffsetIdx = accessChain.descHeapInfo.structRsrcTyOffsetCount;
if (rsrcOffsetIdx != 0)
accessChain.base = accessChain.descHeapInfo.structRemappedBase;
Id base = accessChain.base;
Id untypedResultTy = accessChain.descHeapInfo.descHeapBaseTy;
uint32_t explicitArrayStride = accessChain.descHeapInfo.descHeapBaseArrayStride;
std::vector<Id>& offsets = accessChain.indexChain;
uint32_t firstArrIndex = accessChain.descHeapInfo.structRsrcTyFirstArrIndex;
// both typeBufferEXT and UntypedPointer only contains storage class info.
StorageClass storageClass = (StorageClass)accessChain.descHeapInfo.descHeapStorageClass;
Id resultTy = makeUntypedPointer(storageClass == spv::StorageClass::StorageBuffer ? spv::StorageClass::StorageBuffer
: spv::StorageClass::Uniform);
// Make the untyped access chain instruction
Instruction* chain = new Instruction(getUniqueId(), makeUntypedPointer(getStorageClass(base)), Op::OpUntypedAccessChainKHR);
if (storageClass == spv::StorageClass::Uniform || storageClass == spv::StorageClass::StorageBuffer) {
// For buffer and uniform heap, split first index as heap array index
// Insert BufferPointer op and construct another access chain with following indexes.
Id bufferTy = makeUntypedPointer(storageClass, true);
Id strideId = NoResult;
if (explicitArrayStride == 0) {
strideId = createConstantSizeOfEXT(bufferTy);
} else {
strideId = makeUintConstant(explicitArrayStride);
}
Id runtimeArrTy = makeRuntimeArray(bufferTy);
addDecorationId(runtimeArrTy, spv::Decoration::ArrayStrideIdEXT, strideId);
chain->addIdOperand(runtimeArrTy);
chain->addIdOperand(base);
// We would only re-target current member resource directly to resource/sampler heap base.
// So the previous access chain index towards final resource type is not needed?
// In current draft, only keep the first 'array index' into last access chain index.
// As those resource can't be declared as an array, in current first draft, array index will
// be the second index. This will be refined later.
chain->addIdOperand(offsets[firstArrIndex]);
if (rsrcOffsetIdx != 0) {
for (uint32_t i = 0; i < rsrcOffsetIdx + 1; i++) {
if (rsrcOffsetIdx + i + 1 < offsets.size())
offsets[i] = offsets[i + rsrcOffsetIdx + 1];
}
} else {
for (uint32_t i = 0; i < offsets.size() - 1; i++) {
offsets[i] = offsets[i + 1];
}
}
for (uint32_t i = 0; i < rsrcOffsetIdx + 1; i++)
offsets.pop_back();
addInstruction(std::unique_ptr<Instruction>(chain));
// Create OpBufferPointer for loading target buffer descriptor.
Instruction* bufferUntypedDataPtr = new Instruction(getUniqueId(), resultTy, Op::OpBufferPointerEXT);
bufferUntypedDataPtr->addIdOperand(chain->getResultId());
addInstruction(std::unique_ptr<Instruction>(bufferUntypedDataPtr));
// Final/Second untyped access chain loading will be created during loading, current results only
// refer to the loading 'base'.
return bufferUntypedDataPtr->getResultId();
} else {
// image/sampler heap
Id strideId = NoResult;
if (explicitArrayStride == 0) {
strideId = createConstantSizeOfEXT(untypedResultTy);
} else {
strideId = makeUintConstant(explicitArrayStride);
}
Id runtimeArrTy = makeRuntimeArray(untypedResultTy);
addDecorationId(runtimeArrTy, spv::Decoration::ArrayStrideIdEXT, strideId);
chain->addIdOperand(runtimeArrTy);
chain->addIdOperand(base);
for (int i = 0; i < (int)offsets.size(); ++i)
chain->addIdOperand(offsets[i]);
addInstruction(std::unique_ptr<Instruction>(chain));
return chain->getResultId();
}
}
// Comments in header // Comments in header
Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets) Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
{ {
@@ -3344,12 +3591,21 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
// Comments in header // Comments in header
void Builder::promoteScalar(Decoration precision, Id& left, Id& right) void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
{ {
int direction = getNumComponents(right) - getNumComponents(left); // choose direction of promotion (+1 for left to right, -1 for right to left)
int direction = !isScalar(right) - !isScalar(left);
auto const &makeVec = [&](Id component, Id other) {
if (isCooperativeVector(other)) {
return makeCooperativeVectorTypeNV(getTypeId(component), getCooperativeVectorNumComponents(getTypeId(other)));
} else {
return makeVectorType(getTypeId(component), getNumComponents(other));
}
};
if (direction > 0) if (direction > 0)
left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right))); left = smearScalar(precision, left, makeVec(left, right));
else if (direction < 0) else if (direction < 0)
right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); right = smearScalar(precision, right, makeVec(right, left));
return; return;
} }
@@ -3361,7 +3617,7 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
assert(getTypeId(scalar) == getScalarTypeId(vectorType)); assert(getTypeId(scalar) == getScalarTypeId(vectorType));
int numComponents = getNumTypeComponents(vectorType); int numComponents = getNumTypeComponents(vectorType);
if (numComponents == 1 && !isCooperativeVectorType(vectorType)) if (numComponents == 1 && !isCooperativeVectorType(vectorType) && !isVectorType(vectorType))
return scalar; return scalar;
Instruction* smear = nullptr; Instruction* smear = nullptr;
@@ -3773,7 +4029,7 @@ Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constitue
{ {
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == constituents.size()) || getNumTypeConstituents(typeId) == constituents.size()) ||
(isCooperativeVectorType(typeId) && constituents.size() == 1)); ((isCooperativeVectorType(typeId) || isVectorType(typeId)) && constituents.size() == 1));
if (generatingOpCodeForSpecConst) { if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be // Sometime, even in spec-constant-op mode, the constant composite to be
@@ -3862,9 +4118,16 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
return smearScalar(precision, sources[0], resultTypeId); return smearScalar(precision, sources[0], resultTypeId);
// Special case: 2 vectors of equal size // Special case: 2 vectors of equal size
if (sources.size() == 1 && isVector(sources[0]) && numTargetComponents == getNumComponents(sources[0])) { if (sources.size() == 1 &&
assert(resultTypeId == getTypeId(sources[0])); (isVector(sources[0]) || isCooperativeVector(sources[0])) &&
return sources[0]; numTargetComponents == getNumComponents(sources[0])) {
if (isCooperativeVector(sources[0]) != isCooperativeVectorType(resultTypeId)) {
assert(isVector(sources[0]) != isVectorType(resultTypeId));
return createUnaryOp(spv::Op::OpBitcast, resultTypeId, sources[0]);
} else {
assert(resultTypeId == getTypeId(sources[0]));
return sources[0];
}
} }
// accumulate the arguments for OpCompositeConstruct // accumulate the arguments for OpCompositeConstruct
@@ -3873,7 +4136,7 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
// lambda to store the result of visiting an argument component // lambda to store the result of visiting an argument component
const auto latchResult = [&](Id comp) { const auto latchResult = [&](Id comp) {
if (numTargetComponents > 1) if (numTargetComponents > 1 || isVectorType(resultTypeId))
constituents.push_back(comp); constituents.push_back(comp);
else else
result = comp; result = comp;
@@ -4251,6 +4514,13 @@ void Builder::clearAccessChain()
accessChain.isRValue = false; accessChain.isRValue = false;
accessChain.coherentFlags.clear(); accessChain.coherentFlags.clear();
accessChain.alignment = 0; accessChain.alignment = 0;
accessChain.descHeapInfo.descHeapBaseTy = NoResult;
accessChain.descHeapInfo.descHeapStorageClass = StorageClass::Max;
accessChain.descHeapInfo.descHeapInstId.clear();
accessChain.descHeapInfo.descHeapBaseArrayStride = NoResult;
accessChain.descHeapInfo.structRemappedBase = NoResult;
accessChain.descHeapInfo.structRsrcTyOffsetCount = 0;
accessChain.descHeapInfo.structRsrcTyFirstArrIndex = 0;
} }
// Comments in header // Comments in header
@@ -4372,7 +4642,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform,
if (constant) { if (constant) {
id = createCompositeExtract(accessChain.base, swizzleBase, indexes); id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
setPrecision(id, precision); setPrecision(id, precision);
} else if (isCooperativeVector(accessChain.base)) { } else if (isVector(accessChain.base) || isCooperativeVector(accessChain.base)) {
assert(accessChain.indexChain.size() == 1); assert(accessChain.indexChain.size() == 1);
id = createVectorExtractDynamic(accessChain.base, resultType, accessChain.indexChain[0]); id = createVectorExtractDynamic(accessChain.base, resultType, accessChain.indexChain[0]);
} else { } else {
@@ -4461,10 +4731,13 @@ Id Builder::accessChainGetLValue()
Id Builder::accessChainGetInferredType() Id Builder::accessChainGetInferredType()
{ {
// anything to operate on? // anything to operate on?
if (accessChain.base == NoResult) // for untyped pointer, it may be remapped to a descriptor heap.
// for descriptor heap, its base data type will be determined later,
// according to load/store results' types.
if (accessChain.base == NoResult || isUntypedPointer(accessChain.base) ||
isStructureHeapMember(getTypeId(accessChain.base), accessChain.indexChain, 0) != 0)
return NoType; return NoType;
Id type = getTypeId(accessChain.base); Id type = getTypeId(accessChain.base);
// do initial dereference // do initial dereference
if (! accessChain.isRValue) if (! accessChain.isRValue)
type = getContainedTypeId(type); type = getContainedTypeId(type);
@@ -4582,7 +4855,13 @@ Id Builder::collapseAccessChain()
// emit the access chain // emit the access chain
StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); // when descHeap info is set, use another access chain process.
if ((isUntypedPointer(accessChain.base) || accessChain.descHeapInfo.structRsrcTyOffsetCount!= 0) &&
accessChain.descHeapInfo.descHeapStorageClass != StorageClass::Max) {
accessChain.instr = createDescHeapAccessChain();
} else {
accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
}
return accessChain.instr; return accessChain.instr;
} }
@@ -4691,6 +4970,16 @@ void Builder::createBranch(bool implicit, Block* block)
block->addPredecessor(buildPoint); block->addPredecessor(buildPoint);
} }
// Create OpConstantSizeOfEXT
Id Builder::createConstantSizeOfEXT(Id typeId)
{
Instruction* inst = new Instruction(getUniqueId(), makeIntType(32), Op::OpConstantSizeOfEXT);
inst->addIdOperand(typeId);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
module.mapInstruction(inst);
return inst->getResultId();
}
void Builder::createSelectionMerge(Block* mergeBlock, SelectionControlMask control) void Builder::createSelectionMerge(Block* mergeBlock, SelectionControlMask control)
{ {
Instruction* merge = new Instruction(Op::OpSelectionMerge); Instruction* merge = new Instruction(Op::OpSelectionMerge);

View File

@@ -230,6 +230,7 @@ public:
Id makePointer(StorageClass, Id pointee); Id makePointer(StorageClass, Id pointee);
Id makeForwardPointer(StorageClass); Id makeForwardPointer(StorageClass);
Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
Id makeUntypedPointer(StorageClass storageClass, bool setBufferPointer = false);
Id makeIntegerType(int width, bool hasSign); // generic Id makeIntegerType(int width, bool hasSign); // generic
Id makeIntType(int width) { return makeIntegerType(width, true); } Id makeIntType(int width) { return makeIntegerType(width, true); }
Id makeUintType(int width) { return makeIntegerType(width, false); } Id makeUintType(int width) { return makeIntegerType(width, false); }
@@ -317,6 +318,14 @@ public:
Id getCooperativeVectorNumComponents(Id typeId) const { return module.getInstruction(typeId)->getIdOperand(1); } Id getCooperativeVectorNumComponents(Id typeId) const { return module.getInstruction(typeId)->getIdOperand(1); }
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
bool isUntypedPointer(Id resultId) const
{
const Id tid = getTypeId(resultId);
// Expect that OpString have no type
if (tid == 0)
return false;
return isUntypedPointerType(tid);
}
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
@@ -334,6 +343,7 @@ public:
{ return getTypeClass(typeId) == Op::OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } { return getTypeClass(typeId) == Op::OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == Op::OpTypeFloat; } bool isFloatType(Id typeId) const { return getTypeClass(typeId) == Op::OpTypeFloat; }
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == Op::OpTypePointer; } bool isPointerType(Id typeId) const { return getTypeClass(typeId) == Op::OpTypePointer; }
bool isUntypedPointerType(Id typeId) const { return getTypeClass(typeId) == Op::OpTypeUntypedPointerKHR; }
bool isScalarType(Id typeId) const bool isScalarType(Id typeId) const
{ return getTypeClass(typeId) == Op::OpTypeFloat || getTypeClass(typeId) == Op::OpTypeInt || { return getTypeClass(typeId) == Op::OpTypeFloat || getTypeClass(typeId) == Op::OpTypeInt ||
getTypeClass(typeId) == Op::OpTypeBool; } getTypeClass(typeId) == Op::OpTypeBool; }
@@ -469,6 +479,7 @@ public:
void addMemberDecoration(Id, unsigned int member, Decoration, const char*); void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals); void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings); void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
void addMemberDecorationIdEXT(Id, unsigned int member, Decoration, const std::vector<unsigned>& operands);
// At the end of what block do the next create*() instructions go? // At the end of what block do the next create*() instructions go?
// Also reset current last DebugScope and current source line to unknown // Also reset current last DebugScope and current source line to unknown
@@ -531,9 +542,16 @@ public:
Id createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name = nullptr, Id createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name = nullptr,
Id initializer = NoResult, bool const compilerGenerated = true); Id initializer = NoResult, bool const compilerGenerated = true);
// Create an untyped global or function local or IO variable.
Id createUntypedVariable(Decoration precision, StorageClass storageClass, const char* name = nullptr,
Id dataType = NoResult, Id initializer = NoResult);
// Create an intermediate with an undefined value. // Create an intermediate with an undefined value.
Id createUndefined(Id type); Id createUndefined(Id type);
// Create load/store instruction with a remapped descriptor heap base.
Instruction* createDescHeapLoadStoreBaseRemap(Id base, Op op);
// Store into an Id and return the l-value // Store into an Id and return the l-value
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMask::MaskNone, void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMask::MaskNone,
spv::Scope scope = spv::Scope::Max, unsigned int alignment = 0); spv::Scope scope = spv::Scope::Max, unsigned int alignment = 0);
@@ -790,6 +808,18 @@ public:
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment.
// Only tracks base and (optional) component selection alignment. // Only tracks base and (optional) component selection alignment.
struct DescHeapInfo {
Id descHeapBaseTy; // for descriptor heap, record its base data type.
StorageClass descHeapStorageClass; // for descriptor heap, record its basic storage class.
uint32_t descHeapBaseArrayStride; // for descriptor heap, record its explicit array stride.
std::vector<Instruction*> descHeapInstId;
// for descriptor heap, record its data type for loading/store results.
uint32_t structRsrcTyOffsetCount;
uint32_t structRsrcTyFirstArrIndex;
Id structRemappedBase;
};
DescHeapInfo descHeapInfo;
// Accumulate whether anything in the chain of structures has coherent decorations. // Accumulate whether anything in the chain of structures has coherent decorations.
struct CoherentFlags { struct CoherentFlags {
CoherentFlags() { clear(); } CoherentFlags() { clear(); }
@@ -856,10 +886,15 @@ public:
// clear accessChain // clear accessChain
void clearAccessChain(); void clearAccessChain();
Id createDescHeapAccessChain();
Id createConstantSizeOfEXT(Id typeId);
uint32_t isStructureHeapMember(Id id, std::vector<Id> indexChain, unsigned int idx, spv::BuiltIn* bt = nullptr,
uint32_t* firstArrIndex = nullptr);
// set new base as an l-value base // set new base as an l-value base
void setAccessChainLValue(Id lValue) void setAccessChainLValue(Id lValue)
{ {
assert(isPointer(lValue)); assert(isPointer(lValue) || isUntypedPointer(lValue));
accessChain.base = lValue; accessChain.base = lValue;
} }
@@ -870,6 +905,25 @@ public:
accessChain.base = rValue; accessChain.base = rValue;
} }
// set access chain info for untyped descriptor heap variable
void setAccessChainDescHeapInfo(StorageClass storageClass = StorageClass::Max, Id baseTy = NoResult,
uint32_t explicitArrayStride = NoResult, uint32_t structRsrcTyOffsetCount = 0,
spv::Id structRemappedBase = NoResult, uint32_t firstArrIndex = NoResult)
{
if (accessChain.descHeapInfo.descHeapStorageClass == StorageClass::Max)
accessChain.descHeapInfo.descHeapStorageClass = storageClass;
if (accessChain.descHeapInfo.descHeapBaseTy == NoResult)
accessChain.descHeapInfo.descHeapBaseTy = baseTy;
if (accessChain.descHeapInfo.descHeapBaseArrayStride == NoResult)
accessChain.descHeapInfo.descHeapBaseArrayStride = explicitArrayStride;
if (accessChain.descHeapInfo.structRemappedBase == NoResult)
accessChain.descHeapInfo.structRemappedBase = structRemappedBase;
if (accessChain.descHeapInfo.structRsrcTyOffsetCount == 0)
accessChain.descHeapInfo.structRsrcTyOffsetCount = structRsrcTyOffsetCount;
if (accessChain.descHeapInfo.structRsrcTyFirstArrIndex == 0)
accessChain.descHeapInfo.structRsrcTyFirstArrIndex = firstArrIndex;
}
// push offset onto the end of the chain // push offset onto the end of the chain
void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{ {

View File

@@ -83,7 +83,10 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
if (containsType(typeId, Op::OpTypeFloat, 16)) if (containsType(typeId, Op::OpTypeFloat, 16))
addCapability(Capability::Float16); addCapability(Capability::Float16);
} else { } else {
StorageClass storageClass = getStorageClass(inst.getIdOperand(0)); StorageClass storageClass = StorageClass::Max;
if (module.getInstruction(inst.getIdOperand(0))->getOpCode() != Op::OpUntypedAccessChainKHR) {
storageClass = getStorageClass(inst.getIdOperand(0));
}
if (width == 8) { if (width == 8) {
switch (storageClass) { switch (storageClass) {
case StorageClass::PhysicalStorageBufferEXT: case StorageClass::PhysicalStorageBufferEXT:

View File

@@ -166,6 +166,7 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidatorOptionsSetAllowOffsetTextureOperand(options, intermediate.usingTextureOffsetNonConst()); spvValidatorOptionsSetAllowOffsetTextureOperand(options, intermediate.usingTextureOffsetNonConst());
spvValidatorOptionsSetAllowVulkan32BitBitwise(options, true);
spvValidateWithOptions(context, options, &binary, &diagnostic); spvValidateWithOptions(context, options, &binary, &diagnostic);
// report // report

View File

@@ -414,6 +414,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
idDescriptor[resultId] = "struct"; idDescriptor[resultId] = "struct";
break; break;
case Op::OpTypePointer: case Op::OpTypePointer:
case Op::OpTypeUntypedPointerKHR:
idDescriptor[resultId] = "ptr"; idDescriptor[resultId] = "ptr";
break; break;
case Op::OpTypeVector: case Op::OpTypeVector:

View File

@@ -350,6 +350,12 @@ const char* DecorationString(int decoration)
case (int)Decoration::HitObjectShaderRecordBufferEXT: return "DecorationHitObjectShaderRecordBufferEXT"; case (int)Decoration::HitObjectShaderRecordBufferEXT: return "DecorationHitObjectShaderRecordBufferEXT";
case (int)Decoration::SaturatedToLargestFloat8NormalConversionEXT: return "DecorationSaturatedToLargestFloat8NormalConversionEXT"; case (int)Decoration::SaturatedToLargestFloat8NormalConversionEXT: return "DecorationSaturatedToLargestFloat8NormalConversionEXT";
case (int)Decoration::BankNV: return "BankNV";
case (int)Decoration::MemberOffsetNV: return "MemberOffsetNV";
case (int)Decoration::ArrayStrideIdEXT: return "DecorationArrayStrideIdEXT";
case (int)Decoration::OffsetIdEXT: return "DecorationOffsetIdEXT";
} }
} }
@@ -491,6 +497,8 @@ const char* BuiltInString(int builtIn)
case (int)BuiltIn::CoreMaxIDARM: return "CoreMaxIDARM"; case (int)BuiltIn::CoreMaxIDARM: return "CoreMaxIDARM";
case (int)BuiltIn::WarpIDARM: return "WarpIDARM"; case (int)BuiltIn::WarpIDARM: return "WarpIDARM";
case (int)BuiltIn::WarpMaxIDARM: return "BuiltInWarpMaxIDARM"; case (int)BuiltIn::WarpMaxIDARM: return "BuiltInWarpMaxIDARM";
case (int)BuiltIn::SamplerHeapEXT: return "SamplerHeapEXT";
case (int)BuiltIn::ResourceHeapEXT: return "ResourceHeapEXT";
default: return "Bad"; default: return "Bad";
} }
@@ -1093,6 +1101,8 @@ const char* CapabilityString(int info)
case (int)Capability::ShaderClockKHR: return "ShaderClockKHR"; case (int)Capability::ShaderClockKHR: return "ShaderClockKHR";
case (int)Capability::QuadControlKHR: return "QuadControlKHR"; case (int)Capability::QuadControlKHR: return "QuadControlKHR";
case (int)Capability::Int64ImageEXT: return "Int64ImageEXT"; case (int)Capability::Int64ImageEXT: return "Int64ImageEXT";
case (int)Capability::DescriptorHeapEXT: return "DescriptorHeapEXT";
case (int)Capability::UntypedPointersKHR: return "UntypedPointersKHR";
case (int)Capability::IntegerFunctions2INTEL: return "IntegerFunctions2INTEL"; case (int)Capability::IntegerFunctions2INTEL: return "IntegerFunctions2INTEL";
@@ -1140,7 +1150,10 @@ const char* CapabilityString(int info)
case (int)Capability::Float8EXT: return "Float8EXT"; case (int)Capability::Float8EXT: return "Float8EXT";
case (int)Capability::Float8CooperativeMatrixEXT: return "Float8CooperativeMatrixEXT"; case (int)Capability::Float8CooperativeMatrixEXT: return "Float8CooperativeMatrixEXT";
case (int)Capability::PushConstantBanksNV: return "PushConstantBanksNV";
case (int)Capability::Shader64BitIndexingEXT: return "CapabilityShader64BitIndexingEXT"; case (int)Capability::Shader64BitIndexingEXT: return "CapabilityShader64BitIndexingEXT";
case (int)Capability::LongVectorEXT: return "LongVectorEXT";
default: return "Bad"; default: return "Bad";
} }
@@ -1523,6 +1536,14 @@ const char* OpcodeString(int op)
case (int)Op::OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR"; case (int)Op::OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR";
case (int)Op::OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR"; case (int)Op::OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR";
case (int)Op::OpBufferPointerEXT: return "OpBufferPointerEXT";
case (int)Op::OpConstantSizeOfEXT: return "OpConstantSizeOfEXT";
case (int)Op::OpTypeBufferEXT: return "OpTypeBufferEXT";
case (int)Op::OpUntypedAccessChainKHR: return "OpUntypedAccessChainKHR";
case (int)Op::OpUntypedVariableKHR: return "OpUntypedVariableKHR";
case (int)Op::OpTypeUntypedPointerKHR: return "OpTypeUntypedPointerKHR";
case (int)Op::OpMemberDecorateIdEXT: return "OpMemberDecorateIdEXT";
case (int)Op::OpUntypedImageTexelPointerEXT: return "OpUntypedImageTexelPointerEXT";
case (int)Op::OpAtomicFAddEXT: return "OpAtomicFAddEXT"; case (int)Op::OpAtomicFAddEXT: return "OpAtomicFAddEXT";
case (int)Op::OpAtomicFMinEXT: return "OpAtomicFMinEXT"; case (int)Op::OpAtomicFMinEXT: return "OpAtomicFMinEXT";
@@ -1819,6 +1840,7 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpTypeStruct)].setResultAndType(true, false); InstructionDesc[enumCast(Op::OpTypeStruct)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpTypeOpaque)].setResultAndType(true, false); InstructionDesc[enumCast(Op::OpTypeOpaque)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpTypePointer)].setResultAndType(true, false); InstructionDesc[enumCast(Op::OpTypePointer)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpTypeUntypedPointerKHR)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpTypeForwardPointer)].setResultAndType(false, false); InstructionDesc[enumCast(Op::OpTypeForwardPointer)].setResultAndType(false, false);
InstructionDesc[enumCast(Op::OpTypeFunction)].setResultAndType(true, false); InstructionDesc[enumCast(Op::OpTypeFunction)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpTypeEvent)].setResultAndType(true, false); InstructionDesc[enumCast(Op::OpTypeEvent)].setResultAndType(true, false);
@@ -1889,6 +1911,7 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpCooperativeVectorStoreNV)].setResultAndType(false, false); InstructionDesc[enumCast(Op::OpCooperativeVectorStoreNV)].setResultAndType(false, false);
InstructionDesc[enumCast(Op::OpCooperativeVectorOuterProductAccumulateNV)].setResultAndType(false, false); InstructionDesc[enumCast(Op::OpCooperativeVectorOuterProductAccumulateNV)].setResultAndType(false, false);
InstructionDesc[enumCast(Op::OpCooperativeVectorReduceSumAccumulateNV)].setResultAndType(false, false); InstructionDesc[enumCast(Op::OpCooperativeVectorReduceSumAccumulateNV)].setResultAndType(false, false);
InstructionDesc[enumCast(Op::OpMemberDecorateIdEXT)].setResultAndType(false, false);
InstructionDesc[enumCast(Op::OpTypeTensorARM)].setResultAndType(true, false); InstructionDesc[enumCast(Op::OpTypeTensorARM)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpTensorReadARM)].setResultAndType(true, true); InstructionDesc[enumCast(Op::OpTensorReadARM)].setResultAndType(true, true);
@@ -2043,6 +2066,7 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpTypeStruct)].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n..."); InstructionDesc[enumCast(Op::OpTypeStruct)].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n...");
InstructionDesc[enumCast(Op::OpTypeOpaque)].operands.push(OperandLiteralString, "The name of the opaque type."); InstructionDesc[enumCast(Op::OpTypeOpaque)].operands.push(OperandLiteralString, "The name of the opaque type.");
InstructionDesc[enumCast(Op::OpTypeUntypedPointerKHR)].operands.push(OperandStorage, "");
InstructionDesc[enumCast(Op::OpTypePointer)].operands.push(OperandStorage, ""); InstructionDesc[enumCast(Op::OpTypePointer)].operands.push(OperandStorage, "");
InstructionDesc[enumCast(Op::OpTypePointer)].operands.push(OperandId, "'Type'"); InstructionDesc[enumCast(Op::OpTypePointer)].operands.push(OperandId, "'Type'");
@@ -2070,6 +2094,9 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpSpecConstantOp)].operands.push(OperandLiteralNumber, "'Opcode'"); InstructionDesc[enumCast(Op::OpSpecConstantOp)].operands.push(OperandLiteralNumber, "'Opcode'");
InstructionDesc[enumCast(Op::OpSpecConstantOp)].operands.push(OperandVariableIds, "'Operands'"); InstructionDesc[enumCast(Op::OpSpecConstantOp)].operands.push(OperandVariableIds, "'Operands'");
InstructionDesc[enumCast(Op::OpUntypedVariableKHR)].operands.push(OperandStorage, "");
InstructionDesc[enumCast(Op::OpUntypedVariableKHR)].operands.push(OperandId, "'Type'", true);
InstructionDesc[enumCast(Op::OpUntypedVariableKHR)].operands.push(OperandId, "'Initializer'", true);
InstructionDesc[enumCast(Op::OpVariable)].operands.push(OperandStorage, ""); InstructionDesc[enumCast(Op::OpVariable)].operands.push(OperandStorage, "");
InstructionDesc[enumCast(Op::OpVariable)].operands.push(OperandId, "'Initializer'", true); InstructionDesc[enumCast(Op::OpVariable)].operands.push(OperandId, "'Initializer'", true);
@@ -2117,6 +2144,11 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpMemberDecorate)].operands.push(OperandDecoration, ""); InstructionDesc[enumCast(Op::OpMemberDecorate)].operands.push(OperandDecoration, "");
InstructionDesc[enumCast(Op::OpMemberDecorate)].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>."); InstructionDesc[enumCast(Op::OpMemberDecorate)].operands.push(OperandVariableLiterals, "See <<Decoration,'Decoration'>>.");
InstructionDesc[enumCast(Op::OpMemberDecorateIdEXT)].operands.push(OperandId, "'Structure Type'");
InstructionDesc[enumCast(Op::OpMemberDecorateIdEXT)].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[enumCast(Op::OpMemberDecorateIdEXT)].operands.push(OperandDecoration, "");
InstructionDesc[enumCast(Op::OpMemberDecorateIdEXT)].operands.push(OperandVariableIds, "See <<Decoration,'Decoration'>>.");
InstructionDesc[enumCast(Op::OpMemberDecorateStringGOOGLE)].operands.push(OperandId, "'Structure Type'"); InstructionDesc[enumCast(Op::OpMemberDecorateStringGOOGLE)].operands.push(OperandId, "'Structure Type'");
InstructionDesc[enumCast(Op::OpMemberDecorateStringGOOGLE)].operands.push(OperandLiteralNumber, "'Member'"); InstructionDesc[enumCast(Op::OpMemberDecorateStringGOOGLE)].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[enumCast(Op::OpMemberDecorateStringGOOGLE)].operands.push(OperandDecoration, ""); InstructionDesc[enumCast(Op::OpMemberDecorateStringGOOGLE)].operands.push(OperandDecoration, "");
@@ -2323,6 +2355,9 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpAccessChain)].operands.push(OperandId, "'Base'"); InstructionDesc[enumCast(Op::OpAccessChain)].operands.push(OperandId, "'Base'");
InstructionDesc[enumCast(Op::OpAccessChain)].operands.push(OperandVariableIds, "'Indexes'"); InstructionDesc[enumCast(Op::OpAccessChain)].operands.push(OperandVariableIds, "'Indexes'");
InstructionDesc[enumCast(Op::OpUntypedAccessChainKHR)].operands.push(OperandId, "'Base Type'");
InstructionDesc[enumCast(Op::OpUntypedAccessChainKHR)].operands.push(OperandId, "'Base'");
InstructionDesc[enumCast(Op::OpUntypedAccessChainKHR)].operands.push(OperandVariableIds, "'Indexes'");
InstructionDesc[enumCast(Op::OpInBoundsAccessChain)].operands.push(OperandId, "'Base'"); InstructionDesc[enumCast(Op::OpInBoundsAccessChain)].operands.push(OperandId, "'Base'");
InstructionDesc[enumCast(Op::OpInBoundsAccessChain)].operands.push(OperandVariableIds, "'Indexes'"); InstructionDesc[enumCast(Op::OpInBoundsAccessChain)].operands.push(OperandVariableIds, "'Indexes'");
@@ -3160,6 +3195,19 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpFragmentFetchAMD)].operands.push(OperandId, "'Coordinate'"); InstructionDesc[enumCast(Op::OpFragmentFetchAMD)].operands.push(OperandId, "'Coordinate'");
InstructionDesc[enumCast(Op::OpFragmentFetchAMD)].operands.push(OperandId, "'Fragment Index'"); InstructionDesc[enumCast(Op::OpFragmentFetchAMD)].operands.push(OperandId, "'Fragment Index'");
InstructionDesc[enumCast(Op::OpTypeBufferEXT)].operands.push(OperandStorage, "");
InstructionDesc[enumCast(Op::OpTypeBufferEXT)].setResultAndType(true, false);
InstructionDesc[enumCast(Op::OpConstantSizeOfEXT)].operands.push(OperandId, "'Type'");
InstructionDesc[enumCast(Op::OpBufferPointerEXT)].operands.push(OperandId, "'Buffer'");
InstructionDesc[enumCast(Op::OpUntypedImageTexelPointerEXT)].operands.push(OperandId, "'ImageType'");
InstructionDesc[enumCast(Op::OpUntypedImageTexelPointerEXT)].operands.push(OperandId, "'Image'");
InstructionDesc[enumCast(Op::OpUntypedImageTexelPointerEXT)].operands.push(OperandId, "'Coordinate'");
InstructionDesc[enumCast(Op::OpUntypedImageTexelPointerEXT)].operands.push(OperandId, "'Sample'");
InstructionDesc[enumCast(Op::OpGroupNonUniformPartitionNV)].operands.push(OperandId, "X"); InstructionDesc[enumCast(Op::OpGroupNonUniformPartitionNV)].operands.push(OperandId, "X");
InstructionDesc[enumCast(Op::OpGroupNonUniformQuadAllKHR)].operands.push(OperandId, "'Predicate'"); InstructionDesc[enumCast(Op::OpGroupNonUniformQuadAllKHR)].operands.push(OperandId, "'Predicate'");

View File

@@ -206,7 +206,7 @@ enum class ExecutionMode : unsigned {
SampleInterlockOrderedEXT = 5368, SampleInterlockOrderedEXT = 5368,
SampleInterlockUnorderedEXT = 5369, SampleInterlockUnorderedEXT = 5369,
ShadingRateInterlockOrderedEXT = 5370, ShadingRateInterlockOrderedEXT = 5370,
ShadingRateInterlockUnorderedEXT = 5371, ShadingRateInterlockUnorderedEXT = 5371,
Shader64BitIndexingEXT = 5427, Shader64BitIndexingEXT = 5427,
SharedLocalMemorySizeINTEL = 5618, SharedLocalMemorySizeINTEL = 5618,
RoundingModeRTPINTEL = 5620, RoundingModeRTPINTEL = 5620,
@@ -564,6 +564,8 @@ enum class Decoration : unsigned {
PayloadNodeSparseArrayAMDX = 5099, PayloadNodeSparseArrayAMDX = 5099,
PayloadNodeArraySizeAMDX = 5100, PayloadNodeArraySizeAMDX = 5100,
PayloadDispatchIndirectAMDX = 5105, PayloadDispatchIndirectAMDX = 5105,
ArrayStrideIdEXT = 5124,
OffsetIdEXT = 5125,
OverrideCoverageNV = 5248, OverrideCoverageNV = 5248,
PassthroughNV = 5250, PassthroughNV = 5250,
ViewportRelativeNV = 5252, ViewportRelativeNV = 5252,
@@ -580,8 +582,10 @@ enum class Decoration : unsigned {
RestrictPointerEXT = 5355, RestrictPointerEXT = 5355,
AliasedPointer = 5356, AliasedPointer = 5356,
AliasedPointerEXT = 5356, AliasedPointerEXT = 5356,
MemberOffsetNV = 5358,
HitObjectShaderRecordBufferNV = 5386, HitObjectShaderRecordBufferNV = 5386,
HitObjectShaderRecordBufferEXT = 5389, HitObjectShaderRecordBufferEXT = 5389,
BankNV = 5397,
BindlessSamplerNV = 5398, BindlessSamplerNV = 5398,
BindlessImageNV = 5399, BindlessImageNV = 5399,
BoundSamplerNV = 5400, BoundSamplerNV = 5400,
@@ -733,6 +737,8 @@ enum class BuiltIn : unsigned {
FragStencilRefEXT = 5014, FragStencilRefEXT = 5014,
RemainingRecursionLevelsAMDX = 5021, RemainingRecursionLevelsAMDX = 5021,
ShaderIndexAMDX = 5073, ShaderIndexAMDX = 5073,
SamplerHeapEXT = 5122,
ResourceHeapEXT = 5123,
ViewportMaskNV = 5253, ViewportMaskNV = 5253,
SecondaryPositionNV = 5257, SecondaryPositionNV = 5257,
SecondaryViewportMaskNV = 5258, SecondaryViewportMaskNV = 5258,
@@ -1127,6 +1133,7 @@ enum class Capability : unsigned {
BFloat16TypeKHR = 5116, BFloat16TypeKHR = 5116,
BFloat16DotProductKHR = 5117, BFloat16DotProductKHR = 5117,
BFloat16CooperativeMatrixKHR = 5118, BFloat16CooperativeMatrixKHR = 5118,
DescriptorHeapEXT = 5128,
SampleMaskOverrideCoverageNV = 5249, SampleMaskOverrideCoverageNV = 5249,
GeometryShaderPassthroughNV = 5251, GeometryShaderPassthroughNV = 5251,
ShaderViewportIndexLayerEXT = 5254, ShaderViewportIndexLayerEXT = 5254,
@@ -1199,7 +1206,9 @@ enum class Capability : unsigned {
RayTracingDisplacementMicromapNV = 5409, RayTracingDisplacementMicromapNV = 5409,
RawAccessChainsNV = 5414, RawAccessChainsNV = 5414,
RayTracingSpheresGeometryNV = 5418, RayTracingSpheresGeometryNV = 5418,
RayTracingLinearSweptSpheresGeometryNV = 5419, RayTracingLinearSweptSpheresGeometryNV = 5419,
PushConstantBanksNV = 5423,
LongVectorEXT = 5425,
Shader64BitIndexingEXT = 5426, Shader64BitIndexingEXT = 5426,
CooperativeMatrixReductionsNV = 5430, CooperativeMatrixReductionsNV = 5430,
CooperativeMatrixConversionsNV = 5431, CooperativeMatrixConversionsNV = 5431,
@@ -2031,6 +2040,11 @@ enum class Op : unsigned {
OpSpecConstantStringAMDX = 5104, OpSpecConstantStringAMDX = 5104,
OpGroupNonUniformQuadAllKHR = 5110, OpGroupNonUniformQuadAllKHR = 5110,
OpGroupNonUniformQuadAnyKHR = 5111, OpGroupNonUniformQuadAnyKHR = 5111,
OpTypeBufferEXT = 5115,
OpBufferPointerEXT = 5119,
OpUntypedImageTexelPointerEXT = 5126,
OpMemberDecorateIdEXT = 5127,
OpConstantSizeOfEXT = 5129,
OpHitObjectRecordHitMotionNV = 5249, OpHitObjectRecordHitMotionNV = 5249,
OpHitObjectRecordHitWithIndexMotionNV = 5250, OpHitObjectRecordHitWithIndexMotionNV = 5250,
OpHitObjectRecordMissMotionNV = 5251, OpHitObjectRecordMissMotionNV = 5251,
@@ -2066,6 +2080,7 @@ enum class Op : unsigned {
OpTypeHitObjectNV = 5281, OpTypeHitObjectNV = 5281,
OpImageSampleFootprintNV = 5283, OpImageSampleFootprintNV = 5283,
OpTypeCooperativeVectorNV = 5288, OpTypeCooperativeVectorNV = 5288,
OpTypeVectorIdEXT = 5288,
OpCooperativeVectorMatrixMulNV = 5289, OpCooperativeVectorMatrixMulNV = 5289,
OpCooperativeVectorOuterProductAccumulateNV = 5290, OpCooperativeVectorOuterProductAccumulateNV = 5290,
OpCooperativeVectorReduceSumAccumulateNV = 5291, OpCooperativeVectorReduceSumAccumulateNV = 5291,
@@ -2816,6 +2831,11 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case Op::OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; case Op::OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; case Op::OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; case Op::OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpBufferPointerEXT: *hasResult = true; *hasResultType = true; break;
case Op::OpUntypedImageTexelPointerEXT: *hasResult = true; *hasResultType = true; break;
case Op::OpMemberDecorateIdEXT: *hasResult = false; *hasResultType = false; break;
case Op::OpConstantSizeOfEXT: *hasResult = true; *hasResultType = true; break;
case Op::OpTypeBufferEXT: *hasResult = true; *hasResultType = false; break;
case Op::OpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break; case Op::OpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; case Op::OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpExtInstWithForwardRefsKHR: *hasResult = true; *hasResultType = true; break; case Op::OpExtInstWithForwardRefsKHR: *hasResult = true; *hasResultType = true; break;
@@ -3426,7 +3446,7 @@ inline const char* ExecutionModeToString(ExecutionMode value) {
case ExecutionMode::SampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT"; case ExecutionMode::SampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT";
case ExecutionMode::SampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT"; case ExecutionMode::SampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT";
case ExecutionMode::ShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT"; case ExecutionMode::ShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT";
case ExecutionMode::ShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT"; case ExecutionMode::ShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
case ExecutionMode::Shader64BitIndexingEXT: return "Shader64BitIndexingEXT"; case ExecutionMode::Shader64BitIndexingEXT: return "Shader64BitIndexingEXT";
case ExecutionMode::SharedLocalMemorySizeINTEL: return "SharedLocalMemorySizeINTEL"; case ExecutionMode::SharedLocalMemorySizeINTEL: return "SharedLocalMemorySizeINTEL";
case ExecutionMode::RoundingModeRTPINTEL: return "RoundingModeRTPINTEL"; case ExecutionMode::RoundingModeRTPINTEL: return "RoundingModeRTPINTEL";
@@ -3736,7 +3756,9 @@ inline const char* DecorationToString(Decoration value) {
case Decoration::NonUniform: return "NonUniform"; case Decoration::NonUniform: return "NonUniform";
case Decoration::RestrictPointer: return "RestrictPointer"; case Decoration::RestrictPointer: return "RestrictPointer";
case Decoration::AliasedPointer: return "AliasedPointer"; case Decoration::AliasedPointer: return "AliasedPointer";
case Decoration::MemberOffsetNV: return "MemberOffsetNV";
case Decoration::HitObjectShaderRecordBufferNV: return "HitObjectShaderRecordBufferNV"; case Decoration::HitObjectShaderRecordBufferNV: return "HitObjectShaderRecordBufferNV";
case Decoration::BankNV: return "BankNV";
case Decoration::HitObjectShaderRecordBufferEXT: return "HitObjectShaderRecordBufferEXT"; case Decoration::HitObjectShaderRecordBufferEXT: return "HitObjectShaderRecordBufferEXT";
case Decoration::BindlessSamplerNV: return "BindlessSamplerNV"; case Decoration::BindlessSamplerNV: return "BindlessSamplerNV";
case Decoration::BindlessImageNV: return "BindlessImageNV"; case Decoration::BindlessImageNV: return "BindlessImageNV";
@@ -4157,7 +4179,9 @@ inline const char* CapabilityToString(Capability value) {
case Capability::RayTracingDisplacementMicromapNV: return "RayTracingDisplacementMicromapNV"; case Capability::RayTracingDisplacementMicromapNV: return "RayTracingDisplacementMicromapNV";
case Capability::RawAccessChainsNV: return "RawAccessChainsNV"; case Capability::RawAccessChainsNV: return "RawAccessChainsNV";
case Capability::RayTracingSpheresGeometryNV: return "RayTracingSpheresGeometryNV"; case Capability::RayTracingSpheresGeometryNV: return "RayTracingSpheresGeometryNV";
case Capability::RayTracingLinearSweptSpheresGeometryNV: return "RayTracingLinearSweptSpheresGeometryNV"; case Capability::RayTracingLinearSweptSpheresGeometryNV: return "RayTracingLinearSweptSpheresGeometryNV";
case Capability::PushConstantBanksNV: return "PushConstantBanksNV";
case Capability::LongVectorEXT: return "LongVectorEXT";
case Capability::Shader64BitIndexingEXT: return "Shader64BitIndexingEXT"; case Capability::Shader64BitIndexingEXT: return "Shader64BitIndexingEXT";
case Capability::CooperativeMatrixReductionsNV: return "CooperativeMatrixReductionsNV"; case Capability::CooperativeMatrixReductionsNV: return "CooperativeMatrixReductionsNV";
case Capability::CooperativeMatrixConversionsNV: return "CooperativeMatrixConversionsNV"; case Capability::CooperativeMatrixConversionsNV: return "CooperativeMatrixConversionsNV";
@@ -4803,6 +4827,11 @@ inline const char* OpToString(Op value) {
case Op::OpSubgroupAllKHR: return "OpSubgroupAllKHR"; case Op::OpSubgroupAllKHR: return "OpSubgroupAllKHR";
case Op::OpSubgroupAnyKHR: return "OpSubgroupAnyKHR"; case Op::OpSubgroupAnyKHR: return "OpSubgroupAnyKHR";
case Op::OpSubgroupAllEqualKHR: return "OpSubgroupAllEqualKHR"; case Op::OpSubgroupAllEqualKHR: return "OpSubgroupAllEqualKHR";
case Op::OpBufferPointerEXT: return "OpBufferPointerEXT";
case Op::OpUntypedImageTexelPointerEXT: return "OpUntypedImageTexelPointerEXT";
case Op::OpMemberDecorateIdEXT: return "OpMemberDecorateIdEXT";
case Op::OpConstantSizeOfEXT: return "OpConstantSizeOfEXT";
case Op::OpTypeBufferEXT: return "OpTypeBufferEXT";
case Op::OpGroupNonUniformRotateKHR: return "OpGroupNonUniformRotateKHR"; case Op::OpGroupNonUniformRotateKHR: return "OpGroupNonUniformRotateKHR";
case Op::OpSubgroupReadInvocationKHR: return "OpSubgroupReadInvocationKHR"; case Op::OpSubgroupReadInvocationKHR: return "OpSubgroupReadInvocationKHR";
case Op::OpExtInstWithForwardRefsKHR: return "OpExtInstWithForwardRefsKHR"; case Op::OpExtInstWithForwardRefsKHR: return "OpExtInstWithForwardRefsKHR";

View File

@@ -222,6 +222,7 @@ public:
} }
Id getResultId() const { return resultId; } Id getResultId() const { return resultId; }
Id getTypeId() const { return typeId; } Id getTypeId() const { return typeId; }
void setTypeId(Id tId) { typeId = tId; }
Id getIdOperand(int op) const { Id getIdOperand(int op) const {
assert(idOperand[op]); assert(idOperand[op]);
return operands[op]; return operands[op];
@@ -574,7 +575,8 @@ public:
} }
StorageClass getStorageClass(Id typeId) const StorageClass getStorageClass(Id typeId) const
{ {
assert(idToInstruction[typeId]->getOpCode() == spv::Op::OpTypePointer); assert(idToInstruction[typeId]->getOpCode() == spv::Op::OpTypePointer ||
idToInstruction[typeId]->getOpCode() == spv::Op::OpTypeUntypedPointerKHR);
return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0);
} }

View File

@@ -113,6 +113,7 @@ enum TOptions : uint64_t {
EOptionDisplayErrorColumn = (1ull << 33), EOptionDisplayErrorColumn = (1ull << 33),
EOptionLinkTimeOptimization = (1ull << 34), EOptionLinkTimeOptimization = (1ull << 34),
EOptionValidateCrossStageIO = (1ull << 35), EOptionValidateCrossStageIO = (1ull << 35),
EOptionBindingsPerResourceType = (1ull << 36),
}; };
bool targetHlslFunctionality1 = false; bool targetHlslFunctionality1 = false;
bool SpvToolsDisassembler = false; bool SpvToolsDisassembler = false;
@@ -918,6 +919,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
Options |= EOptionLinkTimeOptimization; Options |= EOptionLinkTimeOptimization;
} else if (lowerword == "validate-io") { } else if (lowerword == "validate-io") {
Options |= EOptionValidateCrossStageIO; Options |= EOptionValidateCrossStageIO;
} else if (lowerword == "bindings-per-resource-type") {
Options |= EOptionBindingsPerResourceType;
} else if (lowerword == "help") { } else if (lowerword == "help") {
usage(); usage();
break; break;
@@ -1465,6 +1468,9 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (emitNonSemanticShaderDebugInfo) if (emitNonSemanticShaderDebugInfo)
shader->setDebugInfo(true); shader->setDebugInfo(true);
if (Options & EOptionBindingsPerResourceType)
shader->setBindingsPerResourceType();
// Set up the environment, some subsettings take precedence over earlier // Set up the environment, some subsettings take precedence over earlier
// ways of setting things. // ways of setting things.
if (Options & EOptionSpv) { if (Options & EOptionSpv) {
@@ -2194,7 +2200,8 @@ void usage()
" creates a C header file that contains a\n" " creates a C header file that contains a\n"
" uint32_t array named <name> initialized with\n" " uint32_t array named <name> initialized with\n"
" the shader binary code\n" " the shader binary code\n"
" --validate-io validate cross stage IO\n"); " --validate-io validate cross stage IO\n"
" --bindings-per-resource-type\n");
exit(EFailUsage); exit(EFailUsage);
} }

View File

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

View File

@@ -384,6 +384,10 @@ GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int opt
if (options & GLSLANG_SHADER_VULKAN_RULES_RELAXED) { if (options & GLSLANG_SHADER_VULKAN_RULES_RELAXED) {
shader->shader->setEnvInputVulkanRulesRelaxed(); shader->shader->setEnvInputVulkanRulesRelaxed();
} }
if (options & GLSLANG_SHADER_BINDINGS_PER_RESOURCE_TYPE) {
shader->shader->setBindingsPerResourceType();
}
} }
GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, int version) GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, int version)

View File

@@ -76,6 +76,7 @@ enum TBasicType {
EbtTensorViewNV, EbtTensorViewNV,
EbtCoopvecNV, EbtCoopvecNV,
EbtTensorARM, EbtTensorARM,
EbtLongVector,
// SPIR-V type defined by spirv_type // SPIR-V type defined by spirv_type
EbtSpirvType, EbtSpirvType,
@@ -143,6 +144,10 @@ enum TStorageQualifier {
EvqTileImageEXT, EvqTileImageEXT,
// EXT_structured_descriptor_heap
EvqSamplerHeap,
EvqResourceHeap,
// end of list // end of list
EvqLast EvqLast
}; };
@@ -353,6 +358,9 @@ enum TBuiltInVariable {
EbvTileOffsetQCOM, EbvTileOffsetQCOM,
EbvTileDimensionQCOM, EbvTileDimensionQCOM,
EbvTileApronSizeQCOM, EbvTileApronSizeQCOM,
// GL_EXT_descriptor_heap
EbvSamplerHeapEXT,
EbvResourceHeapEXT,
EbvLast EbvLast
}; };
@@ -603,6 +611,22 @@ __inline bool isTypeUnsignedInt(TBasicType type)
} }
} }
__inline TBasicType unsignedTypeToSigned(TBasicType type)
{
switch (type) {
case EbtUint8:
return EbtInt8;
case EbtUint16:
return EbtInt16;
case EbtUint:
return EbtInt;
case EbtUint64:
return EbtInt64;
default:
return type;
}
}
__inline bool isTypeInt(TBasicType type) __inline bool isTypeInt(TBasicType type)
{ {
return isTypeSignedInt(type) || isTypeUnsignedInt(type); return isTypeSignedInt(type) || isTypeUnsignedInt(type);

View File

@@ -517,6 +517,7 @@ public:
spirvByReference = false; spirvByReference = false;
spirvLiteral = false; spirvLiteral = false;
defaultBlock = false; defaultBlock = false;
usedByAtomic = false;
} }
// drop qualifiers that don't belong in a temporary variable // drop qualifiers that don't belong in a temporary variable
@@ -536,6 +537,7 @@ public:
spirvDecorate = nullptr; spirvDecorate = nullptr;
spirvByReference = false; spirvByReference = false;
spirvLiteral = false; spirvLiteral = false;
usedByAtomic = false;
} }
void clearInterstage() void clearInterstage()
@@ -617,6 +619,7 @@ public:
bool nullInit : 1; bool nullInit : 1;
bool spirvByReference : 1; bool spirvByReference : 1;
bool spirvLiteral : 1; bool spirvLiteral : 1;
bool usedByAtomic : 1; // EXT_descriptor_heap
bool isWriteOnly() const { return writeonly; } bool isWriteOnly() const { return writeonly; }
bool isReadOnly() const { return readonly; } bool isReadOnly() const { return readonly; }
bool isRestrict() const { return restrict; } bool isRestrict() const { return restrict; }
@@ -660,6 +663,8 @@ public:
bool isSpirvByReference() const { return spirvByReference; } bool isSpirvByReference() const { return spirvByReference; }
void setSpirvLiteral() { spirvLiteral = true; } void setSpirvLiteral() { spirvLiteral = true; }
bool isSpirvLiteral() const { return spirvLiteral; } bool isSpirvLiteral() const { return spirvLiteral; }
void setUsedByAtomic() { usedByAtomic = true; }
bool isUsedByAtomic() const { return usedByAtomic; }
bool isPipeInput() const bool isPipeInput() const
{ {
@@ -875,6 +880,11 @@ public:
clearInterstageLayout(); clearInterstageLayout();
layoutSpecConstantId = layoutSpecConstantIdEnd; layoutSpecConstantId = layoutSpecConstantIdEnd;
layoutBank = layoutBankEnd;
layoutDescriptorHeap = false;
layoutDescriptorStride = layoutDescriptorStrideEnd;
layoutHeapOffset = 0;
layoutDescriptorInnerBlock = false;
} }
void clearInterstageLayout() void clearInterstageLayout()
{ {
@@ -916,6 +926,7 @@ public:
TLayoutPacking layoutPacking : 4; TLayoutPacking layoutPacking : 4;
int layoutOffset; int layoutOffset;
int layoutAlign; int layoutAlign;
int layoutMemberOffset;
unsigned int layoutLocation : 12; unsigned int layoutLocation : 12;
static const unsigned int layoutLocationEnd = 0xFFF; static const unsigned int layoutLocationEnd = 0xFFF;
@@ -950,6 +961,12 @@ public:
unsigned int layoutSpecConstantId : 11; unsigned int layoutSpecConstantId : 11;
static const unsigned int layoutSpecConstantIdEnd = 0x7FF; static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
unsigned int layoutBank : 4;
static const unsigned int layoutBankEnd = 0xF;
unsigned int layoutDescriptorStride : 4;
static const unsigned int layoutDescriptorStrideEnd = 0x0;
// stored as log2 of the actual alignment value // stored as log2 of the actual alignment value
unsigned int layoutBufferReferenceAlign : 6; unsigned int layoutBufferReferenceAlign : 6;
static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
@@ -966,6 +983,9 @@ public:
bool layoutQuadDeriv; bool layoutQuadDeriv;
bool layoutHitObjectShaderRecordNV; bool layoutHitObjectShaderRecordNV;
bool layoutHitObjectShaderRecordEXT; bool layoutHitObjectShaderRecordEXT;
bool layoutDescriptorHeap;
bool layoutDescriptorInnerBlock;
int layoutHeapOffset;
// GL_EXT_spirv_intrinsics // GL_EXT_spirv_intrinsics
int spirvStorageClass; int spirvStorageClass;
@@ -991,6 +1011,7 @@ public:
layoutPacking = ElpNone; layoutPacking = ElpNone;
layoutOffset = layoutNotSet; layoutOffset = layoutNotSet;
layoutAlign = layoutNotSet; layoutAlign = layoutNotSet;
layoutMemberOffset = layoutNotSet;
layoutSet = layoutSetEnd; layoutSet = layoutSetEnd;
layoutBinding = layoutBindingEnd; layoutBinding = layoutBindingEnd;
@@ -1115,6 +1136,14 @@ public:
// is just whether or not it was declared with an ID. // is just whether or not it was declared with an ID.
return layoutSpecConstantId != layoutSpecConstantIdEnd; return layoutSpecConstantId != layoutSpecConstantIdEnd;
} }
bool hasBank() const
{
return layoutBank != layoutBankEnd;
}
bool hasMemberOffset() const
{
return layoutMemberOffset != layoutNotSet;
}
bool isSpecConstant() const bool isSpecConstant() const
{ {
// True if type is a specialization constant, whether or not it // True if type is a specialization constant, whether or not it
@@ -1514,6 +1543,7 @@ public:
bool coopmatNV : 1; bool coopmatNV : 1;
bool coopmatKHR : 1; bool coopmatKHR : 1;
bool coopvecNV : 1; bool coopvecNV : 1;
bool longVector : 1;
bool tileAttachmentQCOM: 1; bool tileAttachmentQCOM: 1;
uint32_t tensorRankARM : 4; uint32_t tensorRankARM : 4;
TArraySizes* arraySizes; TArraySizes* arraySizes;
@@ -1527,8 +1557,11 @@ public:
bool isCoopmatNV() const { return coopmatNV; } bool isCoopmatNV() const { return coopmatNV; }
bool isCoopmatKHR() const { return coopmatKHR; } bool isCoopmatKHR() const { return coopmatKHR; }
bool isCoopvecNV() const { return coopvecNV; } bool isCoopvecNV() const { return coopvecNV; }
bool isCoopmatOrvec() const { return isCoopmat() || isCoopvecNV() || isLongVector(); }
bool isLongVector() const { return longVector; }
bool isCoopvecOrLongVector() const { return isCoopvecNV() || isLongVector(); }
bool isTensorARM() const { return tensorRankARM; } bool isTensorARM() const { return tensorRankARM; }
bool hasTypeParameter() const { return isCoopmat() || isCoopvecNV() || isTensorARM(); } bool hasTypeParameter() const { return isCoopmat() || isCoopvecNV() || isLongVector() || isTensorARM(); }
bool isTensorLayoutNV() const { return basicType == EbtTensorLayoutNV; } bool isTensorLayoutNV() const { return basicType == EbtTensorLayoutNV; }
bool isTensorViewNV() const { return basicType == EbtTensorViewNV; } bool isTensorViewNV() const { return basicType == EbtTensorViewNV; }
@@ -1546,6 +1579,7 @@ public:
coopmatNV = false; coopmatNV = false;
coopmatKHR = false; coopmatKHR = false;
coopvecNV = false; coopvecNV = false;
longVector = false;
tileAttachmentQCOM = false; tileAttachmentQCOM = false;
tensorRankARM = 0; tensorRankARM = 0;
spirvType = nullptr; spirvType = nullptr;
@@ -1607,7 +1641,7 @@ public:
// for "empty" type (no args) or simple scalar/vector/matrix // for "empty" type (no args) or simple scalar/vector/matrix
explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
bool isVector = false) : bool isVector = false) :
basicType(t), vectorSize(static_cast<uint32_t>(vs) & 0b1111), matrixCols(static_cast<uint32_t>(mc) & 0b1111), matrixRows(static_cast<uint32_t>(mr) & 0b1111), vector1(isVector && vs == 1), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), basicType(t), vectorSize(static_cast<uint32_t>(vs) & 0b1111), matrixCols(static_cast<uint32_t>(mc) & 0b1111), matrixRows(static_cast<uint32_t>(mr) & 0b1111), vector1(isVector && vs == 1), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), longVector(false),
tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr), tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr),
spirvType(nullptr) spirvType(nullptr)
{ {
@@ -1623,7 +1657,7 @@ public:
// for explicit precision qualifier // for explicit precision qualifier
TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
bool isVector = false) : bool isVector = false) :
basicType(t), vectorSize(static_cast<uint32_t>(vs) & 0b1111), matrixCols(static_cast<uint32_t>(mc) & 0b1111), matrixRows(static_cast<uint32_t>(mr) & 0b1111), vector1(isVector && vs == 1), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), basicType(t), vectorSize(static_cast<uint32_t>(vs) & 0b1111), matrixCols(static_cast<uint32_t>(mc) & 0b1111), matrixRows(static_cast<uint32_t>(mr) & 0b1111), vector1(isVector && vs == 1), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), longVector(false),
tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr), tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr),
spirvType(nullptr) spirvType(nullptr)
{ {
@@ -1641,7 +1675,7 @@ public:
// for turning a TPublicType into a TType, using a shallow copy // for turning a TPublicType into a TType, using a shallow copy
explicit TType(const TPublicType& p) : explicit TType(const TPublicType& p) :
basicType(p.basicType), basicType(p.basicType),
vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmatNV(p.coopmatNV), coopmatKHR(p.coopmatKHR), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(p.coopvecNV), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmatNV(p.coopmatNV), coopmatKHR(p.coopmatKHR), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(p.coopvecNV), longVector(p.longVector),
tileAttachmentQCOM(p.tileAttachmentQCOM), tensorRankARM(p.tensorRankARM), arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters), tileAttachmentQCOM(p.tileAttachmentQCOM), tensorRankARM(p.tensorRankARM), arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters),
spirvType(p.spirvType) spirvType(p.spirvType)
{ {
@@ -1692,7 +1726,7 @@ public:
coopmatKHRUseValid = true; coopmatKHRUseValid = true;
} }
} }
if (p.isCoopvecNV() && p.typeParameters) { if ((p.isCoopvecNV() || p.isLongVector()) && p.typeParameters) {
basicType = p.typeParameters->basicType; basicType = p.typeParameters->basicType;
} }
if (p.isTensorARM() && p.typeParameters) { if (p.isTensorARM() && p.typeParameters) {
@@ -1704,7 +1738,7 @@ public:
} }
// for construction of sampler types // for construction of sampler types
TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
basicType(EbtSampler), vectorSize(1u), matrixCols(0u), matrixRows(0u), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), basicType(EbtSampler), vectorSize(1u), matrixCols(0u), matrixRows(0u), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), longVector(false),
tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
sampler(sampler), typeParameters(nullptr), spirvType(nullptr) sampler(sampler), typeParameters(nullptr), spirvType(nullptr)
{ {
@@ -1747,12 +1781,13 @@ public:
// dereference from vector to scalar // dereference from vector to scalar
vectorSize = 1; vectorSize = 1;
vector1 = false; vector1 = false;
} else if (isCoopMat() || isCoopVecNV()) { } else if (isCoopMat() || isCoopVecNV() || isLongVector()) {
coopmatNV = false; coopmatNV = false;
coopmatKHR = false; coopmatKHR = false;
coopmatKHRuse = 0; coopmatKHRuse = 0;
coopmatKHRUseValid = false; coopmatKHRUseValid = false;
coopvecNV = false; coopvecNV = false;
longVector = false;
typeParameters = nullptr; typeParameters = nullptr;
} else if (isTileAttachmentQCOM()) { } else if (isTileAttachmentQCOM()) {
tileAttachmentQCOM = false; tileAttachmentQCOM = false;
@@ -1762,7 +1797,7 @@ public:
} }
// for making structures, ... // for making structures, ...
TType(TTypeList* userDef, const TString& n) : TType(TTypeList* userDef, const TString& n) :
basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), longVector(false),
tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr), tileAttachmentQCOM(false), tensorRankARM(0), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr),
spirvType(nullptr) spirvType(nullptr)
{ {
@@ -1772,7 +1807,7 @@ public:
} }
// For interface blocks // For interface blocks
TType(TTypeList* userDef, const TString& n, const TQualifier& q) : TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), coopvecNV(false), longVector(false),
tileAttachmentQCOM(false), tensorRankARM(0), qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr), tileAttachmentQCOM(false), tensorRankARM(0), qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr),
spirvType(nullptr) spirvType(nullptr)
{ {
@@ -1821,6 +1856,7 @@ public:
coopmatKHRuse = copyOf.coopmatKHRuse; coopmatKHRuse = copyOf.coopmatKHRuse;
coopmatKHRUseValid = copyOf.coopmatKHRUseValid; coopmatKHRUseValid = copyOf.coopmatKHRUseValid;
coopvecNV = copyOf.isCoopVecNV(); coopvecNV = copyOf.isCoopVecNV();
longVector = copyOf.isLongVector();
tileAttachmentQCOM = copyOf.tileAttachmentQCOM; tileAttachmentQCOM = copyOf.tileAttachmentQCOM;
tensorRankARM = copyOf.tensorRankARM; tensorRankARM = copyOf.tensorRankARM;
} }
@@ -1907,7 +1943,7 @@ public:
virtual const TTypeParameters* getTypeParameters() const { return typeParameters; } virtual const TTypeParameters* getTypeParameters() const { return typeParameters; }
virtual TTypeParameters* getTypeParameters() { return typeParameters; } virtual TTypeParameters* getTypeParameters() { return typeParameters; }
virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray() && ! isCoopVecNV(); } virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray() && ! isCoopVecNV() && ! isLongVector(); }
virtual bool isScalarOrVec1() const { return isScalar() || vector1; } virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
virtual bool isScalarOrVector() const { return !isMatrix() && !isStruct() && !isArray(); } virtual bool isScalarOrVector() const { return !isMatrix() && !isStruct() && !isArray(); }
virtual bool isVector() const { return vectorSize > 1u || vector1; } virtual bool isVector() const { return vectorSize > 1u || vector1; }
@@ -1962,9 +1998,12 @@ public:
bool isCoopMatNV() const { return coopmatNV; } bool isCoopMatNV() const { return coopmatNV; }
bool isCoopMatKHR() const { return coopmatKHR; } bool isCoopMatKHR() const { return coopmatKHR; }
bool isCoopVecNV() const { return coopvecNV; } bool isCoopVecNV() const { return coopvecNV; }
bool isCoopMatOrVec() const { return isCoopMat() || isCoopVecNV() || isLongVector(); }
bool isLongVector() const { return longVector; }
bool isCoopVecOrLongVector() const { return isCoopVecNV() || isLongVector(); }
bool isTileAttachmentQCOM() const { return tileAttachmentQCOM; } bool isTileAttachmentQCOM() const { return tileAttachmentQCOM; }
bool isTensorARM() const { return tensorRankARM; } bool isTensorARM() const { return tensorRankARM; }
bool hasTypeParameter() const { return isCoopMat() || isCoopVecNV() || isTensorARM(); } bool hasTypeParameter() const { return isCoopMat() || isCoopVecNV() || isLongVector() || isTensorARM(); }
int getTensorRankARM() const { return static_cast<int>(tensorRankARM); } int getTensorRankARM() const { return static_cast<int>(tensorRankARM); }
bool isReference() const { return getBasicType() == EbtReference; } bool isReference() const { return getBasicType() == EbtReference; }
bool isSpirvType() const { return getBasicType() == EbtSpirvType; } bool isSpirvType() const { return getBasicType() == EbtSpirvType; }
@@ -1997,6 +2036,22 @@ public:
return contains([](const TType* t) { return t->isArray(); } ); return contains([](const TType* t) { return t->isArray(); } );
} }
// Recursively check the structure for any arrays, needed for some error checks
virtual bool containsHeapArray() const
{
const auto containsResourceArray = [](const TType* t) {
return (t->isArray() &&
(t->isImage() || t->isTexture() || t->getBasicType() == EbtSampler ||
t->getBasicType() == EbtAccStruct ||
t->getQualifier().storage == EvqUniform ||
t->getQualifier().storage == EvqResourceHeap ||
t->getQualifier().storage == EvqSamplerHeap ||
t->getQualifier().storage == EvqBuffer));
};
return contains(containsResourceArray);
}
// Check the structure for any structures, needed for some error checks // Check the structure for any structures, needed for some error checks
virtual bool containsStructure() const virtual bool containsStructure() const
{ {
@@ -2101,6 +2156,10 @@ public:
{ {
return contains([](const TType* t) { return t->coopvecNV; } ); return contains([](const TType* t) { return t->coopvecNV; } );
} }
bool containsLongVector() const
{
return contains([](const TType* t) { return t->longVector; } );
}
bool containsReference() const bool containsReference() const
{ {
return containsBasicType(EbtReference); return containsBasicType(EbtReference);
@@ -2225,6 +2284,7 @@ public:
case EbtTensorViewNV: return "tensorViewNV"; case EbtTensorViewNV: return "tensorViewNV";
case EbtCoopvecNV: return "coopvecNV"; case EbtCoopvecNV: return "coopvecNV";
case EbtTensorARM: return "tensorARM"; case EbtTensorARM: return "tensorARM";
case EbtLongVector: return "vector";
default: return "unknown type"; default: return "unknown type";
} }
} }
@@ -2342,11 +2402,29 @@ public:
if (qualifier.layoutHitObjectShaderRecordEXT) if (qualifier.layoutHitObjectShaderRecordEXT)
appendStr(" hitobjectshaderrecordext"); appendStr(" hitobjectshaderrecordext");
if (qualifier.hasBank()) {
appendStr(" bank=");
appendUint(qualifier.layoutBank);
}
if (qualifier.hasMemberOffset()) {
appendStr(" member_offset=");
appendInt(qualifier.layoutMemberOffset);
}
if (qualifier.layoutBindlessSampler) if (qualifier.layoutBindlessSampler)
appendStr(" layoutBindlessSampler"); appendStr(" layoutBindlessSampler");
if (qualifier.layoutBindlessImage) if (qualifier.layoutBindlessImage)
appendStr(" layoutBindlessImage"); appendStr(" layoutBindlessImage");
if (qualifier.layoutDescriptorHeap)
appendStr(" descriptor_heap");
if (qualifier.layoutDescriptorStride != TQualifier::layoutDescriptorStrideEnd) {
appendStr(" descriptor_stride=");
appendInt(qualifier.layoutDescriptorStride);
}
if (qualifier.layoutHeapOffset)
appendStr(" heap_offset=");
appendStr(")"); appendStr(")");
} }
} }
@@ -2551,6 +2629,10 @@ public:
appendStr(" "); appendStr(" ");
appendStr("coopvecNV"); appendStr("coopvecNV");
} }
if (isLongVector()) {
appendStr(" ");
appendStr("vector");
}
appendStr("<"); appendStr("<");
for (int i = 0; i < (int)typeParameters->arraySizes->getNumDims(); ++i) { for (int i = 0; i < (int)typeParameters->arraySizes->getNumDims(); ++i) {
@@ -2632,7 +2714,7 @@ public:
{ {
uint32_t components = 0; uint32_t components = 0;
if (isCoopVecNV()) { if (isCoopVecOrLongVector()) {
components = typeParameters->arraySizes->getDimSize(0); components = typeParameters->arraySizes->getDimSize(0);
} else if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { } else if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
@@ -2649,6 +2731,10 @@ public:
return static_cast<int>(components); return static_cast<int>(components);
} }
bool hasSpecConstantVectorComponents() const {
return getTypeParameters() && getTypeParameters()->arraySizes->getDimNode(0) != nullptr;
}
// append this type's mangled name to the passed in 'name' // append this type's mangled name to the passed in 'name'
void appendMangledName(TString& name) const void appendMangledName(TString& name) const
{ {
@@ -2839,6 +2925,7 @@ public:
isCoopMatNV() == right.isCoopMatNV() && isCoopMatNV() == right.isCoopMatNV() &&
isCoopMatKHR() == right.isCoopMatKHR() && isCoopMatKHR() == right.isCoopMatKHR() &&
isCoopVecNV() == right.isCoopVecNV() && isCoopVecNV() == right.isCoopVecNV() &&
isLongVector() == right.isLongVector() &&
isTensorARM() == right.isTensorARM() && isTensorARM() == right.isTensorARM() &&
sameStructType(right, lpidx, rpidx) && sameStructType(right, lpidx, rpidx) &&
sameReferenceType(right); sameReferenceType(right);
@@ -2935,6 +3022,26 @@ public:
return rv; return rv;
} }
bool sameLongVectorBaseType(const TType &right) const {
bool rv = false;
if (isLongVector() && right.isLongVector()) {
if (isFloatingDomain())
rv = right.isFloatingDomain() || right.getBasicType() == EbtLongVector;
else if (isTypeUnsignedInt(getBasicType()))
rv = isTypeUnsignedInt(right.getBasicType()) || right.getBasicType() == EbtLongVector;
else if (isTypeSignedInt(getBasicType()))
rv = isTypeSignedInt(right.getBasicType()) || right.getBasicType() == EbtLongVector;
else if (getBasicType() == EbtBool)
rv = right.getBasicType() == EbtBool || right.getBasicType() == EbtLongVector;
else if (getBasicType() == EbtLongVector)
rv = right.isLongVector();
else
rv = false;
}
return rv;
}
bool sameCoopMatUse(const TType &right) const { bool sameCoopMatUse(const TType &right) const {
return coopmatKHRuse == right.coopmatKHRuse; return coopmatKHRuse == right.coopmatKHRuse;
} }
@@ -2965,6 +3072,31 @@ public:
return true; return true;
} }
bool sameLongVectorShape(const TType &right) const
{
if (!isLongVector() || !right.isLongVector() || !typeParameters || !right.typeParameters)
return false;
return typeParameters->arraySizes->getDimSize(0) == right.typeParameters->arraySizes->getDimSize(0);
}
static bool vectorAndLongVectorMatch(const TType &left, const TType &right)
{
if (left.isVector() && right.isLongVector() &&
right.getTypeParameters() &&
!right.hasSpecConstantVectorComponents() &&
left.getVectorSize() == right.getTypeParameters()->arraySizes->getDimSize(0)) {
return true;
}
if (right.isVector() && left.isLongVector() &&
left.getTypeParameters() &&
!left.hasSpecConstantVectorComponents() &&
right.getVectorSize() == left.getTypeParameters()->arraySizes->getDimSize(0)) {
return true;
}
return false;
}
// See if two types match in all ways (just the actual type, not qualification) // See if two types match in all ways (just the actual type, not qualification)
bool operator==(const TType& right) const bool operator==(const TType& right) const
{ {
@@ -3065,6 +3197,7 @@ protected:
uint32_t coopmatKHRuse : 3; // Accepts one of three values: 0, 1, 2 (gl_MatrixUseA, gl_MatrixUseB, gl_MatrixUseAccumulator) uint32_t coopmatKHRuse : 3; // Accepts one of three values: 0, 1, 2 (gl_MatrixUseA, gl_MatrixUseB, gl_MatrixUseAccumulator)
bool coopmatKHRUseValid : 1; // True if coopmatKHRuse has been set bool coopmatKHRUseValid : 1; // True if coopmatKHRuse has been set
bool coopvecNV : 1; bool coopvecNV : 1;
bool longVector : 1;
bool tileAttachmentQCOM : 1; bool tileAttachmentQCOM : 1;
uint32_t tensorRankARM : 4; // 0 means not a tensor; non-zero indicates the tensor rank. uint32_t tensorRankARM : 4; // 0 means not a tensor; non-zero indicates the tensor rank.
TQualifier qualifier; TQualifier qualifier;

View File

@@ -213,6 +213,7 @@ typedef enum {
GLSLANG_SHADER_AUTO_MAP_BINDINGS = (1 << 0), GLSLANG_SHADER_AUTO_MAP_BINDINGS = (1 << 0),
GLSLANG_SHADER_AUTO_MAP_LOCATIONS = (1 << 1), GLSLANG_SHADER_AUTO_MAP_LOCATIONS = (1 << 1),
GLSLANG_SHADER_VULKAN_RULES_RELAXED = (1 << 2), GLSLANG_SHADER_VULKAN_RULES_RELAXED = (1 << 2),
GLSLANG_SHADER_BINDINGS_PER_RESOURCE_TYPE = (1 << 3),
LAST_ELEMENT_MARKER(GLSLANG_SHADER_COUNT), LAST_ELEMENT_MARKER(GLSLANG_SHADER_COUNT),
} glslang_shader_options_t; } glslang_shader_options_t;

View File

@@ -394,6 +394,83 @@ void AddTabledBuiltin(TString& decls, const BuiltInFunction& function)
} }
} }
// Add long vector prototype for the builtin function. This is similar to
// AddTabledBuiltin, but only generates builtins where one type is an
// arbitrary vector. See comments on "enum ArgClass" for more details.
void AddLongVectorBuiltin(TString& decls, const BuiltInFunction& function)
{
const auto isScalarType = [](int type) { return (type & TypeStringColumnMask) == 0; };
// loop across these two:
// 0: the varying arg set, and
// 1: the fixed scalar args
const ArgClass ClassFixed = (ArgClass)(ClassLS | ClassXLS | ClassLS2 | ClassFS | ClassFS2);
for (int fixed = 0; fixed < ((function.classes & ClassFixed) > 0 ? 2 : 1); ++fixed) {
if (fixed == 0 && (function.classes & ClassXLS))
continue;
// Iterate over the different scalar types (needed for ClassRS)
for (int type = 0; type < TypeStringCount; ++type) {
if (!isScalarType(type))
continue;
// skip types not selected: go from type to row number to type bit
if ((function.types & (1 << (type >> TypeStringRowShift))) == 0)
continue;
// skip scalar-only
if (function.classes & ClassV1)
continue;
// skip 3-vector
if (function.classes & ClassV3)
continue;
TString decl;
// return type
if (function.classes & ClassB)
decl.append("vector");
else if (function.classes & ClassRS)
decl.append(TypeString[type & TypeStringScalarMask]);
else
decl.append("vector");
decl.append(" ");
decl.append(function.name);
decl.append("(");
// arguments
for (int arg = 0; arg < function.numArguments; ++arg) {
if (arg == function.numArguments - 1 && (function.classes & ClassLO))
decl.append("out ");
if (arg == 0) {
if (function.classes & ClassCVN)
decl.append("coherent volatile nontemporal ");
if (function.classes & ClassFIO)
decl.append("inout ");
if (function.classes & ClassFO)
decl.append("out ");
}
if ((function.classes & ClassLB) && arg == function.numArguments - 1)
decl.append("vector");
else if (fixed && ((arg == function.numArguments - 1 && (function.classes & (ClassLS | ClassXLS |
ClassLS2))) ||
(arg == function.numArguments - 2 && (function.classes & ClassLS2)) ||
(arg == 0 && (function.classes & (ClassFS | ClassFS2))) ||
(arg == 1 && (function.classes & ClassFS2))))
decl.append(TypeString[type & TypeStringScalarMask]);
else
decl.append("vector");
if (arg < function.numArguments - 1)
decl.append(",");
}
decl.append(");\n");
decls.append(decl);
}
}
}
// See if the tabled versioning information allows the current version. // See if the tabled versioning information allows the current version.
bool ValidVersion(const BuiltInFunction& function, int version, EProfile profile, const SpvVersion& /* spVersion */) bool ValidVersion(const BuiltInFunction& function, int version, EProfile profile, const SpvVersion& /* spVersion */)
{ {
@@ -432,8 +509,12 @@ void TBuiltIns::addTabledBuiltins(int version, EProfile profile, const SpvVersio
{ {
const auto forEachFunction = [&](TString& decls, const span<const BuiltInFunction>& functions) { const auto forEachFunction = [&](TString& decls, const span<const BuiltInFunction>& functions) {
for (const auto& fn : functions) { for (const auto& fn : functions) {
if (ValidVersion(fn, version, profile, spvVersion)) if (ValidVersion(fn, version, profile, spvVersion)) {
AddTabledBuiltin(decls, fn); AddTabledBuiltin(decls, fn);
if (profile != EEsProfile) {
AddLongVectorBuiltin(decls, fn);
}
}
} }
}; };
@@ -2498,6 +2579,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
snprintf(buf, bufSize, op, intTypes[j], intTypes[j]); snprintf(buf, bufSize, op, intTypes[j], intTypes[j]);
commonBuiltins.append(buf); commonBuiltins.append(buf);
} }
snprintf(buf, bufSize, op, "vector", "vector");
commonBuiltins.append(buf);
} }
stageBuiltins[EShLangCompute].append( stageBuiltins[EShLangCompute].append(
@@ -5060,12 +5143,124 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"coopvecNV log(coopvecNV);\n" "coopvecNV log(coopvecNV);\n"
"coopvecNV tanh(coopvecNV);\n" "coopvecNV tanh(coopvecNV);\n"
"coopvecNV atan(coopvecNV);\n" "coopvecNV atan(coopvecNV);\n"
"coopvecNV clamp(coopvecNV, coopvecNV, coopvecNV);\n" "coopvecNV clamp(coopvecNV, coopvecNV, coopvecNV);\n";
"\n"
;
commonBuiltins.append(cooperativeVectorFuncs.c_str()); commonBuiltins.append(cooperativeVectorFuncs.c_str());
if (profile != EEsProfile) {
std::string longVectorFuncs =
// manually add long vector prototypes for functions not in BaseFunctions/etc
"vector frexp(vector, vector);\n"
"vector ldexp(vector, vector);\n"
"vector fma(vector, vector, vector);\n"
"vector floatBitsToInt(vector);\n"
"vector floatBitsToUint(vector);\n"
"vector intBitsToFloat(vector);\n"
"vector uintBitsToFloat(vector);\n"
"vector doubleBitsToInt64(vector);"
"vector doubleBitsToUint64(vector);"
"vector int64BitsToDouble(vector);"
"vector uint64BitsToDouble(vector);"
"vector bfloat16BitsToIntEXT(vector);"
"vector bfloat16BitsToUintEXT(vector);"
"vector intBitsToBFloat16EXT(vector);"
"vector uintBitsToBFloat16EXT(vector);"
"vector halfBitsToInt16(vector);"
"vector halfBitsToUint16(vector);"
"vector float16BitsToInt16(vector);"
"vector float16BitsToUint16(vector);"
"vector int16BitsToFloat16(vector);"
"vector uint16BitsToFloat16(vector);"
"vector int16BitsToHalf(vector);"
"vector uint16BitsToHalf(vector);"
"vector floate5m2BitsToIntEXT(vector);"
"vector floate5m2BitsToUintEXT(vector);"
"vector intBitsToFloate5m2EXT(vector);"
"vector uintBitsToFloate5m2EXT(vector);"
"vector floate4m3BitsToIntEXT(vector);"
"vector floate4m3BitsToUintEXT(vector);"
"vector intBitsToFloate4m3EXT(vector);"
"vector uintBitsToFloate4m3EXT(vector);"
"vector uaddCarry(highp vector, highp vector, out lowp vector carry);"
"vector usubBorrow(highp vector, highp vector, out lowp vector borrow);"
"void umulExtended(highp vector, highp vector, out highp vector, out highp vector);"
"void imulExtended(highp vector, highp vector, out highp vector, out highp vector);"
"vector bitfieldExtract(vector, int, int);"
"vector bitfieldInsert(vector, vector, int, int);"
"vector bitfieldReverse(highp vector);"
"vector bitCount(vector);"
"vector findLSB(vector);"
"vector findMSB(vector);"
// BaseFunctions overloads with a scalar parameter don't get generated in AddLongVectorBuiltin
"vector mod(vector, double);\n"
"vector min(vector, double);\n"
"vector max(vector, double);\n"
"vector clamp(vector, double, double);"
"vector mix(vector, vector, double);"
"vector step(double, vector);"
"vector smoothstep(double, double, vector);"
"vector refract(vector, vector, double);"
"vector mod(vector, float16_t);\n"
"vector min(vector, float16_t);\n"
"vector max(vector, float16_t);\n"
"vector clamp(vector, float16_t, float16_t);"
"vector mix(vector, vector, float16_t);"
"vector step(float16_t, vector);"
"vector smoothstep(float16_t, float16_t, vector);"
"vector refract(vector, vector, float16_t);"
"vector min(vector, uint64_t);\n"
"vector max(vector, uint64_t);\n"
"vector clamp(vector, uint64_t, uint64_t);"
"vector mix(vector, vector, uint64_t);"
"vector min(vector, int64_t);\n"
"vector max(vector, int64_t);\n"
"vector clamp(vector, int64_t, int64_t);"
"vector mix(vector, vector, int64_t);"
"vector min(vector, uint16_t);\n"
"vector max(vector, uint16_t);\n"
"vector clamp(vector, uint16_t, uint16_t);"
"vector mix(vector, vector, uint16_t);"
"vector min(vector, int16_t);\n"
"vector max(vector, int16_t);\n"
"vector clamp(vector, int16_t, int16_t);"
"vector mix(vector, vector, int16_t);"
"vector min(vector, uint8_t);\n"
"vector max(vector, uint8_t);\n"
"vector clamp(vector, uint8_t, uint8_t);"
"vector mix(vector, vector, uint8_t);"
"vector min(vector, int8_t);\n"
"vector max(vector, int8_t);\n"
"vector clamp(vector, int8_t, int8_t);"
"vector mix(vector, vector, int8_t);"
"vector expectEXT(vector, vector);"
;
std::string longVectorDerivativeFuncs =
"vector dFdxFine(vector);"
"vector dFdyFine(vector);"
"vector fwidthFine(vector);"
"vector dFdxCoarse(vector);"
"vector dFdyCoarse(vector);"
"vector fwidthCoarse(vector);"
;
commonBuiltins.append(longVectorFuncs.c_str());
stageBuiltins[EShLangFragment].append(longVectorDerivativeFuncs.c_str());
stageBuiltins[EShLangCompute].append(longVectorDerivativeFuncs.c_str());
}
const char *scalarAndVectorTypes[] = { const char *scalarAndVectorTypes[] = {
"int8_t", "int8_t",
"int16_t", "int16_t",
@@ -11548,4 +11743,407 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
} }
} }
// Determine whether this fnCandidate overload is supported for these arguments.
// Some of this is based on the BaseFunctions table, but for functions not in that
// table there's some handcoded logic.
// If the overload is supported, then this sets the specific parameter/result
// types and returns true.
bool IsSupportedLongVectorBuiltin(const TFunction* fnCandidate, TType* resultType, TIntermNode* arguments)
{
TOperator op = fnCandidate->getBuiltInOp();
const auto &getArg = [&](uint32_t i) {
TIntermAggregate* aggregate = arguments->getAsAggregate();
return fnCandidate->getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped());
};
bool valid = true;
const auto &checkFnTypes = [&](TIntermTyped *t, uint32_t types) {
if (t->getType().isFloatingDomain() && !(types & TypeF)) {
valid = false;
}
if (isTypeSignedInt(t->getType().getBasicType()) && !(types & TypeI)) {
valid = false;
}
if (isTypeUnsignedInt(t->getType().getBasicType()) && !(types & TypeU)) {
valid = false;
}
if (t->getType().getBasicType() == EbtBool && !(types & TypeB)) {
valid = false;
}
};
const auto &checkShape = [&](TIntermTyped *t0, TIntermTyped *t1) {
if (!t0->getType().sameLongVectorShape(t1->getType())) {
valid = false;
}
};
const auto &checkSameType = [&](TIntermTyped *t0, TIntermTyped *t1) {
if (t0->getType() != t1->getType()) {
valid = false;
}
};
const auto &checkArgsMatch = [&](uint32_t argStart, uint32_t argEnd, uint32_t types) {
for (uint32_t i = argStart; i < argEnd; ++i) {
checkFnTypes(getArg(i), types);
if (i != argStart) {
checkSameType(getArg(argStart), getArg(i));
}
}
};
uint32_t paramCount = fnCandidate->getParamCount();
bool foundInBase = false;
for (const auto &fn : BaseFunctions) {
if (fn.op != op) {
continue;
}
valid = true;
foundInBase = true;
TIntermTyped *firstLongVector = nullptr;
for (uint32_t i = 0; i < paramCount; ++i) {
TIntermTyped* arg = getArg(i);
ArgType argType = fn.types;
if (i == paramCount - 1 && (fn.classes & ClassLB)) {
argType = TypeB;
}
checkFnTypes(arg, argType);
if ((fn.classes & ClassLS) && getArg(paramCount-1)->getType().isScalar()) {
if (getArg(paramCount-1)->getType().getBasicType() != arg->getBasicType()) {
valid = false;
}
}
if (arg->getType().isLongVector()) {
if (firstLongVector != nullptr) {
checkShape(firstLongVector, arg);
}
if (firstLongVector == nullptr) {
firstLongVector = arg;
}
}
}
uint32_t argsToMatchStart = 0;
uint32_t argsToMatchEnd = paramCount;
if (fn.classes & ClassFS)
argsToMatchStart++;
if (fn.classes & ClassFS2)
argsToMatchStart += 2;
if ((fn.classes & ClassLS) && getArg(paramCount-1)->getType().isScalar())
argsToMatchEnd--;
if (fn.classes & ClassXLS)
argsToMatchEnd--;
if (fn.classes & ClassLS2)
argsToMatchEnd -= 2;
if (fn.classes & ClassLB)
argsToMatchEnd--;
checkArgsMatch(argsToMatchStart, argsToMatchEnd, fn.types);
// These ops (arbitrarily) don't support double precision
switch (op) {
case EOpRadians:
case EOpDegrees:
case EOpSin:
case EOpCos:
case EOpTan:
case EOpAcos:
case EOpAsin:
case EOpAtan:
case EOpAcosh:
case EOpAsinh:
case EOpAtanh:
case EOpTanh:
case EOpCosh:
case EOpSinh:
case EOpPow:
case EOpExp:
case EOpLog:
case EOpExp2:
case EOpLog2:
if (getArg(0)->getType().getBasicType() == EbtDouble) {
return false;
}
break;
default:
break;
}
if (valid) {
// It's valid, so override the types and return true
assert(firstLongVector);
resultType->deepCopy(firstLongVector->getType());
if (fn.classes & ClassB) {
resultType->setBasicType(EbtBool);
}
if (fn.classes & ClassRS) {
resultType->deepCopy(TType(firstLongVector->getType().getBasicType()));
}
if (fn.classes & ClassLO) {
getArg(fnCandidate->getParamCount() - 1)->setType(getArg(0)->getType());
}
return true;
}
}
// If it was in the base table but not supported, fail. The rest of the logic
// is for ops not in the base table.
if (foundInBase) {
return false;
}
// Check the arg0 type and if this and other checks have passed, then set
// the result type to the bitcasted result
const auto &checkBitCast = [&](TBasicType fromBasicType, TBasicType newBasicType) {
if (getArg(0)->getType().getBasicType() != fromBasicType) {
valid = false;
}
if (valid) {
resultType->deepCopy(getArg(0)->getType());
resultType->setBasicType(newBasicType);
}
};
valid = true;
switch (op) {
case EOpFrexp:
case EOpLdexp:
checkFnTypes(getArg(0), TypeF);
checkFnTypes(getArg(1), TypeI);
checkShape(getArg(0), getArg(1));
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpFloatBitsToInt:
if (fnCandidate->getName() == "bfloat16BitsToIntEXT") {
checkBitCast(EbtBFloat16, EbtInt16);
} else if (fnCandidate->getName() == "floate5m2BitsToIntEXT") {
checkBitCast(EbtFloatE5M2, EbtInt8);
} else if (fnCandidate->getName() == "floate4m3BitsToIntEXT") {
checkBitCast(EbtFloatE4M3, EbtInt8);
} else {
checkBitCast(EbtFloat, EbtInt);
}
return valid;
case EOpFloatBitsToUint:
if (fnCandidate->getName() == "bfloat16BitsToUintEXT") {
checkBitCast(EbtBFloat16, EbtUint16);
} else if (fnCandidate->getName() == "floate5m2BitsToUintEXT") {
checkBitCast(EbtFloatE5M2, EbtUint8);
} else if (fnCandidate->getName() == "floate4m3BitsToUintEXT") {
checkBitCast(EbtFloatE4M3, EbtUint8);
} else {
checkBitCast(EbtFloat, EbtUint);
}
return valid;
case EOpIntBitsToFloat:
if (fnCandidate->getName() == "intBitsToBFloat16EXT") {
checkBitCast(EbtInt16, EbtBFloat16);
} else if (fnCandidate->getName() == "intBitsToFloate5m2EXT") {
checkBitCast(EbtInt8, EbtFloatE5M2);
} else if (fnCandidate->getName() == "intBitsToFloate4m3EXT") {
checkBitCast(EbtInt8, EbtFloatE4M3);
} else {
checkBitCast(EbtInt, EbtFloat);
}
return valid;
case EOpUintBitsToFloat:
if (fnCandidate->getName() == "uintBitsToBFloat16EXT") {
checkBitCast(EbtUint16, EbtBFloat16);
} else if (fnCandidate->getName() == "uintBitsToFloate5m2EXT") {
checkBitCast(EbtUint8, EbtFloatE5M2);
} else if (fnCandidate->getName() == "uintBitsToFloate4m3EXT") {
checkBitCast(EbtUint8, EbtFloatE4M3);
} else {
checkBitCast(EbtUint, EbtFloat);
}
return valid;
case EOpDoubleBitsToInt64:
checkBitCast(EbtDouble, EbtInt64);
return valid;
case EOpDoubleBitsToUint64:
checkBitCast(EbtDouble, EbtUint64);
return valid;
case EOpInt64BitsToDouble:
checkBitCast(EbtInt64, EbtDouble);
return valid;
case EOpUint64BitsToDouble:
checkBitCast(EbtUint64, EbtDouble);
return valid;
case EOpFloat16BitsToInt16:
checkBitCast(EbtFloat16, EbtInt16);
return valid;
case EOpFloat16BitsToUint16:
checkBitCast(EbtFloat16, EbtUint16);
return valid;
case EOpInt16BitsToFloat16:
checkBitCast(EbtInt16, EbtFloat16);
return valid;
case EOpUint16BitsToFloat16:
checkBitCast(EbtUint16, EbtFloat16);
return valid;
case EOpFma:
checkArgsMatch(0, paramCount, TypeF);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpAddCarry:
case EOpSubBorrow:
checkArgsMatch(0, paramCount, TypeU);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpUMulExtended:
checkArgsMatch(0, paramCount, TypeU);
return valid;
case EOpIMulExtended:
checkArgsMatch(0, paramCount, TypeI);
return valid;
case EOpBitfieldExtract:
case EOpBitFieldReverse:
checkFnTypes(getArg(0), TypeIU);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpBitfieldInsert:
checkArgsMatch(0, 2, TypeIU);
checkSameType(getArg(0), getArg(1));
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpFindLSB:
case EOpFindMSB:
case EOpBitCount:
checkFnTypes(getArg(0), TypeIU);
if (valid) {
TType newType;
newType.deepCopy(getArg(0)->getType());
newType.setBasicType(unsignedTypeToSigned(newType.getBasicType()));
resultType->deepCopy(newType);
}
return valid;
case EOpDPdx:
case EOpDPdxFine:
case EOpDPdxCoarse:
case EOpDPdy:
case EOpDPdyFine:
case EOpDPdyCoarse:
case EOpFwidth:
case EOpFwidthFine:
case EOpFwidthCoarse:
checkFnTypes(getArg(0), TypeF);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpExpectEXT:
checkArgsMatch(0, paramCount, TypeIU | TypeB);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpSubgroupPartition:
resultType->deepCopy(TType(EbtUint, EvqTemporary, 4));
return valid;
case EOpSubgroupAllEqual:
resultType->deepCopy(TType(EbtBool));
return valid;
case EOpSubgroupAnd:
case EOpSubgroupOr:
case EOpSubgroupXor:
case EOpSubgroupInclusiveAnd:
case EOpSubgroupInclusiveOr:
case EOpSubgroupInclusiveXor:
case EOpSubgroupExclusiveAnd:
case EOpSubgroupExclusiveOr:
case EOpSubgroupExclusiveXor:
case EOpSubgroupClusteredAnd:
case EOpSubgroupClusteredOr:
case EOpSubgroupClusteredXor:
case EOpSubgroupPartitionedAnd:
case EOpSubgroupPartitionedOr:
case EOpSubgroupPartitionedXor:
case EOpSubgroupPartitionedInclusiveAnd:
case EOpSubgroupPartitionedInclusiveOr:
case EOpSubgroupPartitionedInclusiveXor:
case EOpSubgroupPartitionedExclusiveAnd:
case EOpSubgroupPartitionedExclusiveOr:
case EOpSubgroupPartitionedExclusiveXor:
checkFnTypes(getArg(0), TypeIU | TypeB);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpSubgroupBroadcast:
case EOpSubgroupBroadcastFirst:
case EOpSubgroupShuffle:
case EOpSubgroupShuffleXor:
case EOpSubgroupShuffleUp:
case EOpSubgroupShuffleDown:
case EOpSubgroupRotate:
case EOpSubgroupClusteredRotate:
case EOpSubgroupQuadBroadcast:
case EOpSubgroupQuadSwapHorizontal:
case EOpSubgroupQuadSwapVertical:
case EOpSubgroupQuadSwapDiagonal:
checkFnTypes(getArg(0), TypeIU | TypeB | TypeF);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
case EOpSubgroupAdd:
case EOpSubgroupMul:
case EOpSubgroupMin:
case EOpSubgroupMax:
case EOpSubgroupInclusiveAdd:
case EOpSubgroupInclusiveMul:
case EOpSubgroupInclusiveMin:
case EOpSubgroupInclusiveMax:
case EOpSubgroupExclusiveAdd:
case EOpSubgroupExclusiveMul:
case EOpSubgroupExclusiveMin:
case EOpSubgroupExclusiveMax:
case EOpSubgroupClusteredAdd:
case EOpSubgroupClusteredMul:
case EOpSubgroupClusteredMin:
case EOpSubgroupClusteredMax:
case EOpSubgroupPartitionedAdd:
case EOpSubgroupPartitionedMul:
case EOpSubgroupPartitionedMin:
case EOpSubgroupPartitionedMax:
case EOpSubgroupPartitionedInclusiveAdd:
case EOpSubgroupPartitionedInclusiveMul:
case EOpSubgroupPartitionedInclusiveMin:
case EOpSubgroupPartitionedInclusiveMax:
case EOpSubgroupPartitionedExclusiveAdd:
case EOpSubgroupPartitionedExclusiveMul:
case EOpSubgroupPartitionedExclusiveMin:
case EOpSubgroupPartitionedExclusiveMax:
checkFnTypes(getArg(0), TypeIU | TypeF);
if (valid) {
resultType->deepCopy(getArg(0)->getType());
}
return valid;
default:
break;
}
return false;
}
} // end namespace glslang } // end namespace glslang

View File

@@ -110,6 +110,9 @@ protected:
// change this back to false if depending on textual spellings of texturing calls when consuming the AST // change this back to false if depending on textual spellings of texturing calls when consuming the AST
// Using PureOperatorBuiltins=false is deprecated. // Using PureOperatorBuiltins=false is deprecated.
constexpr bool PureOperatorBuiltins = true; constexpr bool PureOperatorBuiltins = true;
bool IsSupportedLongVectorBuiltin(const TFunction* fnCandidate, TType* resultType, TIntermNode* arguments);
} // end namespace glslang } // end namespace glslang
#endif // _INITIALIZE_INCLUDED_ #endif // _INITIALIZE_INCLUDED_

View File

@@ -407,11 +407,15 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child,
} }
if (newType != EbtVoid) { if (newType != EbtVoid) {
child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(), TType newTType(newType, EvqTemporary, child->getVectorSize(), child->getMatrixCols(), child->getMatrixRows(), child->isVector());
child->getMatrixCols(), if (child->getType().isLongVector()) {
child->getMatrixRows(), newTType.shallowCopy(child->getType());
child->isVector()), newTType.setBasicType(newType);
child); newTType.makeTemporary();
newTType.getQualifier().clear();
}
child = addConversion(op, newTType, child);
if (child == nullptr) if (child == nullptr)
return nullptr; return nullptr;
} }
@@ -647,6 +651,12 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
} }
TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows()); TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
if (node->getType().isLongVector()) {
newType.shallowCopy(node->getType());
newType.setBasicType(convertTo);
newType.makeTemporary();
newType.getQualifier().clear();
}
newNode = addUnaryNode(newOp, node, node->getLoc(), newType); newNode = addUnaryNode(newOp, node, node->getLoc(), newType);
if (node->getAsConstantUnion()) { if (node->getAsConstantUnion()) {
@@ -1859,7 +1869,7 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
if (type.isCoopMatKHR()) if (type.isCoopMatKHR())
return EOpConstructCooperativeMatrixKHR; return EOpConstructCooperativeMatrixKHR;
if (type.isCoopVecNV()) if (type.isCoopVecOrLongVector())
return EOpConstructCooperativeVectorNV; return EOpConstructCooperativeVectorNV;
switch (type.getBasicType()) { switch (type.getBasicType()) {
@@ -3456,6 +3466,8 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
return false; return false;
} }
bool vectorAndLongVectorMatch = TType::vectorAndLongVectorMatch(left->getType(), right->getType());
// Finish handling the case, for all ops, where both operands are scalars. // Finish handling the case, for all ops, where both operands are scalars.
if (left->isScalar() && right->isScalar()) if (left->isScalar() && right->isScalar())
return true; return true;
@@ -3464,6 +3476,10 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1) if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1)
return false; return false;
// Finish handling the case, for all ops, where there are two vectors of different sizes
if (left->getType().isLongVector() && right->getType().isLongVector() && !left->getType().sameLongVectorShape(right->getType()))
return false;
// //
// We now have a mix of scalars, vectors, or matrices, for non-relational operations. // We now have a mix of scalars, vectors, or matrices, for non-relational operations.
// //
@@ -3549,7 +3565,8 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
break; break;
case EOpAssign: case EOpAssign:
if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()) if ((left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()) &&
!vectorAndLongVectorMatch)
return false; return false;
[[fallthrough]]; [[fallthrough]];
@@ -3576,7 +3593,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
return false; return false;
if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
return false; return false;
if (right->isVector() || right->isMatrix()) { if ((right->isVector() || right->isMatrix()) && !vectorAndLongVectorMatch) {
node.getWritableType().shallowCopy(right->getType()); node.getWritableType().shallowCopy(right->getType());
node.getWritableType().getQualifier().makeTemporary(); node.getWritableType().getQualifier().makeTemporary();
} }

View File

@@ -565,7 +565,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
variableCheck(base); variableCheck(base);
if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat() && if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat() &&
! base->isReference() && ! base->getType().isCoopVecNV()) { ! base->isReference() && ! base->getType().isCoopVecOrLongVector()) {
if (base->getAsSymbolNode()) if (base->getAsSymbolNode())
error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
else else
@@ -996,7 +996,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
const char* feature = ".length() on vectors and matrices"; const char* feature = ".length() on vectors and matrices";
requireProfile(loc, ~EEsProfile, feature); requireProfile(loc, ~EEsProfile, feature);
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature); profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
} else if (!base->getType().isCoopMat() && !base->getType().isCoopVecNV()) { } else if (!base->getType().isCoopMat() && !base->getType().isCoopVecOrLongVector()) {
bool enhanced = intermediate.getEnhancedMsgs(); bool enhanced = intermediate.getEnhancedMsgs();
error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString(enhanced).c_str()); error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString(enhanced).c_str());
return base; return base;
@@ -1421,6 +1421,7 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
if ((*fnCandidate)[0].type->getSampler().isMultiSample() && version <= 140) if ((*fnCandidate)[0].type->getSampler().isMultiSample() && version <= 140)
requireExtensions(loc, 1, &E_GL_ARB_texture_multisample, fnCandidate->getName().c_str()); requireExtensions(loc, 1, &E_GL_ARB_texture_multisample, fnCandidate->getName().c_str());
} }
bool hasLongVectorArg = false;
if (arguments != nullptr) { if (arguments != nullptr) {
// Make sure qualifications work for these arguments. // Make sure qualifications work for these arguments.
TIntermAggregate* aggregate = arguments->getAsAggregate(); TIntermAggregate* aggregate = arguments->getAsAggregate();
@@ -1516,6 +1517,10 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
} }
} }
if (argType.isLongVector()) {
hasLongVectorArg = true;
}
// TODO 4.5 functionality: A shader will fail to compile // TODO 4.5 functionality: A shader will fail to compile
// if the value passed to the memargument of an atomic memory function does not correspond to a buffer or // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or
// shared variable. It is acceptable to pass an element of an array or a single component of a vector to the // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the
@@ -1558,6 +1563,12 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
userFunctionCallCheck(loc, *call); userFunctionCallCheck(loc, *call);
} }
if (hasLongVectorArg && fnCandidate->getBuiltInOp() != EOpNull) {
TType longVectorResultType(EbtVoid);
handleLongVectorBuiltin(loc, fnCandidate, &longVectorResultType, arguments);
result->setType(longVectorResultType);
}
// Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore.
// Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output.
// Also, build the qualifier list for user function calls, which are always called with an aggregate. // Also, build the qualifier list for user function calls, which are always called with an aggregate.
@@ -1574,7 +1585,7 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
handleVector2CoopMatConversionCall(loc, fnCandidate, result, arguments); handleVector2CoopMatConversionCall(loc, fnCandidate, result, arguments);
if (result->getAsTyped()->getType().isCoopVecNV() && if (result->getAsTyped()->getType().isCoopVecOrLongVector() &&
!result->getAsTyped()->getType().isParameterized()) { !result->getAsTyped()->getType().isParameterized()) {
if (auto unaryNode = result->getAsUnaryNode()) if (auto unaryNode = result->getAsUnaryNode())
result->setType(unaryNode->getOperand()->getAsTyped()->getType()); result->setType(unaryNode->getOperand()->getAsTyped()->getType());
@@ -2179,6 +2190,12 @@ void TParseContext::handleVector2CoopMatConversionCall(const TSourceLoc& loc, co
} }
} }
void TParseContext::handleLongVectorBuiltin(const TSourceLoc& loc, const TFunction* fnCandidate, TType* resultType, TIntermNode* arguments)
{
if (!IsSupportedLongVectorBuiltin(fnCandidate, resultType, arguments)) {
error(loc, "can't resolve types (ambiguous long vector overload)", fnCandidate->getName().c_str(), "");
}
}
TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments, TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments,
const TFunction& function) const TFunction& function)
@@ -2187,6 +2204,26 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(), TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(),
function.getParamCount() == 1, function.getParamCount() == 1,
arguments, function.getType()); arguments, function.getType());
// EXT_descriptor_heap
// All the image atomic ops' first param is image variable.
if (extensionTurnedOn(E_GL_EXT_descriptor_heap) && function.getBuiltInOp() <= EOpImageAtomicStore &&
function.getBuiltInOp() >= EOpImageAtomicAdd) {
TIntermNode* imageNode = nullptr;
if (arguments->getAsAggregate() && arguments->getAsAggregate()->getSequence().size() > 0)
imageNode = arguments->getAsAggregate()->getSequence()[0];
else if (arguments->getAsUnaryNode())
imageNode = arguments->getAsUnaryNode();
if (imageNode && imageNode->getAsBinaryNode()) {
auto imageSymbol = imageNode->getAsBinaryNode()->getLeft();
if (imageSymbol && imageSymbol->getType().isImage()) {
imageSymbol->getQualifier().setUsedByAtomic();
result->getQualifier().setUsedByAtomic();
}
}
}
if (result != nullptr && obeyPrecisionQualifiers()) if (result != nullptr && obeyPrecisionQualifiers())
computeBuiltinPrecisions(*result, function); computeBuiltinPrecisions(*result, function);
@@ -2475,7 +2512,7 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction
length = type.getMatrixCols(); length = type.getMatrixCols();
else if (type.isVector()) else if (type.isVector())
length = type.getVectorSize(); length = type.getVectorSize();
else if (type.isCoopMat() || type.isCoopVecNV()) else if (type.isCoopMat() || type.isCoopVecOrLongVector())
return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
else { else {
// we should not get here, because earlier semantic checking should have prevented this path // we should not get here, because earlier semantic checking should have prevented this path
@@ -3600,10 +3637,10 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
error(loc, "second parameter must not have floate5m2 or floate4m3 basic type", "", ""); error(loc, "second parameter must not have floate5m2 or floate4m3 basic type", "", "");
} }
if (!(op0Type.isScalar() || op0Type.isVector() || op0Type.isCoopMatKHR())) { if (!(op0Type.isScalar() || op0Type.isVector() || op0Type.isLongVector() || op0Type.isCoopMatKHR())) {
error(loc, "first parameter must be scalar, vector, or cooperative matrix", "", ""); error(loc, "first parameter must be scalar, vector, or cooperative matrix", "", "");
} }
if (!(op1Type.isScalar() || op1Type.isVector() || op1Type.isCoopMatKHR())) { if (!(op1Type.isScalar() || op1Type.isVector() || op1Type.isLongVector() || op1Type.isCoopMatKHR())) {
error(loc, "second parameter must be scalar, vector, or cooperative matrix", "", ""); error(loc, "second parameter must be scalar, vector, or cooperative matrix", "", "");
} }
if (!(op0Type.sameElementShape(op1Type) || op0Type.sameCoopMatShape(op1Type))) { if (!(op0Type.sameElementShape(op1Type) || op0Type.sameCoopMatShape(op1Type))) {
@@ -6289,9 +6326,11 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
paramCheckFixStorage(loc, qualifier.storage, type); paramCheckFixStorage(loc, qualifier.storage, type);
} }
void TParseContext::nestedBlockCheck(const TSourceLoc& loc) void TParseContext::nestedBlockCheck(const TSourceLoc& loc, const bool allowedInnerStruct)
{ {
if (structNestingLevel > 0 || blockNestingLevel > 0) if ((!allowedInnerStruct && structNestingLevel > 0) ||
(allowedInnerStruct && structNestingLevel <= 0) ||
blockNestingLevel > 0)
error(loc, "cannot nest a block definition inside a structure or block", "", ""); error(loc, "cannot nest a block definition inside a structure or block", "", "");
++blockNestingLevel; ++blockNestingLevel;
} }
@@ -6373,7 +6412,8 @@ void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publ
const TSourceLoc& memberLoc = typeList[member].loc; const TSourceLoc& memberLoc = typeList[member].loc;
if (memberQualifier.isAuxiliary() || if (memberQualifier.isAuxiliary() ||
memberQualifier.isInterpolation() || memberQualifier.isInterpolation() ||
(memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal)) (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal &&
!memberQualifier.layoutDescriptorHeap && !memberQualifier.layoutDescriptorInnerBlock))
error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
if (memberQualifier.isMemory()) if (memberQualifier.isMemory())
error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), "");
@@ -6667,6 +6707,12 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
return; return;
} }
} }
if (id == "descriptor_heap") {
requireExtensions(loc, 1, &E_GL_EXT_descriptor_heap, "descriptor_stride");
requireVulkan(loc, "descriptor_heap");
publicType.qualifier.layoutDescriptorHeap = true;
return;
}
if (id == "push_constant") { if (id == "push_constant") {
requireVulkan(loc, "push_constant"); requireVulkan(loc, "push_constant");
publicType.qualifier.layoutPushConstant = true; publicType.qualifier.layoutPushConstant = true;
@@ -7187,6 +7233,45 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
return; return;
} }
if (id == "bank") {
requireExtensions(loc, 1, &E_GL_NV_push_constant_bank, "bank");
if (nonLiteral)
error(loc, "needs a literal integer", id.c_str(), "");
else if (value < 0 || (unsigned int)value >= TQualifier::layoutBankEnd)
error(loc, "bank out of range", id.c_str(), "");
else
publicType.qualifier.layoutBank = value;
return;
}
if (id == "member_offset") {
requireExtensions(loc, 1, &E_GL_NV_push_constant_bank, "member_offset");
if (nonLiteral)
error(loc, "needs a literal integer", id.c_str(), "");
else if (value < 0)
error(loc, "must be equal or greater than 0", id.c_str(), "");
else
publicType.qualifier.layoutMemberOffset = value;
return;
}
if (id == "descriptor_stride") {
requireExtensions(loc, 1, &E_GL_EXT_descriptor_heap, "descriptor_stride");
requireVulkan(loc, "descriptor_stride");
if (!IsPow2(value))
error(loc, "must be a power of 2", "descriptor_stride", "");
else
publicType.qualifier.layoutDescriptorStride = uint32_t(value);
return;
}
if (id == "heap_offset") {
requireExtensions(loc, 1, &E_GL_EXT_descriptor_heap, "heap_offset");
requireExtensions(loc, 1, &E_GL_EXT_structured_descriptor_heap, "heap_offset");
requireVulkan(loc, "heap_offset");
publicType.qualifier.layoutHeapOffset = uint32_t(value);
return;
}
switch (language) { switch (language) {
case EShLangTessControl: case EShLangTessControl:
if (id == "vertices") { if (id == "vertices") {
@@ -7427,6 +7512,14 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
dst.layoutXfbOffset = src.layoutXfbOffset; dst.layoutXfbOffset = src.layoutXfbOffset;
if (src.hasAttachment()) if (src.hasAttachment())
dst.layoutAttachment = src.layoutAttachment; dst.layoutAttachment = src.layoutAttachment;
if (src.layoutDescriptorHeap)
dst.layoutDescriptorHeap = true;
if (src.layoutDescriptorInnerBlock)
dst.layoutDescriptorInnerBlock = true;
if (src.layoutDescriptorStride != TQualifier::layoutDescriptorStrideEnd)
dst.layoutDescriptorStride = src.layoutDescriptorStride;
if (src.layoutHeapOffset != 0)
dst.layoutHeapOffset = src.layoutHeapOffset;
if (src.layoutPushConstant) if (src.layoutPushConstant)
dst.layoutPushConstant = true; dst.layoutPushConstant = true;
@@ -7458,6 +7551,10 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
dst.layoutTileAttachmentQCOM |= src.layoutTileAttachmentQCOM; dst.layoutTileAttachmentQCOM |= src.layoutTileAttachmentQCOM;
if (src.layoutHitObjectShaderRecordEXT) if (src.layoutHitObjectShaderRecordEXT)
dst.layoutHitObjectShaderRecordEXT = true; dst.layoutHitObjectShaderRecordEXT = true;
if (src.hasBank())
dst.layoutBank = src.layoutBank;
if (src.hasMemberOffset())
dst.layoutMemberOffset = src.layoutMemberOffset;
} }
} }
@@ -7713,7 +7810,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
// SPIR-V // SPIR-V
if (spvVersion.spv > 0) { if (spvVersion.spv > 0) {
if (qualifier.isUniformOrBuffer()) { if (qualifier.isUniformOrBuffer() && !intermediate.IsRequestedExtension(E_GL_EXT_descriptor_heap)) {
if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() && if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() &&
!qualifier.isShaderRecord() && !qualifier.isShaderRecord() &&
!qualifier.hasAttachment() && !qualifier.hasAttachment() &&
@@ -7837,6 +7934,8 @@ static bool storageCanHaveLayoutInBlock(const enum TStorageQualifier storage)
case EvqUniform: case EvqUniform:
case EvqBuffer: case EvqBuffer:
case EvqShared: case EvqShared:
case EvqSamplerHeap:
case EvqResourceHeap:
return true; return true;
default: default:
return false; return false;
@@ -7972,6 +8071,21 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) { if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) {
error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", ""); error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", "");
} }
if (qualifier.hasBank()) {
if (!qualifier.isPushConstant())
error(loc, "can only be used with push_constant", "bank", "");
}
if (qualifier.hasMemberOffset()) {
if (!qualifier.isPushConstant())
error(loc, "can only be used with push_constant", "member_offset", "");
}
if (qualifier.layoutDescriptorStride != TQualifier::layoutDescriptorStrideEnd &&
!qualifier.layoutDescriptorHeap)
error(loc, "must specify 'descriptor_heap' to use 'descriptor_stride'", "descriptor_stride", "");
if (qualifier.layoutHeapOffset != 0 && !qualifier.layoutDescriptorHeap &&
qualifier.storage != EvqSamplerHeap && qualifier.storage != EvqResourceHeap)
error(loc, "must specify 'descriptor_heap' to use 'heap_offset'", "heap_offset", "");
} }
// For places that can't have shader-level layout qualifiers // For places that can't have shader-level layout qualifiers
@@ -8303,12 +8417,16 @@ const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFu
if (fromElementType == toElementType) if (fromElementType == toElementType)
return true; return true;
} }
if (TType::vectorAndLongVectorMatch(from, to))
return true;
if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
return false; return false;
if (from.isCoopMat() && to.isCoopMat()) if (from.isCoopMat() && to.isCoopMat())
return from.sameCoopMatBaseType(to); return from.sameCoopMatBaseType(to);
if (from.isCoopVecNV() && to.isCoopVecNV()) if (from.isCoopVecNV() && to.isCoopVecNV())
return from.sameCoopVecBaseType(to); return from.sameCoopVecBaseType(to);
if (from.isLongVector() && to.isLongVector())
return from.sameLongVectorBaseType(to);
if (from.isTensorARM() && to.isTensorARM()) if (from.isTensorARM() && to.isTensorARM())
return from.sameTensorBaseTypeARM(to); return from.sameTensorBaseTypeARM(to);
return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
@@ -8319,10 +8437,13 @@ const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFu
// Assumes 'convertible' already said true. // Assumes 'convertible' already said true.
const auto better = [&](const TType& from, const TType& to1, const TType& to2) -> bool { const auto better = [&](const TType& from, const TType& to1, const TType& to2) -> bool {
// 1. exact match // 1. exact match
if (from == to2) bool to2Matches = from == to2 || (from.isLongVector() && to2.getBasicType() == EbtLongVector);
return from != to1; bool to1Matches = from == to1 || (from.isLongVector() && to1.getBasicType() == EbtLongVector);
if (from == to1) if (to2Matches)
return !to1Matches;
if (to1Matches)
return false; return false;
if (extensionTurnedOn(E_GL_NV_gpu_shader5)) { if (extensionTurnedOn(E_GL_NV_gpu_shader5)) {
// This map refers to the conversion table mentioned under the // This map refers to the conversion table mentioned under the
// section "Modify Section 6.1, Function Definitions, p. 63" in NV_gpu_shader5 spec // section "Modify Section 6.1, Function Definitions, p. 63" in NV_gpu_shader5 spec
@@ -8416,12 +8537,16 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc,
if (fromElementType == toElementType) if (fromElementType == toElementType)
return true; return true;
} }
if (TType::vectorAndLongVectorMatch(from, to))
return true;
if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
return false; return false;
if (from.isCoopMat() && to.isCoopMat()) if (from.isCoopMat() && to.isCoopMat())
return from.sameCoopMatBaseType(to); return from.sameCoopMatBaseType(to);
if (from.isCoopVecNV() && to.isCoopVecNV()) if (from.isCoopVecNV() && to.isCoopVecNV())
return from.sameCoopVecBaseType(to); return from.sameCoopVecBaseType(to);
if (from.isLongVector() && to.isLongVector())
return from.sameLongVectorBaseType(to);
if (from.isTensorARM() && to.isTensorARM()) if (from.isTensorARM() && to.isTensorARM())
return from.sameTensorBaseTypeARM(to); return from.sameTensorBaseTypeARM(to);
return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
@@ -8432,9 +8557,11 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc,
// Assumes 'convertible' already said true. // Assumes 'convertible' already said true.
const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool { const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool {
// 1. exact match // 1. exact match
if (from == to2) bool to2Matches = from == to2 || (from.isLongVector() && to2.getBasicType() == EbtLongVector);
return from != to1; bool to1Matches = from == to1 || (from.isLongVector() && to1.getBasicType() == EbtLongVector);
if (from == to1) if (to2Matches)
return !to1Matches;
if (to1Matches)
return false; return false;
// 2. Promotion (integral, floating-point) is better // 2. Promotion (integral, floating-point) is better
@@ -8728,6 +8855,11 @@ bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString
// merge qualifiers // merge qualifiers
mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true); mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true);
// set default value for bank when no decoration is present.
if (updatedBlock->getWritableType().getQualifier().isPushConstant() && !updatedBlock->getWritableType().getQualifier().hasBank()) {
updatedBlock->getWritableType().getQualifier().layoutBank = 0;
}
return true; return true;
} }
@@ -9077,7 +9209,15 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
if (!publicType.typeParameters || !publicType.typeParameters->arraySizes || publicType.typeParameters->arraySizes->getNumDims() != 1) { if (!publicType.typeParameters || !publicType.typeParameters->arraySizes || publicType.typeParameters->arraySizes->getNumDims() != 1) {
error(loc, "expected two type parameters", identifier.c_str(), ""); error(loc, "expected two type parameters", identifier.c_str(), "");
} else if (publicType.typeParameters->arraySizes->getDimSize(0) <= 0) { } else if (publicType.typeParameters->arraySizes->getDimNode(0) == nullptr && publicType.typeParameters->arraySizes->getDimSize(0) <= 0) {
error(loc, "expected positive number of components", identifier.c_str(), "");
}
} else if (type.isLongVector()) {
intermediate.setUseStorageBuffer();
if (!publicType.typeParameters || !publicType.typeParameters->arraySizes || publicType.typeParameters->arraySizes->getNumDims() != 1) {
error(loc, "expected two type parameters", identifier.c_str(), "");
} else if (publicType.typeParameters->arraySizes->getDimNode(0) == nullptr && publicType.typeParameters->arraySizes->getDimSize(0) <= 0) {
error(loc, "expected positive number of components", identifier.c_str(), ""); error(loc, "expected positive number of components", identifier.c_str(), "");
} }
} else if (type.isTensorARM()) { } else if (type.isTensorARM()) {
@@ -9221,6 +9361,11 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
initNode = executeInitializer(loc, initializer, variable); initNode = executeInitializer(loc, initializer, variable);
} }
// EXT_descriptor_heap
if (!untypedHeapCheck(symbol, type, loc, identifier.c_str())) {
return nullptr;
}
// look for errors in layout qualifier use // look for errors in layout qualifier use
layoutObjectCheck(loc, *symbol); layoutObjectCheck(loc, *symbol);
@@ -10162,6 +10307,60 @@ void TParseContext::updateBindlessQualifier(TType& memberType)
} }
} }
void TParseContext::descHeapBuiltinRemap(TType* type, bool isInnerBlock)
{
if (type->isStruct()) {
TTypeList* types = type->getWritableStruct();
for (auto typeLoc : *types) {
descHeapBuiltinRemap(typeLoc.type, isInnerBlock);
}
}
auto* qualifier = &type->getQualifier();
if (type->getBasicType() == EbtSampler) {
if (type->isImage() || type->isTexture())
qualifier->builtIn = EbvResourceHeapEXT;
else
qualifier->builtIn = EbvSamplerHeapEXT;
qualifier->layoutDescriptorHeap = true;
} else if (qualifier->isUniformOrBuffer() || type->getBasicType() == EbtAccStruct) {
qualifier->builtIn = EbvResourceHeapEXT;
qualifier->layoutDescriptorHeap = true;
qualifier->layoutDescriptorInnerBlock = isInnerBlock;
}
}
bool TParseContext::untypedHeapCheck(TSymbol* symbol, const TType& type, const TSourceLoc& loc, const char* name)
{
// EXT_descriptor_heap
bool isHeapStruct =
(type.getQualifier().storage == EvqSamplerHeap || type.getQualifier().storage == EvqResourceHeap);
if (intermediate.IsRequestedExtension(E_GL_EXT_descriptor_heap) && spvVersion.vulkan > 0 &&
!type.getQualifier().hasSet() && !type.getQualifier().hasBinding()) {
if (type.getQualifier().layoutDescriptorHeap || isHeapStruct) {
if ((intermediate.isEsProfile() && intermediate.getVersion() < 310) ||
(!intermediate.isEsProfile() && intermediate.getVersion() < 420)) {
TString warnMsg = "layout(descriptor_heap) is turned on beyond version/profile limits.";
infoSink.info.message(EPrefixWarning, warnMsg.c_str());
}
if (IsAnonymous(symbol->getName()) &&
(type.getQualifier().isUniformOrBuffer() || type.getBasicType() == EbtBlock)) {
error(loc, "layout(descriptor_heap) decorated block should be explicitly "
"declared with a run-time sized array type.", name, "");
return false;
}
if (!type.containsHeapArray()) {
error(loc, "layout(descriptor_heap) decorated variable could only be declared as an array.",
name, "");
return false;
}
descHeapBuiltinRemap(&symbol->getWritableType(), isHeapStruct);
}
}
return true;
}
// //
// Do everything needed to add an interface block. Returns the declarator node if there's an instance declaration. // Do everything needed to add an interface block. Returns the declarator node if there's an instance declaration.
// //
@@ -10213,12 +10412,12 @@ TIntermNode* TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeL
} }
// For bindless texture, sampler can be declared as uniform/storage block member, // For bindless texture, sampler can be declared as uniform/storage block member,
if (memberType.containsOpaque()) { if (memberType.containsOpaque() && !extensionTurnedOn(E_GL_EXT_structured_descriptor_heap)) {
if (memberType.containsSampler() && extensionTurnedOn(E_GL_ARB_bindless_texture)) if (memberType.containsSampler() && extensionTurnedOn(E_GL_ARB_bindless_texture))
updateBindlessQualifier(memberType); updateBindlessQualifier(memberType);
else else
error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), ""); 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()) if (memberType.containsCoopMat())
error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), ""); error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), "");
@@ -10444,6 +10643,11 @@ TIntermNode* TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeL
return nullptr; return nullptr;
} }
// EXT_descriptor_heap
if (!untypedHeapCheck(&variable, blockType, loc, blockName->c_str())) {
return nullptr;
}
// Check for general layout qualifier errors // Check for general layout qualifier errors
layoutObjectCheck(loc, variable); layoutObjectCheck(loc, variable);
@@ -10559,6 +10763,14 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
profileRequires(loc, ~EEsProfile, 460, E_GL_EXT_shader_invocation_reorder, "hitObjectAttributeEXT block"); profileRequires(loc, ~EEsProfile, 460, E_GL_EXT_shader_invocation_reorder, "hitObjectAttributeEXT block");
requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask), "hitObjectAttributeEXT block"); requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask), "hitObjectAttributeEXT block");
break; break;
case EvqResourceHeap:
profileRequires(loc, ~EEsProfile, 460, E_GL_EXT_structured_descriptor_heap, "resourceheap block");
profileRequires(loc, ~EEsProfile, 460, E_GL_EXT_descriptor_heap, "resourceheap block");
break;
case EvqSamplerHeap:
profileRequires(loc, ~EEsProfile, 460, E_GL_EXT_structured_descriptor_heap, "samplerheap block");
profileRequires(loc, ~EEsProfile, 460, E_GL_EXT_descriptor_heap, "samplerheap block");
break;
default: default:
error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), ""); error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), "");
break; break;

View File

@@ -416,7 +416,7 @@ public:
void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
void nestedBlockCheck(const TSourceLoc&); void nestedBlockCheck(const TSourceLoc&, const bool allowedInnerStruct = false);
void nestedStructCheck(const TSourceLoc&); void nestedStructCheck(const TSourceLoc&);
void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
void opaqueCheck(const TSourceLoc&, const TType&, const char* op); void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
@@ -456,6 +456,8 @@ public:
TParameter getParamWithDefault(const TPublicType& ty, TString* identifier, TIntermTyped* initializer, TParameter getParamWithDefault(const TPublicType& ty, TString* identifier, TIntermTyped* initializer,
const TSourceLoc& loc); const TSourceLoc& loc);
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
void descHeapBuiltinRemap(TType* type, bool isInnerBlock);
bool untypedHeapCheck(TSymbol* symbol, const TType& type, const TSourceLoc& loc, const char* name);
TIntermNode* declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = nullptr, TArraySizes* arraySizes = nullptr); TIntermNode* declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = nullptr, TArraySizes* arraySizes = nullptr);
void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&); void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
void blockStageIoCheck(const TSourceLoc&, const TQualifier&); void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
@@ -516,6 +518,7 @@ protected:
void finish() override; void finish() override;
void handleCoopMat2FunctionCall(const TSourceLoc& loc, const TFunction* fnCandidate, TIntermTyped* result, TIntermNode* arguments); void handleCoopMat2FunctionCall(const TSourceLoc& loc, const TFunction* fnCandidate, TIntermTyped* result, TIntermNode* arguments);
void handleVector2CoopMatConversionCall(const TSourceLoc& loc, const TFunction* fnCandidate, TIntermTyped* &result, TIntermNode* arguments); void handleVector2CoopMatConversionCall(const TSourceLoc& loc, const TFunction* fnCandidate, TIntermTyped* &result, TIntermNode* arguments);
void handleLongVectorBuiltin(const TSourceLoc& loc, const TFunction* fnCandidate, TType* resultType, TIntermNode* arguments);
virtual const char* getGlobalUniformBlockName() const override; virtual const char* getGlobalUniformBlockName() const override;
virtual void finalizeGlobalUniformBlockLayout(TVariable&) override; virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;

View File

@@ -779,6 +779,9 @@ const std::unordered_map<const char*, int, str_hash, str_eq> KeywordMap {
{"tensorViewNV",TENSORVIEWNV}, {"tensorViewNV",TENSORVIEWNV},
{"coopvecNV",COOPVECNV}, {"coopvecNV",COOPVECNV},
{"vector",VECTOR},
{"resourceheap",RESOURCEHEAP},
{"samplerheap",SAMPLERHEAP},
}; };
const std::unordered_set<const char*, str_hash, str_eq> ReservedSet { const std::unordered_set<const char*, str_hash, str_eq> ReservedSet {
"common", "common",
@@ -1353,13 +1356,14 @@ int TScanContext::tokenizeIdentifier()
case U64VEC2: case U64VEC2:
case U64VEC3: case U64VEC3:
case U64VEC4: case U64VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) || parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) || parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case INT8_T: case INT8_T:
@@ -1370,13 +1374,14 @@ int TScanContext::tokenizeIdentifier()
case U8VEC2: case U8VEC2:
case U8VEC3: case U8VEC3:
case U8VEC4: case U8VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) || parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) ||
parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) || parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case INT16_T: case INT16_T:
@@ -1387,14 +1392,15 @@ int TScanContext::tokenizeIdentifier()
case U16VEC2: case U16VEC2:
case U16VEC3: case U16VEC3:
case U16VEC4: case U16VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) || parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) || parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case INT32_T: case INT32_T:
case UINT32_T: case UINT32_T:
@@ -1404,23 +1410,25 @@ int TScanContext::tokenizeIdentifier()
case U32VEC2: case U32VEC2:
case U32VEC3: case U32VEC3:
case U32VEC4: case U32VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) || parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case FLOAT32_T: case FLOAT32_T:
case F32VEC2: case F32VEC2:
case F32VEC3: case F32VEC3:
case F32VEC4: case F32VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) || parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case F32MAT2: case F32MAT2:
case F32MAT3: case F32MAT3:
@@ -1434,25 +1442,27 @@ int TScanContext::tokenizeIdentifier()
case F32MAT4X2: case F32MAT4X2:
case F32MAT4X3: case F32MAT4X3:
case F32MAT4X4: case F32MAT4X4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case FLOAT64_T: case FLOAT64_T:
case F64VEC2: case F64VEC2:
case F64VEC3: case F64VEC3:
case F64VEC4: case F64VEC4:
afterType = true; if (parseContext.symbolTable.atBuiltInLevel() ||
if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || (parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) &&
(parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) ||
parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) {
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) afterType = true;
return keyword; return keyword;
return identifierOrType(); }
return identifierOrType();
case F64MAT2: case F64MAT2:
case F64MAT3: case F64MAT3:
case F64MAT4: case F64MAT4:
@@ -1465,26 +1475,27 @@ int TScanContext::tokenizeIdentifier()
case F64MAT4X2: case F64MAT4X2:
case F64MAT4X3: case F64MAT4X3:
case F64MAT4X4: case F64MAT4X4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case FLOAT16_T: case FLOAT16_T:
case F16VEC2: case F16VEC2:
case F16VEC3: case F16VEC3:
case F16VEC4: case F16VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) || parseContext.extensionTurnedOn(E_GL_NV_gpu_shader5) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case F16MAT2: case F16MAT2:
@@ -1499,12 +1510,13 @@ int TScanContext::tokenizeIdentifier()
case F16MAT4X2: case F16MAT4X2:
case F16MAT4X3: case F16MAT4X3:
case F16MAT4X4: case F16MAT4X4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
@@ -1512,10 +1524,11 @@ int TScanContext::tokenizeIdentifier()
case BF16VEC2: case BF16VEC2:
case BF16VEC3: case BF16VEC3:
case BF16VEC4: case BF16VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_bfloat16)) parseContext.extensionTurnedOn(E_GL_EXT_bfloat16)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
@@ -1523,10 +1536,11 @@ int TScanContext::tokenizeIdentifier()
case FE5M2VEC2: case FE5M2VEC2:
case FE5M2VEC3: case FE5M2VEC3:
case FE5M2VEC4: case FE5M2VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_float_e5m2)) parseContext.extensionTurnedOn(E_GL_EXT_float_e5m2)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
@@ -1534,10 +1548,11 @@ int TScanContext::tokenizeIdentifier()
case FE4M3VEC2: case FE4M3VEC2:
case FE4M3VEC3: case FE4M3VEC3:
case FE4M3VEC4: case FE4M3VEC4:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_float_e4m3)) parseContext.extensionTurnedOn(E_GL_EXT_float_e4m3)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
@@ -1806,10 +1821,11 @@ int TScanContext::tokenizeIdentifier()
case F16SUBPASSINPUT: case F16SUBPASSINPUT:
case F16SUBPASSINPUTMS: case F16SUBPASSINPUTMS:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch)) parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case EXPLICITINTERPAMD: case EXPLICITINTERPAMD:
@@ -1858,38 +1874,51 @@ int TScanContext::tokenizeIdentifier()
return identifierOrType(); return identifierOrType();
case FCOOPMATNV: case FCOOPMATNV:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix)) parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case UCOOPMATNV: case UCOOPMATNV:
case ICOOPMATNV: case ICOOPMATNV:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_NV_integer_cooperative_matrix)) parseContext.extensionTurnedOn(E_GL_NV_integer_cooperative_matrix)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case TENSORARM: case TENSORARM:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_ARM_tensors)) parseContext.extensionTurnedOn(E_GL_ARM_tensors)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case COOPMAT: case COOPMAT:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_KHR_cooperative_matrix)) parseContext.extensionTurnedOn(E_GL_KHR_cooperative_matrix)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType(); return identifierOrType();
case COOPVECNV: case COOPVECNV:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_NV_cooperative_vector)) parseContext.extensionTurnedOn(E_GL_NV_cooperative_vector)) {
afterType = true;
return keyword; return keyword;
}
return identifierOrType();
case VECTOR:
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_long_vector)) {
afterType = true;
return keyword;
}
return identifierOrType(); return identifierOrType();
case DEMOTE: case DEMOTE:
@@ -1944,9 +1973,17 @@ int TScanContext::tokenizeIdentifier()
case FUNCTION: case FUNCTION:
case TENSORLAYOUTNV: case TENSORLAYOUTNV:
case TENSORVIEWNV: case TENSORVIEWNV:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix2)) parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix2)) {
afterType = true;
return keyword;
}
return identifierOrType();
case RESOURCEHEAP:
case SAMPLERHEAP:
if (parseContext.extensionTurnedOn(E_GL_EXT_structured_descriptor_heap) &&
parseContext.extensionTurnedOn(E_GL_EXT_descriptor_heap))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();

View File

@@ -1855,6 +1855,7 @@ void TShader::setUniformLocationBase(int base)
{ {
intermediate->setUniformLocationBase(base); intermediate->setUniformLocationBase(base);
} }
void TShader::setBindingsPerResourceType() { intermediate->setBindingsPerResourceType(); }
void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
void TShader::setResourceSetBinding(const std::vector<std::string>& base) { intermediate->setResourceSetBinding(base); } void TShader::setResourceSetBinding(const std::vector<std::string>& base) { intermediate->setResourceSetBinding(base); }
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }

View File

@@ -317,6 +317,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_NV_cooperative_matrix2] = EBhDisable; extensionBehavior[E_GL_NV_cooperative_matrix2] = EBhDisable;
extensionBehavior[E_GL_NV_cluster_acceleration_structure] = EBhDisable; extensionBehavior[E_GL_NV_cluster_acceleration_structure] = EBhDisable;
extensionBehavior[E_GL_NV_linear_swept_spheres] = EBhDisable; extensionBehavior[E_GL_NV_linear_swept_spheres] = EBhDisable;
extensionBehavior[E_GL_NV_push_constant_bank] = EBhDisable;
// ARM // ARM
extensionBehavior[E_GL_ARM_shader_core_builtins] = EBhDisable; extensionBehavior[E_GL_ARM_shader_core_builtins] = EBhDisable;
@@ -345,6 +346,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable; extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable; extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable;
extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable; extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable;
extensionBehavior[E_GL_EXT_descriptor_heap] = EBhDisable;
// OES matching AEP // OES matching AEP
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable; extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
@@ -389,6 +391,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_uniform_buffer_unsized_array] = EBhDisable; extensionBehavior[E_GL_EXT_uniform_buffer_unsized_array] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_64bit_indexing] = EBhDisable; extensionBehavior[E_GL_EXT_shader_64bit_indexing] = EBhDisable;
extensionBehavior[E_GL_EXT_conservative_depth] = EBhDisable; extensionBehavior[E_GL_EXT_conservative_depth] = EBhDisable;
extensionBehavior[E_GL_EXT_long_vector] = EBhDisable;
// OVR extensions // OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable; extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
@@ -457,6 +460,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_implicit_conversions 1\n" "#define GL_EXT_shader_implicit_conversions 1\n"
"#define GL_EXT_shader_integer_mix 1\n" "#define GL_EXT_shader_integer_mix 1\n"
"#define GL_EXT_blend_func_extended 1\n" "#define GL_EXT_blend_func_extended 1\n"
"#define GL_EXT_descriptor_heap 1\n"
// OES matching AEP // OES matching AEP
"#define GL_OES_geometry_shader 1\n" "#define GL_OES_geometry_shader 1\n"
@@ -639,6 +643,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_64bit_indexing 1\n" "#define GL_EXT_shader_64bit_indexing 1\n"
"#define GL_EXT_shader_invocation_reorder 1\n" "#define GL_EXT_shader_invocation_reorder 1\n"
"#define GL_EXT_descriptor_heap 1\n"
; ;
if (spvVersion.spv == 0) { if (spvVersion.spv == 0) {
@@ -662,6 +667,11 @@ void TParseVersions::getPreamble(std::string& preamble)
} }
} }
if ((!isEsProfile() && version >= 460) ||
(isEsProfile() && version >= 320)) {
preamble += "#define GL_EXT_nontemporal_keyword 1\n";
}
if ((!isEsProfile() && version >= 140) || if ((!isEsProfile() && version >= 140) ||
(isEsProfile() && version >= 310)) { (isEsProfile() && version >= 310)) {
preamble += preamble +=
@@ -1519,6 +1529,14 @@ void TParseVersions::tensorCheckARM(const TSourceLoc& loc, const char* op, bool
} }
} }
void TParseVersions::longVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn)
{
if (!builtIn) {
const char* const extensions[] = {E_GL_EXT_long_vector};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
}
}
// Call for any operation removed because SPIR-V is in use. // Call for any operation removed because SPIR-V is in use.
void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op) void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
{ {

View File

@@ -229,6 +229,8 @@ const char* const E_GL_EXT_texture_offset_non_const = "GL_EXT_texture_of
const char* const E_GL_EXT_nontemporal_keyword = "GL_EXT_nontemporal_keyword"; const char* const E_GL_EXT_nontemporal_keyword = "GL_EXT_nontemporal_keyword";
const char* const E_GL_EXT_uniform_buffer_unsized_array = "GL_EXT_uniform_buffer_unsized_array"; const char* const E_GL_EXT_uniform_buffer_unsized_array = "GL_EXT_uniform_buffer_unsized_array";
const char* const E_GL_EXT_conservative_depth = "GL_EXT_conservative_depth"; const char* const E_GL_EXT_conservative_depth = "GL_EXT_conservative_depth";
const char* const E_GL_EXT_descriptor_heap = "GL_EXT_descriptor_heap";
const char* const E_GL_EXT_structured_descriptor_heap = "GL_EXT_structured_descriptor_heap";
// Arrays of extensions for the above viewportEXTs duplications // Arrays of extensions for the above viewportEXTs duplications
@@ -293,6 +295,7 @@ const char* const E_GL_NV_cooperative_vector = "GL_NV_coopera
const char* const E_GL_NV_cluster_acceleration_structure = "GL_NV_cluster_acceleration_structure"; const char* const E_GL_NV_cluster_acceleration_structure = "GL_NV_cluster_acceleration_structure";
const char* const E_GL_NV_linear_swept_spheres = "GL_NV_linear_swept_spheres"; const char* const E_GL_NV_linear_swept_spheres = "GL_NV_linear_swept_spheres";
const char* const E_GL_NV_gpu_shader5 = "GL_NV_gpu_shader5"; const char* const E_GL_NV_gpu_shader5 = "GL_NV_gpu_shader5";
const char* const E_GL_NV_push_constant_bank = "GL_NV_push_constant_bank";
// ARM // ARM
const char* const E_GL_ARM_shader_core_builtins = "GL_ARM_shader_core_builtins"; const char* const E_GL_ARM_shader_core_builtins = "GL_ARM_shader_core_builtins";
@@ -366,6 +369,7 @@ const char* const E_GL_EXT_integer_dot_product = "GL_EXT_inte
const char* const E_GL_EXT_bfloat16 = "GL_EXT_bfloat16"; const char* const E_GL_EXT_bfloat16 = "GL_EXT_bfloat16";
const char* const E_GL_EXT_float_e5m2 = "GL_EXT_float_e5m2"; const char* const E_GL_EXT_float_e5m2 = "GL_EXT_float_e5m2";
const char* const E_GL_EXT_float_e4m3 = "GL_EXT_float_e4m3"; const char* const E_GL_EXT_float_e4m3 = "GL_EXT_float_e4m3";
const char* const E_GL_EXT_long_vector = "GL_EXT_long_vector";
const char* const E_GL_EXT_shader_64bit_indexing = "GL_EXT_shader_64bit_indexing"; const char* const E_GL_EXT_shader_64bit_indexing = "GL_EXT_shader_64bit_indexing";

View File

@@ -182,6 +182,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV %token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV
%token <lex> COOPMAT %token <lex> COOPMAT
%token <lex> COOPVECNV %token <lex> COOPVECNV
%token <lex> VECTOR
%token <lex> HITOBJECTNV HITOBJECTATTRNV HITOBJECTEXT HITOBJECTATTREXT %token <lex> HITOBJECTNV HITOBJECTATTRNV HITOBJECTEXT HITOBJECTATTREXT
%token <lex> TENSORLAYOUTNV TENSORVIEWNV %token <lex> TENSORLAYOUTNV TENSORVIEWNV
%token <lex> TENSORARM %token <lex> TENSORARM
@@ -284,7 +285,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> SUBROUTINE DEMOTE FUNCTION %token <lex> SUBROUTINE DEMOTE FUNCTION
%token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV %token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
%token <lex> PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT %token <lex> PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT
%token <lex> PATCH SAMPLE NONUNIFORM %token <lex> PATCH SAMPLE NONUNIFORM RESOURCEHEAP SAMPLERHEAP
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY NONTEMPORAL DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY NONTEMPORAL DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
%token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT %token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
%token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXEXT PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV PERPRIMITIVEEXT TASKPAYLOADWORKGROUPEXT %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXEXT PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV PERPRIMITIVEEXT TASKPAYLOADWORKGROUPEXT
@@ -326,8 +327,10 @@ extern int yylex(YYSTYPE*, TParseContext&);
%type <interm.type> single_type_qualifier %type <interm.type> single_type_qualifier
%type <interm.type> type_specifier_nonarray %type <interm.type> type_specifier_nonarray
%type <interm.type> struct_specifier %type <interm.type> struct_specifier
%type <interm.type> block_heap_inner_structure
%type <interm.typeLine> struct_declarator %type <interm.typeLine> struct_declarator
%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list %type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.typeList> struct_declaration_with_heap struct_declaration_without_heap
%type <interm> block_structure %type <interm> block_structure
%type <interm.function> function_header function_declarator %type <interm.function> function_header function_declarator
%type <interm.function> function_header_with_parameters %type <interm.function> function_header_with_parameters
@@ -934,7 +937,7 @@ declaration
; ;
block_structure block_structure
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_without_heap RIGHT_BRACE {
--parseContext.blockNestingLevel; --parseContext.blockNestingLevel;
parseContext.blockName = $2.string; parseContext.blockName = $2.string;
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
@@ -943,6 +946,7 @@ block_structure
$$.loc = $1.loc; $$.loc = $1.loc;
$$.typeList = $5; $$.typeList = $5;
} }
;
identifier_list identifier_list
: IDENTIFIER { : IDENTIFIER {
@@ -1530,6 +1534,16 @@ storage_qualifier
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.sample = true; $$.qualifier.sample = true;
} }
| RESOURCEHEAP {
parseContext.globalCheck($1.loc, "resourceHeap");
$$.init($1.loc);
$$.qualifier.storage = EvqResourceHeap;
}
| SAMPLERHEAP {
parseContext.globalCheck($1.loc, "samplerHeap");
$$.init($1.loc);
$$.qualifier.storage = EvqSamplerHeap;
}
| HITATTRNV { | HITATTRNV {
parseContext.globalCheck($1.loc, "hitAttributeNV"); parseContext.globalCheck($1.loc, "hitAttributeNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
@@ -3652,6 +3666,12 @@ type_specifier_nonarray
$$.tensorRankARM = 1; // placeholder value $$.tensorRankARM = 1; // placeholder value
$$.basicType = EbtTensorARM; $$.basicType = EbtTensorARM;
} }
| VECTOR {
parseContext.longVectorCheck($1.loc, "vector", parseContext.symbolTable.atBuiltInLevel());
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtLongVector;
$$.longVector = true;
}
| spirv_type_specifier { | spirv_type_specifier {
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier");
$$ = $1; $$ = $1;
@@ -3704,7 +3724,6 @@ precision_qualifier
struct_specifier struct_specifier
: STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE { : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
TType* structure = new TType($5, *$2.string); TType* structure = new TType($5, *$2.string);
parseContext.structArrayCheck($2.loc, *structure); parseContext.structArrayCheck($2.loc, *structure);
@@ -3730,10 +3749,71 @@ struct_specifier
; ;
struct_declaration_list struct_declaration_list
: struct_declaration_without_heap {
$$ = $1;
}
| struct_declaration_with_heap {
$$ = $1;
}
| struct_declaration_with_heap struct_declaration_without_heap {
$$ = $1;
for (unsigned int i = 0; i < $2->size(); ++i) {
for (unsigned int j = 0; j < $$->size(); ++j) {
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName())
parseContext.error((*$2)[i].loc, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
}
$$->push_back((*$2)[i]);
}
}
| struct_declaration_without_heap struct_declaration_with_heap {
$$ = $1;
for (unsigned int i = 0; i < $2->size(); ++i) {
for (unsigned int j = 0; j < $$->size(); ++j) {
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName())
parseContext.error((*$2)[i].loc, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
}
$$->push_back((*$2)[i]);
}
}
;
struct_declaration_with_heap
: block_heap_inner_structure struct_declarator_list SEMICOLON {
$$ = $2;
parseContext.voidErrorCheck($1.loc, (*$2)[0].type->getFieldName(), $1.basicType);
parseContext.precisionQualifierCheck($1.loc, $1.basicType, $1.qualifier, $1.hasTypeParameter());
for (unsigned int i = 0; i < $$->size(); ++i) {
TType type($1);
type.setFieldName((*$$)[i].type->getFieldName());
type.transferArraySizes((*$$)[i].type->getArraySizes());
type.copyArrayInnerSizes($1.arraySizes);
parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes());
(*$$)[i].type->shallowCopy(type);
}
}
;
block_heap_inner_structure
: type_qualifier LEFT_BRACE { parseContext.nestedBlockCheck($1.loc, true); } struct_declaration_without_heap RIGHT_BRACE {
--parseContext.blockNestingLevel;
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
$$.init($1.loc);
TType* innerStructure = new TType($4, TString(""));
$$.basicType = EbtBlock;
$$.userDef = innerStructure;
$$.qualifier = $1.qualifier;
$$.qualifier.layoutDescriptorHeap = true;
$$.qualifier.layoutDescriptorInnerBlock = true;
}
;
struct_declaration_without_heap
: struct_declaration { : struct_declaration {
$$ = $1; $$ = $1;
} }
| struct_declaration_list struct_declaration { | struct_declaration_without_heap struct_declaration {
$$ = $1; $$ = $1;
for (unsigned int i = 0; i < $2->size(); ++i) { for (unsigned int i = 0; i < $2->size(); ++i) {
for (unsigned int j = 0; j < $$->size(); ++j) { for (unsigned int j = 0; j < $$->size(); ++j) {

File diff suppressed because it is too large Load Diff

View File

@@ -231,311 +231,314 @@ extern int yydebug;
UCOOPMATNV = 432, /* UCOOPMATNV */ UCOOPMATNV = 432, /* UCOOPMATNV */
COOPMAT = 433, /* COOPMAT */ COOPMAT = 433, /* COOPMAT */
COOPVECNV = 434, /* COOPVECNV */ COOPVECNV = 434, /* COOPVECNV */
HITOBJECTNV = 435, /* HITOBJECTNV */ VECTOR = 435, /* VECTOR */
HITOBJECTATTRNV = 436, /* HITOBJECTATTRNV */ HITOBJECTNV = 436, /* HITOBJECTNV */
HITOBJECTEXT = 437, /* HITOBJECTEXT */ HITOBJECTATTRNV = 437, /* HITOBJECTATTRNV */
HITOBJECTATTREXT = 438, /* HITOBJECTATTREXT */ HITOBJECTEXT = 438, /* HITOBJECTEXT */
TENSORLAYOUTNV = 439, /* TENSORLAYOUTNV */ HITOBJECTATTREXT = 439, /* HITOBJECTATTREXT */
TENSORVIEWNV = 440, /* TENSORVIEWNV */ TENSORLAYOUTNV = 440, /* TENSORLAYOUTNV */
TENSORARM = 441, /* TENSORARM */ TENSORVIEWNV = 441, /* TENSORVIEWNV */
SAMPLERCUBEARRAY = 442, /* SAMPLERCUBEARRAY */ TENSORARM = 442, /* TENSORARM */
SAMPLERCUBEARRAYSHADOW = 443, /* SAMPLERCUBEARRAYSHADOW */ SAMPLERCUBEARRAY = 443, /* SAMPLERCUBEARRAY */
ISAMPLERCUBEARRAY = 444, /* ISAMPLERCUBEARRAY */ SAMPLERCUBEARRAYSHADOW = 444, /* SAMPLERCUBEARRAYSHADOW */
USAMPLERCUBEARRAY = 445, /* USAMPLERCUBEARRAY */ ISAMPLERCUBEARRAY = 445, /* ISAMPLERCUBEARRAY */
SAMPLER1D = 446, /* SAMPLER1D */ USAMPLERCUBEARRAY = 446, /* USAMPLERCUBEARRAY */
SAMPLER1DARRAY = 447, /* SAMPLER1DARRAY */ SAMPLER1D = 447, /* SAMPLER1D */
SAMPLER1DARRAYSHADOW = 448, /* SAMPLER1DARRAYSHADOW */ SAMPLER1DARRAY = 448, /* SAMPLER1DARRAY */
ISAMPLER1D = 449, /* ISAMPLER1D */ SAMPLER1DARRAYSHADOW = 449, /* SAMPLER1DARRAYSHADOW */
SAMPLER1DSHADOW = 450, /* SAMPLER1DSHADOW */ ISAMPLER1D = 450, /* ISAMPLER1D */
SAMPLER2DRECT = 451, /* SAMPLER2DRECT */ SAMPLER1DSHADOW = 451, /* SAMPLER1DSHADOW */
SAMPLER2DRECTSHADOW = 452, /* SAMPLER2DRECTSHADOW */ SAMPLER2DRECT = 452, /* SAMPLER2DRECT */
ISAMPLER2DRECT = 453, /* ISAMPLER2DRECT */ SAMPLER2DRECTSHADOW = 453, /* SAMPLER2DRECTSHADOW */
USAMPLER2DRECT = 454, /* USAMPLER2DRECT */ ISAMPLER2DRECT = 454, /* ISAMPLER2DRECT */
SAMPLERBUFFER = 455, /* SAMPLERBUFFER */ USAMPLER2DRECT = 455, /* USAMPLER2DRECT */
ISAMPLERBUFFER = 456, /* ISAMPLERBUFFER */ SAMPLERBUFFER = 456, /* SAMPLERBUFFER */
USAMPLERBUFFER = 457, /* USAMPLERBUFFER */ ISAMPLERBUFFER = 457, /* ISAMPLERBUFFER */
SAMPLER2DMS = 458, /* SAMPLER2DMS */ USAMPLERBUFFER = 458, /* USAMPLERBUFFER */
ISAMPLER2DMS = 459, /* ISAMPLER2DMS */ SAMPLER2DMS = 459, /* SAMPLER2DMS */
USAMPLER2DMS = 460, /* USAMPLER2DMS */ ISAMPLER2DMS = 460, /* ISAMPLER2DMS */
SAMPLER2DMSARRAY = 461, /* SAMPLER2DMSARRAY */ USAMPLER2DMS = 461, /* USAMPLER2DMS */
ISAMPLER2DMSARRAY = 462, /* ISAMPLER2DMSARRAY */ SAMPLER2DMSARRAY = 462, /* SAMPLER2DMSARRAY */
USAMPLER2DMSARRAY = 463, /* USAMPLER2DMSARRAY */ ISAMPLER2DMSARRAY = 463, /* ISAMPLER2DMSARRAY */
SAMPLEREXTERNALOES = 464, /* SAMPLEREXTERNALOES */ USAMPLER2DMSARRAY = 464, /* USAMPLER2DMSARRAY */
SAMPLEREXTERNAL2DY2YEXT = 465, /* SAMPLEREXTERNAL2DY2YEXT */ SAMPLEREXTERNALOES = 465, /* SAMPLEREXTERNALOES */
ISAMPLER1DARRAY = 466, /* ISAMPLER1DARRAY */ SAMPLEREXTERNAL2DY2YEXT = 466, /* SAMPLEREXTERNAL2DY2YEXT */
USAMPLER1D = 467, /* USAMPLER1D */ ISAMPLER1DARRAY = 467, /* ISAMPLER1DARRAY */
USAMPLER1DARRAY = 468, /* USAMPLER1DARRAY */ USAMPLER1D = 468, /* USAMPLER1D */
F16SAMPLER1D = 469, /* F16SAMPLER1D */ USAMPLER1DARRAY = 469, /* USAMPLER1DARRAY */
F16SAMPLER2D = 470, /* F16SAMPLER2D */ F16SAMPLER1D = 470, /* F16SAMPLER1D */
F16SAMPLER3D = 471, /* F16SAMPLER3D */ F16SAMPLER2D = 471, /* F16SAMPLER2D */
F16SAMPLER2DRECT = 472, /* F16SAMPLER2DRECT */ F16SAMPLER3D = 472, /* F16SAMPLER3D */
F16SAMPLERCUBE = 473, /* F16SAMPLERCUBE */ F16SAMPLER2DRECT = 473, /* F16SAMPLER2DRECT */
F16SAMPLER1DARRAY = 474, /* F16SAMPLER1DARRAY */ F16SAMPLERCUBE = 474, /* F16SAMPLERCUBE */
F16SAMPLER2DARRAY = 475, /* F16SAMPLER2DARRAY */ F16SAMPLER1DARRAY = 475, /* F16SAMPLER1DARRAY */
F16SAMPLERCUBEARRAY = 476, /* F16SAMPLERCUBEARRAY */ F16SAMPLER2DARRAY = 476, /* F16SAMPLER2DARRAY */
F16SAMPLERBUFFER = 477, /* F16SAMPLERBUFFER */ F16SAMPLERCUBEARRAY = 477, /* F16SAMPLERCUBEARRAY */
F16SAMPLER2DMS = 478, /* F16SAMPLER2DMS */ F16SAMPLERBUFFER = 478, /* F16SAMPLERBUFFER */
F16SAMPLER2DMSARRAY = 479, /* F16SAMPLER2DMSARRAY */ F16SAMPLER2DMS = 479, /* F16SAMPLER2DMS */
F16SAMPLER1DSHADOW = 480, /* F16SAMPLER1DSHADOW */ F16SAMPLER2DMSARRAY = 480, /* F16SAMPLER2DMSARRAY */
F16SAMPLER2DSHADOW = 481, /* F16SAMPLER2DSHADOW */ F16SAMPLER1DSHADOW = 481, /* F16SAMPLER1DSHADOW */
F16SAMPLER1DARRAYSHADOW = 482, /* F16SAMPLER1DARRAYSHADOW */ F16SAMPLER2DSHADOW = 482, /* F16SAMPLER2DSHADOW */
F16SAMPLER2DARRAYSHADOW = 483, /* F16SAMPLER2DARRAYSHADOW */ F16SAMPLER1DARRAYSHADOW = 483, /* F16SAMPLER1DARRAYSHADOW */
F16SAMPLER2DRECTSHADOW = 484, /* F16SAMPLER2DRECTSHADOW */ F16SAMPLER2DARRAYSHADOW = 484, /* F16SAMPLER2DARRAYSHADOW */
F16SAMPLERCUBESHADOW = 485, /* F16SAMPLERCUBESHADOW */ F16SAMPLER2DRECTSHADOW = 485, /* F16SAMPLER2DRECTSHADOW */
F16SAMPLERCUBEARRAYSHADOW = 486, /* F16SAMPLERCUBEARRAYSHADOW */ F16SAMPLERCUBESHADOW = 486, /* F16SAMPLERCUBESHADOW */
IMAGE1D = 487, /* IMAGE1D */ F16SAMPLERCUBEARRAYSHADOW = 487, /* F16SAMPLERCUBEARRAYSHADOW */
IIMAGE1D = 488, /* IIMAGE1D */ IMAGE1D = 488, /* IMAGE1D */
UIMAGE1D = 489, /* UIMAGE1D */ IIMAGE1D = 489, /* IIMAGE1D */
IMAGE2D = 490, /* IMAGE2D */ UIMAGE1D = 490, /* UIMAGE1D */
IIMAGE2D = 491, /* IIMAGE2D */ IMAGE2D = 491, /* IMAGE2D */
UIMAGE2D = 492, /* UIMAGE2D */ IIMAGE2D = 492, /* IIMAGE2D */
IMAGE3D = 493, /* IMAGE3D */ UIMAGE2D = 493, /* UIMAGE2D */
IIMAGE3D = 494, /* IIMAGE3D */ IMAGE3D = 494, /* IMAGE3D */
UIMAGE3D = 495, /* UIMAGE3D */ IIMAGE3D = 495, /* IIMAGE3D */
IMAGE2DRECT = 496, /* IMAGE2DRECT */ UIMAGE3D = 496, /* UIMAGE3D */
IIMAGE2DRECT = 497, /* IIMAGE2DRECT */ IMAGE2DRECT = 497, /* IMAGE2DRECT */
UIMAGE2DRECT = 498, /* UIMAGE2DRECT */ IIMAGE2DRECT = 498, /* IIMAGE2DRECT */
IMAGECUBE = 499, /* IMAGECUBE */ UIMAGE2DRECT = 499, /* UIMAGE2DRECT */
IIMAGECUBE = 500, /* IIMAGECUBE */ IMAGECUBE = 500, /* IMAGECUBE */
UIMAGECUBE = 501, /* UIMAGECUBE */ IIMAGECUBE = 501, /* IIMAGECUBE */
IMAGEBUFFER = 502, /* IMAGEBUFFER */ UIMAGECUBE = 502, /* UIMAGECUBE */
IIMAGEBUFFER = 503, /* IIMAGEBUFFER */ IMAGEBUFFER = 503, /* IMAGEBUFFER */
UIMAGEBUFFER = 504, /* UIMAGEBUFFER */ IIMAGEBUFFER = 504, /* IIMAGEBUFFER */
IMAGE1DARRAY = 505, /* IMAGE1DARRAY */ UIMAGEBUFFER = 505, /* UIMAGEBUFFER */
IIMAGE1DARRAY = 506, /* IIMAGE1DARRAY */ IMAGE1DARRAY = 506, /* IMAGE1DARRAY */
UIMAGE1DARRAY = 507, /* UIMAGE1DARRAY */ IIMAGE1DARRAY = 507, /* IIMAGE1DARRAY */
IMAGE2DARRAY = 508, /* IMAGE2DARRAY */ UIMAGE1DARRAY = 508, /* UIMAGE1DARRAY */
IIMAGE2DARRAY = 509, /* IIMAGE2DARRAY */ IMAGE2DARRAY = 509, /* IMAGE2DARRAY */
UIMAGE2DARRAY = 510, /* UIMAGE2DARRAY */ IIMAGE2DARRAY = 510, /* IIMAGE2DARRAY */
IMAGECUBEARRAY = 511, /* IMAGECUBEARRAY */ UIMAGE2DARRAY = 511, /* UIMAGE2DARRAY */
IIMAGECUBEARRAY = 512, /* IIMAGECUBEARRAY */ IMAGECUBEARRAY = 512, /* IMAGECUBEARRAY */
UIMAGECUBEARRAY = 513, /* UIMAGECUBEARRAY */ IIMAGECUBEARRAY = 513, /* IIMAGECUBEARRAY */
IMAGE2DMS = 514, /* IMAGE2DMS */ UIMAGECUBEARRAY = 514, /* UIMAGECUBEARRAY */
IIMAGE2DMS = 515, /* IIMAGE2DMS */ IMAGE2DMS = 515, /* IMAGE2DMS */
UIMAGE2DMS = 516, /* UIMAGE2DMS */ IIMAGE2DMS = 516, /* IIMAGE2DMS */
IMAGE2DMSARRAY = 517, /* IMAGE2DMSARRAY */ UIMAGE2DMS = 517, /* UIMAGE2DMS */
IIMAGE2DMSARRAY = 518, /* IIMAGE2DMSARRAY */ IMAGE2DMSARRAY = 518, /* IMAGE2DMSARRAY */
UIMAGE2DMSARRAY = 519, /* UIMAGE2DMSARRAY */ IIMAGE2DMSARRAY = 519, /* IIMAGE2DMSARRAY */
F16IMAGE1D = 520, /* F16IMAGE1D */ UIMAGE2DMSARRAY = 520, /* UIMAGE2DMSARRAY */
F16IMAGE2D = 521, /* F16IMAGE2D */ F16IMAGE1D = 521, /* F16IMAGE1D */
F16IMAGE3D = 522, /* F16IMAGE3D */ F16IMAGE2D = 522, /* F16IMAGE2D */
F16IMAGE2DRECT = 523, /* F16IMAGE2DRECT */ F16IMAGE3D = 523, /* F16IMAGE3D */
F16IMAGECUBE = 524, /* F16IMAGECUBE */ F16IMAGE2DRECT = 524, /* F16IMAGE2DRECT */
F16IMAGE1DARRAY = 525, /* F16IMAGE1DARRAY */ F16IMAGECUBE = 525, /* F16IMAGECUBE */
F16IMAGE2DARRAY = 526, /* F16IMAGE2DARRAY */ F16IMAGE1DARRAY = 526, /* F16IMAGE1DARRAY */
F16IMAGECUBEARRAY = 527, /* F16IMAGECUBEARRAY */ F16IMAGE2DARRAY = 527, /* F16IMAGE2DARRAY */
F16IMAGEBUFFER = 528, /* F16IMAGEBUFFER */ F16IMAGECUBEARRAY = 528, /* F16IMAGECUBEARRAY */
F16IMAGE2DMS = 529, /* F16IMAGE2DMS */ F16IMAGEBUFFER = 529, /* F16IMAGEBUFFER */
F16IMAGE2DMSARRAY = 530, /* F16IMAGE2DMSARRAY */ F16IMAGE2DMS = 530, /* F16IMAGE2DMS */
I64IMAGE1D = 531, /* I64IMAGE1D */ F16IMAGE2DMSARRAY = 531, /* F16IMAGE2DMSARRAY */
U64IMAGE1D = 532, /* U64IMAGE1D */ I64IMAGE1D = 532, /* I64IMAGE1D */
I64IMAGE2D = 533, /* I64IMAGE2D */ U64IMAGE1D = 533, /* U64IMAGE1D */
U64IMAGE2D = 534, /* U64IMAGE2D */ I64IMAGE2D = 534, /* I64IMAGE2D */
I64IMAGE3D = 535, /* I64IMAGE3D */ U64IMAGE2D = 535, /* U64IMAGE2D */
U64IMAGE3D = 536, /* U64IMAGE3D */ I64IMAGE3D = 536, /* I64IMAGE3D */
I64IMAGE2DRECT = 537, /* I64IMAGE2DRECT */ U64IMAGE3D = 537, /* U64IMAGE3D */
U64IMAGE2DRECT = 538, /* U64IMAGE2DRECT */ I64IMAGE2DRECT = 538, /* I64IMAGE2DRECT */
I64IMAGECUBE = 539, /* I64IMAGECUBE */ U64IMAGE2DRECT = 539, /* U64IMAGE2DRECT */
U64IMAGECUBE = 540, /* U64IMAGECUBE */ I64IMAGECUBE = 540, /* I64IMAGECUBE */
I64IMAGEBUFFER = 541, /* I64IMAGEBUFFER */ U64IMAGECUBE = 541, /* U64IMAGECUBE */
U64IMAGEBUFFER = 542, /* U64IMAGEBUFFER */ I64IMAGEBUFFER = 542, /* I64IMAGEBUFFER */
I64IMAGE1DARRAY = 543, /* I64IMAGE1DARRAY */ U64IMAGEBUFFER = 543, /* U64IMAGEBUFFER */
U64IMAGE1DARRAY = 544, /* U64IMAGE1DARRAY */ I64IMAGE1DARRAY = 544, /* I64IMAGE1DARRAY */
I64IMAGE2DARRAY = 545, /* I64IMAGE2DARRAY */ U64IMAGE1DARRAY = 545, /* U64IMAGE1DARRAY */
U64IMAGE2DARRAY = 546, /* U64IMAGE2DARRAY */ I64IMAGE2DARRAY = 546, /* I64IMAGE2DARRAY */
I64IMAGECUBEARRAY = 547, /* I64IMAGECUBEARRAY */ U64IMAGE2DARRAY = 547, /* U64IMAGE2DARRAY */
U64IMAGECUBEARRAY = 548, /* U64IMAGECUBEARRAY */ I64IMAGECUBEARRAY = 548, /* I64IMAGECUBEARRAY */
I64IMAGE2DMS = 549, /* I64IMAGE2DMS */ U64IMAGECUBEARRAY = 549, /* U64IMAGECUBEARRAY */
U64IMAGE2DMS = 550, /* U64IMAGE2DMS */ I64IMAGE2DMS = 550, /* I64IMAGE2DMS */
I64IMAGE2DMSARRAY = 551, /* I64IMAGE2DMSARRAY */ U64IMAGE2DMS = 551, /* U64IMAGE2DMS */
U64IMAGE2DMSARRAY = 552, /* U64IMAGE2DMSARRAY */ I64IMAGE2DMSARRAY = 552, /* I64IMAGE2DMSARRAY */
TEXTURECUBEARRAY = 553, /* TEXTURECUBEARRAY */ U64IMAGE2DMSARRAY = 553, /* U64IMAGE2DMSARRAY */
ITEXTURECUBEARRAY = 554, /* ITEXTURECUBEARRAY */ TEXTURECUBEARRAY = 554, /* TEXTURECUBEARRAY */
UTEXTURECUBEARRAY = 555, /* UTEXTURECUBEARRAY */ ITEXTURECUBEARRAY = 555, /* ITEXTURECUBEARRAY */
TEXTURE1D = 556, /* TEXTURE1D */ UTEXTURECUBEARRAY = 556, /* UTEXTURECUBEARRAY */
ITEXTURE1D = 557, /* ITEXTURE1D */ TEXTURE1D = 557, /* TEXTURE1D */
UTEXTURE1D = 558, /* UTEXTURE1D */ ITEXTURE1D = 558, /* ITEXTURE1D */
TEXTURE1DARRAY = 559, /* TEXTURE1DARRAY */ UTEXTURE1D = 559, /* UTEXTURE1D */
ITEXTURE1DARRAY = 560, /* ITEXTURE1DARRAY */ TEXTURE1DARRAY = 560, /* TEXTURE1DARRAY */
UTEXTURE1DARRAY = 561, /* UTEXTURE1DARRAY */ ITEXTURE1DARRAY = 561, /* ITEXTURE1DARRAY */
TEXTURE2DRECT = 562, /* TEXTURE2DRECT */ UTEXTURE1DARRAY = 562, /* UTEXTURE1DARRAY */
ITEXTURE2DRECT = 563, /* ITEXTURE2DRECT */ TEXTURE2DRECT = 563, /* TEXTURE2DRECT */
UTEXTURE2DRECT = 564, /* UTEXTURE2DRECT */ ITEXTURE2DRECT = 564, /* ITEXTURE2DRECT */
TEXTUREBUFFER = 565, /* TEXTUREBUFFER */ UTEXTURE2DRECT = 565, /* UTEXTURE2DRECT */
ITEXTUREBUFFER = 566, /* ITEXTUREBUFFER */ TEXTUREBUFFER = 566, /* TEXTUREBUFFER */
UTEXTUREBUFFER = 567, /* UTEXTUREBUFFER */ ITEXTUREBUFFER = 567, /* ITEXTUREBUFFER */
TEXTURE2DMS = 568, /* TEXTURE2DMS */ UTEXTUREBUFFER = 568, /* UTEXTUREBUFFER */
ITEXTURE2DMS = 569, /* ITEXTURE2DMS */ TEXTURE2DMS = 569, /* TEXTURE2DMS */
UTEXTURE2DMS = 570, /* UTEXTURE2DMS */ ITEXTURE2DMS = 570, /* ITEXTURE2DMS */
TEXTURE2DMSARRAY = 571, /* TEXTURE2DMSARRAY */ UTEXTURE2DMS = 571, /* UTEXTURE2DMS */
ITEXTURE2DMSARRAY = 572, /* ITEXTURE2DMSARRAY */ TEXTURE2DMSARRAY = 572, /* TEXTURE2DMSARRAY */
UTEXTURE2DMSARRAY = 573, /* UTEXTURE2DMSARRAY */ ITEXTURE2DMSARRAY = 573, /* ITEXTURE2DMSARRAY */
F16TEXTURE1D = 574, /* F16TEXTURE1D */ UTEXTURE2DMSARRAY = 574, /* UTEXTURE2DMSARRAY */
F16TEXTURE2D = 575, /* F16TEXTURE2D */ F16TEXTURE1D = 575, /* F16TEXTURE1D */
F16TEXTURE3D = 576, /* F16TEXTURE3D */ F16TEXTURE2D = 576, /* F16TEXTURE2D */
F16TEXTURE2DRECT = 577, /* F16TEXTURE2DRECT */ F16TEXTURE3D = 577, /* F16TEXTURE3D */
F16TEXTURECUBE = 578, /* F16TEXTURECUBE */ F16TEXTURE2DRECT = 578, /* F16TEXTURE2DRECT */
F16TEXTURE1DARRAY = 579, /* F16TEXTURE1DARRAY */ F16TEXTURECUBE = 579, /* F16TEXTURECUBE */
F16TEXTURE2DARRAY = 580, /* F16TEXTURE2DARRAY */ F16TEXTURE1DARRAY = 580, /* F16TEXTURE1DARRAY */
F16TEXTURECUBEARRAY = 581, /* F16TEXTURECUBEARRAY */ F16TEXTURE2DARRAY = 581, /* F16TEXTURE2DARRAY */
F16TEXTUREBUFFER = 582, /* F16TEXTUREBUFFER */ F16TEXTURECUBEARRAY = 582, /* F16TEXTURECUBEARRAY */
F16TEXTURE2DMS = 583, /* F16TEXTURE2DMS */ F16TEXTUREBUFFER = 583, /* F16TEXTUREBUFFER */
F16TEXTURE2DMSARRAY = 584, /* F16TEXTURE2DMSARRAY */ F16TEXTURE2DMS = 584, /* F16TEXTURE2DMS */
SUBPASSINPUT = 585, /* SUBPASSINPUT */ F16TEXTURE2DMSARRAY = 585, /* F16TEXTURE2DMSARRAY */
SUBPASSINPUTMS = 586, /* SUBPASSINPUTMS */ SUBPASSINPUT = 586, /* SUBPASSINPUT */
ISUBPASSINPUT = 587, /* ISUBPASSINPUT */ SUBPASSINPUTMS = 587, /* SUBPASSINPUTMS */
ISUBPASSINPUTMS = 588, /* ISUBPASSINPUTMS */ ISUBPASSINPUT = 588, /* ISUBPASSINPUT */
USUBPASSINPUT = 589, /* USUBPASSINPUT */ ISUBPASSINPUTMS = 589, /* ISUBPASSINPUTMS */
USUBPASSINPUTMS = 590, /* USUBPASSINPUTMS */ USUBPASSINPUT = 590, /* USUBPASSINPUT */
F16SUBPASSINPUT = 591, /* F16SUBPASSINPUT */ USUBPASSINPUTMS = 591, /* USUBPASSINPUTMS */
F16SUBPASSINPUTMS = 592, /* F16SUBPASSINPUTMS */ F16SUBPASSINPUT = 592, /* F16SUBPASSINPUT */
SPIRV_INSTRUCTION = 593, /* SPIRV_INSTRUCTION */ F16SUBPASSINPUTMS = 593, /* F16SUBPASSINPUTMS */
SPIRV_EXECUTION_MODE = 594, /* SPIRV_EXECUTION_MODE */ SPIRV_INSTRUCTION = 594, /* SPIRV_INSTRUCTION */
SPIRV_EXECUTION_MODE_ID = 595, /* SPIRV_EXECUTION_MODE_ID */ SPIRV_EXECUTION_MODE = 595, /* SPIRV_EXECUTION_MODE */
SPIRV_DECORATE = 596, /* SPIRV_DECORATE */ SPIRV_EXECUTION_MODE_ID = 596, /* SPIRV_EXECUTION_MODE_ID */
SPIRV_DECORATE_ID = 597, /* SPIRV_DECORATE_ID */ SPIRV_DECORATE = 597, /* SPIRV_DECORATE */
SPIRV_DECORATE_STRING = 598, /* SPIRV_DECORATE_STRING */ SPIRV_DECORATE_ID = 598, /* SPIRV_DECORATE_ID */
SPIRV_TYPE = 599, /* SPIRV_TYPE */ SPIRV_DECORATE_STRING = 599, /* SPIRV_DECORATE_STRING */
SPIRV_STORAGE_CLASS = 600, /* SPIRV_STORAGE_CLASS */ SPIRV_TYPE = 600, /* SPIRV_TYPE */
SPIRV_BY_REFERENCE = 601, /* SPIRV_BY_REFERENCE */ SPIRV_STORAGE_CLASS = 601, /* SPIRV_STORAGE_CLASS */
SPIRV_LITERAL = 602, /* SPIRV_LITERAL */ SPIRV_BY_REFERENCE = 602, /* SPIRV_BY_REFERENCE */
ATTACHMENTEXT = 603, /* ATTACHMENTEXT */ SPIRV_LITERAL = 603, /* SPIRV_LITERAL */
IATTACHMENTEXT = 604, /* IATTACHMENTEXT */ ATTACHMENTEXT = 604, /* ATTACHMENTEXT */
UATTACHMENTEXT = 605, /* UATTACHMENTEXT */ IATTACHMENTEXT = 605, /* IATTACHMENTEXT */
LEFT_OP = 606, /* LEFT_OP */ UATTACHMENTEXT = 606, /* UATTACHMENTEXT */
RIGHT_OP = 607, /* RIGHT_OP */ LEFT_OP = 607, /* LEFT_OP */
INC_OP = 608, /* INC_OP */ RIGHT_OP = 608, /* RIGHT_OP */
DEC_OP = 609, /* DEC_OP */ INC_OP = 609, /* INC_OP */
LE_OP = 610, /* LE_OP */ DEC_OP = 610, /* DEC_OP */
GE_OP = 611, /* GE_OP */ LE_OP = 611, /* LE_OP */
EQ_OP = 612, /* EQ_OP */ GE_OP = 612, /* GE_OP */
NE_OP = 613, /* NE_OP */ EQ_OP = 613, /* EQ_OP */
AND_OP = 614, /* AND_OP */ NE_OP = 614, /* NE_OP */
OR_OP = 615, /* OR_OP */ AND_OP = 615, /* AND_OP */
XOR_OP = 616, /* XOR_OP */ OR_OP = 616, /* OR_OP */
MUL_ASSIGN = 617, /* MUL_ASSIGN */ XOR_OP = 617, /* XOR_OP */
DIV_ASSIGN = 618, /* DIV_ASSIGN */ MUL_ASSIGN = 618, /* MUL_ASSIGN */
ADD_ASSIGN = 619, /* ADD_ASSIGN */ DIV_ASSIGN = 619, /* DIV_ASSIGN */
MOD_ASSIGN = 620, /* MOD_ASSIGN */ ADD_ASSIGN = 620, /* ADD_ASSIGN */
LEFT_ASSIGN = 621, /* LEFT_ASSIGN */ MOD_ASSIGN = 621, /* MOD_ASSIGN */
RIGHT_ASSIGN = 622, /* RIGHT_ASSIGN */ LEFT_ASSIGN = 622, /* LEFT_ASSIGN */
AND_ASSIGN = 623, /* AND_ASSIGN */ RIGHT_ASSIGN = 623, /* RIGHT_ASSIGN */
XOR_ASSIGN = 624, /* XOR_ASSIGN */ AND_ASSIGN = 624, /* AND_ASSIGN */
OR_ASSIGN = 625, /* OR_ASSIGN */ XOR_ASSIGN = 625, /* XOR_ASSIGN */
SUB_ASSIGN = 626, /* SUB_ASSIGN */ OR_ASSIGN = 626, /* OR_ASSIGN */
STRING_LITERAL = 627, /* STRING_LITERAL */ SUB_ASSIGN = 627, /* SUB_ASSIGN */
LEFT_PAREN = 628, /* LEFT_PAREN */ STRING_LITERAL = 628, /* STRING_LITERAL */
RIGHT_PAREN = 629, /* RIGHT_PAREN */ LEFT_PAREN = 629, /* LEFT_PAREN */
LEFT_BRACKET = 630, /* LEFT_BRACKET */ RIGHT_PAREN = 630, /* RIGHT_PAREN */
RIGHT_BRACKET = 631, /* RIGHT_BRACKET */ LEFT_BRACKET = 631, /* LEFT_BRACKET */
LEFT_BRACE = 632, /* LEFT_BRACE */ RIGHT_BRACKET = 632, /* RIGHT_BRACKET */
RIGHT_BRACE = 633, /* RIGHT_BRACE */ LEFT_BRACE = 633, /* LEFT_BRACE */
DOT = 634, /* DOT */ RIGHT_BRACE = 634, /* RIGHT_BRACE */
COMMA = 635, /* COMMA */ DOT = 635, /* DOT */
COLON = 636, /* COLON */ COMMA = 636, /* COMMA */
EQUAL = 637, /* EQUAL */ COLON = 637, /* COLON */
SEMICOLON = 638, /* SEMICOLON */ EQUAL = 638, /* EQUAL */
BANG = 639, /* BANG */ SEMICOLON = 639, /* SEMICOLON */
DASH = 640, /* DASH */ BANG = 640, /* BANG */
TILDE = 641, /* TILDE */ DASH = 641, /* DASH */
PLUS = 642, /* PLUS */ TILDE = 642, /* TILDE */
STAR = 643, /* STAR */ PLUS = 643, /* PLUS */
SLASH = 644, /* SLASH */ STAR = 644, /* STAR */
PERCENT = 645, /* PERCENT */ SLASH = 645, /* SLASH */
LEFT_ANGLE = 646, /* LEFT_ANGLE */ PERCENT = 646, /* PERCENT */
RIGHT_ANGLE = 647, /* RIGHT_ANGLE */ LEFT_ANGLE = 647, /* LEFT_ANGLE */
VERTICAL_BAR = 648, /* VERTICAL_BAR */ RIGHT_ANGLE = 648, /* RIGHT_ANGLE */
CARET = 649, /* CARET */ VERTICAL_BAR = 649, /* VERTICAL_BAR */
AMPERSAND = 650, /* AMPERSAND */ CARET = 650, /* CARET */
QUESTION = 651, /* QUESTION */ AMPERSAND = 651, /* AMPERSAND */
INVARIANT = 652, /* INVARIANT */ QUESTION = 652, /* QUESTION */
HIGH_PRECISION = 653, /* HIGH_PRECISION */ INVARIANT = 653, /* INVARIANT */
MEDIUM_PRECISION = 654, /* MEDIUM_PRECISION */ HIGH_PRECISION = 654, /* HIGH_PRECISION */
LOW_PRECISION = 655, /* LOW_PRECISION */ MEDIUM_PRECISION = 655, /* MEDIUM_PRECISION */
PRECISION = 656, /* PRECISION */ LOW_PRECISION = 656, /* LOW_PRECISION */
PACKED = 657, /* PACKED */ PRECISION = 657, /* PRECISION */
RESOURCE = 658, /* RESOURCE */ PACKED = 658, /* PACKED */
SUPERP = 659, /* SUPERP */ RESOURCE = 659, /* RESOURCE */
FLOATCONSTANT = 660, /* FLOATCONSTANT */ SUPERP = 660, /* SUPERP */
INTCONSTANT = 661, /* INTCONSTANT */ FLOATCONSTANT = 661, /* FLOATCONSTANT */
UINTCONSTANT = 662, /* UINTCONSTANT */ INTCONSTANT = 662, /* INTCONSTANT */
BOOLCONSTANT = 663, /* BOOLCONSTANT */ UINTCONSTANT = 663, /* UINTCONSTANT */
IDENTIFIER = 664, /* IDENTIFIER */ BOOLCONSTANT = 664, /* BOOLCONSTANT */
TYPE_NAME = 665, /* TYPE_NAME */ IDENTIFIER = 665, /* IDENTIFIER */
CENTROID = 666, /* CENTROID */ TYPE_NAME = 666, /* TYPE_NAME */
IN = 667, /* IN */ CENTROID = 667, /* CENTROID */
OUT = 668, /* OUT */ IN = 668, /* IN */
INOUT = 669, /* INOUT */ OUT = 669, /* OUT */
STRUCT = 670, /* STRUCT */ INOUT = 670, /* INOUT */
VOID = 671, /* VOID */ STRUCT = 671, /* STRUCT */
WHILE = 672, /* WHILE */ VOID = 672, /* VOID */
BREAK = 673, /* BREAK */ WHILE = 673, /* WHILE */
CONTINUE = 674, /* CONTINUE */ BREAK = 674, /* BREAK */
DO = 675, /* DO */ CONTINUE = 675, /* CONTINUE */
ELSE = 676, /* ELSE */ DO = 676, /* DO */
FOR = 677, /* FOR */ ELSE = 677, /* ELSE */
IF = 678, /* IF */ FOR = 678, /* FOR */
DISCARD = 679, /* DISCARD */ IF = 679, /* IF */
RETURN = 680, /* RETURN */ DISCARD = 680, /* DISCARD */
SWITCH = 681, /* SWITCH */ RETURN = 681, /* RETURN */
CASE = 682, /* CASE */ SWITCH = 682, /* SWITCH */
DEFAULT = 683, /* DEFAULT */ CASE = 683, /* CASE */
TERMINATE_INVOCATION = 684, /* TERMINATE_INVOCATION */ DEFAULT = 684, /* DEFAULT */
TERMINATE_RAY = 685, /* TERMINATE_RAY */ TERMINATE_INVOCATION = 685, /* TERMINATE_INVOCATION */
IGNORE_INTERSECTION = 686, /* IGNORE_INTERSECTION */ TERMINATE_RAY = 686, /* TERMINATE_RAY */
UNIFORM = 687, /* UNIFORM */ IGNORE_INTERSECTION = 687, /* IGNORE_INTERSECTION */
SHARED = 688, /* SHARED */ UNIFORM = 688, /* UNIFORM */
BUFFER = 689, /* BUFFER */ SHARED = 689, /* SHARED */
TILEIMAGEEXT = 690, /* TILEIMAGEEXT */ BUFFER = 690, /* BUFFER */
FLAT = 691, /* FLAT */ TILEIMAGEEXT = 691, /* TILEIMAGEEXT */
SMOOTH = 692, /* SMOOTH */ FLAT = 692, /* FLAT */
LAYOUT = 693, /* LAYOUT */ SMOOTH = 693, /* SMOOTH */
DOUBLECONSTANT = 694, /* DOUBLECONSTANT */ LAYOUT = 694, /* LAYOUT */
INT16CONSTANT = 695, /* INT16CONSTANT */ DOUBLECONSTANT = 695, /* DOUBLECONSTANT */
UINT16CONSTANT = 696, /* UINT16CONSTANT */ INT16CONSTANT = 696, /* INT16CONSTANT */
FLOAT16CONSTANT = 697, /* FLOAT16CONSTANT */ UINT16CONSTANT = 697, /* UINT16CONSTANT */
INT32CONSTANT = 698, /* INT32CONSTANT */ FLOAT16CONSTANT = 698, /* FLOAT16CONSTANT */
UINT32CONSTANT = 699, /* UINT32CONSTANT */ INT32CONSTANT = 699, /* INT32CONSTANT */
INT64CONSTANT = 700, /* INT64CONSTANT */ UINT32CONSTANT = 700, /* UINT32CONSTANT */
UINT64CONSTANT = 701, /* UINT64CONSTANT */ INT64CONSTANT = 701, /* INT64CONSTANT */
SUBROUTINE = 702, /* SUBROUTINE */ UINT64CONSTANT = 702, /* UINT64CONSTANT */
DEMOTE = 703, /* DEMOTE */ SUBROUTINE = 703, /* SUBROUTINE */
FUNCTION = 704, /* FUNCTION */ DEMOTE = 704, /* DEMOTE */
PAYLOADNV = 705, /* PAYLOADNV */ FUNCTION = 705, /* FUNCTION */
PAYLOADINNV = 706, /* PAYLOADINNV */ PAYLOADNV = 706, /* PAYLOADNV */
HITATTRNV = 707, /* HITATTRNV */ PAYLOADINNV = 707, /* PAYLOADINNV */
CALLDATANV = 708, /* CALLDATANV */ HITATTRNV = 708, /* HITATTRNV */
CALLDATAINNV = 709, /* CALLDATAINNV */ CALLDATANV = 709, /* CALLDATANV */
PAYLOADEXT = 710, /* PAYLOADEXT */ CALLDATAINNV = 710, /* CALLDATAINNV */
PAYLOADINEXT = 711, /* PAYLOADINEXT */ PAYLOADEXT = 711, /* PAYLOADEXT */
HITATTREXT = 712, /* HITATTREXT */ PAYLOADINEXT = 712, /* PAYLOADINEXT */
CALLDATAEXT = 713, /* CALLDATAEXT */ HITATTREXT = 713, /* HITATTREXT */
CALLDATAINEXT = 714, /* CALLDATAINEXT */ CALLDATAEXT = 714, /* CALLDATAEXT */
PATCH = 715, /* PATCH */ CALLDATAINEXT = 715, /* CALLDATAINEXT */
SAMPLE = 716, /* SAMPLE */ PATCH = 716, /* PATCH */
NONUNIFORM = 717, /* NONUNIFORM */ SAMPLE = 717, /* SAMPLE */
COHERENT = 718, /* COHERENT */ NONUNIFORM = 718, /* NONUNIFORM */
VOLATILE = 719, /* VOLATILE */ RESOURCEHEAP = 719, /* RESOURCEHEAP */
RESTRICT = 720, /* RESTRICT */ SAMPLERHEAP = 720, /* SAMPLERHEAP */
READONLY = 721, /* READONLY */ COHERENT = 721, /* COHERENT */
WRITEONLY = 722, /* WRITEONLY */ VOLATILE = 722, /* VOLATILE */
NONTEMPORAL = 723, /* NONTEMPORAL */ RESTRICT = 723, /* RESTRICT */
DEVICECOHERENT = 724, /* DEVICECOHERENT */ READONLY = 724, /* READONLY */
QUEUEFAMILYCOHERENT = 725, /* QUEUEFAMILYCOHERENT */ WRITEONLY = 725, /* WRITEONLY */
WORKGROUPCOHERENT = 726, /* WORKGROUPCOHERENT */ NONTEMPORAL = 726, /* NONTEMPORAL */
SUBGROUPCOHERENT = 727, /* SUBGROUPCOHERENT */ DEVICECOHERENT = 727, /* DEVICECOHERENT */
NONPRIVATE = 728, /* NONPRIVATE */ QUEUEFAMILYCOHERENT = 728, /* QUEUEFAMILYCOHERENT */
SHADERCALLCOHERENT = 729, /* SHADERCALLCOHERENT */ WORKGROUPCOHERENT = 729, /* WORKGROUPCOHERENT */
NOPERSPECTIVE = 730, /* NOPERSPECTIVE */ SUBGROUPCOHERENT = 730, /* SUBGROUPCOHERENT */
EXPLICITINTERPAMD = 731, /* EXPLICITINTERPAMD */ NONPRIVATE = 731, /* NONPRIVATE */
PERVERTEXEXT = 732, /* PERVERTEXEXT */ SHADERCALLCOHERENT = 732, /* SHADERCALLCOHERENT */
PERVERTEXNV = 733, /* PERVERTEXNV */ NOPERSPECTIVE = 733, /* NOPERSPECTIVE */
PERPRIMITIVENV = 734, /* PERPRIMITIVENV */ EXPLICITINTERPAMD = 734, /* EXPLICITINTERPAMD */
PERVIEWNV = 735, /* PERVIEWNV */ PERVERTEXEXT = 735, /* PERVERTEXEXT */
PERTASKNV = 736, /* PERTASKNV */ PERVERTEXNV = 736, /* PERVERTEXNV */
PERPRIMITIVEEXT = 737, /* PERPRIMITIVEEXT */ PERPRIMITIVENV = 737, /* PERPRIMITIVENV */
TASKPAYLOADWORKGROUPEXT = 738, /* TASKPAYLOADWORKGROUPEXT */ PERVIEWNV = 738, /* PERVIEWNV */
PRECISE = 739 /* PRECISE */ PERTASKNV = 739, /* PERTASKNV */
PERPRIMITIVEEXT = 740, /* PERPRIMITIVEEXT */
TASKPAYLOADWORKGROUPEXT = 741, /* TASKPAYLOADWORKGROUPEXT */
PRECISE = 742 /* PRECISE */
}; };
typedef enum yytokentype yytoken_kind_t; typedef enum yytokentype yytoken_kind_t;
#endif #endif
@@ -583,7 +586,7 @@ union YYSTYPE
glslang::TTypeParameters* typeParameters; glslang::TTypeParameters* typeParameters;
} interm; } interm;
#line 587 "MachineIndependent/glslang_tab.cpp.h" #line 590 "MachineIndependent/glslang_tab.cpp.h"
}; };
typedef union YYSTYPE YYSTYPE; typedef union YYSTYPE YYSTYPE;

View File

@@ -888,38 +888,38 @@ bool TDefaultIoResolverBase::doAutoBindingMapping() const { return referenceInte
bool TDefaultIoResolverBase::doAutoLocationMapping() const { return referenceIntermediate.getAutoMapLocations(); } bool TDefaultIoResolverBase::doAutoLocationMapping() const { return referenceIntermediate.getAutoMapLocations(); }
TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int set, int slot) { TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int resource, int set, int slot) {
return std::lower_bound(slots[set].begin(), slots[set].end(), slot); return std::lower_bound(slots[resource][set].begin(), slots[resource][set].end(), slot);
} }
bool TDefaultIoResolverBase::checkEmpty(int set, int slot) { bool TDefaultIoResolverBase::checkEmpty(int resource, int set, int slot) {
TSlotSet::iterator at = findSlot(set, slot); TSlotSet::iterator at = findSlot(resource, set, slot);
return ! (at != slots[set].end() && *at == slot); return ! (at != slots[resource][set].end() && *at == slot);
} }
int TDefaultIoResolverBase::reserveSlot(int set, int slot, int size) { int TDefaultIoResolverBase::reserveSlot(int resource, int set, int slot, int size) {
TSlotSet::iterator at = findSlot(set, slot); TSlotSet::iterator at = findSlot(resource, set, slot);
// tolerate aliasing, by not double-recording aliases // tolerate aliasing, by not double-recording aliases
// (policy about appropriateness of the alias is higher up) // (policy about appropriateness of the alias is higher up)
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
if (at == slots[set].end() || *at != slot + i) if (at == slots[resource][set].end() || *at != slot + i)
at = slots[set].insert(at, slot + i); at = slots[resource][set].insert(at, slot + i);
++at; ++at;
} }
return slot; return slot;
} }
int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) { int TDefaultIoResolverBase::getFreeSlot(int resource, int set, int base, int size) {
TSlotSet::iterator at = findSlot(set, base); TSlotSet::iterator at = findSlot(resource, set, base);
if (at == slots[set].end()) if (at == slots[resource][set].end())
return reserveSlot(set, base, size); return reserveSlot(resource, set, base, size);
// look for a big enough gap // look for a big enough gap
for (; at != slots[set].end(); ++at) { for (; at != slots[resource][set].end(); ++at) {
if (*at - base >= size) if (*at - base >= size)
break; break;
base = *at + 1; base = *at + 1;
} }
return reserveSlot(set, base, size); return reserveSlot(resource, set, base, size);
} }
int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) { int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) {
@@ -1123,13 +1123,13 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
// //
// vs: out vec4 a; // vs: out vec4 a;
// fs: in vec4 a; // fs: in vec4 a;
location = getFreeSlot(resourceKey, 0, typeLocationSize); location = getFreeSlot(0, resourceKey, 0, typeLocationSize);
storageSlotMap[resourceKey][name] = location; storageSlotMap[resourceKey][name] = location;
} }
} else { } else {
// the first interface declarated in a program. // the first interface declarated in a program.
TVarSlotMap varSlotMap; TVarSlotMap varSlotMap;
location = getFreeSlot(resourceKey, 0, typeLocationSize); location = getFreeSlot(0, resourceKey, 0, typeLocationSize);
varSlotMap[name] = location; varSlotMap[name] = location;
storageSlotMap[resourceKey] = varSlotMap; storageSlotMap[resourceKey] = varSlotMap;
} }
@@ -1196,13 +1196,13 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
// //
// vs: uniform vec4 a; // vs: uniform vec4 a;
// fs: uniform vec4 a; // fs: uniform vec4 a;
location = getFreeSlot(resourceKey, 0, computeTypeLocationSize(type, currentStage)); location = getFreeSlot(0, resourceKey, 0, computeTypeLocationSize(type, currentStage));
storageSlotMap[resourceKey][name] = location; storageSlotMap[resourceKey][name] = location;
} }
} else { } else {
// the first uniform declaration in a program. // the first uniform declaration in a program.
TVarSlotMap varSlotMap; TVarSlotMap varSlotMap;
location = getFreeSlot(resourceKey, 0, size); location = getFreeSlot(0, resourceKey, 0, size);
varSlotMap[name] = location; varSlotMap[name] = location;
storageSlotMap[resourceKey] = varSlotMap; storageSlotMap[resourceKey] = varSlotMap;
} }
@@ -1222,13 +1222,12 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent
// There is no 'set' qualifier in OpenGL shading language, each resource has its own // There is no 'set' qualifier in OpenGL shading language, each resource has its own
// binding name space, so remap the 'set' to resource type which make each resource // binding name space, so remap the 'set' to resource type which make each resource
// binding is valid from 0 to MAX_XXRESOURCE_BINDINGS // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
int set = referenceIntermediate.getSpv().openGl != 0 ? resource : ent.newSet; int set = referenceIntermediate.getSpv().openGl != 0 ? 0 : ent.newSet;
int resourceKey = set; int resourceKey = referenceIntermediate.getSpv().openGl != 0 || referenceIntermediate.getBindingsPerResourceType() ? resource : 0;
if (resource < EResCount) { if (resource < EResCount) {
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings); int newBinding = reserveSlot(resourceKey, set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
return ent.newBinding = newBinding; return ent.newBinding = newBinding;
} else { } else {
// The resource in current stage is not declared with binding, but it is possible declared // The resource in current stage is not declared with binding, but it is possible declared
// with explicit binding in other stages, find the resourceSlotMap firstly to check whether // with explicit binding in other stages, find the resourceSlotMap firstly to check whether
@@ -1236,9 +1235,9 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent
bool hasBinding = false; bool hasBinding = false;
ent.newBinding = -1; // leave as -1 if it isn't set below ent.newBinding = -1; // leave as -1 if it isn't set below
if (! resourceSlotMap[resourceKey].empty()) { if (! resourceSlotMap[resourceKey][set].empty()) {
TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name); TVarSlotMap::iterator iter = resourceSlotMap[resourceKey][set].find(name);
if (iter != resourceSlotMap[resourceKey].end()) { if (iter != resourceSlotMap[resourceKey][set].end()) {
hasBinding = true; hasBinding = true;
ent.newBinding = iter->second; ent.newBinding = iter->second;
} }
@@ -1246,8 +1245,8 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent
if (!hasBinding && (ent.live && doAutoBindingMapping())) { if (!hasBinding && (ent.live && doAutoBindingMapping())) {
// find free slot, the caller did make sure it passes all vars with binding // find free slot, the caller did make sure it passes all vars with binding
// first and now all are passed that do not have a binding and needs one // first and now all are passed that do not have a binding and needs one
int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings); int binding = getFreeSlot(resourceKey, set, getBaseBinding(stage, resource, set), numBindings);
resourceSlotMap[resourceKey][name] = binding; resourceSlotMap[resourceKey][set][name] = binding;
ent.newBinding = binding; ent.newBinding = binding;
} }
return ent.newBinding; return ent.newBinding;
@@ -1302,7 +1301,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
TVarSlotMap::iterator iter = varSlotMap.find(name); TVarSlotMap::iterator iter = varSlotMap.find(name);
if (iter == varSlotMap.end()) { if (iter == varSlotMap.end()) {
int numLocations = TIntermediate::computeTypeUniformLocationSize(type); int numLocations = TIntermediate::computeTypeUniformLocationSize(type);
reserveSlot(storageKey, location, numLocations); reserveSlot(0, storageKey, location, numLocations);
varSlotMap[name] = location; varSlotMap[name] = location;
} else { } else {
// Allocate location by name for OpenGL driver, so the uniform in different // Allocate location by name for OpenGL driver, so the uniform in different
@@ -1328,7 +1327,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
TVarSlotMap::iterator iter = varSlotMap.find(name); TVarSlotMap::iterator iter = varSlotMap.find(name);
if (iter == varSlotMap.end()) { if (iter == varSlotMap.end()) {
int numLocations = TIntermediate::computeTypeUniformLocationSize(type); int numLocations = TIntermediate::computeTypeUniformLocationSize(type);
reserveSlot(storageKey, location, numLocations); reserveSlot(0, storageKey, location, numLocations);
varSlotMap[name] = location; varSlotMap[name] = location;
} else { } else {
// Allocate location by name for OpenGL driver, so the uniform in different // Allocate location by name for OpenGL driver, so the uniform in different
@@ -1350,19 +1349,18 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
const TType& type = ent.symbol->getType(); const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getAccessName(); const TString& name = ent.symbol->getAccessName();
TResourceType resource = getResourceType(type); TResourceType resource = getResourceType(type);
int set = referenceIntermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent); int set = referenceIntermediate.getSpv().openGl != 0 ? 0 : resolveSet(ent.stage, ent);
int resourceKey = set; int resourceKey = referenceIntermediate.getSpv().openGl != 0 || referenceIntermediate.getBindingsPerResourceType() ? resource : 0;
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey]; TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey][set];
TVarSlotMap::iterator iter = varSlotMap.find(name); TVarSlotMap::iterator iter = varSlotMap.find(name);
int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set); int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set);
if (iter == varSlotMap.end()) { if (iter == varSlotMap.end()) {
// Reserve the slots for the ubo, ssbo and opaques who has explicit binding // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
varSlotMap[name] = binding; varSlotMap[name] = binding;
reserveSlot(resourceKey, binding, numBindings); reserveSlot(resourceKey, set, binding, numBindings);
} else { } else {
// Allocate binding by name for OpenGL driver, so the resource in different // Allocate binding by name for OpenGL driver, so the resource in different
// stages should be declared with the same binding // stages should be declared with the same binding
@@ -1427,14 +1425,15 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
// On OpenGL arrays of opaque types take a seperate binding for each element // On OpenGL arrays of opaque types take a seperate binding for each element
int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
TResourceType resource = getResourceType(type); TResourceType resource = getResourceType(type);
int resourceKey = referenceIntermediate.getBindingsPerResourceType() ? resource : 0;
if (resource < EResCount) { if (resource < EResCount) {
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
return ent.newBinding = reserveSlot( return ent.newBinding = reserveSlot(
set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings); resourceKey, set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
} else if (ent.live && doAutoBindingMapping()) { } else if (ent.live && doAutoBindingMapping()) {
// find free slot, the caller did make sure it passes all vars with binding // find free slot, the caller did make sure it passes all vars with binding
// first and now all are passed that do not have a binding and needs one // first and now all are passed that do not have a binding and needs one
return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings); return ent.newBinding = getFreeSlot(resourceKey, set, getBaseBinding(stage, resource, set), numBindings);
} }
} }
return ent.newBinding = -1; return ent.newBinding = -1;
@@ -1515,13 +1514,14 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
const TType& type = ent.symbol->getType(); const TType& type = ent.symbol->getType();
const int set = getLayoutSet(type); const int set = getLayoutSet(type);
TResourceType resource = getResourceType(type); TResourceType resource = getResourceType(type);
int resourceKey = referenceIntermediate.getBindingsPerResourceType() ? resource : 0;
if (resource < EResCount) { if (resource < EResCount) {
if (type.getQualifier().hasBinding()) { if (type.getQualifier().hasBinding()) {
return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding); return ent.newBinding = reserveSlot(resourceKey, set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding);
} else if (ent.live && doAutoBindingMapping()) { } else if (ent.live && doAutoBindingMapping()) {
// find free slot, the caller did make sure it passes all vars with binding // find free slot, the caller did make sure it passes all vars with binding
// first and now all are passed that do not have a binding and needs one // first and now all are passed that do not have a binding and needs one
return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set)); return ent.newBinding = getFreeSlot(resourceKey, set, getBaseBinding(stage, resource, set));
} }
} }
return ent.newBinding = -1; return ent.newBinding = -1;

View File

@@ -37,6 +37,7 @@
#define _IOMAPPER_INCLUDED #define _IOMAPPER_INCLUDED
#include <cstdint> #include <cstdint>
#include <array>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
// //
@@ -55,6 +56,7 @@ public:
TDefaultIoResolverBase(const TIntermediate& intermediate); TDefaultIoResolverBase(const TIntermediate& intermediate);
typedef std::vector<int> TSlotSet; typedef std::vector<int> TSlotSet;
typedef std::unordered_map<int, TSlotSet> TSlotSetMap; typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
typedef std::array<TSlotSetMap, EResCount> TSlotSetMapResourceArray;
// grow the reflection stage by stage // grow the reflection stage by stage
void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {}
@@ -72,11 +74,11 @@ public:
virtual TResourceType getResourceType(const glslang::TType& type) = 0; virtual TResourceType getResourceType(const glslang::TType& type) = 0;
bool doAutoBindingMapping() const; bool doAutoBindingMapping() const;
bool doAutoLocationMapping() const; bool doAutoLocationMapping() const;
TSlotSet::iterator findSlot(int set, int slot); TSlotSet::iterator findSlot(int resource, int set, int slot);
bool checkEmpty(int set, int slot); bool checkEmpty(int resource, int set, int slot);
bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
int reserveSlot(int set, int slot, int size = 1); int reserveSlot(int resource, int set, int slot, int size = 1);
int getFreeSlot(int set, int base, int size = 1); int getFreeSlot(int resource, int set, int base, int size = 1);
int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
@@ -90,7 +92,7 @@ public:
} }
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
TSlotSetMap slots; TSlotSetMapResourceArray slots;
bool hasError = false; bool hasError = false;
protected: protected:
@@ -173,6 +175,7 @@ struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
public: public:
typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding> typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
typedef std::map<int, TVarSlotMap> TSlotMap; // <resourceKey, TVarSlotMap> typedef std::map<int, TVarSlotMap> TSlotMap; // <resourceKey, TVarSlotMap>
typedef std::array<TSlotMap, EResCount> TResourceSlotMap;
TDefaultGlslIoResolver(const TIntermediate& intermediate); TDefaultGlslIoResolver(const TIntermediate& intermediate);
bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
TResourceType getResourceType(const glslang::TType& type) override; TResourceType getResourceType(const glslang::TType& type) override;
@@ -200,7 +203,7 @@ protected:
// Use for mark current shader stage for resolver // Use for mark current shader stage for resolver
EShLanguage currentStage; EShLanguage currentStage;
// Slot map for storage resource(location of uniform and interface symbol) It's a program share slot // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot
TSlotMap resourceSlotMap; TResourceSlotMap resourceSlotMap;
// Slot map for other resource(image, ubo, ssbo), It's a program share slot. // Slot map for other resource(image, ubo, ssbo), It's a program share slot.
TSlotMap storageSlotMap; TSlotMap storageSlotMap;
}; };

View File

@@ -524,7 +524,8 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
numErrors += unit.getNumErrors(); numErrors += unit.getNumErrors();
// Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant
// is the same for all units. // is the same for all units.
if (numPushConstants > 1 || unit.numPushConstants > 1) if (!IsRequestedExtension(glslang::E_GL_NV_push_constant_bank) &&
(numPushConstants > 1 || unit.numPushConstants > 1))
error(infoSink, "Only one push_constant block is allowed per stage"); error(infoSink, "Only one push_constant block is allowed per stage");
numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1); numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1);
@@ -1125,7 +1126,8 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
mergeErrorCheck(infoSink, *symbol, *unitSymbol); mergeErrorCheck(infoSink, *symbol, *unitSymbol);
} }
// If different symbols, verify they arn't push_constant since there can only be one per stage // If different symbols, verify they arn't push_constant since there can only be one per stage
else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage) else if (!IsRequestedExtension(glslang::E_GL_NV_push_constant_bank) &&
(symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage))
error(infoSink, "Only one push_constant block is allowed per stage"); error(infoSink, "Only one push_constant block is allowed per stage");
} }
@@ -1590,7 +1592,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
// overlap/alias/missing I/O, etc. // overlap/alias/missing I/O, etc.
inOutLocationCheck(infoSink); inOutLocationCheck(infoSink);
if (getNumPushConstants() > 1) if (!IsRequestedExtension(glslang::E_GL_NV_push_constant_bank) && (getNumPushConstants() > 1))
error(infoSink, "Only one push_constant block is allowed per stage"); error(infoSink, "Only one push_constant block is allowed per stage");
// invocations // invocations
@@ -2573,6 +2575,22 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
} }
} }
// rules 2 and 3
if (type.isLongVector()) {
int scalarAlign = getBaseAlignmentScalar(type, size);
uint32_t vectorSize = type.getTypeParameters()->arraySizes->getDimSize(0);
switch (vectorSize) {
case 1: // HLSL has this, GLSL does not
return scalarAlign;
case 2:
size *= 2;
return 2 * scalarAlign;
default:
size *= vectorSize;
return 4 * scalarAlign;
}
}
// rules 5 and 7 // rules 5 and 7
if (type.isMatrix()) { if (type.isMatrix()) {
// rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
@@ -2653,6 +2671,14 @@ int TIntermediate::getScalarAlignment(const TType& type, int& size, int& stride,
return scalarAlign; return scalarAlign;
} }
if (type.isLongVector()) {
int scalarAlign = getBaseAlignmentScalar(type, size);
uint32_t vectorSize = type.getTypeParameters()->arraySizes->getDimSize(0);
size *= vectorSize;
return scalarAlign;
}
if (type.isMatrix()) { if (type.isMatrix()) {
TType derefType(type, 0, rowMajor); TType derefType(type, 0, rowMajor);

View File

@@ -352,6 +352,7 @@ public:
hlslOffsets(false), hlslOffsets(false),
hlslIoMapping(false), hlslIoMapping(false),
useVariablePointers(false), useVariablePointers(false),
bindingsPerResourceType(false),
textureSamplerTransformMode(EShTexSampTransKeep), textureSamplerTransformMode(EShTexSampTransKeep),
needToLegalize(false), needToLegalize(false),
binaryDoubleOutput(false), binaryDoubleOutput(false),
@@ -840,6 +841,13 @@ public:
bool usingVariablePointers() const { return useVariablePointers; } bool usingVariablePointers() const { return useVariablePointers; }
void setBindingsPerResourceType()
{
bindingsPerResourceType = true;
processes.addProcess("bindings-per-resource-type");
}
bool getBindingsPerResourceType() const { return bindingsPerResourceType; }
#ifdef ENABLE_HLSL #ifdef ENABLE_HLSL
template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; } template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
bool hasCounterBufferName(const TString& name) const { bool hasCounterBufferName(const TString& name) const {
@@ -1302,6 +1310,7 @@ protected:
bool hlslOffsets; bool hlslOffsets;
bool hlslIoMapping; bool hlslIoMapping;
bool useVariablePointers; bool useVariablePointers;
bool bindingsPerResourceType;
std::set<TString> semanticNameSet; std::set<TString> semanticNameSet;

View File

@@ -127,6 +127,7 @@ public:
virtual void coopmatConverisonCheckQCOM(const TSourceLoc& loc, const char* op, bool builtIn = false); virtual void coopmatConverisonCheckQCOM(const TSourceLoc& loc, const char* op, bool builtIn = false);
virtual void tensorLayoutViewCheck(const TSourceLoc&, const char* op, bool builtIn = false); virtual void tensorLayoutViewCheck(const TSourceLoc&, const char* op, bool builtIn = false);
virtual void coopvecCheck(const TSourceLoc&, const char* op, bool builtIn = false); virtual void coopvecCheck(const TSourceLoc&, const char* op, bool builtIn = false);
virtual void longVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
virtual void intattachmentCheck(const TSourceLoc&, const char *op, bool builtIn = false); virtual void intattachmentCheck(const TSourceLoc&, const char *op, bool builtIn = false);
virtual void tensorCheckARM(const TSourceLoc&, const char *op, bool builtIn = false); virtual void tensorCheckARM(const TSourceLoc&, const char *op, bool builtIn = false);
bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }

View File

@@ -496,6 +496,7 @@ public:
void setResourceSetBinding(const std::vector<std::string>& base); void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map); void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map); void setAutoMapLocations(bool map);
void setBindingsPerResourceType();
void addUniformLocationOverride(const char* name, int loc); void addUniformLocationOverride(const char* name, int loc);
void setUniformLocationBase(int base); void setUniformLocationBase(int base);
void setInvertY(bool invert); void setInvertY(bool invert);