mirror of
https://github.com/love2d/love.git
synced 2026-08-19 04:06:17 +02:00
Update glslang
This commit is contained in:
@@ -36,5 +36,6 @@ static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fu
|
|||||||
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
|
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
|
||||||
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
|
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
|
||||||
static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
|
static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
|
||||||
|
static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64";
|
||||||
|
|
||||||
#endif // #ifndef GLSLextEXT_H
|
#endif // #ifndef GLSLextEXT_H
|
||||||
|
|||||||
@@ -48,4 +48,8 @@ static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shade
|
|||||||
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
|
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
|
||||||
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
|
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
|
||||||
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
|
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
|
||||||
|
static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate";
|
||||||
|
static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation";
|
||||||
|
static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout";
|
||||||
|
|
||||||
#endif // #ifndef GLSLextKHR_H
|
#endif // #ifndef GLSLextKHR_H
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ protected:
|
|||||||
spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
|
spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
|
||||||
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
||||||
spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier);
|
spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier);
|
||||||
|
spv::Decoration TranslateNonUniformDecoration(const spv::Builder::AccessChain::CoherentFlags& coherentFlags);
|
||||||
spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type);
|
spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type);
|
||||||
spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
|
spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
|
||||||
spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
|
spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
|
||||||
@@ -189,6 +190,7 @@ protected:
|
|||||||
bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam);
|
bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam);
|
||||||
void makeFunctions(const glslang::TIntermSequence&);
|
void makeFunctions(const glslang::TIntermSequence&);
|
||||||
void makeGlobalInitializers(const glslang::TIntermSequence&);
|
void makeGlobalInitializers(const glslang::TIntermSequence&);
|
||||||
|
void collectRayTracingLinkerObjects();
|
||||||
void visitFunctions(const glslang::TIntermSequence&);
|
void visitFunctions(const glslang::TIntermSequence&);
|
||||||
void handleFunctionEntry(const glslang::TIntermAggregate* node);
|
void handleFunctionEntry(const glslang::TIntermAggregate* node);
|
||||||
void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
|
void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments,
|
||||||
@@ -253,17 +255,17 @@ protected:
|
|||||||
bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
|
bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp
|
||||||
spv::Id stdBuiltins;
|
spv::Id stdBuiltins;
|
||||||
spv::Id nonSemanticDebugPrintf;
|
spv::Id nonSemanticDebugPrintf;
|
||||||
std::unordered_map<const char*, spv::Id> extBuiltinMap;
|
std::unordered_map<std::string, spv::Id> extBuiltinMap;
|
||||||
|
|
||||||
std::unordered_map<int, spv::Id> symbolValues;
|
std::unordered_map<long long, spv::Id> symbolValues;
|
||||||
std::unordered_set<int> rValueParameters; // set of formal function parameters passed as rValues,
|
std::unordered_set<long long> rValueParameters; // set of formal function parameters passed as rValues,
|
||||||
// rather than a pointer
|
// rather than a pointer
|
||||||
std::unordered_map<std::string, spv::Function*> functionMap;
|
std::unordered_map<std::string, spv::Function*> functionMap;
|
||||||
std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
|
std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
|
||||||
// for mapping glslang block indices to spv indices (e.g., due to hidden members):
|
// for mapping glslang block indices to spv indices (e.g., due to hidden members):
|
||||||
std::unordered_map<int, std::vector<int>> memberRemapper;
|
std::unordered_map<long long, std::vector<int>> memberRemapper;
|
||||||
// for mapping glslang symbol struct to symbol Id
|
// for mapping glslang symbol struct to symbol Id
|
||||||
std::unordered_map<const glslang::TTypeList*, int> glslangTypeToIdMap;
|
std::unordered_map<const glslang::TTypeList*, long long> glslangTypeToIdMap;
|
||||||
std::stack<bool> breakForLoop; // false means break for switch
|
std::stack<bool> breakForLoop; // false means break for switch
|
||||||
std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
|
std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
|
||||||
// Map pointee types for EbtReference to their forward pointers
|
// Map pointee types for EbtReference to their forward pointers
|
||||||
@@ -272,6 +274,9 @@ protected:
|
|||||||
// requiring local translation to and from SPIR-V type on every access.
|
// requiring local translation to and from SPIR-V type on every access.
|
||||||
// Maps <builtin-variable-id -> AST-required-type-id>
|
// Maps <builtin-variable-id -> AST-required-type-id>
|
||||||
std::unordered_map<spv::Id, spv::Id> forceType;
|
std::unordered_map<spv::Id, spv::Id> forceType;
|
||||||
|
|
||||||
|
// Used later for generating OpTraceKHR/OpExecuteCallableKHR
|
||||||
|
std::unordered_map<unsigned int, glslang::TIntermSymbol *> locationToSymbol[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -375,6 +380,7 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto
|
|||||||
case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
|
case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
|
||||||
case glslang::EvqVaryingIn: return spv::DecorationBlock;
|
case glslang::EvqVaryingIn: return spv::DecorationBlock;
|
||||||
case glslang::EvqVaryingOut: return spv::DecorationBlock;
|
case glslang::EvqVaryingOut: return spv::DecorationBlock;
|
||||||
|
case glslang::EvqShared: return spv::DecorationBlock;
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
case glslang::EvqPayload: return spv::DecorationBlock;
|
case glslang::EvqPayload: return spv::DecorationBlock;
|
||||||
case glslang::EvqPayloadIn: return spv::DecorationBlock;
|
case glslang::EvqPayloadIn: return spv::DecorationBlock;
|
||||||
@@ -431,6 +437,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
|
|||||||
break;
|
break;
|
||||||
case glslang::EbtBlock:
|
case glslang::EbtBlock:
|
||||||
switch (type.getQualifier().storage) {
|
switch (type.getQualifier().storage) {
|
||||||
|
case glslang::EvqShared:
|
||||||
case glslang::EvqUniform:
|
case glslang::EvqUniform:
|
||||||
case glslang::EvqBuffer:
|
case glslang::EvqBuffer:
|
||||||
switch (type.getQualifier().layoutPacking) {
|
switch (type.getQualifier().layoutPacking) {
|
||||||
@@ -539,6 +546,20 @@ spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glsl
|
|||||||
return spv::DecorationMax;
|
return spv::DecorationMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If lvalue flags contains nonUniform, return SPIR-V NonUniform decoration.
|
||||||
|
spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(
|
||||||
|
const spv::Builder::AccessChain::CoherentFlags& coherentFlags)
|
||||||
|
{
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
if (coherentFlags.isNonUniform()) {
|
||||||
|
builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5);
|
||||||
|
builder.addCapability(spv::CapabilityShaderNonUniformEXT);
|
||||||
|
return spv::DecorationNonUniformEXT;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
return spv::DecorationMax;
|
||||||
|
}
|
||||||
|
|
||||||
spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(
|
spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess(
|
||||||
const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
|
const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
|
||||||
{
|
{
|
||||||
@@ -614,6 +635,7 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere
|
|||||||
flags.volatil;
|
flags.volatil;
|
||||||
flags.isImage = type.getBasicType() == glslang::EbtSampler;
|
flags.isImage = type.getBasicType() == glslang::EbtSampler;
|
||||||
#endif
|
#endif
|
||||||
|
flags.nonUniform = type.getQualifier().nonUniform;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,13 +731,20 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
|||||||
return spv::BuiltInCullDistance;
|
return spv::BuiltInCullDistance;
|
||||||
|
|
||||||
case glslang::EbvViewportIndex:
|
case glslang::EbvViewportIndex:
|
||||||
builder.addCapability(spv::CapabilityMultiViewport);
|
if (glslangIntermediate->getStage() == EShLangGeometry ||
|
||||||
|
glslangIntermediate->getStage() == EShLangFragment) {
|
||||||
|
builder.addCapability(spv::CapabilityMultiViewport);
|
||||||
|
}
|
||||||
if (glslangIntermediate->getStage() == EShLangVertex ||
|
if (glslangIntermediate->getStage() == EShLangVertex ||
|
||||||
glslangIntermediate->getStage() == EShLangTessControl ||
|
glslangIntermediate->getStage() == EShLangTessControl ||
|
||||||
glslangIntermediate->getStage() == EShLangTessEvaluation) {
|
glslangIntermediate->getStage() == EShLangTessEvaluation) {
|
||||||
|
|
||||||
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
|
if (builder.getSpvVersion() < spv::Spv_1_5) {
|
||||||
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
|
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
|
||||||
|
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
builder.addCapability(spv::CapabilityShaderViewportIndex);
|
||||||
}
|
}
|
||||||
return spv::BuiltInViewportIndex;
|
return spv::BuiltInViewportIndex;
|
||||||
|
|
||||||
@@ -734,13 +763,19 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
|||||||
if (glslangIntermediate->getStage() == EShLangMeshNV) {
|
if (glslangIntermediate->getStage() == EShLangMeshNV) {
|
||||||
return spv::BuiltInLayer;
|
return spv::BuiltInLayer;
|
||||||
}
|
}
|
||||||
builder.addCapability(spv::CapabilityGeometry);
|
if (glslangIntermediate->getStage() == EShLangGeometry ||
|
||||||
|
glslangIntermediate->getStage() == EShLangFragment) {
|
||||||
|
builder.addCapability(spv::CapabilityGeometry);
|
||||||
|
}
|
||||||
if (glslangIntermediate->getStage() == EShLangVertex ||
|
if (glslangIntermediate->getStage() == EShLangVertex ||
|
||||||
glslangIntermediate->getStage() == EShLangTessControl ||
|
glslangIntermediate->getStage() == EShLangTessControl ||
|
||||||
glslangIntermediate->getStage() == EShLangTessEvaluation) {
|
glslangIntermediate->getStage() == EShLangTessEvaluation) {
|
||||||
|
|
||||||
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
|
if (builder.getSpvVersion() < spv::Spv_1_5) {
|
||||||
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
|
builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5);
|
||||||
|
builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT);
|
||||||
|
} else
|
||||||
|
builder.addCapability(spv::CapabilityShaderLayer);
|
||||||
}
|
}
|
||||||
return spv::BuiltInLayer;
|
return spv::BuiltInLayer;
|
||||||
|
|
||||||
@@ -769,6 +804,16 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
|||||||
builder.addCapability(spv::CapabilityStencilExportEXT);
|
builder.addCapability(spv::CapabilityStencilExportEXT);
|
||||||
return spv::BuiltInFragStencilRefEXT;
|
return spv::BuiltInFragStencilRefEXT;
|
||||||
|
|
||||||
|
case glslang::EbvShadingRateKHR:
|
||||||
|
builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate);
|
||||||
|
builder.addCapability(spv::CapabilityFragmentShadingRateKHR);
|
||||||
|
return spv::BuiltInShadingRateKHR;
|
||||||
|
|
||||||
|
case glslang::EbvPrimitiveShadingRateKHR:
|
||||||
|
builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate);
|
||||||
|
builder.addCapability(spv::CapabilityFragmentShadingRateKHR);
|
||||||
|
return spv::BuiltInPrimitiveShadingRateKHR;
|
||||||
|
|
||||||
case glslang::EbvInvocationId: return spv::BuiltInInvocationId;
|
case glslang::EbvInvocationId: return spv::BuiltInInvocationId;
|
||||||
case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner;
|
case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner;
|
||||||
case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter;
|
case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter;
|
||||||
@@ -963,7 +1008,17 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
|||||||
case glslang::EbvInstanceCustomIndex:
|
case glslang::EbvInstanceCustomIndex:
|
||||||
return spv::BuiltInInstanceCustomIndexKHR;
|
return spv::BuiltInInstanceCustomIndexKHR;
|
||||||
case glslang::EbvHitT:
|
case glslang::EbvHitT:
|
||||||
return spv::BuiltInHitTKHR;
|
{
|
||||||
|
// this is a GLSL alias of RayTmax
|
||||||
|
// in SPV_NV_ray_tracing it has a dedicated builtin
|
||||||
|
// but in SPV_KHR_ray_tracing it gets mapped to RayTmax
|
||||||
|
auto& extensions = glslangIntermediate->getRequestedExtensions();
|
||||||
|
if (extensions.find("GL_NV_ray_tracing") != extensions.end()) {
|
||||||
|
return spv::BuiltInHitTNV;
|
||||||
|
} else {
|
||||||
|
return spv::BuiltInRayTmaxKHR;
|
||||||
|
}
|
||||||
|
}
|
||||||
case glslang::EbvHitKind:
|
case glslang::EbvHitKind:
|
||||||
return spv::BuiltInHitKindKHR;
|
return spv::BuiltInHitKindKHR;
|
||||||
case glslang::EbvObjectToWorld:
|
case glslang::EbvObjectToWorld:
|
||||||
@@ -1071,6 +1126,10 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
|
|||||||
builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
|
builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case glslang::ElfR64ui:
|
||||||
|
case glslang::ElfR64i:
|
||||||
|
builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
|
||||||
|
builder.addCapability(spv::CapabilityInt64ImageEXT);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1117,6 +1176,8 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
|
|||||||
case glslang::ElfRg8ui: return spv::ImageFormatRg8ui;
|
case glslang::ElfRg8ui: return spv::ImageFormatRg8ui;
|
||||||
case glslang::ElfR16ui: return spv::ImageFormatR16ui;
|
case glslang::ElfR16ui: return spv::ImageFormatR16ui;
|
||||||
case glslang::ElfR8ui: return spv::ImageFormatR8ui;
|
case glslang::ElfR8ui: return spv::ImageFormatR8ui;
|
||||||
|
case glslang::ElfR64ui: return spv::ImageFormatR64ui;
|
||||||
|
case glslang::ElfR64i: return spv::ImageFormatR64i;
|
||||||
default: return spv::ImageFormatMax;
|
default: return spv::ImageFormatMax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1187,7 +1248,7 @@ spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang:
|
|||||||
spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
|
spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
|
||||||
{
|
{
|
||||||
if (type.getBasicType() == glslang::EbtRayQuery)
|
if (type.getBasicType() == glslang::EbtRayQuery)
|
||||||
return spv::StorageClassFunction;
|
return spv::StorageClassPrivate;
|
||||||
if (type.getQualifier().isPipeInput())
|
if (type.getQualifier().isPipeInput())
|
||||||
return spv::StorageClassInput;
|
return spv::StorageClassInput;
|
||||||
if (type.getQualifier().isPipeOutput())
|
if (type.getQualifier().isPipeOutput())
|
||||||
@@ -1219,6 +1280,12 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
|
|||||||
return spv::StorageClassUniformConstant;
|
return spv::StorageClassUniformConstant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type.getQualifier().storage == glslang::EvqShared && type.getBasicType() == glslang::EbtBlock) {
|
||||||
|
builder.addExtension(spv::E_SPV_KHR_workgroup_memory_explicit_layout);
|
||||||
|
builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR);
|
||||||
|
return spv::StorageClassWorkgroup;
|
||||||
|
}
|
||||||
|
|
||||||
switch (type.getQualifier().storage) {
|
switch (type.getQualifier().storage) {
|
||||||
case glslang::EvqGlobal: return spv::StorageClassPrivate;
|
case glslang::EvqGlobal: return spv::StorageClassPrivate;
|
||||||
case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
|
case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
|
||||||
@@ -1353,6 +1420,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa
|
|||||||
if (parent.writeonly)
|
if (parent.writeonly)
|
||||||
child.writeonly = true;
|
child.writeonly = true;
|
||||||
#endif
|
#endif
|
||||||
|
if (parent.nonUniform)
|
||||||
|
child.nonUniform = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier)
|
bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier)
|
||||||
@@ -1424,7 +1493,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
|
|
||||||
if (glslangIntermediate->usingPhysicalStorageBuffer()) {
|
if (glslangIntermediate->usingPhysicalStorageBuffer()) {
|
||||||
addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
|
addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
|
||||||
builder.addIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer, spv::Spv_1_5);
|
builder.addIncorporatedExtension(spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5);
|
||||||
builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
|
builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
|
||||||
}
|
}
|
||||||
if (glslangIntermediate->usingVulkanMemoryModel()) {
|
if (glslangIntermediate->usingVulkanMemoryModel()) {
|
||||||
@@ -1454,7 +1523,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (glslangIntermediate->getLayoutPrimitiveCulling()) {
|
if (glslangIntermediate->getLayoutPrimitiveCulling()) {
|
||||||
builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
|
builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
@@ -1482,15 +1551,16 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
|
builder.addExtension(spv::E_SPV_KHR_post_depth_coverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
|
if (glslangIntermediate->isDepthReplacing())
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
|
|
||||||
switch(glslangIntermediate->getDepth()) {
|
switch(glslangIntermediate->getDepth()) {
|
||||||
case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break;
|
case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break;
|
||||||
case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break;
|
case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break;
|
||||||
default: mode = spv::ExecutionModeMax; break;
|
case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break;
|
||||||
|
default: mode = spv::ExecutionModeMax; break;
|
||||||
}
|
}
|
||||||
if (mode != spv::ExecutionModeMax)
|
if (mode != spv::ExecutionModeMax)
|
||||||
builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
|
builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
|
||||||
@@ -1621,7 +1691,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
{
|
{
|
||||||
auto& extensions = glslangIntermediate->getRequestedExtensions();
|
auto& extensions = glslangIntermediate->getRequestedExtensions();
|
||||||
if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
|
if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
|
||||||
builder.addCapability(spv::CapabilityRayTracingProvisionalKHR);
|
builder.addCapability(spv::CapabilityRayTracingKHR);
|
||||||
builder.addExtension("SPV_KHR_ray_tracing");
|
builder.addExtension("SPV_KHR_ray_tracing");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1710,6 +1780,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
|
|||||||
if (symbol->getType().getQualifier().isSpecConstant())
|
if (symbol->getType().getQualifier().isSpecConstant())
|
||||||
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
|
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
|
||||||
|
|
||||||
|
#ifdef ENABLE_HLSL
|
||||||
|
// Skip symbol handling if it is string-typed
|
||||||
|
if (symbol->getBasicType() == glslang::EbtString)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
// getSymbolId() will set up all the IO decorations on the first call.
|
// getSymbolId() will set up all the IO decorations on the first call.
|
||||||
// Formal function parameters were mapped during makeFunctions().
|
// Formal function parameters were mapped during makeFunctions().
|
||||||
spv::Id id = getSymbolId(symbol);
|
spv::Id id = getSymbolId(symbol);
|
||||||
@@ -1852,9 +1928,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
|
spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
|
||||||
|
|
||||||
// do the operation
|
// do the operation
|
||||||
|
spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType());
|
||||||
|
coherentFlags |= TranslateCoherent(node->getRight()->getType());
|
||||||
OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
|
OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()),
|
||||||
TranslateNoContractionDecoration(node->getType().getQualifier()),
|
TranslateNoContractionDecoration(node->getType().getQualifier()),
|
||||||
TranslateNonUniformDecoration(node->getType().getQualifier()) };
|
TranslateNonUniformDecoration(coherentFlags) };
|
||||||
rValue = createBinaryOperation(node->getOp(), decorations,
|
rValue = createBinaryOperation(node->getOp(), decorations,
|
||||||
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
|
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
|
||||||
node->getType().getBasicType());
|
node->getType().getBasicType());
|
||||||
@@ -1885,13 +1963,16 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
if (! node->getLeft()->getType().isArray() &&
|
if (! node->getLeft()->getType().isArray() &&
|
||||||
node->getLeft()->getType().isVector() &&
|
node->getLeft()->getType().isVector() &&
|
||||||
node->getOp() == glslang::EOpIndexDirect) {
|
node->getOp() == glslang::EOpIndexDirect) {
|
||||||
|
// Swizzle is uniform so propagate uniform into access chain
|
||||||
|
spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType());
|
||||||
|
coherentFlags.nonUniform = 0;
|
||||||
// This is essentially a hard-coded vector swizzle of size 1,
|
// This is essentially a hard-coded vector swizzle of size 1,
|
||||||
// so short circuit the access-chain stuff with a swizzle.
|
// so short circuit the access-chain stuff with a swizzle.
|
||||||
std::vector<unsigned> swizzle;
|
std::vector<unsigned> swizzle;
|
||||||
swizzle.push_back(glslangIndex);
|
swizzle.push_back(glslangIndex);
|
||||||
int dummySize;
|
int dummySize;
|
||||||
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
|
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
|
||||||
TranslateCoherent(node->getLeft()->getType()),
|
coherentFlags,
|
||||||
glslangIntermediate->getBaseAlignmentScalar(
|
glslangIntermediate->getBaseAlignmentScalar(
|
||||||
node->getLeft()->getType(), dummySize));
|
node->getLeft()->getType(), dummySize));
|
||||||
} else {
|
} else {
|
||||||
@@ -1914,7 +1995,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
{
|
{
|
||||||
// This may be, e.g., an anonymous block-member selection, which generally need
|
// This may be, e.g., an anonymous block-member selection, which generally need
|
||||||
// index remapping due to hidden members in anonymous blocks.
|
// index remapping due to hidden members in anonymous blocks.
|
||||||
int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
|
long long glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
|
||||||
if (memberRemapper.find(glslangId) != memberRemapper.end()) {
|
if (memberRemapper.find(glslangId) != memberRemapper.end()) {
|
||||||
std::vector<int>& remapper = memberRemapper[glslangId];
|
std::vector<int>& remapper = memberRemapper[glslangId];
|
||||||
assert(remapper.size() > 0);
|
assert(remapper.size() > 0);
|
||||||
@@ -1922,9 +2003,14 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct reference propagates uniform lvalue
|
||||||
|
spv::Builder::AccessChain::CoherentFlags coherentFlags =
|
||||||
|
TranslateCoherent(node->getLeft()->getType());
|
||||||
|
coherentFlags.nonUniform = 0;
|
||||||
|
|
||||||
// normal case for indexing array or structure or block
|
// normal case for indexing array or structure or block
|
||||||
builder.accessChainPush(builder.makeIntConstant(spvIndex),
|
builder.accessChainPush(builder.makeIntConstant(spvIndex),
|
||||||
TranslateCoherent(node->getLeft()->getType()),
|
coherentFlags,
|
||||||
node->getLeft()->getType().getBufferReferenceAlignment());
|
node->getLeft()->getType().getBufferReferenceAlignment());
|
||||||
|
|
||||||
// Add capabilities here for accessing PointSize and clip/cull distance.
|
// Add capabilities here for accessing PointSize and clip/cull distance.
|
||||||
@@ -1958,15 +2044,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||||||
// restore the saved access chain
|
// restore the saved access chain
|
||||||
builder.setAccessChain(partial);
|
builder.setAccessChain(partial);
|
||||||
|
|
||||||
|
// Only if index is nonUniform should we propagate nonUniform into access chain
|
||||||
|
spv::Builder::AccessChain::CoherentFlags index_flags = TranslateCoherent(node->getRight()->getType());
|
||||||
|
spv::Builder::AccessChain::CoherentFlags coherent_flags = TranslateCoherent(node->getLeft()->getType());
|
||||||
|
coherent_flags.nonUniform = index_flags.nonUniform;
|
||||||
|
|
||||||
if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) {
|
if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) {
|
||||||
int dummySize;
|
int dummySize;
|
||||||
builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
|
builder.accessChainPushComponent(
|
||||||
TranslateCoherent(node->getLeft()->getType()),
|
index, convertGlslangToSpvType(node->getLeft()->getType()), coherent_flags,
|
||||||
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
|
glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(),
|
||||||
dummySize));
|
dummySize));
|
||||||
} else
|
} else
|
||||||
builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()),
|
builder.accessChainPush(index, coherent_flags,
|
||||||
node->getLeft()->getType().getBufferReferenceAlignment());
|
node->getLeft()->getType().getBufferReferenceAlignment());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case glslang::EOpVectorSwizzle:
|
case glslang::EOpVectorSwizzle:
|
||||||
@@ -2050,8 +2141,9 @@ std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(glslang::TBuil
|
|||||||
// these require changing a 64-bit scaler -> a vector of 32-bit components
|
// these require changing a 64-bit scaler -> a vector of 32-bit components
|
||||||
if (glslangType.isVector())
|
if (glslangType.isVector())
|
||||||
break;
|
break;
|
||||||
std::pair<spv::Id, spv::Id> ret(builder.makeVectorType(builder.makeUintType(32), 4),
|
spv::Id ivec4_type = builder.makeVectorType(builder.makeUintType(32), 4);
|
||||||
builder.makeUintType(64));
|
spv::Id uint64_type = builder.makeUintType(64);
|
||||||
|
std::pair<spv::Id, spv::Id> ret(ivec4_type, uint64_type);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// There are no SPIR-V builtins defined for these and map onto original non-transposed
|
// There are no SPIR-V builtins defined for these and map onto original non-transposed
|
||||||
@@ -2090,7 +2182,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
|
|||||||
// handle 32-bit v.xy* -> 64-bit
|
// handle 32-bit v.xy* -> 64-bit
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
builder.setAccessChainLValue(object);
|
builder.setAccessChainLValue(object);
|
||||||
object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
|
object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
|
||||||
std::vector<spv::Id> components;
|
std::vector<spv::Id> components;
|
||||||
components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0));
|
components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0));
|
||||||
components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1));
|
components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1));
|
||||||
@@ -2106,7 +2198,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
|
|||||||
// and we insert a transpose after loading the original non-transposed builtins
|
// and we insert a transpose after loading the original non-transposed builtins
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
builder.setAccessChainLValue(object);
|
builder.setAccessChainLValue(object);
|
||||||
object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
|
object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
|
||||||
return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object);
|
return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -2292,7 +2384,8 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
|||||||
|
|
||||||
// The result of operation is always stored, but conditionally the
|
// The result of operation is always stored, but conditionally the
|
||||||
// consumed result. The consumed result is always an r-value.
|
// consumed result. The consumed result is always an r-value.
|
||||||
builder.accessChainStore(result);
|
builder.accessChainStore(result,
|
||||||
|
TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags));
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
if (node->getOp() == glslang::EOpPreIncrement ||
|
if (node->getOp() == glslang::EOpPreIncrement ||
|
||||||
node->getOp() == glslang::EOpPreDecrement)
|
node->getOp() == glslang::EOpPreDecrement)
|
||||||
@@ -2421,6 +2514,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
// anything else gets there, so visit out of order, doing them all now.
|
// anything else gets there, so visit out of order, doing them all now.
|
||||||
makeGlobalInitializers(node->getAsAggregate()->getSequence());
|
makeGlobalInitializers(node->getAsAggregate()->getSequence());
|
||||||
|
|
||||||
|
//Pre process linker objects for ray tracing stages
|
||||||
|
if (glslangIntermediate->isRayTracingStage())
|
||||||
|
collectRayTracingLinkerObjects();
|
||||||
|
|
||||||
// Initializers are done, don't want to visit again, but functions and link objects need to be processed,
|
// Initializers are done, don't want to visit again, but functions and link objects need to be processed,
|
||||||
// so do them manually.
|
// so do them manually.
|
||||||
visitFunctions(node->getAsAggregate()->getSequence());
|
visitFunctions(node->getAsAggregate()->getSequence());
|
||||||
@@ -2611,6 +2708,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
else
|
else
|
||||||
constructed = builder.createConstructor(precision, arguments, resultType());
|
constructed = builder.createConstructor(precision, arguments, resultType());
|
||||||
|
|
||||||
|
if (node->getType().getQualifier().isNonUniform()) {
|
||||||
|
builder.addDecoration(constructed, spv::DecorationNonUniformEXT);
|
||||||
|
}
|
||||||
|
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
builder.setAccessChainRValue(constructed);
|
builder.setAccessChainRValue(constructed);
|
||||||
|
|
||||||
@@ -2683,6 +2784,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case glslang::EOpAtomicAdd:
|
case glslang::EOpAtomicAdd:
|
||||||
|
case glslang::EOpAtomicSubtract:
|
||||||
case glslang::EOpAtomicMin:
|
case glslang::EOpAtomicMin:
|
||||||
case glslang::EOpAtomicMax:
|
case glslang::EOpAtomicMax:
|
||||||
case glslang::EOpAtomicAnd:
|
case glslang::EOpAtomicAnd:
|
||||||
@@ -2726,10 +2828,12 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
binOp = node->getOp();
|
binOp = node->getOp();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case glslang::EOpIgnoreIntersection:
|
case glslang::EOpIgnoreIntersectionNV:
|
||||||
case glslang::EOpTerminateRay:
|
case glslang::EOpTerminateRayNV:
|
||||||
case glslang::EOpTrace:
|
case glslang::EOpTraceNV:
|
||||||
case glslang::EOpExecuteCallable:
|
case glslang::EOpTraceKHR:
|
||||||
|
case glslang::EOpExecuteCallableNV:
|
||||||
|
case glslang::EOpExecuteCallableKHR:
|
||||||
case glslang::EOpWritePackedPrimitiveIndices4x8NV:
|
case glslang::EOpWritePackedPrimitiveIndices4x8NV:
|
||||||
noReturnValue = true;
|
noReturnValue = true;
|
||||||
break;
|
break;
|
||||||
@@ -2738,7 +2842,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
case glslang::EOpRayQueryGenerateIntersection:
|
case glslang::EOpRayQueryGenerateIntersection:
|
||||||
case glslang::EOpRayQueryConfirmIntersection:
|
case glslang::EOpRayQueryConfirmIntersection:
|
||||||
builder.addExtension("SPV_KHR_ray_query");
|
builder.addExtension("SPV_KHR_ray_query");
|
||||||
builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
|
builder.addCapability(spv::CapabilityRayQueryKHR);
|
||||||
noReturnValue = true;
|
noReturnValue = true;
|
||||||
break;
|
break;
|
||||||
case glslang::EOpRayQueryProceed:
|
case glslang::EOpRayQueryProceed:
|
||||||
@@ -2761,7 +2865,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
case glslang::EOpRayQueryGetIntersectionObjectToWorld:
|
case glslang::EOpRayQueryGetIntersectionObjectToWorld:
|
||||||
case glslang::EOpRayQueryGetIntersectionWorldToObject:
|
case glslang::EOpRayQueryGetIntersectionWorldToObject:
|
||||||
builder.addExtension("SPV_KHR_ray_query");
|
builder.addExtension("SPV_KHR_ray_query");
|
||||||
builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
|
builder.addCapability(spv::CapabilityRayQueryKHR);
|
||||||
break;
|
break;
|
||||||
case glslang::EOpCooperativeMatrixLoad:
|
case glslang::EOpCooperativeMatrixLoad:
|
||||||
case glslang::EOpCooperativeMatrixStore:
|
case glslang::EOpCooperativeMatrixStore:
|
||||||
@@ -2852,6 +2956,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case glslang::EOpAtomicAdd:
|
case glslang::EOpAtomicAdd:
|
||||||
|
case glslang::EOpAtomicSubtract:
|
||||||
case glslang::EOpAtomicMin:
|
case glslang::EOpAtomicMin:
|
||||||
case glslang::EOpAtomicMax:
|
case glslang::EOpAtomicMax:
|
||||||
case glslang::EOpAtomicAnd:
|
case glslang::EOpAtomicAnd:
|
||||||
@@ -3014,11 +3119,18 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
)) {
|
)) {
|
||||||
bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
|
bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
|
||||||
operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
|
operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
|
||||||
}
|
} else if ((arg == 10 && glslangOp == glslang::EOpTraceKHR) ||
|
||||||
else {
|
(arg == 1 && glslangOp == glslang::EOpExecuteCallableKHR)) {
|
||||||
|
const int opdNum = glslangOp == glslang::EOpTraceKHR ? 10 : 1;
|
||||||
|
const int set = glslangOp == glslang::EOpTraceKHR ? 0 : 1;
|
||||||
|
const int location = glslangOperands[opdNum]->getAsConstantUnion()->getConstArray()[0].getUConst();
|
||||||
|
auto itNode = locationToSymbol[set].find(location);
|
||||||
|
visitSymbol(itNode->second);
|
||||||
|
spv::Id symId = getSymbolId(itNode->second);
|
||||||
|
operands.push_back(symId);
|
||||||
|
} else {
|
||||||
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
|
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3054,7 +3166,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
#endif
|
#endif
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
// Handle all atomics
|
// Handle all atomics
|
||||||
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType(),
|
glslang::TBasicType typeProxy = (node->getOp() == glslang::EOpAtomicStore)
|
||||||
|
? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType();
|
||||||
|
result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy,
|
||||||
lvalueCoherentFlags);
|
lvalueCoherentFlags);
|
||||||
} else if (node->getOp() == glslang::EOpDebugPrintf) {
|
} else if (node->getOp() == glslang::EOpDebugPrintf) {
|
||||||
if (!nonSemanticDebugPrintf) {
|
if (!nonSemanticDebugPrintf) {
|
||||||
@@ -3089,7 +3203,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) {
|
for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) {
|
||||||
builder.setAccessChain(complexLvalues[i]);
|
builder.setAccessChain(complexLvalues[i]);
|
||||||
builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision));
|
builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision),
|
||||||
|
TranslateNonUniformDecoration(complexLvalues[i].coherentFlags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3420,7 +3535,11 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
|
|||||||
|
|
||||||
switch (node->getFlowOp()) {
|
switch (node->getFlowOp()) {
|
||||||
case glslang::EOpKill:
|
case glslang::EOpKill:
|
||||||
builder.makeDiscard();
|
builder.makeStatementTerminator(spv::OpKill, "post-discard");
|
||||||
|
break;
|
||||||
|
case glslang::EOpTerminateInvocation:
|
||||||
|
builder.addExtension(spv::E_SPV_KHR_terminate_invocation);
|
||||||
|
builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation");
|
||||||
break;
|
break;
|
||||||
case glslang::EOpBreak:
|
case glslang::EOpBreak:
|
||||||
if (breakForLoop.top())
|
if (breakForLoop.top())
|
||||||
@@ -3457,6 +3576,12 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
|
|||||||
builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
|
builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation);
|
||||||
builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
|
builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT);
|
||||||
break;
|
break;
|
||||||
|
case glslang::EOpTerminateRayKHR:
|
||||||
|
builder.makeStatementTerminator(spv::OpTerminateRayKHR, "post-terminateRayKHR");
|
||||||
|
break;
|
||||||
|
case glslang::EOpIgnoreIntersectionKHR:
|
||||||
|
builder.makeStatementTerminator(spv::OpIgnoreIntersectionKHR, "post-ignoreIntersectionKHR");
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -3511,6 +3636,11 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
if (storageClass == spv::StorageClassWorkgroup &&
|
||||||
|
node->getType().getBasicType() == glslang::EbtBlock) {
|
||||||
|
builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (node->getType().contains16BitFloat())
|
if (node->getType().contains16BitFloat())
|
||||||
builder.addCapability(spv::CapabilityFloat16);
|
builder.addCapability(spv::CapabilityFloat16);
|
||||||
if (node->getType().contains16BitInt())
|
if (node->getType().contains16BitInt())
|
||||||
@@ -3529,6 +3659,9 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||||||
} else if (storageClass == spv::StorageClassStorageBuffer) {
|
} else if (storageClass == spv::StorageClassStorageBuffer) {
|
||||||
builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
|
builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
|
||||||
builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
|
builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
|
||||||
|
} else if (storageClass == spv::StorageClassWorkgroup &&
|
||||||
|
node->getType().getBasicType() == glslang::EbtBlock) {
|
||||||
|
builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR);
|
||||||
} else {
|
} else {
|
||||||
builder.addCapability(spv::CapabilityInt8);
|
builder.addCapability(spv::CapabilityInt8);
|
||||||
}
|
}
|
||||||
@@ -3540,13 +3673,14 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||||||
|
|
||||||
spv::Id initializer = spv::NoResult;
|
spv::Id initializer = spv::NoResult;
|
||||||
|
|
||||||
if (node->getType().getQualifier().storage == glslang::EvqUniform &&
|
if (node->getType().getQualifier().storage == glslang::EvqUniform && !node->getConstArray().empty()) {
|
||||||
!node->getConstArray().empty()) {
|
int nextConst = 0;
|
||||||
int nextConst = 0;
|
initializer = createSpvConstantFromConstUnionArray(node->getType(),
|
||||||
initializer = createSpvConstantFromConstUnionArray(node->getType(),
|
node->getConstArray(),
|
||||||
node->getConstArray(),
|
nextConst,
|
||||||
nextConst,
|
false /* specConst */);
|
||||||
false /* specConst */);
|
} else if (node->getType().getQualifier().isNullInit()) {
|
||||||
|
initializer = builder.makeNullConstant(spvType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer);
|
return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer);
|
||||||
@@ -3564,6 +3698,12 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
|
|||||||
builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
|
builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch);
|
||||||
builder.addCapability(spv::CapabilityFloat16ImageAMD);
|
builder.addCapability(spv::CapabilityFloat16ImageAMD);
|
||||||
return builder.makeFloatType(16);
|
return builder.makeFloatType(16);
|
||||||
|
case glslang::EbtInt64: return builder.makeIntType(64);
|
||||||
|
builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
|
||||||
|
builder.addCapability(spv::CapabilityFloat16ImageAMD);
|
||||||
|
case glslang::EbtUint64: return builder.makeUintType(64);
|
||||||
|
builder.addExtension(spv::E_SPV_EXT_shader_image_int64);
|
||||||
|
builder.addCapability(spv::CapabilityFloat16ImageAMD);
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -3670,10 +3810,36 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||||||
spvType = builder.makeUintType(32);
|
spvType = builder.makeUintType(32);
|
||||||
break;
|
break;
|
||||||
case glslang::EbtAccStruct:
|
case glslang::EbtAccStruct:
|
||||||
|
switch (glslangIntermediate->getStage()) {
|
||||||
|
case EShLangRayGen:
|
||||||
|
case EShLangIntersect:
|
||||||
|
case EShLangAnyHit:
|
||||||
|
case EShLangClosestHit:
|
||||||
|
case EShLangMiss:
|
||||||
|
case EShLangCallable:
|
||||||
|
// these all should have the RayTracingNV/KHR capability already
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
auto& extensions = glslangIntermediate->getRequestedExtensions();
|
||||||
|
if (extensions.find("GL_EXT_ray_query") != extensions.end()) {
|
||||||
|
builder.addExtension(spv::E_SPV_KHR_ray_query);
|
||||||
|
builder.addCapability(spv::CapabilityRayQueryKHR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
spvType = builder.makeAccelerationStructureType();
|
spvType = builder.makeAccelerationStructureType();
|
||||||
break;
|
break;
|
||||||
case glslang::EbtRayQuery:
|
case glslang::EbtRayQuery:
|
||||||
spvType = builder.makeRayQueryType();
|
{
|
||||||
|
auto& extensions = glslangIntermediate->getRequestedExtensions();
|
||||||
|
if (extensions.find("GL_EXT_ray_query") != extensions.end()) {
|
||||||
|
builder.addExtension(spv::E_SPV_KHR_ray_query);
|
||||||
|
builder.addCapability(spv::CapabilityRayQueryKHR);
|
||||||
|
}
|
||||||
|
spvType = builder.makeRayQueryType();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case glslang::EbtReference:
|
case glslang::EbtReference:
|
||||||
{
|
{
|
||||||
@@ -3929,6 +4095,8 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
|
|||||||
// Name and decorate the non-hidden members
|
// Name and decorate the non-hidden members
|
||||||
int offset = -1;
|
int offset = -1;
|
||||||
int locationOffset = 0; // for use within the members of this struct
|
int locationOffset = 0; // for use within the members of this struct
|
||||||
|
bool memberLocationInvalid = type.isArrayOfArrays() ||
|
||||||
|
(type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false));
|
||||||
for (int i = 0; i < (int)glslangMembers->size(); i++) {
|
for (int i = 0; i < (int)glslangMembers->size(); i++) {
|
||||||
glslang::TType& glslangMember = *(*glslangMembers)[i].type;
|
glslang::TType& glslangMember = *(*glslangMembers)[i].type;
|
||||||
int member = i;
|
int member = i;
|
||||||
@@ -3981,7 +4149,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
|
|||||||
// just track whether a member needs to be decorated.
|
// just track whether a member needs to be decorated.
|
||||||
// Ignore member locations if the container is an array, as that's
|
// Ignore member locations if the container is an array, as that's
|
||||||
// ill-specified and decisions have been made to not allow this.
|
// ill-specified and decisions have been made to not allow this.
|
||||||
if (! type.isArray() && memberQualifier.hasLocation())
|
if (!memberLocationInvalid && memberQualifier.hasLocation())
|
||||||
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
|
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation);
|
||||||
|
|
||||||
if (qualifier.hasLocation()) // track for upcoming inheritance
|
if (qualifier.hasLocation()) // track for upcoming inheritance
|
||||||
@@ -4087,6 +4255,7 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
|
|||||||
alignment |= type.getBufferReferenceAlignment();
|
alignment |= type.getBufferReferenceAlignment();
|
||||||
|
|
||||||
spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
|
spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
|
||||||
|
TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags),
|
||||||
TranslateNonUniformDecoration(type.getQualifier()),
|
TranslateNonUniformDecoration(type.getQualifier()),
|
||||||
nominalTypeId,
|
nominalTypeId,
|
||||||
spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
|
spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
|
||||||
@@ -4154,7 +4323,7 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
|
|||||||
unsigned int alignment = builder.getAccessChain().alignment;
|
unsigned int alignment = builder.getAccessChain().alignment;
|
||||||
alignment |= type.getBufferReferenceAlignment();
|
alignment |= type.getBufferReferenceAlignment();
|
||||||
|
|
||||||
builder.accessChainStore(rvalue,
|
builder.accessChainStore(rvalue, TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags),
|
||||||
spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
|
spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) &
|
||||||
~spv::MemoryAccessMakePointerVisibleKHRMask),
|
~spv::MemoryAccessMakePointerVisibleKHRMask),
|
||||||
TranslateMemoryScope(coherentFlags), alignment);
|
TranslateMemoryScope(coherentFlags), alignment);
|
||||||
@@ -4259,6 +4428,7 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang:
|
|||||||
// has to be a uniform or buffer block or task in/out blocks
|
// has to be a uniform or buffer block or task in/out blocks
|
||||||
if (type.getQualifier().storage != glslang::EvqUniform &&
|
if (type.getQualifier().storage != glslang::EvqUniform &&
|
||||||
type.getQualifier().storage != glslang::EvqBuffer &&
|
type.getQualifier().storage != glslang::EvqBuffer &&
|
||||||
|
type.getQualifier().storage != glslang::EvqShared &&
|
||||||
!type.getQualifier().isTaskMemory())
|
!type.getQualifier().isTaskMemory())
|
||||||
return glslang::ElpNone;
|
return glslang::ElpNone;
|
||||||
|
|
||||||
@@ -4542,7 +4712,39 @@ void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Walk over all linker objects to create a map for payload and callable data linker objects
|
||||||
|
// and their location to be used during codegen for OpTraceKHR and OpExecuteCallableKHR
|
||||||
|
// This is done here since it is possible that these linker objects are not be referenced in the AST
|
||||||
|
void TGlslangToSpvTraverser::collectRayTracingLinkerObjects()
|
||||||
|
{
|
||||||
|
glslang::TIntermAggregate* linkerObjects = glslangIntermediate->findLinkerObjects();
|
||||||
|
for (auto& objSeq : linkerObjects->getSequence()) {
|
||||||
|
auto objNode = objSeq->getAsSymbolNode();
|
||||||
|
if (objNode != nullptr) {
|
||||||
|
if (objNode->getQualifier().hasLocation()) {
|
||||||
|
unsigned int location = objNode->getQualifier().layoutLocation;
|
||||||
|
auto st = objNode->getQualifier().storage;
|
||||||
|
int set;
|
||||||
|
switch (st)
|
||||||
|
{
|
||||||
|
case glslang::EvqPayload:
|
||||||
|
case glslang::EvqPayloadIn:
|
||||||
|
set = 0;
|
||||||
|
break;
|
||||||
|
case glslang::EvqCallableData:
|
||||||
|
case glslang::EvqCallableDataIn:
|
||||||
|
set = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set = -1;
|
||||||
|
}
|
||||||
|
if (set != -1)
|
||||||
|
locationToSymbol[set].insert(std::make_pair(location, objNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Process all the functions, while skipping initializers.
|
// Process all the functions, while skipping initializers.
|
||||||
void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
|
void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
|
||||||
{
|
{
|
||||||
@@ -4686,8 +4888,10 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lvalue) {
|
if (lvalue) {
|
||||||
arguments.push_back(builder.accessChainGetLValue());
|
spv::Id lvalue_id = builder.accessChainGetLValue();
|
||||||
|
arguments.push_back(lvalue_id);
|
||||||
lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
|
lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
|
||||||
|
builder.addDecoration(lvalue_id, TranslateNonUniformDecoration(lvalueCoherentFlags));
|
||||||
lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
|
lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType());
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -4750,12 +4954,15 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
|||||||
|
|
||||||
const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint;
|
const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint;
|
||||||
|
|
||||||
|
if (builder.isSampledImage(params.sampler) &&
|
||||||
|
((cracked.query && node->getOp() != glslang::EOpTextureQueryLod) || cracked.fragMask || cracked.fetch)) {
|
||||||
|
params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
|
||||||
|
if (imageType.getQualifier().isNonUniform()) {
|
||||||
|
builder.addDecoration(params.sampler, spv::DecorationNonUniformEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Check for queries
|
// Check for queries
|
||||||
if (cracked.query) {
|
if (cracked.query) {
|
||||||
// OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first
|
|
||||||
if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler))
|
|
||||||
params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
|
|
||||||
|
|
||||||
switch (node->getOp()) {
|
switch (node->getOp()) {
|
||||||
case glslang::EOpImageQuerySize:
|
case glslang::EOpImageQuerySize:
|
||||||
case glslang::EOpTextureQuerySize:
|
case glslang::EOpTextureQuerySize:
|
||||||
@@ -5009,10 +5216,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
|||||||
auto opIt = arguments.begin();
|
auto opIt = arguments.begin();
|
||||||
std::vector<spv::Id> operands;
|
std::vector<spv::Id> operands;
|
||||||
|
|
||||||
// Extract the image if necessary
|
|
||||||
if (builder.isSampledImage(params.sampler))
|
|
||||||
params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
|
|
||||||
|
|
||||||
operands.push_back(params.sampler);
|
operands.push_back(params.sampler);
|
||||||
++opIt;
|
++opIt;
|
||||||
|
|
||||||
@@ -5073,13 +5276,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
|||||||
bias = true;
|
bias = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if the sampler param should really be just the SPV image part
|
|
||||||
if (cracked.fetch) {
|
|
||||||
// a fetch needs to have the image extracted first
|
|
||||||
if (builder.isSampledImage(params.sampler))
|
|
||||||
params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if (cracked.gather) {
|
if (cracked.gather) {
|
||||||
const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
|
const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
|
||||||
@@ -5239,7 +5435,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
|||||||
|
|
||||||
builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
|
builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
|
||||||
builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
|
builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1),
|
||||||
i+1));
|
i+1), TranslateNonUniformDecoration(imageType.getQualifier()));
|
||||||
}
|
}
|
||||||
return builder.createCompositeExtract(res, resultType(), 0);
|
return builder.createCompositeExtract(res, resultType(), 0);
|
||||||
}
|
}
|
||||||
@@ -5375,6 +5571,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
|||||||
// 3. Make the call.
|
// 3. Make the call.
|
||||||
spv::Id result = builder.createFunctionCall(function, spvArgs);
|
spv::Id result = builder.createFunctionCall(function, spvArgs);
|
||||||
builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
|
builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
|
||||||
|
builder.addDecoration(result, TranslateNonUniformDecoration(node->getType().getQualifier()));
|
||||||
|
|
||||||
// 4. Copy back out an "out" arguments.
|
// 4. Copy back out an "out" arguments.
|
||||||
lValueCount = 0;
|
lValueCount = 0;
|
||||||
@@ -5384,6 +5581,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
|||||||
else if (writableParam(qualifiers[a])) {
|
else if (writableParam(qualifiers[a])) {
|
||||||
if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
|
if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
|
||||||
spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision);
|
spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision);
|
||||||
|
builder.addDecoration(copy, TranslateNonUniformDecoration(argTypes[a]->getQualifier()));
|
||||||
builder.setAccessChain(lValues[lValueCount]);
|
builder.setAccessChain(lValues[lValueCount]);
|
||||||
multiTypeStore(*argTypes[a], copy);
|
multiTypeStore(*argTypes[a], copy);
|
||||||
}
|
}
|
||||||
@@ -6171,6 +6369,11 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe
|
|||||||
case glslang::EOpConstructReference:
|
case glslang::EOpConstructReference:
|
||||||
unaryOp = spv::OpBitcast;
|
unaryOp = spv::OpBitcast;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case glslang::EOpConvUint64ToAccStruct:
|
||||||
|
case glslang::EOpConvUvec2ToAccStruct:
|
||||||
|
unaryOp = spv::OpConvertUToAccelerationStructureKHR;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case glslang::EOpCopyObject:
|
case glslang::EOpCopyObject:
|
||||||
@@ -6633,9 +6836,6 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora
|
|||||||
break;
|
break;
|
||||||
case glslang::EOpConvPtrToUvec2:
|
case glslang::EOpConvPtrToUvec2:
|
||||||
case glslang::EOpConvUvec2ToPtr:
|
case glslang::EOpConvUvec2ToPtr:
|
||||||
if (builder.isVector(operand))
|
|
||||||
builder.promoteIncorporatedExtension(spv::E_SPV_EXT_physical_storage_buffer,
|
|
||||||
spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5);
|
|
||||||
convOp = spv::OpBitcast;
|
convOp = spv::OpBitcast;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -6693,6 +6893,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
|||||||
builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
|
builder.addCapability(spv::CapabilityAtomicFloat64AddEXT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case glslang::EOpAtomicSubtract:
|
||||||
case glslang::EOpAtomicCounterSubtract:
|
case glslang::EOpAtomicCounterSubtract:
|
||||||
opCode = spv::OpAtomicISub;
|
opCode = spv::OpAtomicISub;
|
||||||
break;
|
break;
|
||||||
@@ -6815,6 +7016,10 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
|||||||
builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
|
builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (builder.getConstantScalar(scopeId) == spv::ScopeQueueFamily) {
|
||||||
|
builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
|
||||||
|
}
|
||||||
|
|
||||||
if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) {
|
if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) {
|
||||||
builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
|
builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
|
||||||
}
|
}
|
||||||
@@ -7757,10 +7962,16 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
|||||||
typeId = builder.makeBoolType();
|
typeId = builder.makeBoolType();
|
||||||
opCode = spv::OpReportIntersectionKHR;
|
opCode = spv::OpReportIntersectionKHR;
|
||||||
break;
|
break;
|
||||||
case glslang::EOpTrace:
|
case glslang::EOpTraceNV:
|
||||||
|
builder.createNoResultOp(spv::OpTraceNV, operands);
|
||||||
|
return 0;
|
||||||
|
case glslang::EOpTraceKHR:
|
||||||
builder.createNoResultOp(spv::OpTraceRayKHR, operands);
|
builder.createNoResultOp(spv::OpTraceRayKHR, operands);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpExecuteCallable:
|
case glslang::EOpExecuteCallableNV:
|
||||||
|
builder.createNoResultOp(spv::OpExecuteCallableNV, operands);
|
||||||
|
return 0;
|
||||||
|
case glslang::EOpExecuteCallableKHR:
|
||||||
builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
|
builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -7805,7 +8016,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
|||||||
opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR;
|
opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR;
|
||||||
break;
|
break;
|
||||||
case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
|
case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
|
||||||
typeId = builder.makeIntType(32);
|
typeId = builder.makeUintType(32);
|
||||||
opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
|
opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
|
||||||
break;
|
break;
|
||||||
case glslang::EOpRayQueryGetIntersectionGeometryIndex:
|
case glslang::EOpRayQueryGetIntersectionGeometryIndex:
|
||||||
@@ -8048,11 +8259,11 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv:
|
|||||||
spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
|
spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
|
||||||
return builder.setPrecision(id, precision);
|
return builder.setPrecision(id, precision);
|
||||||
}
|
}
|
||||||
case glslang::EOpIgnoreIntersection:
|
case glslang::EOpIgnoreIntersectionNV:
|
||||||
builder.createNoResultOp(spv::OpIgnoreIntersectionKHR);
|
builder.createNoResultOp(spv::OpIgnoreIntersectionNV);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpTerminateRay:
|
case glslang::EOpTerminateRayNV:
|
||||||
builder.createNoResultOp(spv::OpTerminateRayKHR);
|
builder.createNoResultOp(spv::OpTerminateRayNV);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpRayQueryInitialize:
|
case glslang::EOpRayQueryInitialize:
|
||||||
builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
|
builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
|
||||||
@@ -8180,7 +8391,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if (symbol->getType().isImage()) {
|
// Subgroup builtins which have input storage class are volatile for ray tracing stages.
|
||||||
|
if (symbol->getType().isImage() || symbol->getQualifier().isPipeInput()) {
|
||||||
std::vector<spv::Decoration> memory;
|
std::vector<spv::Decoration> memory;
|
||||||
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
|
TranslateMemoryDecoration(symbol->getType().getQualifier(), memory,
|
||||||
glslangIntermediate->usingVulkanMemoryModel());
|
glslangIntermediate->usingVulkanMemoryModel());
|
||||||
@@ -8188,9 +8400,6 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
|||||||
builder.addDecoration(id, memory[i]);
|
builder.addDecoration(id, memory[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// nonuniform
|
|
||||||
builder.addDecoration(id, TranslateNonUniformDecoration(symbol->getType().getQualifier()));
|
|
||||||
|
|
||||||
if (builtIn == spv::BuiltInSampleMask) {
|
if (builtIn == spv::BuiltInSampleMask) {
|
||||||
spv::Decoration decoration;
|
spv::Decoration decoration;
|
||||||
// GL_NV_sample_mask_override_coverage extension
|
// GL_NV_sample_mask_override_coverage extension
|
||||||
|
|||||||
@@ -621,13 +621,13 @@ Id Builder::makeAccelerationStructureType()
|
|||||||
Id Builder::makeRayQueryType()
|
Id Builder::makeRayQueryType()
|
||||||
{
|
{
|
||||||
Instruction *type;
|
Instruction *type;
|
||||||
if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) {
|
if (groupedTypes[OpTypeRayQueryKHR].size() == 0) {
|
||||||
type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR);
|
type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR);
|
||||||
groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type);
|
groupedTypes[OpTypeRayQueryKHR].push_back(type);
|
||||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||||
module.mapInstruction(type);
|
module.mapInstruction(type);
|
||||||
} else {
|
} else {
|
||||||
type = groupedTypes[OpTypeRayQueryProvisionalKHR].back();
|
type = groupedTypes[OpTypeRayQueryKHR].back();
|
||||||
}
|
}
|
||||||
|
|
||||||
return type->getResultId();
|
return type->getResultId();
|
||||||
@@ -869,6 +869,30 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id Builder::makeNullConstant(Id typeId)
|
||||||
|
{
|
||||||
|
Instruction* constant;
|
||||||
|
|
||||||
|
// See if we already made it.
|
||||||
|
Id existing = NoResult;
|
||||||
|
for (int i = 0; i < (int)nullConstants.size(); ++i) {
|
||||||
|
constant = nullConstants[i];
|
||||||
|
if (constant->getTypeId() == typeId)
|
||||||
|
existing = constant->getResultId();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing != NoResult)
|
||||||
|
return existing;
|
||||||
|
|
||||||
|
// Make it
|
||||||
|
Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull);
|
||||||
|
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
|
||||||
|
nullConstants.push_back(c);
|
||||||
|
module.mapInstruction(c);
|
||||||
|
|
||||||
|
return c->getResultId();
|
||||||
|
}
|
||||||
|
|
||||||
Id Builder::makeBoolConstant(bool b, bool specConstant)
|
Id Builder::makeBoolConstant(bool b, bool specConstant)
|
||||||
{
|
{
|
||||||
Id typeId = makeBoolType();
|
Id typeId = makeBoolType();
|
||||||
@@ -1447,10 +1471,10 @@ void Builder::leaveFunction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comments in header
|
// Comments in header
|
||||||
void Builder::makeDiscard()
|
void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
|
||||||
{
|
{
|
||||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
|
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
|
||||||
createAndSetNoPredecessorBlock("post-discard");
|
createAndSetNoPredecessorBlock(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comments in header
|
// Comments in header
|
||||||
@@ -2761,12 +2785,14 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comments in header
|
// Comments in header
|
||||||
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
||||||
{
|
{
|
||||||
assert(accessChain.isRValue == false);
|
assert(accessChain.isRValue == false);
|
||||||
|
|
||||||
transferAccessChainSwizzle(true);
|
transferAccessChainSwizzle(true);
|
||||||
Id base = collapseAccessChain();
|
Id base = collapseAccessChain();
|
||||||
|
addDecoration(base, nonUniform);
|
||||||
|
|
||||||
Id source = rvalue;
|
Id source = rvalue;
|
||||||
|
|
||||||
// dynamic component should be gone
|
// dynamic component should be gone
|
||||||
@@ -2789,8 +2815,9 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comments in header
|
// Comments in header
|
||||||
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType,
|
Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform,
|
||||||
spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess,
|
||||||
|
spv::Scope scope, unsigned int alignment)
|
||||||
{
|
{
|
||||||
Id id;
|
Id id;
|
||||||
|
|
||||||
@@ -2854,9 +2881,9 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
|
|||||||
// Buffer accesses need the access chain decorated, and this is where
|
// Buffer accesses need the access chain decorated, and this is where
|
||||||
// loaded image types get decorated. TODO: This should maybe move to
|
// loaded image types get decorated. TODO: This should maybe move to
|
||||||
// createImageTextureFunctionCall.
|
// createImageTextureFunctionCall.
|
||||||
addDecoration(id, nonUniform);
|
addDecoration(id, l_nonUniform);
|
||||||
id = createLoad(id, precision, memoryAccess, scope, alignment);
|
id = createLoad(id, precision, memoryAccess, scope, alignment);
|
||||||
addDecoration(id, nonUniform);
|
addDecoration(id, r_nonUniform);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done, unless there are swizzles to do
|
// Done, unless there are swizzles to do
|
||||||
@@ -2877,7 +2904,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
|
|||||||
if (accessChain.component != NoResult)
|
if (accessChain.component != NoResult)
|
||||||
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
|
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
|
||||||
|
|
||||||
addDecoration(id, nonUniform);
|
addDecoration(id, r_nonUniform);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For making new constants (will return old constant if the requested one was already made).
|
// For making new constants (will return old constant if the requested one was already made).
|
||||||
|
Id makeNullConstant(Id typeId);
|
||||||
Id makeBoolConstant(bool b, bool specConstant = false);
|
Id makeBoolConstant(bool b, bool specConstant = false);
|
||||||
Id makeInt8Constant(int i, bool specConstant = false)
|
Id makeInt8Constant(int i, bool specConstant = false)
|
||||||
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
|
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
|
||||||
@@ -357,8 +358,9 @@ public:
|
|||||||
// Generate all the code needed to finish up a function.
|
// Generate all the code needed to finish up a function.
|
||||||
void leaveFunction();
|
void leaveFunction();
|
||||||
|
|
||||||
// Create a discard.
|
// Create block terminator instruction for certain statements like
|
||||||
void makeDiscard();
|
// discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT
|
||||||
|
void makeStatementTerminator(spv::Op opcode, const char *name);
|
||||||
|
|
||||||
// Create a global or function local or IO variable.
|
// Create a global or function local or IO variable.
|
||||||
Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
|
Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
|
||||||
@@ -624,6 +626,7 @@ public:
|
|||||||
CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
|
CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
|
||||||
#else
|
#else
|
||||||
bool isVolatile() const { return volatil; }
|
bool isVolatile() const { return volatil; }
|
||||||
|
bool isNonUniform() const { return nonUniform; }
|
||||||
bool anyCoherent() const {
|
bool anyCoherent() const {
|
||||||
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
|
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
|
||||||
subgroupcoherent || shadercallcoherent;
|
subgroupcoherent || shadercallcoherent;
|
||||||
@@ -638,6 +641,7 @@ public:
|
|||||||
unsigned nonprivate : 1;
|
unsigned nonprivate : 1;
|
||||||
unsigned volatil : 1;
|
unsigned volatil : 1;
|
||||||
unsigned isImage : 1;
|
unsigned isImage : 1;
|
||||||
|
unsigned nonUniform : 1;
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
coherent = 0;
|
coherent = 0;
|
||||||
@@ -649,6 +653,7 @@ public:
|
|||||||
nonprivate = 0;
|
nonprivate = 0;
|
||||||
volatil = 0;
|
volatil = 0;
|
||||||
isImage = 0;
|
isImage = 0;
|
||||||
|
nonUniform = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoherentFlags operator |=(const CoherentFlags &other) {
|
CoherentFlags operator |=(const CoherentFlags &other) {
|
||||||
@@ -661,6 +666,7 @@ public:
|
|||||||
nonprivate |= other.nonprivate;
|
nonprivate |= other.nonprivate;
|
||||||
volatil |= other.volatil;
|
volatil |= other.volatil;
|
||||||
isImage |= other.isImage;
|
isImage |= other.isImage;
|
||||||
|
nonUniform |= other.nonUniform;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -721,11 +727,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use accessChain and swizzle to store value
|
// use accessChain and swizzle to store value
|
||||||
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
void accessChainStore(Id rvalue, Decoration nonUniform,
|
||||||
|
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
||||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
||||||
|
|
||||||
// use accessChain and swizzle to load an r-value
|
// use accessChain and swizzle to load an r-value
|
||||||
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
|
Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType,
|
||||||
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
|
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
|
||||||
unsigned int alignment = 0);
|
unsigned int alignment = 0);
|
||||||
|
|
||||||
@@ -832,6 +839,8 @@ public:
|
|||||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
|
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
|
||||||
// map type opcodes to type instructions
|
// map type opcodes to type instructions
|
||||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
|
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
|
||||||
|
// list of OpConstantNull instructions
|
||||||
|
std::vector<Instruction*> nullConstants;
|
||||||
|
|
||||||
// stack of switches
|
// stack of switches
|
||||||
std::stack<Block*> switchMerges;
|
std::stack<Block*> switchMerges;
|
||||||
|
|||||||
@@ -436,6 +436,38 @@ void Builder::postProcessFeatures() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If any Vulkan memory model-specific functionality is used, update the
|
||||||
|
// OpMemoryModel to match.
|
||||||
|
if (capabilities.find(spv::CapabilityVulkanMemoryModelKHR) != capabilities.end()) {
|
||||||
|
memoryModel = spv::MemoryModelVulkanKHR;
|
||||||
|
addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Aliased decoration if there's more than one Workgroup Block variable.
|
||||||
|
if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) {
|
||||||
|
assert(entryPoints.size() == 1);
|
||||||
|
auto &ep = entryPoints[0];
|
||||||
|
|
||||||
|
std::vector<Id> workgroup_variables;
|
||||||
|
for (int i = 0; i < (int)ep->getNumOperands(); i++) {
|
||||||
|
if (!ep->isIdOperand(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Id id = ep->getIdOperand(i);
|
||||||
|
const Instruction *instr = module.getInstruction(id);
|
||||||
|
if (instr->getOpCode() != spv::OpVariable)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup)
|
||||||
|
workgroup_variables.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workgroup_variables.size() > 1) {
|
||||||
|
for (size_t i = 0; i < workgroup_variables.size(); i++)
|
||||||
|
addDecoration(workgroup_variables[i], spv::DecorationAliased);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
|
|
||||||
#include "SpvTools.h"
|
#include "SpvTools.h"
|
||||||
#include "spirv-tools/optimizer.hpp"
|
#include "spirv-tools/optimizer.hpp"
|
||||||
#include "spirv-tools/libspirv.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
@@ -114,11 +113,18 @@ void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
|
|||||||
out << std::endl;
|
out << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the SPIRV-Tools disassembler to print SPIR-V.
|
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
|
||||||
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
|
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
|
||||||
|
{
|
||||||
|
SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
|
||||||
|
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
|
||||||
|
spv_target_env requested_context)
|
||||||
{
|
{
|
||||||
// disassemble
|
// disassemble
|
||||||
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
|
spv_context context = spvContextCreate(requested_context);
|
||||||
spv_text text;
|
spv_text text;
|
||||||
spv_diagnostic diagnostic = nullptr;
|
spv_diagnostic diagnostic = nullptr;
|
||||||
spvBinaryToText(context, spirv.data(), spirv.size(),
|
spvBinaryToText(context, spirv.data(), spirv.size(),
|
||||||
@@ -147,6 +153,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
|
|||||||
spv_validator_options options = spvValidatorOptionsCreate();
|
spv_validator_options options = spvValidatorOptionsCreate();
|
||||||
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
|
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
|
||||||
spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
|
spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
|
||||||
|
spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
|
||||||
|
spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
|
||||||
spvValidateWithOptions(context, options, &binary, &diagnostic);
|
spvValidateWithOptions(context, options, &binary, &diagnostic);
|
||||||
|
|
||||||
// report
|
// report
|
||||||
@@ -174,10 +182,7 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
|
|||||||
// line information into all SPIR-V instructions. This avoids loss of
|
// line information into all SPIR-V instructions. This avoids loss of
|
||||||
// information when instructions are deleted or moved. Later, remove
|
// information when instructions are deleted or moved. Later, remove
|
||||||
// redundant information to minimize final SPRIR-V size.
|
// redundant information to minimize final SPRIR-V size.
|
||||||
if (options->generateDebugInfo) {
|
if (options->stripDebugInfo) {
|
||||||
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
|
|
||||||
}
|
|
||||||
else if (options->stripDebugInfo) {
|
|
||||||
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
|
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
|
||||||
}
|
}
|
||||||
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
|
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
|
||||||
@@ -207,9 +212,6 @@ void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector
|
|||||||
}
|
}
|
||||||
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
|
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
|
||||||
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
|
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
|
||||||
if (options->generateDebugInfo) {
|
|
||||||
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
|
|
||||||
}
|
|
||||||
|
|
||||||
spvtools::OptimizerOptions spvOptOptions;
|
spvtools::OptimizerOptions spvOptOptions;
|
||||||
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
|
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
|
||||||
|
|||||||
@@ -41,9 +41,10 @@
|
|||||||
#ifndef GLSLANG_SPV_TOOLS_H
|
#ifndef GLSLANG_SPV_TOOLS_H
|
||||||
#define GLSLANG_SPV_TOOLS_H
|
#define GLSLANG_SPV_TOOLS_H
|
||||||
|
|
||||||
#ifdef ENABLE_OPT
|
#if ENABLE_OPT
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include "spirv-tools/libspirv.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../glslang/MachineIndependent/localintermediate.h"
|
#include "../glslang/MachineIndependent/localintermediate.h"
|
||||||
@@ -62,11 +63,15 @@ struct SpvOptions {
|
|||||||
bool validate;
|
bool validate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ENABLE_OPT
|
#if ENABLE_OPT
|
||||||
|
|
||||||
// Use the SPIRV-Tools disassembler to print SPIR-V.
|
// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment.
|
||||||
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
|
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
|
||||||
|
|
||||||
|
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
|
||||||
|
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
|
||||||
|
spv_target_env requested_context);
|
||||||
|
|
||||||
// Apply the SPIRV-Tools validator to generated SPIR-V.
|
// Apply the SPIRV-Tools validator to generated SPIR-V.
|
||||||
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||||
spv::SpvBuildLogger*, bool prelegalization);
|
spv::SpvBuildLogger*, bool prelegalization);
|
||||||
|
|||||||
@@ -372,6 +372,8 @@ const char* BuiltInString(int builtIn)
|
|||||||
case 4424: return "BaseVertex";
|
case 4424: return "BaseVertex";
|
||||||
case 4425: return "BaseInstance";
|
case 4425: return "BaseInstance";
|
||||||
case 4426: return "DrawIndex";
|
case 4426: return "DrawIndex";
|
||||||
|
case 4432: return "PrimitiveShadingRateKHR";
|
||||||
|
case 4444: return "ShadingRateKHR";
|
||||||
case 5014: return "FragStencilRefEXT";
|
case 5014: return "FragStencilRefEXT";
|
||||||
|
|
||||||
case 4992: return "BaryCoordNoPerspAMD";
|
case 4992: return "BaryCoordNoPerspAMD";
|
||||||
@@ -393,7 +395,7 @@ const char* BuiltInString(int builtIn)
|
|||||||
case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
|
case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
|
||||||
case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
|
case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
|
||||||
case BuiltInWorldToObjectKHR: return "WorldToObjectKHR";
|
case BuiltInWorldToObjectKHR: return "WorldToObjectKHR";
|
||||||
case BuiltInHitTKHR: return "HitTKHR";
|
case BuiltInHitTNV: return "HitTNV";
|
||||||
case BuiltInHitKindKHR: return "HitKindKHR";
|
case BuiltInHitKindKHR: return "HitKindKHR";
|
||||||
case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR";
|
case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR";
|
||||||
case BuiltInViewportMaskNV: return "ViewportMaskNV";
|
case BuiltInViewportMaskNV: return "ViewportMaskNV";
|
||||||
@@ -521,6 +523,8 @@ const char* ImageFormatString(int format)
|
|||||||
case 37: return "Rg8ui";
|
case 37: return "Rg8ui";
|
||||||
case 38: return "R16ui";
|
case 38: return "R16ui";
|
||||||
case 39: return "R8ui";
|
case 39: return "R8ui";
|
||||||
|
case 40: return "R64ui";
|
||||||
|
case 41: return "R64i";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Bad";
|
return "Bad";
|
||||||
@@ -911,9 +915,10 @@ const char* CapabilityString(int info)
|
|||||||
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
|
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
|
||||||
case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
|
case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
|
||||||
case CapabilityRayTracingNV: return "RayTracingNV";
|
case CapabilityRayTracingNV: return "RayTracingNV";
|
||||||
|
case CapabilityRayTracingKHR: return "RayTracingKHR";
|
||||||
|
case CapabilityRayQueryKHR: return "RayQueryKHR";
|
||||||
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
|
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
|
||||||
case CapabilityRayQueryProvisionalKHR: return "RayQueryProvisionalKHR";
|
case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR";
|
||||||
case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR";
|
|
||||||
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
|
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
|
||||||
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
|
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
|
||||||
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
|
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
|
||||||
@@ -952,14 +957,21 @@ const char* CapabilityString(int info)
|
|||||||
case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
|
case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
|
||||||
case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
|
case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
|
||||||
|
|
||||||
|
case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR";
|
||||||
|
|
||||||
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
|
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
|
||||||
case CapabilityShaderClockKHR: return "ShaderClockKHR";
|
case CapabilityShaderClockKHR: return "ShaderClockKHR";
|
||||||
|
case CapabilityInt64ImageEXT: return "Int64ImageEXT";
|
||||||
|
|
||||||
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";
|
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";
|
||||||
|
|
||||||
case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT";
|
case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT";
|
||||||
case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT";
|
case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT";
|
||||||
|
|
||||||
|
case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR";
|
||||||
|
case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR";
|
||||||
|
case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR";
|
||||||
|
|
||||||
default: return "Bad";
|
default: return "Bad";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1329,6 +1341,8 @@ const char* OpcodeString(int op)
|
|||||||
case 365: return "OpGroupNonUniformQuadBroadcast";
|
case 365: return "OpGroupNonUniformQuadBroadcast";
|
||||||
case 366: return "OpGroupNonUniformQuadSwap";
|
case 366: return "OpGroupNonUniformQuadSwap";
|
||||||
|
|
||||||
|
case OpTerminateInvocation: return "OpTerminateInvocation";
|
||||||
|
|
||||||
case 4421: return "OpSubgroupBallotKHR";
|
case 4421: return "OpSubgroupBallotKHR";
|
||||||
case 4422: return "OpSubgroupFirstInvocationKHR";
|
case 4422: return "OpSubgroupFirstInvocationKHR";
|
||||||
case 4428: return "OpSubgroupAllKHR";
|
case 4428: return "OpSubgroupAllKHR";
|
||||||
@@ -1355,17 +1369,23 @@ const char* OpcodeString(int op)
|
|||||||
case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
|
case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
|
||||||
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
|
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
|
||||||
|
|
||||||
|
case OpReportIntersectionKHR: return "OpReportIntersectionKHR";
|
||||||
|
case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV";
|
||||||
|
case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR";
|
||||||
|
case OpTerminateRayNV: return "OpTerminateRayNV";
|
||||||
|
case OpTerminateRayKHR: return "OpTerminateRayKHR";
|
||||||
|
case OpTraceNV: return "OpTraceNV";
|
||||||
|
case OpTraceRayKHR: return "OpTraceRayKHR";
|
||||||
|
case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR";
|
||||||
|
case OpExecuteCallableNV: return "OpExecuteCallableNV";
|
||||||
|
case OpExecuteCallableKHR: return "OpExecuteCallableKHR";
|
||||||
|
case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR";
|
||||||
|
|
||||||
case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
|
case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
|
||||||
case OpReportIntersectionKHR: return "OpReportIntersectionKHR";
|
|
||||||
case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR";
|
|
||||||
case OpTerminateRayKHR: return "OpTerminateRayKHR";
|
|
||||||
case OpTraceRayKHR: return "OpTraceRayKHR";
|
|
||||||
case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR";
|
|
||||||
case OpExecuteCallableKHR: return "OpExecuteCallableKHR";
|
|
||||||
case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
|
case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
|
||||||
case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
|
case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
|
||||||
|
|
||||||
case OpTypeRayQueryProvisionalKHR: return "OpTypeRayQueryProvisionalKHR";
|
case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR";
|
||||||
case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR";
|
case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR";
|
||||||
case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR";
|
case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR";
|
||||||
case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR";
|
case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR";
|
||||||
@@ -1497,6 +1517,7 @@ void Parameterize()
|
|||||||
InstructionDesc[OpBranchConditional].setResultAndType(false, false);
|
InstructionDesc[OpBranchConditional].setResultAndType(false, false);
|
||||||
InstructionDesc[OpSwitch].setResultAndType(false, false);
|
InstructionDesc[OpSwitch].setResultAndType(false, false);
|
||||||
InstructionDesc[OpKill].setResultAndType(false, false);
|
InstructionDesc[OpKill].setResultAndType(false, false);
|
||||||
|
InstructionDesc[OpTerminateInvocation].setResultAndType(false, false);
|
||||||
InstructionDesc[OpReturn].setResultAndType(false, false);
|
InstructionDesc[OpReturn].setResultAndType(false, false);
|
||||||
InstructionDesc[OpReturnValue].setResultAndType(false, false);
|
InstructionDesc[OpReturnValue].setResultAndType(false, false);
|
||||||
InstructionDesc[OpUnreachable].setResultAndType(false, false);
|
InstructionDesc[OpUnreachable].setResultAndType(false, false);
|
||||||
@@ -2698,7 +2719,7 @@ void Parameterize()
|
|||||||
|
|
||||||
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
|
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
|
||||||
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
|
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
|
||||||
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'");
|
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'");
|
||||||
|
|
||||||
InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
|
InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
|
||||||
|
|
||||||
@@ -2761,7 +2782,20 @@ void Parameterize()
|
|||||||
|
|
||||||
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
|
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
|
||||||
|
|
||||||
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'NV Acceleration Structure'");
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
|
||||||
|
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
|
||||||
|
InstructionDesc[OpTraceNV].setResultAndType(false, false);
|
||||||
|
|
||||||
|
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Acceleration Structure'");
|
||||||
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
|
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
|
||||||
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
|
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
|
||||||
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
|
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
|
||||||
@@ -2777,17 +2811,28 @@ void Parameterize()
|
|||||||
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
|
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
|
||||||
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
|
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
|
||||||
|
|
||||||
|
InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
|
||||||
|
|
||||||
InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
|
InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
|
||||||
|
|
||||||
|
InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
|
||||||
|
|
||||||
InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
|
InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
|
||||||
|
|
||||||
|
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
|
||||||
|
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
|
||||||
|
InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
|
||||||
|
|
||||||
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
|
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
|
||||||
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData ID");
|
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData");
|
||||||
InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
|
InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
|
||||||
|
|
||||||
|
InstructionDesc[OpConvertUToAccelerationStructureKHR].operands.push(OperandId, "Value");
|
||||||
|
InstructionDesc[OpConvertUToAccelerationStructureKHR].setResultAndType(true, true);
|
||||||
|
|
||||||
// Ray Query
|
// Ray Query
|
||||||
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
|
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
|
||||||
InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false);
|
InstructionDesc[OpTypeRayQueryKHR].setResultAndType(true, false);
|
||||||
|
|
||||||
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
|
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
|
||||||
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
|
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ namespace spv {
|
|||||||
typedef unsigned int Id;
|
typedef unsigned int Id;
|
||||||
|
|
||||||
#define SPV_VERSION 0x10500
|
#define SPV_VERSION 0x10500
|
||||||
#define SPV_REVISION 3
|
#define SPV_REVISION 4
|
||||||
|
|
||||||
static const unsigned int MagicNumber = 0x07230203;
|
static const unsigned int MagicNumber = 0x07230203;
|
||||||
static const unsigned int Version = 0x00010500;
|
static const unsigned int Version = 0x00010500;
|
||||||
static const unsigned int Revision = 3;
|
static const unsigned int Revision = 4;
|
||||||
static const unsigned int OpCodeMask = 0xffff;
|
static const unsigned int OpCodeMask = 0xffff;
|
||||||
static const unsigned int WordCountShift = 16;
|
static const unsigned int WordCountShift = 16;
|
||||||
|
|
||||||
@@ -168,10 +168,16 @@ enum ExecutionMode {
|
|||||||
ExecutionModeSampleInterlockUnorderedEXT = 5369,
|
ExecutionModeSampleInterlockUnorderedEXT = 5369,
|
||||||
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
|
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
|
||||||
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
|
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
|
||||||
|
ExecutionModeSharedLocalMemorySizeINTEL = 5618,
|
||||||
|
ExecutionModeRoundingModeRTPINTEL = 5620,
|
||||||
|
ExecutionModeRoundingModeRTNINTEL = 5621,
|
||||||
|
ExecutionModeFloatingPointModeALTINTEL = 5622,
|
||||||
|
ExecutionModeFloatingPointModeIEEEINTEL = 5623,
|
||||||
ExecutionModeMaxWorkgroupSizeINTEL = 5893,
|
ExecutionModeMaxWorkgroupSizeINTEL = 5893,
|
||||||
ExecutionModeMaxWorkDimINTEL = 5894,
|
ExecutionModeMaxWorkDimINTEL = 5894,
|
||||||
ExecutionModeNoGlobalOffsetINTEL = 5895,
|
ExecutionModeNoGlobalOffsetINTEL = 5895,
|
||||||
ExecutionModeNumSIMDWorkitemsINTEL = 5896,
|
ExecutionModeNumSIMDWorkitemsINTEL = 5896,
|
||||||
|
ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
|
||||||
ExecutionModeMax = 0x7fffffff,
|
ExecutionModeMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -204,6 +210,8 @@ enum StorageClass {
|
|||||||
StorageClassPhysicalStorageBuffer = 5349,
|
StorageClassPhysicalStorageBuffer = 5349,
|
||||||
StorageClassPhysicalStorageBufferEXT = 5349,
|
StorageClassPhysicalStorageBufferEXT = 5349,
|
||||||
StorageClassCodeSectionINTEL = 5605,
|
StorageClassCodeSectionINTEL = 5605,
|
||||||
|
StorageClassDeviceOnlyINTEL = 5936,
|
||||||
|
StorageClassHostOnlyINTEL = 5937,
|
||||||
StorageClassMax = 0x7fffffff,
|
StorageClassMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -274,6 +282,8 @@ enum ImageFormat {
|
|||||||
ImageFormatRg8ui = 37,
|
ImageFormatRg8ui = 37,
|
||||||
ImageFormatR16ui = 38,
|
ImageFormatR16ui = 38,
|
||||||
ImageFormatR8ui = 39,
|
ImageFormatR8ui = 39,
|
||||||
|
ImageFormatR64ui = 40,
|
||||||
|
ImageFormatR64i = 41,
|
||||||
ImageFormatMax = 0x7fffffff,
|
ImageFormatMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -372,6 +382,8 @@ enum FPFastMathModeShift {
|
|||||||
FPFastMathModeNSZShift = 2,
|
FPFastMathModeNSZShift = 2,
|
||||||
FPFastMathModeAllowRecipShift = 3,
|
FPFastMathModeAllowRecipShift = 3,
|
||||||
FPFastMathModeFastShift = 4,
|
FPFastMathModeFastShift = 4,
|
||||||
|
FPFastMathModeAllowContractFastINTELShift = 16,
|
||||||
|
FPFastMathModeAllowReassocINTELShift = 17,
|
||||||
FPFastMathModeMax = 0x7fffffff,
|
FPFastMathModeMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -382,6 +394,8 @@ enum FPFastMathModeMask {
|
|||||||
FPFastMathModeNSZMask = 0x00000004,
|
FPFastMathModeNSZMask = 0x00000004,
|
||||||
FPFastMathModeAllowRecipMask = 0x00000008,
|
FPFastMathModeAllowRecipMask = 0x00000008,
|
||||||
FPFastMathModeFastMask = 0x00000010,
|
FPFastMathModeFastMask = 0x00000010,
|
||||||
|
FPFastMathModeAllowContractFastINTELMask = 0x00010000,
|
||||||
|
FPFastMathModeAllowReassocINTELMask = 0x00020000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FPRoundingMode {
|
enum FPRoundingMode {
|
||||||
@@ -482,12 +496,22 @@ enum Decoration {
|
|||||||
DecorationRestrictPointerEXT = 5355,
|
DecorationRestrictPointerEXT = 5355,
|
||||||
DecorationAliasedPointer = 5356,
|
DecorationAliasedPointer = 5356,
|
||||||
DecorationAliasedPointerEXT = 5356,
|
DecorationAliasedPointerEXT = 5356,
|
||||||
|
DecorationSIMTCallINTEL = 5599,
|
||||||
DecorationReferencedIndirectlyINTEL = 5602,
|
DecorationReferencedIndirectlyINTEL = 5602,
|
||||||
|
DecorationClobberINTEL = 5607,
|
||||||
|
DecorationSideEffectsINTEL = 5608,
|
||||||
|
DecorationVectorComputeVariableINTEL = 5624,
|
||||||
|
DecorationFuncParamIOKindINTEL = 5625,
|
||||||
|
DecorationVectorComputeFunctionINTEL = 5626,
|
||||||
|
DecorationStackCallINTEL = 5627,
|
||||||
|
DecorationGlobalVariableOffsetINTEL = 5628,
|
||||||
DecorationCounterBuffer = 5634,
|
DecorationCounterBuffer = 5634,
|
||||||
DecorationHlslCounterBufferGOOGLE = 5634,
|
DecorationHlslCounterBufferGOOGLE = 5634,
|
||||||
DecorationHlslSemanticGOOGLE = 5635,
|
DecorationHlslSemanticGOOGLE = 5635,
|
||||||
DecorationUserSemantic = 5635,
|
DecorationUserSemantic = 5635,
|
||||||
DecorationUserTypeGOOGLE = 5636,
|
DecorationUserTypeGOOGLE = 5636,
|
||||||
|
DecorationFunctionRoundingModeINTEL = 5822,
|
||||||
|
DecorationFunctionDenormModeINTEL = 5823,
|
||||||
DecorationRegisterINTEL = 5825,
|
DecorationRegisterINTEL = 5825,
|
||||||
DecorationMemoryINTEL = 5826,
|
DecorationMemoryINTEL = 5826,
|
||||||
DecorationNumbanksINTEL = 5827,
|
DecorationNumbanksINTEL = 5827,
|
||||||
@@ -500,6 +524,17 @@ enum Decoration {
|
|||||||
DecorationMergeINTEL = 5834,
|
DecorationMergeINTEL = 5834,
|
||||||
DecorationBankBitsINTEL = 5835,
|
DecorationBankBitsINTEL = 5835,
|
||||||
DecorationForcePow2DepthINTEL = 5836,
|
DecorationForcePow2DepthINTEL = 5836,
|
||||||
|
DecorationBurstCoalesceINTEL = 5899,
|
||||||
|
DecorationCacheSizeINTEL = 5900,
|
||||||
|
DecorationDontStaticallyCoalesceINTEL = 5901,
|
||||||
|
DecorationPrefetchINTEL = 5902,
|
||||||
|
DecorationStallEnableINTEL = 5905,
|
||||||
|
DecorationFuseLoopsInFunctionINTEL = 5907,
|
||||||
|
DecorationBufferLocationINTEL = 5921,
|
||||||
|
DecorationIOPipeStorageINTEL = 5944,
|
||||||
|
DecorationFunctionFloatingPointModeINTEL = 6080,
|
||||||
|
DecorationSingleElementVectorINTEL = 6085,
|
||||||
|
DecorationVectorComputeCallableFunctionINTEL = 6087,
|
||||||
DecorationMax = 0x7fffffff,
|
DecorationMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -558,8 +593,10 @@ enum BuiltIn {
|
|||||||
BuiltInBaseVertex = 4424,
|
BuiltInBaseVertex = 4424,
|
||||||
BuiltInBaseInstance = 4425,
|
BuiltInBaseInstance = 4425,
|
||||||
BuiltInDrawIndex = 4426,
|
BuiltInDrawIndex = 4426,
|
||||||
|
BuiltInPrimitiveShadingRateKHR = 4432,
|
||||||
BuiltInDeviceIndex = 4438,
|
BuiltInDeviceIndex = 4438,
|
||||||
BuiltInViewIndex = 4440,
|
BuiltInViewIndex = 4440,
|
||||||
|
BuiltInShadingRateKHR = 4444,
|
||||||
BuiltInBaryCoordNoPerspAMD = 4992,
|
BuiltInBaryCoordNoPerspAMD = 4992,
|
||||||
BuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
BuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
||||||
BuiltInBaryCoordNoPerspSampleAMD = 4994,
|
BuiltInBaryCoordNoPerspSampleAMD = 4994,
|
||||||
@@ -610,7 +647,6 @@ enum BuiltIn {
|
|||||||
BuiltInObjectToWorldNV = 5330,
|
BuiltInObjectToWorldNV = 5330,
|
||||||
BuiltInWorldToObjectKHR = 5331,
|
BuiltInWorldToObjectKHR = 5331,
|
||||||
BuiltInWorldToObjectNV = 5331,
|
BuiltInWorldToObjectNV = 5331,
|
||||||
BuiltInHitTKHR = 5332,
|
|
||||||
BuiltInHitTNV = 5332,
|
BuiltInHitTNV = 5332,
|
||||||
BuiltInHitKindKHR = 5333,
|
BuiltInHitKindKHR = 5333,
|
||||||
BuiltInHitKindNV = 5333,
|
BuiltInHitKindNV = 5333,
|
||||||
@@ -653,6 +689,7 @@ enum LoopControlShift {
|
|||||||
LoopControlLoopCoalesceINTELShift = 20,
|
LoopControlLoopCoalesceINTELShift = 20,
|
||||||
LoopControlMaxInterleavingINTELShift = 21,
|
LoopControlMaxInterleavingINTELShift = 21,
|
||||||
LoopControlSpeculatedIterationsINTELShift = 22,
|
LoopControlSpeculatedIterationsINTELShift = 22,
|
||||||
|
LoopControlNoFusionINTELShift = 23,
|
||||||
LoopControlMax = 0x7fffffff,
|
LoopControlMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -674,6 +711,7 @@ enum LoopControlMask {
|
|||||||
LoopControlLoopCoalesceINTELMask = 0x00100000,
|
LoopControlLoopCoalesceINTELMask = 0x00100000,
|
||||||
LoopControlMaxInterleavingINTELMask = 0x00200000,
|
LoopControlMaxInterleavingINTELMask = 0x00200000,
|
||||||
LoopControlSpeculatedIterationsINTELMask = 0x00400000,
|
LoopControlSpeculatedIterationsINTELMask = 0x00400000,
|
||||||
|
LoopControlNoFusionINTELMask = 0x00800000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FunctionControlShift {
|
enum FunctionControlShift {
|
||||||
@@ -870,8 +908,12 @@ enum Capability {
|
|||||||
CapabilityGroupNonUniformQuad = 68,
|
CapabilityGroupNonUniformQuad = 68,
|
||||||
CapabilityShaderLayer = 69,
|
CapabilityShaderLayer = 69,
|
||||||
CapabilityShaderViewportIndex = 70,
|
CapabilityShaderViewportIndex = 70,
|
||||||
|
CapabilityFragmentShadingRateKHR = 4422,
|
||||||
CapabilitySubgroupBallotKHR = 4423,
|
CapabilitySubgroupBallotKHR = 4423,
|
||||||
CapabilityDrawParameters = 4427,
|
CapabilityDrawParameters = 4427,
|
||||||
|
CapabilityWorkgroupMemoryExplicitLayoutKHR = 4428,
|
||||||
|
CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429,
|
||||||
|
CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430,
|
||||||
CapabilitySubgroupVoteKHR = 4431,
|
CapabilitySubgroupVoteKHR = 4431,
|
||||||
CapabilityStorageBuffer16BitAccess = 4433,
|
CapabilityStorageBuffer16BitAccess = 4433,
|
||||||
CapabilityStorageUniformBufferBlock16 = 4433,
|
CapabilityStorageUniformBufferBlock16 = 4433,
|
||||||
@@ -894,12 +936,15 @@ enum Capability {
|
|||||||
CapabilityRoundingModeRTE = 4467,
|
CapabilityRoundingModeRTE = 4467,
|
||||||
CapabilityRoundingModeRTZ = 4468,
|
CapabilityRoundingModeRTZ = 4468,
|
||||||
CapabilityRayQueryProvisionalKHR = 4471,
|
CapabilityRayQueryProvisionalKHR = 4471,
|
||||||
CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
|
CapabilityRayQueryKHR = 4472,
|
||||||
|
CapabilityRayTraversalPrimitiveCullingKHR = 4478,
|
||||||
|
CapabilityRayTracingKHR = 4479,
|
||||||
CapabilityFloat16ImageAMD = 5008,
|
CapabilityFloat16ImageAMD = 5008,
|
||||||
CapabilityImageGatherBiasLodAMD = 5009,
|
CapabilityImageGatherBiasLodAMD = 5009,
|
||||||
CapabilityFragmentMaskAMD = 5010,
|
CapabilityFragmentMaskAMD = 5010,
|
||||||
CapabilityStencilExportEXT = 5013,
|
CapabilityStencilExportEXT = 5013,
|
||||||
CapabilityImageReadWriteLodAMD = 5015,
|
CapabilityImageReadWriteLodAMD = 5015,
|
||||||
|
CapabilityInt64ImageEXT = 5016,
|
||||||
CapabilityShaderClockKHR = 5055,
|
CapabilityShaderClockKHR = 5055,
|
||||||
CapabilitySampleMaskOverrideCoverageNV = 5249,
|
CapabilitySampleMaskOverrideCoverageNV = 5249,
|
||||||
CapabilityGeometryShaderPassthroughNV = 5251,
|
CapabilityGeometryShaderPassthroughNV = 5251,
|
||||||
@@ -959,21 +1004,37 @@ enum Capability {
|
|||||||
CapabilitySubgroupBufferBlockIOINTEL = 5569,
|
CapabilitySubgroupBufferBlockIOINTEL = 5569,
|
||||||
CapabilitySubgroupImageBlockIOINTEL = 5570,
|
CapabilitySubgroupImageBlockIOINTEL = 5570,
|
||||||
CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
|
CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
|
||||||
|
CapabilityRoundToInfinityINTEL = 5582,
|
||||||
|
CapabilityFloatingPointModeINTEL = 5583,
|
||||||
CapabilityIntegerFunctions2INTEL = 5584,
|
CapabilityIntegerFunctions2INTEL = 5584,
|
||||||
CapabilityFunctionPointersINTEL = 5603,
|
CapabilityFunctionPointersINTEL = 5603,
|
||||||
CapabilityIndirectReferencesINTEL = 5604,
|
CapabilityIndirectReferencesINTEL = 5604,
|
||||||
|
CapabilityAsmINTEL = 5606,
|
||||||
|
CapabilityVectorComputeINTEL = 5617,
|
||||||
|
CapabilityVectorAnyINTEL = 5619,
|
||||||
CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
|
CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
|
||||||
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
|
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
|
||||||
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
|
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
|
||||||
|
CapabilityVariableLengthArrayINTEL = 5817,
|
||||||
|
CapabilityFunctionFloatControlINTEL = 5821,
|
||||||
CapabilityFPGAMemoryAttributesINTEL = 5824,
|
CapabilityFPGAMemoryAttributesINTEL = 5824,
|
||||||
|
CapabilityFPFastMathModeINTEL = 5837,
|
||||||
|
CapabilityArbitraryPrecisionIntegersINTEL = 5844,
|
||||||
CapabilityUnstructuredLoopControlsINTEL = 5886,
|
CapabilityUnstructuredLoopControlsINTEL = 5886,
|
||||||
CapabilityFPGALoopControlsINTEL = 5888,
|
CapabilityFPGALoopControlsINTEL = 5888,
|
||||||
CapabilityKernelAttributesINTEL = 5892,
|
CapabilityKernelAttributesINTEL = 5892,
|
||||||
CapabilityFPGAKernelAttributesINTEL = 5897,
|
CapabilityFPGAKernelAttributesINTEL = 5897,
|
||||||
|
CapabilityFPGAMemoryAccessesINTEL = 5898,
|
||||||
|
CapabilityFPGAClusterAttributesINTEL = 5904,
|
||||||
|
CapabilityLoopFuseINTEL = 5906,
|
||||||
|
CapabilityFPGABufferLocationINTEL = 5920,
|
||||||
|
CapabilityUSMStorageClassesINTEL = 5935,
|
||||||
|
CapabilityIOPipesINTEL = 5943,
|
||||||
CapabilityBlockingPipesINTEL = 5945,
|
CapabilityBlockingPipesINTEL = 5945,
|
||||||
CapabilityFPGARegINTEL = 5948,
|
CapabilityFPGARegINTEL = 5948,
|
||||||
CapabilityAtomicFloat32AddEXT = 6033,
|
CapabilityAtomicFloat32AddEXT = 6033,
|
||||||
CapabilityAtomicFloat64AddEXT = 6034,
|
CapabilityAtomicFloat64AddEXT = 6034,
|
||||||
|
CapabilityLongConstantCompositeINTEL = 6089,
|
||||||
CapabilityMax = 0x7fffffff,
|
CapabilityMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1024,6 +1085,34 @@ enum RayQueryCandidateIntersectionType {
|
|||||||
RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
|
RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FragmentShadingRateShift {
|
||||||
|
FragmentShadingRateVertical2PixelsShift = 0,
|
||||||
|
FragmentShadingRateVertical4PixelsShift = 1,
|
||||||
|
FragmentShadingRateHorizontal2PixelsShift = 2,
|
||||||
|
FragmentShadingRateHorizontal4PixelsShift = 3,
|
||||||
|
FragmentShadingRateMax = 0x7fffffff,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FragmentShadingRateMask {
|
||||||
|
FragmentShadingRateMaskNone = 0,
|
||||||
|
FragmentShadingRateVertical2PixelsMask = 0x00000001,
|
||||||
|
FragmentShadingRateVertical4PixelsMask = 0x00000002,
|
||||||
|
FragmentShadingRateHorizontal2PixelsMask = 0x00000004,
|
||||||
|
FragmentShadingRateHorizontal4PixelsMask = 0x00000008,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FPDenormMode {
|
||||||
|
FPDenormModePreserve = 0,
|
||||||
|
FPDenormModeFlushToZero = 1,
|
||||||
|
FPDenormModeMax = 0x7fffffff,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FPOperationMode {
|
||||||
|
FPOperationModeIEEE = 0,
|
||||||
|
FPOperationModeALT = 1,
|
||||||
|
FPOperationModeMax = 0x7fffffff,
|
||||||
|
};
|
||||||
|
|
||||||
enum Op {
|
enum Op {
|
||||||
OpNop = 0,
|
OpNop = 0,
|
||||||
OpUndef = 1,
|
OpUndef = 1,
|
||||||
@@ -1369,13 +1458,19 @@ enum Op {
|
|||||||
OpPtrEqual = 401,
|
OpPtrEqual = 401,
|
||||||
OpPtrNotEqual = 402,
|
OpPtrNotEqual = 402,
|
||||||
OpPtrDiff = 403,
|
OpPtrDiff = 403,
|
||||||
|
OpTerminateInvocation = 4416,
|
||||||
OpSubgroupBallotKHR = 4421,
|
OpSubgroupBallotKHR = 4421,
|
||||||
OpSubgroupFirstInvocationKHR = 4422,
|
OpSubgroupFirstInvocationKHR = 4422,
|
||||||
OpSubgroupAllKHR = 4428,
|
OpSubgroupAllKHR = 4428,
|
||||||
OpSubgroupAnyKHR = 4429,
|
OpSubgroupAnyKHR = 4429,
|
||||||
OpSubgroupAllEqualKHR = 4430,
|
OpSubgroupAllEqualKHR = 4430,
|
||||||
OpSubgroupReadInvocationKHR = 4432,
|
OpSubgroupReadInvocationKHR = 4432,
|
||||||
OpTypeRayQueryProvisionalKHR = 4472,
|
OpTraceRayKHR = 4445,
|
||||||
|
OpExecuteCallableKHR = 4446,
|
||||||
|
OpConvertUToAccelerationStructureKHR = 4447,
|
||||||
|
OpIgnoreIntersectionKHR = 4448,
|
||||||
|
OpTerminateRayKHR = 4449,
|
||||||
|
OpTypeRayQueryKHR = 4472,
|
||||||
OpRayQueryInitializeKHR = 4473,
|
OpRayQueryInitializeKHR = 4473,
|
||||||
OpRayQueryTerminateKHR = 4474,
|
OpRayQueryTerminateKHR = 4474,
|
||||||
OpRayQueryGenerateIntersectionKHR = 4475,
|
OpRayQueryGenerateIntersectionKHR = 4475,
|
||||||
@@ -1398,15 +1493,11 @@ enum Op {
|
|||||||
OpWritePackedPrimitiveIndices4x8NV = 5299,
|
OpWritePackedPrimitiveIndices4x8NV = 5299,
|
||||||
OpReportIntersectionKHR = 5334,
|
OpReportIntersectionKHR = 5334,
|
||||||
OpReportIntersectionNV = 5334,
|
OpReportIntersectionNV = 5334,
|
||||||
OpIgnoreIntersectionKHR = 5335,
|
|
||||||
OpIgnoreIntersectionNV = 5335,
|
OpIgnoreIntersectionNV = 5335,
|
||||||
OpTerminateRayKHR = 5336,
|
|
||||||
OpTerminateRayNV = 5336,
|
OpTerminateRayNV = 5336,
|
||||||
OpTraceNV = 5337,
|
OpTraceNV = 5337,
|
||||||
OpTraceRayKHR = 5337,
|
|
||||||
OpTypeAccelerationStructureKHR = 5341,
|
OpTypeAccelerationStructureKHR = 5341,
|
||||||
OpTypeAccelerationStructureNV = 5341,
|
OpTypeAccelerationStructureNV = 5341,
|
||||||
OpExecuteCallableKHR = 5344,
|
|
||||||
OpExecuteCallableNV = 5344,
|
OpExecuteCallableNV = 5344,
|
||||||
OpTypeCooperativeMatrixNV = 5358,
|
OpTypeCooperativeMatrixNV = 5358,
|
||||||
OpCooperativeMatrixLoadNV = 5359,
|
OpCooperativeMatrixLoadNV = 5359,
|
||||||
@@ -1441,8 +1532,11 @@ enum Op {
|
|||||||
OpUSubSatINTEL = 5596,
|
OpUSubSatINTEL = 5596,
|
||||||
OpIMul32x16INTEL = 5597,
|
OpIMul32x16INTEL = 5597,
|
||||||
OpUMul32x16INTEL = 5598,
|
OpUMul32x16INTEL = 5598,
|
||||||
OpFunctionPointerINTEL = 5600,
|
OpConstFunctionPointerINTEL = 5600,
|
||||||
OpFunctionPointerCallINTEL = 5601,
|
OpFunctionPointerCallINTEL = 5601,
|
||||||
|
OpAsmTargetINTEL = 5609,
|
||||||
|
OpAsmINTEL = 5610,
|
||||||
|
OpAsmCallINTEL = 5611,
|
||||||
OpDecorateString = 5632,
|
OpDecorateString = 5632,
|
||||||
OpDecorateStringGOOGLE = 5632,
|
OpDecorateStringGOOGLE = 5632,
|
||||||
OpMemberDecorateString = 5633,
|
OpMemberDecorateString = 5633,
|
||||||
@@ -1565,7 +1659,12 @@ enum Op {
|
|||||||
OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
|
OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
|
||||||
OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
|
OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
|
||||||
OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
|
OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
|
||||||
|
OpVariableLengthArrayINTEL = 5818,
|
||||||
|
OpSaveMemoryINTEL = 5819,
|
||||||
|
OpRestoreMemoryINTEL = 5820,
|
||||||
OpLoopControlINTEL = 5887,
|
OpLoopControlINTEL = 5887,
|
||||||
|
OpPtrCastToCrossWorkgroupINTEL = 5934,
|
||||||
|
OpCrossWorkgroupCastToPtrINTEL = 5938,
|
||||||
OpReadPipeBlockingINTEL = 5946,
|
OpReadPipeBlockingINTEL = 5946,
|
||||||
OpWritePipeBlockingINTEL = 5947,
|
OpWritePipeBlockingINTEL = 5947,
|
||||||
OpFPGARegINTEL = 5949,
|
OpFPGARegINTEL = 5949,
|
||||||
@@ -1587,6 +1686,10 @@ enum Op {
|
|||||||
OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
|
OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
|
||||||
OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
|
OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
|
||||||
OpAtomicFAddEXT = 6035,
|
OpAtomicFAddEXT = 6035,
|
||||||
|
OpTypeBufferSurfaceINTEL = 6086,
|
||||||
|
OpTypeStructContinuedINTEL = 6090,
|
||||||
|
OpConstantCompositeContinuedINTEL = 6091,
|
||||||
|
OpSpecConstantCompositeContinuedINTEL = 6092,
|
||||||
OpMax = 0x7fffffff,
|
OpMax = 0x7fffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1939,13 +2042,19 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
|||||||
case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
|
case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
|
case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
|
case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break;
|
||||||
case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
|
case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
|
||||||
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
|
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
|
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
|
case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
|
||||||
@@ -2005,8 +2114,11 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
|||||||
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpConstFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpAsmINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpDecorateString: *hasResult = false; *hasResultType = false; break;
|
case OpDecorateString: *hasResult = false; *hasResultType = false; break;
|
||||||
case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
|
case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
|
||||||
case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
@@ -2127,7 +2239,12 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
|||||||
case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;
|
||||||
case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
|
case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
|
case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
|
||||||
@@ -2149,6 +2266,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
|||||||
case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
|
case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
|
case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
|
||||||
case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
|
case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
|
||||||
|
case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;
|
||||||
|
case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
|
||||||
|
case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SPV_ENABLE_UTILITY_CODE */
|
#endif /* SPV_ENABLE_UTILITY_CODE */
|
||||||
@@ -2164,6 +2285,7 @@ inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask
|
|||||||
inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
|
inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
|
||||||
inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
|
inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
|
||||||
inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
|
inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); }
|
||||||
|
|
||||||
} // end namespace spv
|
} // end namespace spv
|
||||||
|
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ public:
|
|||||||
case OpBranchConditional:
|
case OpBranchConditional:
|
||||||
case OpSwitch:
|
case OpSwitch:
|
||||||
case OpKill:
|
case OpKill:
|
||||||
|
case OpTerminateInvocation:
|
||||||
case OpReturn:
|
case OpReturn:
|
||||||
case OpReturnValue:
|
case OpReturnValue:
|
||||||
case OpUnreachable:
|
case OpUnreachable:
|
||||||
|
|||||||
@@ -228,6 +228,9 @@ enum TBuiltInVariable {
|
|||||||
EbvViewIndex,
|
EbvViewIndex,
|
||||||
EbvDeviceIndex,
|
EbvDeviceIndex,
|
||||||
|
|
||||||
|
EbvShadingRateKHR,
|
||||||
|
EbvPrimitiveShadingRateKHR,
|
||||||
|
|
||||||
EbvFragSizeEXT,
|
EbvFragSizeEXT,
|
||||||
EbvFragInvocationCountEXT,
|
EbvFragInvocationCountEXT,
|
||||||
|
|
||||||
@@ -480,6 +483,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
|
|||||||
case EbvWarpID: return "WarpIDNV";
|
case EbvWarpID: return "WarpIDNV";
|
||||||
case EbvSMID: return "SMIDNV";
|
case EbvSMID: return "SMIDNV";
|
||||||
|
|
||||||
|
case EbvShadingRateKHR: return "ShadingRateKHR";
|
||||||
|
case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR";
|
||||||
|
|
||||||
default: return "unknown built-in variable";
|
default: return "unknown built-in variable";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,6 +406,7 @@ enum TLayoutFormat {
|
|||||||
ElfRg8i,
|
ElfRg8i,
|
||||||
ElfR16i,
|
ElfR16i,
|
||||||
ElfR8i,
|
ElfR8i,
|
||||||
|
ElfR64i,
|
||||||
|
|
||||||
ElfIntGuard, // to help with comparisons
|
ElfIntGuard, // to help with comparisons
|
||||||
|
|
||||||
@@ -423,6 +424,7 @@ enum TLayoutFormat {
|
|||||||
ElfRg8ui,
|
ElfRg8ui,
|
||||||
ElfR16ui,
|
ElfR16ui,
|
||||||
ElfR8ui,
|
ElfR8ui,
|
||||||
|
ElfR64ui,
|
||||||
|
|
||||||
ElfCount
|
ElfCount
|
||||||
};
|
};
|
||||||
@@ -497,7 +499,9 @@ public:
|
|||||||
declaredBuiltIn = EbvNone;
|
declaredBuiltIn = EbvNone;
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
noContraction = false;
|
noContraction = false;
|
||||||
|
nullInit = false;
|
||||||
#endif
|
#endif
|
||||||
|
defaultBlock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop qualifiers that don't belong in a temporary variable
|
// drop qualifiers that don't belong in a temporary variable
|
||||||
@@ -510,6 +514,8 @@ public:
|
|||||||
clearMemory();
|
clearMemory();
|
||||||
specConstant = false;
|
specConstant = false;
|
||||||
nonUniform = false;
|
nonUniform = false;
|
||||||
|
nullInit = false;
|
||||||
|
defaultBlock = false;
|
||||||
clearLayout();
|
clearLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,6 +574,7 @@ public:
|
|||||||
bool specConstant : 1;
|
bool specConstant : 1;
|
||||||
bool nonUniform : 1;
|
bool nonUniform : 1;
|
||||||
bool explicitOffset : 1;
|
bool explicitOffset : 1;
|
||||||
|
bool defaultBlock : 1; // default blocks with matching names have structures merged when linking
|
||||||
|
|
||||||
#ifdef GLSLANG_WEB
|
#ifdef GLSLANG_WEB
|
||||||
bool isWriteOnly() const { return false; }
|
bool isWriteOnly() const { return false; }
|
||||||
@@ -586,6 +593,8 @@ public:
|
|||||||
bool isNoContraction() const { return false; }
|
bool isNoContraction() const { return false; }
|
||||||
void setNoContraction() { }
|
void setNoContraction() { }
|
||||||
bool isPervertexNV() const { return false; }
|
bool isPervertexNV() const { return false; }
|
||||||
|
void setNullInit() { }
|
||||||
|
bool isNullInit() const { return false; }
|
||||||
#else
|
#else
|
||||||
bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
|
bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
|
||||||
bool nopersp : 1;
|
bool nopersp : 1;
|
||||||
@@ -607,6 +616,7 @@ public:
|
|||||||
bool subgroupcoherent : 1;
|
bool subgroupcoherent : 1;
|
||||||
bool shadercallcoherent : 1;
|
bool shadercallcoherent : 1;
|
||||||
bool nonprivate : 1;
|
bool nonprivate : 1;
|
||||||
|
bool nullInit : 1;
|
||||||
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; }
|
||||||
@@ -642,6 +652,8 @@ public:
|
|||||||
bool isNoContraction() const { return noContraction; }
|
bool isNoContraction() const { return noContraction; }
|
||||||
void setNoContraction() { noContraction = true; }
|
void setNoContraction() { noContraction = true; }
|
||||||
bool isPervertexNV() const { return pervertexNV; }
|
bool isPervertexNV() const { return pervertexNV; }
|
||||||
|
void setNullInit() { nullInit = true; }
|
||||||
|
bool isNullInit() const { return nullInit; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool isPipeInput() const
|
bool isPipeInput() const
|
||||||
@@ -747,6 +759,46 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TBlockStorageClass getBlockStorage() const {
|
||||||
|
if (storage == EvqUniform && !isPushConstant()) {
|
||||||
|
return EbsUniform;
|
||||||
|
}
|
||||||
|
else if (storage == EvqUniform) {
|
||||||
|
return EbsPushConstant;
|
||||||
|
}
|
||||||
|
else if (storage == EvqBuffer) {
|
||||||
|
return EbsStorageBuffer;
|
||||||
|
}
|
||||||
|
return EbsNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBlockStorage(TBlockStorageClass newBacking) {
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
layoutPushConstant = (newBacking == EbsPushConstant);
|
||||||
|
#endif
|
||||||
|
switch (newBacking) {
|
||||||
|
case EbsUniform :
|
||||||
|
if (layoutPacking == ElpStd430) {
|
||||||
|
// std430 would not be valid
|
||||||
|
layoutPacking = ElpStd140;
|
||||||
|
}
|
||||||
|
storage = EvqUniform;
|
||||||
|
break;
|
||||||
|
case EbsStorageBuffer :
|
||||||
|
storage = EvqBuffer;
|
||||||
|
break;
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
case EbsPushConstant :
|
||||||
|
storage = EvqUniform;
|
||||||
|
layoutSet = TQualifier::layoutSetEnd;
|
||||||
|
layoutBinding = TQualifier::layoutBindingEnd;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef GLSLANG_WEB
|
#ifdef GLSLANG_WEB
|
||||||
bool isPerView() const { return false; }
|
bool isPerView() const { return false; }
|
||||||
bool isTaskMemory() const { return false; }
|
bool isTaskMemory() const { return false; }
|
||||||
@@ -755,6 +807,12 @@ public:
|
|||||||
bool isPerPrimitive() const { return perPrimitiveNV; }
|
bool isPerPrimitive() const { return perPrimitiveNV; }
|
||||||
bool isPerView() const { return perViewNV; }
|
bool isPerView() const { return perViewNV; }
|
||||||
bool isTaskMemory() const { return perTaskNV; }
|
bool isTaskMemory() const { return perTaskNV; }
|
||||||
|
bool isAnyPayload() const {
|
||||||
|
return storage == EvqPayload || storage == EvqPayloadIn;
|
||||||
|
}
|
||||||
|
bool isAnyCallable() const {
|
||||||
|
return storage == EvqCallableData || storage == EvqCallableDataIn;
|
||||||
|
}
|
||||||
|
|
||||||
// True if this type of IO is supposed to be arrayed with extra level for per-vertex data
|
// True if this type of IO is supposed to be arrayed with extra level for per-vertex data
|
||||||
bool isArrayedIo(EShLanguage language) const
|
bool isArrayedIo(EShLanguage language) const
|
||||||
@@ -837,6 +895,7 @@ public:
|
|||||||
return hasNonXfbLayout() ||
|
return hasNonXfbLayout() ||
|
||||||
hasXfb();
|
hasXfb();
|
||||||
}
|
}
|
||||||
|
|
||||||
TLayoutMatrix layoutMatrix : 3;
|
TLayoutMatrix layoutMatrix : 3;
|
||||||
TLayoutPacking layoutPacking : 4;
|
TLayoutPacking layoutPacking : 4;
|
||||||
int layoutOffset;
|
int layoutOffset;
|
||||||
@@ -1117,6 +1176,8 @@ public:
|
|||||||
case ElfR32ui: return "r32ui";
|
case ElfR32ui: return "r32ui";
|
||||||
case ElfR16ui: return "r16ui";
|
case ElfR16ui: return "r16ui";
|
||||||
case ElfR8ui: return "r8ui";
|
case ElfR8ui: return "r8ui";
|
||||||
|
case ElfR64ui: return "r64ui";
|
||||||
|
case ElfR64i: return "r64i";
|
||||||
default: return "none";
|
default: return "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1986,6 +2047,7 @@ public:
|
|||||||
case EbtAccStruct: return "accelerationStructureNV";
|
case EbtAccStruct: return "accelerationStructureNV";
|
||||||
case EbtRayQuery: return "rayQueryEXT";
|
case EbtRayQuery: return "rayQueryEXT";
|
||||||
case EbtReference: return "reference";
|
case EbtReference: return "reference";
|
||||||
|
case EbtString: return "string";
|
||||||
#endif
|
#endif
|
||||||
default: return "unknown type";
|
default: return "unknown type";
|
||||||
}
|
}
|
||||||
@@ -2153,6 +2215,8 @@ public:
|
|||||||
appendStr(" specialization-constant");
|
appendStr(" specialization-constant");
|
||||||
if (qualifier.nonUniform)
|
if (qualifier.nonUniform)
|
||||||
appendStr(" nonuniform");
|
appendStr(" nonuniform");
|
||||||
|
if (qualifier.isNullInit())
|
||||||
|
appendStr(" null-init");
|
||||||
appendStr(" ");
|
appendStr(" ");
|
||||||
appendStr(getStorageQualifierString());
|
appendStr(getStorageQualifierString());
|
||||||
if (isArray()) {
|
if (isArray()) {
|
||||||
@@ -2272,6 +2336,17 @@ public:
|
|||||||
name += ';' ;
|
name += ';' ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These variables are inconsistently declared inside and outside of gl_PerVertex in glslang right now.
|
||||||
|
// They are declared inside of 'in gl_PerVertex', but sitting as standalone when they are 'out'puts.
|
||||||
|
bool isInconsistentGLPerVertexMember(const TString& name) const
|
||||||
|
{
|
||||||
|
if (name == "gl_SecondaryPositionNV" ||
|
||||||
|
name == "gl_PositionPerViewNV")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Do two structure types match? They could be declared independently,
|
// Do two structure types match? They could be declared independently,
|
||||||
// in different places, but still might satisfy the definition of matching.
|
// in different places, but still might satisfy the definition of matching.
|
||||||
// From the spec:
|
// From the spec:
|
||||||
@@ -2287,22 +2362,48 @@ public:
|
|||||||
(isStruct() && right.isStruct() && structure == right.structure))
|
(isStruct() && right.isStruct() && structure == right.structure))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Both being nullptr was caught above, now they both have to be structures of the same number of elements
|
|
||||||
if (!isStruct() || !right.isStruct() ||
|
|
||||||
structure->size() != right.structure->size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Structure names have to match
|
// Structure names have to match
|
||||||
if (*typeName != *right.typeName)
|
if (*typeName != *right.typeName)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compare the names and types of all the members, which have to match
|
// There are inconsistencies with how gl_PerVertex is setup. For now ignore those as errors if they
|
||||||
for (unsigned int i = 0; i < structure->size(); ++i) {
|
// are known inconsistencies.
|
||||||
if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName())
|
bool isGLPerVertex = *typeName == "gl_PerVertex";
|
||||||
return false;
|
|
||||||
|
|
||||||
if (*(*structure)[i].type != *(*right.structure)[i].type)
|
// Both being nullptr was caught above, now they both have to be structures of the same number of elements
|
||||||
return false;
|
if (!isStruct() || !right.isStruct() ||
|
||||||
|
(structure->size() != right.structure->size() && !isGLPerVertex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Compare the names and types of all the members, which have to match
|
||||||
|
for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) {
|
||||||
|
if (li < structure->size() && ri < right.structure->size()) {
|
||||||
|
if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) {
|
||||||
|
if (*(*structure)[li].type != *(*right.structure)[ri].type)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// If one of the members is something that's inconsistently declared, skip over it
|
||||||
|
// for now.
|
||||||
|
if (isGLPerVertex) {
|
||||||
|
if (isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
|
||||||
|
ri--;
|
||||||
|
continue;
|
||||||
|
} else if (isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
|
||||||
|
li--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we get here, then there should only be inconsistently declared members left
|
||||||
|
} else if (li < structure->size()) {
|
||||||
|
if (!isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName()))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -203,28 +203,44 @@ typedef struct glsl_include_callbacks_s {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int glslang_initialize_process();
|
#ifdef GLSLANG_IS_SHARED_LIBRARY
|
||||||
void glslang_finalize_process();
|
#ifdef _WIN32
|
||||||
|
#ifdef GLSLANG_EXPORTING
|
||||||
|
#define GLSLANG_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define GLSLANG_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#elif __GNUC__ >= 4
|
||||||
|
#define GLSLANG_EXPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
#endif // GLSLANG_IS_SHARED_LIBRARY
|
||||||
|
|
||||||
glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
|
#ifndef GLSLANG_EXPORT
|
||||||
void glslang_shader_delete(glslang_shader_t* shader);
|
#define GLSLANG_EXPORT
|
||||||
int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
|
#endif
|
||||||
int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
|
|
||||||
const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
|
|
||||||
const char* glslang_shader_get_info_log(glslang_shader_t* shader);
|
|
||||||
const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
|
|
||||||
|
|
||||||
glslang_program_t* glslang_program_create();
|
GLSLANG_EXPORT int glslang_initialize_process();
|
||||||
void glslang_program_delete(glslang_program_t* program);
|
GLSLANG_EXPORT void glslang_finalize_process();
|
||||||
void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
|
|
||||||
int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
|
GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
|
||||||
void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
|
GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader);
|
||||||
size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
|
GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
|
||||||
void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);
|
GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
|
||||||
unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program);
|
GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
|
||||||
const char* glslang_program_SPIRV_get_messages(glslang_program_t* program);
|
GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader);
|
||||||
const char* glslang_program_get_info_log(glslang_program_t* program);
|
GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
|
||||||
const char* glslang_program_get_info_debug_log(glslang_program_t* program);
|
|
||||||
|
GLSLANG_EXPORT glslang_program_t* glslang_program_create();
|
||||||
|
GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program);
|
||||||
|
GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
|
||||||
|
GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
|
||||||
|
GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
|
||||||
|
GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
|
||||||
|
GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);
|
||||||
|
GLSLANG_EXPORT unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program);
|
||||||
|
GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t* program);
|
||||||
|
GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program);
|
||||||
|
GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,8 +100,9 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
GLSLANG_TARGET_VULKAN_1_0 = (1 << 22),
|
GLSLANG_TARGET_VULKAN_1_0 = (1 << 22),
|
||||||
GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12),
|
GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12),
|
||||||
|
GLSLANG_TARGET_VULKAN_1_2 = (1 << 22) | (2 << 12),
|
||||||
GLSLANG_TARGET_OPENGL_450 = 450,
|
GLSLANG_TARGET_OPENGL_450 = 450,
|
||||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT),
|
LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT = 4),
|
||||||
} glslang_target_client_version_t;
|
} glslang_target_client_version_t;
|
||||||
|
|
||||||
/* SH_TARGET_LanguageVersion counterpart */
|
/* SH_TARGET_LanguageVersion counterpart */
|
||||||
@@ -112,7 +113,7 @@ typedef enum {
|
|||||||
GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8),
|
GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8),
|
||||||
GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8),
|
GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8),
|
||||||
GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8),
|
GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8),
|
||||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT),
|
LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT = 6),
|
||||||
} glslang_target_language_version_t;
|
} glslang_target_language_version_t;
|
||||||
|
|
||||||
/* EShExecutable counterpart */
|
/* EShExecutable counterpart */
|
||||||
|
|||||||
@@ -280,6 +280,12 @@ enum TOperator {
|
|||||||
EOpConvUvec2ToPtr,
|
EOpConvUvec2ToPtr,
|
||||||
EOpConvPtrToUvec2,
|
EOpConvPtrToUvec2,
|
||||||
|
|
||||||
|
// uint64_t -> accelerationStructureEXT
|
||||||
|
EOpConvUint64ToAccStruct,
|
||||||
|
|
||||||
|
// uvec2 -> accelerationStructureEXT
|
||||||
|
EOpConvUvec2ToAccStruct,
|
||||||
|
|
||||||
//
|
//
|
||||||
// binary operations
|
// binary operations
|
||||||
//
|
//
|
||||||
@@ -587,6 +593,7 @@ enum TOperator {
|
|||||||
EOpTime,
|
EOpTime,
|
||||||
|
|
||||||
EOpAtomicAdd,
|
EOpAtomicAdd,
|
||||||
|
EOpAtomicSubtract,
|
||||||
EOpAtomicMin,
|
EOpAtomicMin,
|
||||||
EOpAtomicMax,
|
EOpAtomicMax,
|
||||||
EOpAtomicAnd,
|
EOpAtomicAnd,
|
||||||
@@ -628,13 +635,16 @@ enum TOperator {
|
|||||||
// Branch
|
// Branch
|
||||||
//
|
//
|
||||||
|
|
||||||
EOpKill, // Fragment only
|
EOpKill, // Fragment only
|
||||||
|
EOpTerminateInvocation, // Fragment only
|
||||||
|
EOpDemote, // Fragment only
|
||||||
|
EOpTerminateRayKHR, // Any-hit only
|
||||||
|
EOpIgnoreIntersectionKHR, // Any-hit only
|
||||||
EOpReturn,
|
EOpReturn,
|
||||||
EOpBreak,
|
EOpBreak,
|
||||||
EOpContinue,
|
EOpContinue,
|
||||||
EOpCase,
|
EOpCase,
|
||||||
EOpDefault,
|
EOpDefault,
|
||||||
EOpDemote, // Fragment only
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constructors
|
// Constructors
|
||||||
@@ -751,6 +761,7 @@ enum TOperator {
|
|||||||
EOpConstructNonuniform, // expected to be transformed away, not present in final AST
|
EOpConstructNonuniform, // expected to be transformed away, not present in final AST
|
||||||
EOpConstructReference,
|
EOpConstructReference,
|
||||||
EOpConstructCooperativeMatrix,
|
EOpConstructCooperativeMatrix,
|
||||||
|
EOpConstructAccStruct,
|
||||||
EOpConstructGuardEnd,
|
EOpConstructGuardEnd,
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -911,11 +922,13 @@ enum TOperator {
|
|||||||
EOpAverageRounded,
|
EOpAverageRounded,
|
||||||
EOpMul32x16,
|
EOpMul32x16,
|
||||||
|
|
||||||
EOpTrace,
|
EOpTraceNV,
|
||||||
|
EOpTraceKHR,
|
||||||
EOpReportIntersection,
|
EOpReportIntersection,
|
||||||
EOpIgnoreIntersection,
|
EOpIgnoreIntersectionNV,
|
||||||
EOpTerminateRay,
|
EOpTerminateRayNV,
|
||||||
EOpExecuteCallable,
|
EOpExecuteCallableNV,
|
||||||
|
EOpExecuteCallableKHR,
|
||||||
EOpWritePackedPrimitiveIndices4x8NV,
|
EOpWritePackedPrimitiveIndices4x8NV,
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -1123,6 +1136,8 @@ public:
|
|||||||
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
virtual TBasicType getBasicType() const { return type.getBasicType(); }
|
||||||
virtual TQualifier& getQualifier() { return type.getQualifier(); }
|
virtual TQualifier& getQualifier() { return type.getQualifier(); }
|
||||||
virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
|
virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
|
||||||
|
virtual TArraySizes* getArraySizes() { return type.getArraySizes(); }
|
||||||
|
virtual const TArraySizes* getArraySizes() const { return type.getArraySizes(); }
|
||||||
virtual void propagatePrecision(TPrecisionQualifier);
|
virtual void propagatePrecision(TPrecisionQualifier);
|
||||||
virtual int getVectorSize() const { return type.getVectorSize(); }
|
virtual int getVectorSize() const { return type.getVectorSize(); }
|
||||||
virtual int getMatrixCols() const { return type.getMatrixCols(); }
|
virtual int getMatrixCols() const { return type.getMatrixCols(); }
|
||||||
@@ -1263,15 +1278,15 @@ public:
|
|||||||
// if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
|
// if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
|
||||||
// per process threadPoolAllocator, then it causes increased memory usage per compile
|
// per process threadPoolAllocator, then it causes increased memory usage per compile
|
||||||
// it is essential to use "symbol = sym" to assign to symbol
|
// it is essential to use "symbol = sym" to assign to symbol
|
||||||
TIntermSymbol(int i, const TString& n, const TType& t)
|
TIntermSymbol(long long i, const TString& n, const TType& t)
|
||||||
: TIntermTyped(t), id(i),
|
: TIntermTyped(t), id(i),
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
flattenSubset(-1),
|
flattenSubset(-1),
|
||||||
#endif
|
#endif
|
||||||
constSubtree(nullptr)
|
constSubtree(nullptr)
|
||||||
{ name = n; }
|
{ name = n; }
|
||||||
virtual int getId() const { return id; }
|
virtual long long getId() const { return id; }
|
||||||
virtual void changeId(int i) { id = i; }
|
virtual void changeId(long long i) { id = i; }
|
||||||
virtual const TString& getName() const { return name; }
|
virtual const TString& getName() const { return name; }
|
||||||
virtual void traverse(TIntermTraverser*);
|
virtual void traverse(TIntermTraverser*);
|
||||||
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
||||||
@@ -1282,15 +1297,17 @@ public:
|
|||||||
TIntermTyped* getConstSubtree() const { return constSubtree; }
|
TIntermTyped* getConstSubtree() const { return constSubtree; }
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
void setFlattenSubset(int subset) { flattenSubset = subset; }
|
void setFlattenSubset(int subset) { flattenSubset = subset; }
|
||||||
|
virtual const TString& getAccessName() const;
|
||||||
|
|
||||||
int getFlattenSubset() const { return flattenSubset; } // -1 means full object
|
int getFlattenSubset() const { return flattenSubset; } // -1 means full object
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is meant for cases where a node has already been constructed, and
|
// This is meant for cases where a node has already been constructed, and
|
||||||
// later on, it becomes necessary to switch to a different symbol.
|
// later on, it becomes necessary to switch to a different symbol.
|
||||||
virtual void switchId(int newId) { id = newId; }
|
virtual void switchId(long long newId) { id = newId; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int id; // the unique id of the symbol this node represents
|
long long id; // the unique id of the symbol this node represents
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced
|
int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -599,17 +599,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
|
|||||||
newConstArray[i].setDConst(log(unionArray[i].getDConst()));
|
newConstArray[i].setDConst(log(unionArray[i].getDConst()));
|
||||||
break;
|
break;
|
||||||
case EOpExp2:
|
case EOpExp2:
|
||||||
{
|
newConstArray[i].setDConst(exp2(unionArray[i].getDConst()));
|
||||||
const double inv_log2_e = 0.69314718055994530941723212145818;
|
break;
|
||||||
newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EOpLog2:
|
case EOpLog2:
|
||||||
{
|
newConstArray[i].setDConst(log2(unionArray[i].getDConst()));
|
||||||
const double log2_e = 1.4426950408889634073599246810019;
|
break;
|
||||||
newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EOpSqrt:
|
case EOpSqrt:
|
||||||
newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
|
newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -509,6 +509,8 @@ TBuiltIns::TBuiltIns()
|
|||||||
prefixes[EbtUint8] = "u8";
|
prefixes[EbtUint8] = "u8";
|
||||||
prefixes[EbtInt16] = "i16";
|
prefixes[EbtInt16] = "i16";
|
||||||
prefixes[EbtUint16] = "u16";
|
prefixes[EbtUint16] = "u16";
|
||||||
|
prefixes[EbtInt64] = "i64";
|
||||||
|
prefixes[EbtUint64] = "u64";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
postfixes[2] = "2";
|
postfixes[2] = "2";
|
||||||
@@ -1631,6 +1633,36 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"uint atomicCounterExchange(atomic_uint, uint);"
|
"uint atomicCounterExchange(atomic_uint, uint);"
|
||||||
"uint atomicCounterCompSwap(atomic_uint, uint, uint);"
|
"uint atomicCounterCompSwap(atomic_uint, uint, uint);"
|
||||||
|
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (spvVersion.vulkanRelaxed) {
|
||||||
|
//
|
||||||
|
// Atomic counter functions act as aliases to normal atomic functions.
|
||||||
|
// replace definitions to take 'volatile coherent uint' instead of 'atomic_uint'
|
||||||
|
// and map to equivalent non-counter atomic op
|
||||||
|
//
|
||||||
|
if ((profile != EEsProfile && version >= 300) ||
|
||||||
|
(profile == EEsProfile && version >= 310)) {
|
||||||
|
commonBuiltins.append(
|
||||||
|
"uint atomicCounterIncrement(volatile coherent uint);"
|
||||||
|
"uint atomicCounterDecrement(volatile coherent uint);"
|
||||||
|
"uint atomicCounter(volatile coherent uint);"
|
||||||
|
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
if (profile != EEsProfile && version >= 460) {
|
||||||
|
commonBuiltins.append(
|
||||||
|
"uint atomicCounterAdd(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterSubtract(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterMin(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterMax(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterAnd(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterOr(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterXor(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterExchange(volatile coherent uint, uint);"
|
||||||
|
"uint atomicCounterCompSwap(volatile coherent uint, uint, uint);"
|
||||||
|
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4134,7 +4166,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
}
|
}
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if ((profile != EEsProfile && version >= 420) || esBarrier) {
|
if ((profile != EEsProfile && version >= 420) || esBarrier) {
|
||||||
if (spvVersion.vulkan == 0) {
|
if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) {
|
||||||
commonBuiltins.append("void memoryBarrierAtomicCounter();");
|
commonBuiltins.append("void memoryBarrierAtomicCounter();");
|
||||||
}
|
}
|
||||||
commonBuiltins.append("void memoryBarrierImage();");
|
commonBuiltins.append("void memoryBarrierImage();");
|
||||||
@@ -4434,9 +4466,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"\n");
|
"\n");
|
||||||
stageBuiltins[EShLangAnyHit].append(
|
stageBuiltins[EShLangAnyHit].append(
|
||||||
"void ignoreIntersectionNV();"
|
"void ignoreIntersectionNV();"
|
||||||
"void ignoreIntersectionEXT();"
|
|
||||||
"void terminateRayNV();"
|
"void terminateRayNV();"
|
||||||
"void terminateRayEXT();"
|
|
||||||
"\n");
|
"\n");
|
||||||
stageBuiltins[EShLangClosestHit].append(
|
stageBuiltins[EShLangClosestHit].append(
|
||||||
"void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
|
"void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
|
||||||
@@ -4863,6 +4893,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"in int gl_VertexIndex;"
|
"in int gl_VertexIndex;"
|
||||||
"in int gl_InstanceIndex;"
|
"in int gl_InstanceIndex;"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (spvVersion.vulkan > 0 && version >= 140 && spvVersion.vulkanRelaxed)
|
||||||
|
stageBuiltins[EShLangVertex].append(
|
||||||
|
"in int gl_VertexID;" // declare with 'in' qualifier
|
||||||
|
"in int gl_InstanceID;"
|
||||||
|
);
|
||||||
|
|
||||||
if (version >= 440) {
|
if (version >= 440) {
|
||||||
stageBuiltins[EShLangVertex].append(
|
stageBuiltins[EShLangVertex].append(
|
||||||
"in int gl_BaseVertexARB;"
|
"in int gl_BaseVertexARB;"
|
||||||
@@ -4900,7 +4937,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"mediump float gl_PointSize;" // needs qualifier fixed later
|
"mediump float gl_PointSize;" // needs qualifier fixed later
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (spvVersion.vulkan == 0)
|
if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed)
|
||||||
stageBuiltins[EShLangVertex].append(
|
stageBuiltins[EShLangVertex].append(
|
||||||
"in highp int gl_VertexID;" // needs qualifier fixed later
|
"in highp int gl_VertexID;" // needs qualifier fixed later
|
||||||
"in highp int gl_InstanceID;" // needs qualifier fixed later
|
"in highp int gl_InstanceID;" // needs qualifier fixed later
|
||||||
@@ -4943,6 +4980,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) {
|
||||||
|
stageBuiltins[EShLangVertex].append(
|
||||||
|
"out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
@@ -5056,6 +5098,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) {
|
||||||
|
stageBuiltins[EShLangGeometry].append(
|
||||||
|
"out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// Define the interface to the tessellation control shader.
|
// Define the interface to the tessellation control shader.
|
||||||
@@ -5353,6 +5401,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"in vec3 gl_BaryCoordNoPerspNV;"
|
"in vec3 gl_BaryCoordNoPerspNV;"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (version >= 450)
|
||||||
|
stageBuiltins[EShLangFragment].append(
|
||||||
|
"flat in int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate
|
||||||
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// ES profile
|
// ES profile
|
||||||
|
|
||||||
@@ -5411,6 +5464,10 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"in vec3 gl_BaryCoordNV;"
|
"in vec3 gl_BaryCoordNV;"
|
||||||
"in vec3 gl_BaryCoordNoPerspNV;"
|
"in vec3 gl_BaryCoordNoPerspNV;"
|
||||||
);
|
);
|
||||||
|
if (version >= 310)
|
||||||
|
stageBuiltins[EShLangFragment].append(
|
||||||
|
"flat in highp int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -5429,6 +5486,12 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version >= 300 /* both ES and non-ES */) {
|
||||||
|
stageBuiltins[EShLangFragment].append(
|
||||||
|
"flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef GLSLANG_ANGLE
|
#ifndef GLSLANG_ANGLE
|
||||||
// GL_ARB_shader_ballot
|
// GL_ARB_shader_ballot
|
||||||
if (profile != EEsProfile && version >= 450) {
|
if (profile != EEsProfile && version >= 450) {
|
||||||
@@ -5441,6 +5504,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"in uint64_t gl_SubGroupLeMaskARB;"
|
"in uint64_t gl_SubGroupLeMaskARB;"
|
||||||
"in uint64_t gl_SubGroupLtMaskARB;"
|
"in uint64_t gl_SubGroupLtMaskARB;"
|
||||||
"\n";
|
"\n";
|
||||||
|
const char* rtBallotDecls =
|
||||||
|
"uniform volatile uint gl_SubGroupSizeARB;"
|
||||||
|
"in volatile uint gl_SubGroupInvocationARB;"
|
||||||
|
"in volatile uint64_t gl_SubGroupEqMaskARB;"
|
||||||
|
"in volatile uint64_t gl_SubGroupGeMaskARB;"
|
||||||
|
"in volatile uint64_t gl_SubGroupGtMaskARB;"
|
||||||
|
"in volatile uint64_t gl_SubGroupLeMaskARB;"
|
||||||
|
"in volatile uint64_t gl_SubGroupLtMaskARB;"
|
||||||
|
"\n";
|
||||||
const char* fragmentBallotDecls =
|
const char* fragmentBallotDecls =
|
||||||
"uniform uint gl_SubGroupSizeARB;"
|
"uniform uint gl_SubGroupSizeARB;"
|
||||||
"flat in uint gl_SubGroupInvocationARB;"
|
"flat in uint gl_SubGroupInvocationARB;"
|
||||||
@@ -5458,6 +5530,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
stageBuiltins[EShLangFragment] .append(fragmentBallotDecls);
|
stageBuiltins[EShLangFragment] .append(fragmentBallotDecls);
|
||||||
stageBuiltins[EShLangMeshNV] .append(ballotDecls);
|
stageBuiltins[EShLangMeshNV] .append(ballotDecls);
|
||||||
stageBuiltins[EShLangTaskNV] .append(ballotDecls);
|
stageBuiltins[EShLangTaskNV] .append(ballotDecls);
|
||||||
|
stageBuiltins[EShLangRayGen] .append(rtBallotDecls);
|
||||||
|
stageBuiltins[EShLangIntersect] .append(rtBallotDecls);
|
||||||
|
// No volatile qualifier on these builtins in any-hit
|
||||||
|
stageBuiltins[EShLangAnyHit] .append(ballotDecls);
|
||||||
|
stageBuiltins[EShLangClosestHit] .append(rtBallotDecls);
|
||||||
|
stageBuiltins[EShLangMiss] .append(rtBallotDecls);
|
||||||
|
stageBuiltins[EShLangCallable] .append(rtBallotDecls);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_KHR_shader_subgroup
|
// GL_KHR_shader_subgroup
|
||||||
@@ -5495,6 +5574,21 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"in highp uint gl_NumSubgroups;"
|
"in highp uint gl_NumSubgroups;"
|
||||||
"in highp uint gl_SubgroupID;"
|
"in highp uint gl_SubgroupID;"
|
||||||
"\n";
|
"\n";
|
||||||
|
// These builtins are volatile for RT stages
|
||||||
|
const char* rtSubgroupDecls =
|
||||||
|
"in mediump volatile uint gl_SubgroupSize;"
|
||||||
|
"in mediump volatile uint gl_SubgroupInvocationID;"
|
||||||
|
"in highp volatile uvec4 gl_SubgroupEqMask;"
|
||||||
|
"in highp volatile uvec4 gl_SubgroupGeMask;"
|
||||||
|
"in highp volatile uvec4 gl_SubgroupGtMask;"
|
||||||
|
"in highp volatile uvec4 gl_SubgroupLeMask;"
|
||||||
|
"in highp volatile uvec4 gl_SubgroupLtMask;"
|
||||||
|
// GL_NV_shader_sm_builtins
|
||||||
|
"in highp uint gl_WarpsPerSMNV;"
|
||||||
|
"in highp uint gl_SMCountNV;"
|
||||||
|
"in highp volatile uint gl_WarpIDNV;"
|
||||||
|
"in highp volatile uint gl_SMIDNV;"
|
||||||
|
"\n";
|
||||||
|
|
||||||
stageBuiltins[EShLangVertex] .append(subgroupDecls);
|
stageBuiltins[EShLangVertex] .append(subgroupDecls);
|
||||||
stageBuiltins[EShLangTessControl] .append(subgroupDecls);
|
stageBuiltins[EShLangTessControl] .append(subgroupDecls);
|
||||||
@@ -5507,12 +5601,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
stageBuiltins[EShLangMeshNV] .append(computeSubgroupDecls);
|
stageBuiltins[EShLangMeshNV] .append(computeSubgroupDecls);
|
||||||
stageBuiltins[EShLangTaskNV] .append(subgroupDecls);
|
stageBuiltins[EShLangTaskNV] .append(subgroupDecls);
|
||||||
stageBuiltins[EShLangTaskNV] .append(computeSubgroupDecls);
|
stageBuiltins[EShLangTaskNV] .append(computeSubgroupDecls);
|
||||||
stageBuiltins[EShLangRayGen] .append(subgroupDecls);
|
stageBuiltins[EShLangRayGen] .append(rtSubgroupDecls);
|
||||||
stageBuiltins[EShLangIntersect] .append(subgroupDecls);
|
stageBuiltins[EShLangIntersect] .append(rtSubgroupDecls);
|
||||||
|
// No volatile qualifier on these builtins in any-hit
|
||||||
stageBuiltins[EShLangAnyHit] .append(subgroupDecls);
|
stageBuiltins[EShLangAnyHit] .append(subgroupDecls);
|
||||||
stageBuiltins[EShLangClosestHit] .append(subgroupDecls);
|
stageBuiltins[EShLangClosestHit] .append(rtSubgroupDecls);
|
||||||
stageBuiltins[EShLangMiss] .append(subgroupDecls);
|
stageBuiltins[EShLangMiss] .append(rtSubgroupDecls);
|
||||||
stageBuiltins[EShLangCallable] .append(subgroupDecls);
|
stageBuiltins[EShLangCallable] .append(rtSubgroupDecls);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_NV_ray_tracing/GL_EXT_ray_tracing
|
// GL_NV_ray_tracing/GL_EXT_ray_tracing
|
||||||
@@ -5580,7 +5675,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"in float gl_RayTminNV;"
|
"in float gl_RayTminNV;"
|
||||||
"in float gl_RayTminEXT;"
|
"in float gl_RayTminEXT;"
|
||||||
"in float gl_RayTmaxNV;"
|
"in float gl_RayTmaxNV;"
|
||||||
"in float gl_RayTmaxEXT;"
|
"in volatile float gl_RayTmaxEXT;"
|
||||||
"in mat4x3 gl_ObjectToWorldNV;"
|
"in mat4x3 gl_ObjectToWorldNV;"
|
||||||
"in mat4x3 gl_ObjectToWorldEXT;"
|
"in mat4x3 gl_ObjectToWorldEXT;"
|
||||||
"in mat3x4 gl_ObjectToWorld3x4EXT;"
|
"in mat3x4 gl_ObjectToWorld3x4EXT;"
|
||||||
@@ -5700,13 +5795,57 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
commonBuiltins.append("const int gl_StorageSemanticsOutput = 0x1000;\n");
|
commonBuiltins.append("const int gl_StorageSemanticsOutput = 0x1000;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !GLSLANG_ANGLE
|
// Adding these to common built-ins triggers an assert due to a memory corruption in related code when testing
|
||||||
|
// So instead add to each stage individually, avoiding the GLSLang bug
|
||||||
if (version >= 300 /* both ES and non-ES */) {
|
if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) {
|
||||||
stageBuiltins[EShLangFragment].append(
|
for (int stage=EShLangVertex; stage<EShLangCount; stage++)
|
||||||
"flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2
|
{
|
||||||
"\n");
|
stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag2VerticalPixelsEXT = 1;\n");
|
||||||
|
stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag4VerticalPixelsEXT = 2;\n");
|
||||||
|
stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag2HorizontalPixelsEXT = 4;\n");
|
||||||
|
stageBuiltins[static_cast<EShLanguage>(stage)].append("const highp int gl_ShadingRateFlag4HorizontalPixelsEXT = 8;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GL_EXT_shader_image_int64
|
||||||
|
if ((profile != EEsProfile && version >= 420) ||
|
||||||
|
(profile == EEsProfile && version >= 310)) {
|
||||||
|
|
||||||
|
const TBasicType bTypes[] = { EbtInt64, EbtUint64 };
|
||||||
|
for (int ms = 0; ms <= 1; ++ms) { // loop over "bool" multisample or not
|
||||||
|
for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not
|
||||||
|
for (int dim = Esd1D; dim < EsdSubpass; ++dim) { // 1D, ..., buffer
|
||||||
|
if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((dim == Esd3D || dim == EsdRect || dim == EsdBuffer) && arrayed)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (dim != Esd2D && ms)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Loop over the bTypes
|
||||||
|
for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) {
|
||||||
|
//
|
||||||
|
// Now, make all the function prototypes for the type we just built...
|
||||||
|
//
|
||||||
|
TSampler sampler;
|
||||||
|
|
||||||
|
sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false,
|
||||||
|
false,
|
||||||
|
ms ? true : false);
|
||||||
|
|
||||||
|
TString typeName = sampler.getString();
|
||||||
|
|
||||||
|
addQueryFunctions(sampler, typeName, version, profile);
|
||||||
|
addImageFunctions(sampler, typeName, version, profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // !GLSLANG_ANGLE
|
||||||
|
|
||||||
#endif // !GLSLANG_WEB
|
#endif // !GLSLANG_WEB
|
||||||
|
|
||||||
// printf("%s\n", commonBuiltins.c_str());
|
// printf("%s\n", commonBuiltins.c_str());
|
||||||
@@ -5803,7 +5942,6 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
|
|||||||
#endif
|
#endif
|
||||||
if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint))
|
if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now, make all the function prototypes for the type we just built...
|
// Now, make all the function prototypes for the type we just built...
|
||||||
//
|
//
|
||||||
@@ -6028,8 +6166,16 @@ void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int
|
|||||||
|
|
||||||
if ( profile != EEsProfile ||
|
if ( profile != EEsProfile ||
|
||||||
(profile == EEsProfile && version >= 310)) {
|
(profile == EEsProfile && version >= 310)) {
|
||||||
if (sampler.type == EbtInt || sampler.type == EbtUint) {
|
if (sampler.type == EbtInt || sampler.type == EbtUint || sampler.type == EbtInt64 || sampler.type == EbtUint64 ) {
|
||||||
const char* dataType = sampler.type == EbtInt ? "highp int" : "highp uint";
|
|
||||||
|
const char* dataType;
|
||||||
|
switch (sampler.type) {
|
||||||
|
case(EbtInt): dataType = "highp int"; break;
|
||||||
|
case(EbtUint): dataType = "highp uint"; break;
|
||||||
|
case(EbtInt64): dataType = "highp int64_t"; break;
|
||||||
|
case(EbtUint64): dataType = "highp uint64_t"; break;
|
||||||
|
default: dataType = "";
|
||||||
|
}
|
||||||
|
|
||||||
const int numBuiltins = 7;
|
const int numBuiltins = 7;
|
||||||
|
|
||||||
@@ -6444,7 +6590,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName,
|
|||||||
s.append(");\n");
|
s.append(");\n");
|
||||||
|
|
||||||
// Add to the per-language set of built-ins
|
// Add to the per-language set of built-ins
|
||||||
if (bias || lodClamp != 0) {
|
if (!grad && (bias || lodClamp != 0)) {
|
||||||
stageBuiltins[EShLangFragment].append(s);
|
stageBuiltins[EShLangFragment].append(s);
|
||||||
stageBuiltins[EShLangCompute].append(s);
|
stageBuiltins[EShLangCompute].append(s);
|
||||||
} else
|
} else
|
||||||
@@ -7342,6 +7488,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
|
SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
|
||||||
|
// treat these built-ins as aliases of VertexIndex and InstanceIndex
|
||||||
|
BuiltInVariable("gl_VertexID", EbvVertexIndex, symbolTable);
|
||||||
|
BuiltInVariable("gl_InstanceID", EbvInstanceIndex, symbolTable);
|
||||||
|
}
|
||||||
|
|
||||||
if (profile != EEsProfile) {
|
if (profile != EEsProfile) {
|
||||||
if (version >= 440) {
|
if (version >= 440) {
|
||||||
symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters);
|
symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters);
|
||||||
@@ -7665,6 +7817,20 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
||||||
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (language == EShLangGeometry || language == EShLangVertex) {
|
||||||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
|
(profile != EEsProfile && version >= 450)) {
|
||||||
|
symbolTable.setVariableExtensions("gl_PrimitiveShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
BuiltInVariable("gl_PrimitiveShadingRateEXT", EbvPrimitiveShadingRateKHR, symbolTable);
|
||||||
|
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !GLSLANG_WEB
|
#endif // !GLSLANG_WEB
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -8192,6 +8358,17 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
}
|
}
|
||||||
|
|
||||||
symbolTable.setFunctionExtensions("helperInvocationEXT", 1, &E_GL_EXT_demote_to_helper_invocation);
|
symbolTable.setFunctionExtensions("helperInvocationEXT", 1, &E_GL_EXT_demote_to_helper_invocation);
|
||||||
|
|
||||||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
|
(profile != EEsProfile && version >= 450)) {
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
BuiltInVariable("gl_ShadingRateEXT", EbvShadingRateKHR, symbolTable);
|
||||||
|
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
}
|
||||||
#endif // !GLSLANG_WEB
|
#endif // !GLSLANG_WEB
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -8324,6 +8501,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_NV_compute_shader_derivatives);
|
symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_NV_compute_shader_derivatives);
|
||||||
symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_NV_compute_shader_derivatives);
|
symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_NV_compute_shader_derivatives);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
|
(profile != EEsProfile && version >= 450)) {
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
}
|
||||||
#endif // !GLSLANG_WEB
|
#endif // !GLSLANG_WEB
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -8378,9 +8563,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing);
|
symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing);
|
||||||
symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
|
symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
|
||||||
symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing);
|
symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing);
|
||||||
symbolTable.setFunctionExtensions("ignoreIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
|
|
||||||
symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing);
|
symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing);
|
||||||
symbolTable.setFunctionExtensions("terminateRayEXT", 1, &E_GL_EXT_ray_tracing);
|
|
||||||
symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing);
|
symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing);
|
||||||
symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing);
|
symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing);
|
||||||
|
|
||||||
@@ -8473,6 +8656,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
||||||
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
||||||
}
|
}
|
||||||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
|
(profile != EEsProfile && version >= 450)) {
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangMeshNV:
|
case EShLangMeshNV:
|
||||||
@@ -8617,6 +8807,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
||||||
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
|
(profile != EEsProfile && version >= 450)) {
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangTaskNV:
|
case EShLangTaskNV:
|
||||||
@@ -8717,6 +8915,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable);
|
||||||
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable);
|
||||||
}
|
}
|
||||||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
|
(profile != EEsProfile && version >= 450)) {
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -8786,6 +8991,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
|
symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter);
|
||||||
symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage);
|
symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage);
|
||||||
|
|
||||||
|
if (spvVersion.vulkanRelaxed) {
|
||||||
|
//
|
||||||
|
// functions signature have been replaced to take uint operations on buffer variables
|
||||||
|
// remap atomic counter functions to atomic operations
|
||||||
|
//
|
||||||
|
symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
symbolTable.relateToOperator("atomicLoad", EOpAtomicLoad);
|
symbolTable.relateToOperator("atomicLoad", EOpAtomicLoad);
|
||||||
symbolTable.relateToOperator("atomicStore", EOpAtomicStore);
|
symbolTable.relateToOperator("atomicStore", EOpAtomicStore);
|
||||||
|
|
||||||
@@ -8793,6 +9006,20 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
|
symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement);
|
||||||
symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter);
|
symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter);
|
||||||
|
|
||||||
|
if (spvVersion.vulkanRelaxed) {
|
||||||
|
//
|
||||||
|
// functions signature have been replaced to take uint operations
|
||||||
|
// remap atomic counter functions to atomic operations
|
||||||
|
//
|
||||||
|
// these atomic counter functions do not match signatures of glsl
|
||||||
|
// atomic functions, so they will be remapped to semantically
|
||||||
|
// equivalent functions in the parser
|
||||||
|
//
|
||||||
|
symbolTable.relateToOperator("atomicCounterIncrement", EOpNull);
|
||||||
|
symbolTable.relateToOperator("atomicCounterDecrement", EOpNull);
|
||||||
|
symbolTable.relateToOperator("atomicCounter", EOpNull);
|
||||||
|
}
|
||||||
|
|
||||||
symbolTable.relateToOperator("clockARB", EOpReadClockSubgroupKHR);
|
symbolTable.relateToOperator("clockARB", EOpReadClockSubgroupKHR);
|
||||||
symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR);
|
symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR);
|
||||||
|
|
||||||
@@ -8811,6 +9038,23 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
|
symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spvVersion.vulkanRelaxed) {
|
||||||
|
//
|
||||||
|
// functions signature have been replaced to take 'uint' instead of 'atomic_uint'
|
||||||
|
// remap atomic counter functions to non-counter atomic ops so
|
||||||
|
// functions act as aliases to non-counter atomic ops
|
||||||
|
//
|
||||||
|
symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicAdd);
|
||||||
|
symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicSubtract);
|
||||||
|
symbolTable.relateToOperator("atomicCounterMin", EOpAtomicMin);
|
||||||
|
symbolTable.relateToOperator("atomicCounterMax", EOpAtomicMax);
|
||||||
|
symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicAnd);
|
||||||
|
symbolTable.relateToOperator("atomicCounterOr", EOpAtomicOr);
|
||||||
|
symbolTable.relateToOperator("atomicCounterXor", EOpAtomicXor);
|
||||||
|
symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicExchange);
|
||||||
|
symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCompSwap);
|
||||||
|
}
|
||||||
|
|
||||||
symbolTable.relateToOperator("fma", EOpFma);
|
symbolTable.relateToOperator("fma", EOpFma);
|
||||||
symbolTable.relateToOperator("frexp", EOpFrexp);
|
symbolTable.relateToOperator("frexp", EOpFrexp);
|
||||||
symbolTable.relateToOperator("ldexp", EOpLdexp);
|
symbolTable.relateToOperator("ldexp", EOpLdexp);
|
||||||
@@ -9197,10 +9441,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
case EShLangClosestHit:
|
case EShLangClosestHit:
|
||||||
case EShLangMiss:
|
case EShLangMiss:
|
||||||
if (profile != EEsProfile && version >= 460) {
|
if (profile != EEsProfile && version >= 460) {
|
||||||
symbolTable.relateToOperator("traceNV", EOpTrace);
|
symbolTable.relateToOperator("traceNV", EOpTraceNV);
|
||||||
symbolTable.relateToOperator("traceRayEXT", EOpTrace);
|
symbolTable.relateToOperator("traceRayEXT", EOpTraceKHR);
|
||||||
symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable);
|
symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
|
||||||
symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable);
|
symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EShLangIntersect:
|
case EShLangIntersect:
|
||||||
@@ -9211,16 +9455,14 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
break;
|
break;
|
||||||
case EShLangAnyHit:
|
case EShLangAnyHit:
|
||||||
if (profile != EEsProfile && version >= 460) {
|
if (profile != EEsProfile && version >= 460) {
|
||||||
symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersection);
|
symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV);
|
||||||
symbolTable.relateToOperator("ignoreIntersectionEXT", EOpIgnoreIntersection);
|
symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV);
|
||||||
symbolTable.relateToOperator("terminateRayNV", EOpTerminateRay);
|
|
||||||
symbolTable.relateToOperator("terminateRayEXT", EOpTerminateRay);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EShLangCallable:
|
case EShLangCallable:
|
||||||
if (profile != EEsProfile && version >= 460) {
|
if (profile != EEsProfile && version >= 460) {
|
||||||
symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable);
|
symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
|
||||||
symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable);
|
symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EShLangMeshNV:
|
case EShLangMeshNV:
|
||||||
|
|||||||
@@ -71,6 +71,13 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
|
|||||||
it->visitConstantUnion(this);
|
it->visitConstantUnion(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TString& TIntermSymbol::getAccessName() const {
|
||||||
|
if (getBasicType() == EbtBlock)
|
||||||
|
return getType().getTypeName();
|
||||||
|
else
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse a binary node.
|
// Traverse a binary node.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace glslang {
|
|||||||
// Returns the added node.
|
// Returns the added node.
|
||||||
//
|
//
|
||||||
|
|
||||||
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray,
|
TIntermSymbol* TIntermediate::addSymbol(long long id, const TString& name, const TType& type, const TConstUnionArray& constArray,
|
||||||
TIntermTyped* constSubtree, const TSourceLoc& loc)
|
TIntermTyped* constSubtree, const TSourceLoc& loc)
|
||||||
{
|
{
|
||||||
TIntermSymbol* node = new TIntermSymbol(id, name, type);
|
TIntermSymbol* node = new TIntermSymbol(id, name, type);
|
||||||
@@ -2298,6 +2298,10 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
|
|||||||
case EbtReference:
|
case EbtReference:
|
||||||
op = EOpConstructReference;
|
op = EOpConstructReference;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EbtAccStruct:
|
||||||
|
op = EOpConstructAccStruct;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -2866,7 +2870,7 @@ void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& calle
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callGraph.push_front(TCall(caller, callee));
|
callGraph.emplace_front(caller, callee);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -3772,11 +3776,16 @@ void TIntermBinary::updatePrecision()
|
|||||||
{
|
{
|
||||||
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
|
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
|
||||||
getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
|
getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
|
||||||
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
|
if (op == EOpRightShift || op == EOpLeftShift) {
|
||||||
if (getQualifier().precision != EpqNone) {
|
// For shifts get precision from left side only and thus no need to propagate
|
||||||
left->propagatePrecision(getQualifier().precision);
|
getQualifier().precision = left->getQualifier().precision;
|
||||||
right->propagatePrecision(getQualifier().precision);
|
} else {
|
||||||
}
|
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
|
||||||
|
if (getQualifier().precision != EpqNone) {
|
||||||
|
left->propagatePrecision(getQualifier().precision);
|
||||||
|
right->propagatePrecision(getQualifier().precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,22 +127,6 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
|
|||||||
{
|
{
|
||||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||||
|
|
||||||
if (binaryNode) {
|
|
||||||
switch(binaryNode->getOp()) {
|
|
||||||
case EOpIndexDirect:
|
|
||||||
case EOpIndexIndirect: // fall through
|
|
||||||
case EOpIndexDirectStruct: // fall through
|
|
||||||
case EOpVectorSwizzle:
|
|
||||||
case EOpMatrixSwizzle:
|
|
||||||
return lValueErrorCheck(loc, op, binaryNode->getLeft());
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
error(loc, " l-value required", op, "", "");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* symbol = nullptr;
|
const char* symbol = nullptr;
|
||||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||||
if (symNode != nullptr)
|
if (symNode != nullptr)
|
||||||
@@ -203,15 +187,40 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
|
|||||||
// Everything else is okay, no error.
|
// Everything else is okay, no error.
|
||||||
//
|
//
|
||||||
if (message == nullptr)
|
if (message == nullptr)
|
||||||
|
{
|
||||||
|
if (binaryNode) {
|
||||||
|
switch (binaryNode->getOp()) {
|
||||||
|
case EOpIndexDirect:
|
||||||
|
case EOpIndexIndirect: // fall through
|
||||||
|
case EOpIndexDirectStruct: // fall through
|
||||||
|
case EOpVectorSwizzle:
|
||||||
|
case EOpMatrixSwizzle:
|
||||||
|
return lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
error(loc, " l-value required", op, "", "");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we get here, we have an error and a message.
|
// If we get here, we have an error and a message.
|
||||||
//
|
//
|
||||||
|
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
|
||||||
|
|
||||||
if (symNode)
|
if (symNode)
|
||||||
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
|
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
|
||||||
else
|
else
|
||||||
error(loc, " l-value required", op, "(%s)", message);
|
if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct)
|
||||||
|
if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
|
||||||
|
error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message);
|
||||||
|
else
|
||||||
|
error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message);
|
||||||
|
else
|
||||||
|
error(loc, " l-value required", op, "(%s)", message);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -219,28 +228,41 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
|
|||||||
// Test for and give an error if the node can't be read from.
|
// Test for and give an error if the node can't be read from.
|
||||||
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||||
{
|
{
|
||||||
|
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||||
|
const TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||||
|
|
||||||
if (! node)
|
if (! node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
if (node->getQualifier().isWriteOnly()) {
|
||||||
if (binaryNode) {
|
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
|
||||||
switch(binaryNode->getOp()) {
|
|
||||||
case EOpIndexDirect:
|
if (symNode != nullptr)
|
||||||
case EOpIndexIndirect:
|
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
|
||||||
case EOpIndexDirectStruct:
|
else if (binaryNode &&
|
||||||
case EOpVectorSwizzle:
|
(binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
|
||||||
case EOpMatrixSwizzle:
|
binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
|
||||||
rValueErrorCheck(loc, op, binaryNode->getLeft());
|
if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
|
||||||
default:
|
error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
|
||||||
break;
|
else
|
||||||
|
error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str());
|
||||||
|
else
|
||||||
|
error(loc, "can't read from writeonly object: ", op, "");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (binaryNode) {
|
||||||
|
switch (binaryNode->getOp()) {
|
||||||
|
case EOpIndexDirect:
|
||||||
|
case EOpIndexIndirect:
|
||||||
|
case EOpIndexDirectStruct:
|
||||||
|
case EOpVectorSwizzle:
|
||||||
|
case EOpMatrixSwizzle:
|
||||||
|
rValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
|
||||||
if (symNode && symNode->getQualifier().isWriteOnly())
|
|
||||||
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add 'symbol' to the list of deferred linkage symbols, which
|
// Add 'symbol' to the list of deferred linkage symbols, which
|
||||||
@@ -579,7 +601,6 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
|
|||||||
selector.push_back(0);
|
selector.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_HLSL
|
|
||||||
//
|
//
|
||||||
// Make the passed-in variable information become a member of the
|
// Make the passed-in variable information become a member of the
|
||||||
// global uniform block. If this doesn't exist yet, make it.
|
// global uniform block. If this doesn't exist yet, make it.
|
||||||
@@ -624,7 +645,67 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
|
|||||||
|
|
||||||
++firstNewMember;
|
++firstNewMember;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) {
|
||||||
|
// Make the atomic counter block, if not yet made.
|
||||||
|
const auto &at = atomicCounterBuffers.find(binding);
|
||||||
|
if (at == atomicCounterBuffers.end()) {
|
||||||
|
atomicCounterBuffers.insert({binding, (TVariable*)nullptr });
|
||||||
|
atomicCounterBlockFirstNewMember.insert({binding, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding];
|
||||||
|
int& bufferNewMember = atomicCounterBlockFirstNewMember[binding];
|
||||||
|
|
||||||
|
if (atomicCounterBuffer == nullptr) {
|
||||||
|
TQualifier blockQualifier;
|
||||||
|
blockQualifier.clear();
|
||||||
|
blockQualifier.storage = EvqBuffer;
|
||||||
|
|
||||||
|
char charBuffer[512];
|
||||||
|
if (binding != TQualifier::layoutBindingEnd) {
|
||||||
|
snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding);
|
||||||
|
} else {
|
||||||
|
snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName());
|
||||||
|
}
|
||||||
|
|
||||||
|
TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier);
|
||||||
|
setUniformBlockDefaults(blockType);
|
||||||
|
blockType.getQualifier().layoutPacking = ElpStd430;
|
||||||
|
atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true);
|
||||||
|
// If we arn't auto mapping bindings then set the block to use the same
|
||||||
|
// binding as what the atomic was set to use
|
||||||
|
if (!intermediate.getAutoMapBindings()) {
|
||||||
|
atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding;
|
||||||
|
}
|
||||||
|
bufferNewMember = 0;
|
||||||
|
|
||||||
|
atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the requested member as a member to the global block.
|
||||||
|
TType* type = new TType;
|
||||||
|
type->shallowCopy(memberType);
|
||||||
|
type->setFieldName(memberName);
|
||||||
|
if (typeList)
|
||||||
|
type->setStruct(typeList);
|
||||||
|
TTypeLoc typeLoc = {type, loc};
|
||||||
|
atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc);
|
||||||
|
|
||||||
|
// Insert into the symbol table.
|
||||||
|
if (bufferNewMember == 0) {
|
||||||
|
// This is the first request; we need a normal symbol table insert
|
||||||
|
if (symbolTable.insert(*atomicCounterBuffer))
|
||||||
|
trackLinkage(*atomicCounterBuffer);
|
||||||
|
else
|
||||||
|
error(loc, "failed to insert the global constant buffer", "buffer", "");
|
||||||
|
} else {
|
||||||
|
// This is a follow-on request; we need to amend the first insert
|
||||||
|
symbolTable.amend(*atomicCounterBuffer, bufferNewMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
++bufferNewMember;
|
||||||
|
}
|
||||||
|
|
||||||
void TParseContextBase::finish()
|
void TParseContextBase::finish()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,6 +87,10 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
|
|||||||
globalInputDefaults.clear();
|
globalInputDefaults.clear();
|
||||||
globalOutputDefaults.clear();
|
globalOutputDefaults.clear();
|
||||||
|
|
||||||
|
globalSharedDefaults.clear();
|
||||||
|
globalSharedDefaults.layoutMatrix = ElmColumnMajor;
|
||||||
|
globalSharedDefaults.layoutPacking = ElpStd430;
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
// "Shaders in the transform
|
// "Shaders in the transform
|
||||||
// feedback capturing mode have an initial global default of
|
// feedback capturing mode have an initial global default of
|
||||||
@@ -221,6 +225,108 @@ void TParseContext::parserError(const char* s)
|
|||||||
error(getCurrentLoc(), "compilation terminated", "", "");
|
error(getCurrentLoc(), "compilation terminated", "", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
|
||||||
|
{
|
||||||
|
bool createBlock = globalUniformBlock == nullptr;
|
||||||
|
|
||||||
|
if (createBlock) {
|
||||||
|
globalUniformBinding = intermediate.getGlobalUniformBinding();
|
||||||
|
globalUniformSet = intermediate.getGlobalUniformSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
// use base class function to create/expand block
|
||||||
|
TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, typeList);
|
||||||
|
|
||||||
|
if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
|
||||||
|
// check for a block storage override
|
||||||
|
TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getGlobalUniformBlockName());
|
||||||
|
TQualifier& qualifier = globalUniformBlock->getWritableType().getQualifier();
|
||||||
|
qualifier.defaultBlock = true;
|
||||||
|
|
||||||
|
if (storageOverride != EbsNone) {
|
||||||
|
if (createBlock) {
|
||||||
|
// Remap block storage
|
||||||
|
qualifier.setBlockStorage(storageOverride);
|
||||||
|
|
||||||
|
// check that the change didn't create errors
|
||||||
|
blockQualifierCheck(loc, qualifier, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remap meber storage as well
|
||||||
|
memberType.getQualifier().setBlockStorage(storageOverride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TParseContext::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
|
||||||
|
{
|
||||||
|
bool createBlock = atomicCounterBuffers.find(binding) == atomicCounterBuffers.end();
|
||||||
|
|
||||||
|
if (createBlock) {
|
||||||
|
atomicCounterBlockSet = intermediate.getAtomicCounterBlockSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
// use base class function to create/expand block
|
||||||
|
TParseContextBase::growAtomicCounterBlock(binding, loc, memberType, memberName, typeList);
|
||||||
|
TQualifier& qualifier = atomicCounterBuffers[binding]->getWritableType().getQualifier();
|
||||||
|
qualifier.defaultBlock = true;
|
||||||
|
|
||||||
|
if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
|
||||||
|
// check for a Block storage override
|
||||||
|
TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getAtomicCounterBlockName());
|
||||||
|
|
||||||
|
if (storageOverride != EbsNone) {
|
||||||
|
if (createBlock) {
|
||||||
|
// Remap block storage
|
||||||
|
|
||||||
|
qualifier.setBlockStorage(storageOverride);
|
||||||
|
|
||||||
|
// check that the change didn't create errors
|
||||||
|
blockQualifierCheck(loc, qualifier, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remap meber storage as well
|
||||||
|
memberType.getQualifier().setBlockStorage(storageOverride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* TParseContext::getGlobalUniformBlockName() const
|
||||||
|
{
|
||||||
|
const char* name = intermediate.getGlobalUniformBlockName();
|
||||||
|
if (std::string(name) == "")
|
||||||
|
return "gl_DefaultUniformBlock";
|
||||||
|
else
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
void TParseContext::finalizeGlobalUniformBlockLayout(TVariable&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void TParseContext::setUniformBlockDefaults(TType& block) const
|
||||||
|
{
|
||||||
|
block.getQualifier().layoutPacking = ElpStd140;
|
||||||
|
block.getQualifier().layoutMatrix = ElmColumnMajor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* TParseContext::getAtomicCounterBlockName() const
|
||||||
|
{
|
||||||
|
const char* name = intermediate.getAtomicCounterBlockName();
|
||||||
|
if (std::string(name) == "")
|
||||||
|
return "gl_AtomicCounterBlock";
|
||||||
|
else
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
void TParseContext::finalizeAtomicCounterBlockLayout(TVariable&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TParseContext::setAtomicCounterBlockDefaults(TType& block) const
|
||||||
|
{
|
||||||
|
block.getQualifier().layoutPacking = ElpStd430;
|
||||||
|
block.getQualifier().layoutMatrix = ElmRowMajor;
|
||||||
|
}
|
||||||
|
|
||||||
void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
|
void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>& tokens)
|
||||||
{
|
{
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
@@ -1131,6 +1237,14 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
|
|||||||
{
|
{
|
||||||
TIntermTyped* result = nullptr;
|
TIntermTyped* result = nullptr;
|
||||||
|
|
||||||
|
if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) {
|
||||||
|
// allow calls that are invalid in Vulkan Semantics to be invisibily
|
||||||
|
// remapped to equivalent valid functions
|
||||||
|
result = vkRelaxedRemapFunctionCall(loc, function, arguments);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (function->getBuiltInOp() == EOpArrayLength)
|
if (function->getBuiltInOp() == EOpArrayLength)
|
||||||
result = handleLengthMethod(loc, function, arguments);
|
result = handleLengthMethod(loc, function, arguments);
|
||||||
else if (function->getBuiltInOp() != EOpNull) {
|
else if (function->getBuiltInOp() != EOpNull) {
|
||||||
@@ -1723,6 +1837,7 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
|
|||||||
// Grab the semantics and storage class semantics from the operands, based on opcode
|
// Grab the semantics and storage class semantics from the operands, based on opcode
|
||||||
switch (callNode.getOp()) {
|
switch (callNode.getOp()) {
|
||||||
case EOpAtomicAdd:
|
case EOpAtomicAdd:
|
||||||
|
case EOpAtomicSubtract:
|
||||||
case EOpAtomicMin:
|
case EOpAtomicMin:
|
||||||
case EOpAtomicMax:
|
case EOpAtomicMax:
|
||||||
case EOpAtomicAnd:
|
case EOpAtomicAnd:
|
||||||
@@ -2076,14 +2191,32 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
case EOpTrace:
|
case EOpTraceNV:
|
||||||
if (!(*argp)[10]->getAsConstantUnion())
|
if (!(*argp)[10]->getAsConstantUnion())
|
||||||
error(loc, "argument must be compile-time constant", "payload number", "");
|
error(loc, "argument must be compile-time constant", "payload number", "a");
|
||||||
break;
|
break;
|
||||||
case EOpExecuteCallable:
|
case EOpTraceKHR:
|
||||||
|
if (!(*argp)[10]->getAsConstantUnion())
|
||||||
|
error(loc, "argument must be compile-time constant", "payload number", "a");
|
||||||
|
else {
|
||||||
|
unsigned int location = (*argp)[10]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst();
|
||||||
|
if (intermediate.checkLocationRT(0, location) < 0)
|
||||||
|
error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EOpExecuteCallableNV:
|
||||||
if (!(*argp)[1]->getAsConstantUnion())
|
if (!(*argp)[1]->getAsConstantUnion())
|
||||||
error(loc, "argument must be compile-time constant", "callable data number", "");
|
error(loc, "argument must be compile-time constant", "callable data number", "");
|
||||||
break;
|
break;
|
||||||
|
case EOpExecuteCallableKHR:
|
||||||
|
if (!(*argp)[1]->getAsConstantUnion())
|
||||||
|
error(loc, "argument must be compile-time constant", "callable data number", "");
|
||||||
|
else {
|
||||||
|
unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst();
|
||||||
|
if (intermediate.checkLocationRT(1, location) < 0)
|
||||||
|
error(loc, "with layout(location =", "no callableDataEXT/callableDataInEXT declared", "%d)", location);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case EOpRayQueryGetIntersectionType:
|
case EOpRayQueryGetIntersectionType:
|
||||||
case EOpRayQueryGetIntersectionT:
|
case EOpRayQueryGetIntersectionT:
|
||||||
@@ -2121,9 +2254,15 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
|||||||
{
|
{
|
||||||
// Make sure the image types have the correct layout() format and correct argument types
|
// Make sure the image types have the correct layout() format and correct argument types
|
||||||
const TType& imageType = arg0->getType();
|
const TType& imageType = arg0->getType();
|
||||||
if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
|
if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint ||
|
||||||
if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
|
imageType.getSampler().type == EbtInt64 || imageType.getSampler().type == EbtUint64) {
|
||||||
|
if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui &&
|
||||||
|
imageType.getQualifier().getFormat() != ElfR64i && imageType.getQualifier().getFormat() != ElfR64ui)
|
||||||
error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
|
error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
|
||||||
|
if (callNode.getType().getBasicType() == EbtInt64 && imageType.getQualifier().getFormat() != ElfR64i)
|
||||||
|
error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), "");
|
||||||
|
else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui)
|
||||||
|
error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), "");
|
||||||
} else {
|
} else {
|
||||||
bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
|
bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
|
||||||
(fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
|
(fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
|
||||||
@@ -2148,6 +2287,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
|||||||
}
|
}
|
||||||
|
|
||||||
case EOpAtomicAdd:
|
case EOpAtomicAdd:
|
||||||
|
case EOpAtomicSubtract:
|
||||||
case EOpAtomicMin:
|
case EOpAtomicMin:
|
||||||
case EOpAtomicMax:
|
case EOpAtomicMax:
|
||||||
case EOpAtomicAnd:
|
case EOpAtomicAnd:
|
||||||
@@ -2728,6 +2868,11 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||||||
if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks
|
if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks
|
||||||
if (symNode && symNode->getQualifier().isExplicitInterpolation())
|
if (symNode && symNode->getQualifier().isExplicitInterpolation())
|
||||||
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
|
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
|
||||||
|
|
||||||
|
// local_size_{xyz} must be assigned or specialized before gl_WorkGroupSize can be assigned.
|
||||||
|
if(node->getQualifier().builtIn == EbvWorkGroupSize &&
|
||||||
|
!(intermediate.isLocalSizeSet() || intermediate.isLocalSizeSpecialized()))
|
||||||
|
error(loc, "can't read from gl_WorkGroupSize before a fixed workgroup size has been declared", op, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -3355,7 +3500,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
|
|||||||
|
|
||||||
if (type.containsNonOpaque()) {
|
if (type.containsNonOpaque()) {
|
||||||
// Vulkan doesn't allow transparent uniforms outside of blocks
|
// Vulkan doesn't allow transparent uniforms outside of blocks
|
||||||
if (spvVersion.vulkan > 0)
|
if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
|
||||||
vulkanRemoved(loc, "non-opaque uniforms outside a block");
|
vulkanRemoved(loc, "non-opaque uniforms outside a block");
|
||||||
// OpenGL wants locations on these (unless they are getting automapped)
|
// OpenGL wants locations on these (unless they are getting automapped)
|
||||||
if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
|
if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations())
|
||||||
@@ -3368,7 +3513,7 @@ void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& t
|
|||||||
//
|
//
|
||||||
void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
|
void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
|
||||||
{
|
{
|
||||||
globalQualifierFixCheck(publicType.loc, publicType.qualifier);
|
globalQualifierFixCheck(publicType.loc, publicType.qualifier, true);
|
||||||
checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
|
checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers);
|
||||||
if (publicType.qualifier.isNonUniform()) {
|
if (publicType.qualifier.isNonUniform()) {
|
||||||
error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
|
error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", "");
|
||||||
@@ -3379,7 +3524,7 @@ void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType)
|
|||||||
//
|
//
|
||||||
// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
|
// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
|
||||||
//
|
//
|
||||||
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier)
|
void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck)
|
||||||
{
|
{
|
||||||
bool nonuniformOkay = false;
|
bool nonuniformOkay = false;
|
||||||
|
|
||||||
@@ -3404,6 +3549,16 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
|
|||||||
case EvqTemporary:
|
case EvqTemporary:
|
||||||
nonuniformOkay = true;
|
nonuniformOkay = true;
|
||||||
break;
|
break;
|
||||||
|
case EvqUniform:
|
||||||
|
// According to GLSL spec: The std430 qualifier is supported only for shader storage blocks; a shader using
|
||||||
|
// the std430 qualifier on a uniform block will fail to compile.
|
||||||
|
// Only check the global declaration: layout(std430) uniform;
|
||||||
|
if (blockName == nullptr &&
|
||||||
|
qualifier.layoutPacking == ElpStd430)
|
||||||
|
{
|
||||||
|
error(loc, "it is invalid to declare std430 qualifier on uniform", "", "");
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3411,7 +3566,9 @@ void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& q
|
|||||||
if (!nonuniformOkay && qualifier.isNonUniform())
|
if (!nonuniformOkay && qualifier.isNonUniform())
|
||||||
error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
|
error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", "");
|
||||||
|
|
||||||
invariantCheck(loc, qualifier);
|
// Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it.
|
||||||
|
if (!isMemberCheck || structNestingLevel > 0)
|
||||||
|
invariantCheck(loc, qualifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -3422,7 +3579,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
|
|||||||
if (! symbolTable.atGlobalLevel())
|
if (! symbolTable.atGlobalLevel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(publicType.userDef && publicType.userDef->isReference())) {
|
if (!(publicType.userDef && publicType.userDef->isReference()) && !parsingBuiltins) {
|
||||||
if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
|
if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
|
||||||
error(loc, "memory qualifiers cannot be used on this type", "", "");
|
error(loc, "memory qualifiers cannot be used on this type", "", "");
|
||||||
} else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
|
} else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
|
||||||
@@ -4083,6 +4240,9 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType
|
|||||||
if (isRuntimeLength(base))
|
if (isRuntimeLength(base))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (base.getType().getQualifier().builtIn == EbvSampleMask)
|
||||||
|
return;
|
||||||
|
|
||||||
// Check for last member of a bufferreference type, which is runtime sizeable
|
// Check for last member of a bufferreference type, which is runtime sizeable
|
||||||
// but doesn't support runtime length
|
// but doesn't support runtime length
|
||||||
if (base.getType().getQualifier().storage == EvqBuffer) {
|
if (base.getType().getQualifier().storage == EvqBuffer) {
|
||||||
@@ -4226,6 +4386,8 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
|
|||||||
(identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) ||
|
(identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 150) || esRedecls)) ||
|
||||||
identifier == "gl_ClipDistance" ||
|
identifier == "gl_ClipDistance" ||
|
||||||
identifier == "gl_CullDistance" ||
|
identifier == "gl_CullDistance" ||
|
||||||
|
identifier == "gl_ShadingRateEXT" ||
|
||||||
|
identifier == "gl_PrimitiveShadingRateEXT" ||
|
||||||
identifier == "gl_FrontColor" ||
|
identifier == "gl_FrontColor" ||
|
||||||
identifier == "gl_BackColor" ||
|
identifier == "gl_BackColor" ||
|
||||||
identifier == "gl_FrontSecondaryColor" ||
|
identifier == "gl_FrontSecondaryColor" ||
|
||||||
@@ -4251,8 +4413,10 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS
|
|||||||
// If it wasn't at a built-in level, then it's already been redeclared;
|
// If it wasn't at a built-in level, then it's already been redeclared;
|
||||||
// that is, this is a redeclaration of a redeclaration; reuse that initial
|
// that is, this is a redeclaration of a redeclaration; reuse that initial
|
||||||
// redeclaration. Otherwise, make the new one.
|
// redeclaration. Otherwise, make the new one.
|
||||||
if (builtIn)
|
if (builtIn) {
|
||||||
makeEditable(symbol);
|
makeEditable(symbol);
|
||||||
|
symbolTable.amendSymbolIdLevel(*symbol);
|
||||||
|
}
|
||||||
|
|
||||||
// Now, modify the type of the copy, as per the type of the current redeclaration.
|
// Now, modify the type of the copy, as per the type of the current redeclaration.
|
||||||
|
|
||||||
@@ -4632,14 +4796,14 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
|
|||||||
|
|
||||||
void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
|
void TParseContext::nestedBlockCheck(const TSourceLoc& loc)
|
||||||
{
|
{
|
||||||
if (structNestingLevel > 0)
|
if (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", "", "");
|
||||||
++structNestingLevel;
|
++blockNestingLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TParseContext::nestedStructCheck(const TSourceLoc& loc)
|
void TParseContext::nestedStructCheck(const TSourceLoc& loc)
|
||||||
{
|
{
|
||||||
if (structNestingLevel > 0)
|
if (structNestingLevel > 0 || blockNestingLevel > 0)
|
||||||
error(loc, "cannot nest a structure definition inside a structure or block", "", "");
|
error(loc, "cannot nest a structure definition inside a structure or block", "", "");
|
||||||
++structNestingLevel;
|
++structNestingLevel;
|
||||||
}
|
}
|
||||||
@@ -4781,7 +4945,7 @@ void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the unique id of the loop index
|
// get the unique id of the loop index
|
||||||
int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
|
long long loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
|
||||||
inductiveLoopIds.insert(loopIndex);
|
inductiveLoopIds.insert(loopIndex);
|
||||||
|
|
||||||
// condition's form must be "loop-index relational-operator constant-expression"
|
// condition's form must be "loop-index relational-operator constant-expression"
|
||||||
@@ -4967,14 +5131,22 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
|
if (id == TQualifier::getLayoutPackingString(ElpPacked)) {
|
||||||
if (spvVersion.spv != 0)
|
if (spvVersion.spv != 0) {
|
||||||
spvRemoved(loc, "packed");
|
if (spvVersion.vulkanRelaxed)
|
||||||
|
return; // silently ignore qualifier
|
||||||
|
else
|
||||||
|
spvRemoved(loc, "packed");
|
||||||
|
}
|
||||||
publicType.qualifier.layoutPacking = ElpPacked;
|
publicType.qualifier.layoutPacking = ElpPacked;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id == TQualifier::getLayoutPackingString(ElpShared)) {
|
if (id == TQualifier::getLayoutPackingString(ElpShared)) {
|
||||||
if (spvVersion.spv != 0)
|
if (spvVersion.spv != 0) {
|
||||||
spvRemoved(loc, "shared");
|
if (spvVersion.vulkanRelaxed)
|
||||||
|
return; // silently ignore qualifier
|
||||||
|
else
|
||||||
|
spvRemoved(loc, "shared");
|
||||||
|
}
|
||||||
publicType.qualifier.layoutPacking = ElpShared;
|
publicType.qualifier.layoutPacking = ElpShared;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5424,7 +5596,14 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
|
|||||||
if (! IsPow2(value))
|
if (! IsPow2(value))
|
||||||
error(loc, "must be a power of 2", "buffer_reference_align", "");
|
error(loc, "must be a power of 2", "buffer_reference_align", "");
|
||||||
else
|
else
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
// Android NDK r15c tageting ABI 15 doesn't have full support for C++11
|
||||||
|
// (no std::exp2/log2). ::exp2 is available from C99 but ::log2 isn't
|
||||||
|
// available up until ABI 18 so we use the mathematical equivalent form
|
||||||
|
publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)(std::log(value) / std::log(2.0));
|
||||||
|
#else
|
||||||
publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value);
|
publicType.qualifier.layoutBufferReferenceAlign = (unsigned int)std::log2(value);
|
||||||
|
#endif
|
||||||
if (nonLiteral)
|
if (nonLiteral)
|
||||||
error(loc, "needs a literal integer", "buffer_reference_align", "");
|
error(loc, "needs a literal integer", "buffer_reference_align", "");
|
||||||
return;
|
return;
|
||||||
@@ -5715,6 +5894,8 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
|
|||||||
error(loc, "can only specify on a uniform block", "push_constant", "");
|
error(loc, "can only specify on a uniform block", "push_constant", "");
|
||||||
if (qualifier.isShaderRecord())
|
if (qualifier.isShaderRecord())
|
||||||
error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
|
error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
|
||||||
|
if (qualifier.hasLocation() && type.isAtomic())
|
||||||
|
error(loc, "cannot specify on atomic counter", "location", "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -5852,16 +6033,12 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
|||||||
if (type.getBasicType() == EbtSampler) {
|
if (type.getBasicType() == EbtSampler) {
|
||||||
int lastBinding = qualifier.layoutBinding;
|
int lastBinding = qualifier.layoutBinding;
|
||||||
if (type.isArray()) {
|
if (type.isArray()) {
|
||||||
if (spvVersion.vulkan > 0)
|
if (spvVersion.vulkan == 0) {
|
||||||
lastBinding += 1;
|
|
||||||
else {
|
|
||||||
if (type.isSizedArray())
|
if (type.isSizedArray())
|
||||||
lastBinding += type.getCumulativeArraySize();
|
lastBinding += (type.getCumulativeArraySize() - 1);
|
||||||
else {
|
else {
|
||||||
lastBinding += 1;
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if (spvVersion.vulkan == 0)
|
warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
|
||||||
warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", "");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5871,7 +6048,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
|||||||
error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
|
error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : "");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (type.isAtomic()) {
|
if (type.isAtomic() && !spvVersion.vulkanRelaxed) {
|
||||||
if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
|
if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) {
|
||||||
error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
|
error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", "");
|
||||||
return;
|
return;
|
||||||
@@ -5985,12 +6162,28 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool storageCanHaveLayoutInBlock(const enum TStorageQualifier storage)
|
||||||
|
{
|
||||||
|
switch (storage) {
|
||||||
|
case EvqUniform:
|
||||||
|
case EvqBuffer:
|
||||||
|
case EvqShared:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do layout error checking that can be done within a layout qualifier proper, not needing to know
|
// Do layout error checking that can be done within a layout qualifier proper, not needing to know
|
||||||
// if there are blocks, atomic counters, variables, etc.
|
// if there are blocks, atomic counters, variables, etc.
|
||||||
void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
|
void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
|
||||||
{
|
{
|
||||||
if (qualifier.storage == EvqShared && qualifier.hasLayout())
|
if (qualifier.storage == EvqShared && qualifier.hasLayout()) {
|
||||||
error(loc, "cannot apply layout qualifiers to a shared variable", "shared", "");
|
if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) {
|
||||||
|
error(loc, "shared block requires at least SPIR-V 1.4", "shared block", "");
|
||||||
|
}
|
||||||
|
profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block");
|
||||||
|
}
|
||||||
|
|
||||||
// "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
|
// "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
|
||||||
if (qualifier.hasComponent() && ! qualifier.hasLocation())
|
if (qualifier.hasComponent() && ! qualifier.hasLocation())
|
||||||
@@ -6073,7 +6266,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
|
|||||||
error(loc, "can only be used on an output", "xfb layout qualifier", "");
|
error(loc, "can only be used on an output", "xfb layout qualifier", "");
|
||||||
}
|
}
|
||||||
if (qualifier.hasUniformLayout()) {
|
if (qualifier.hasUniformLayout()) {
|
||||||
if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) {
|
if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) {
|
||||||
if (qualifier.hasMatrix() || qualifier.hasPacking())
|
if (qualifier.hasMatrix() || qualifier.hasPacking())
|
||||||
error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
|
error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
|
||||||
if (qualifier.hasOffset() || qualifier.hasAlign())
|
if (qualifier.hasOffset() || qualifier.hasAlign())
|
||||||
@@ -6525,6 +6718,68 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc,
|
|||||||
return bestMatch;
|
return bestMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Adjust function calls that aren't declared in Vulkan to a
|
||||||
|
// calls with equivalent effects
|
||||||
|
//
|
||||||
|
TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments)
|
||||||
|
{
|
||||||
|
TIntermTyped* result = nullptr;
|
||||||
|
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
if (function->getBuiltInOp() != EOpNull) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function->getName() == "atomicCounterIncrement") {
|
||||||
|
// change atomicCounterIncrement into an atomicAdd of 1
|
||||||
|
TString name("atomicAdd");
|
||||||
|
TType uintType(EbtUint);
|
||||||
|
|
||||||
|
TFunction realFunc(&name, function->getType());
|
||||||
|
|
||||||
|
for (int i = 0; i < function->getParamCount(); ++i) {
|
||||||
|
realFunc.addParameter((*function)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TParameter tmpP = { 0, &uintType };
|
||||||
|
realFunc.addParameter(tmpP);
|
||||||
|
arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true));
|
||||||
|
|
||||||
|
result = handleFunctionCall(loc, &realFunc, arguments);
|
||||||
|
} else if (function->getName() == "atomicCounterDecrement") {
|
||||||
|
// change atomicCounterDecrement into an atomicAdd with -1
|
||||||
|
// and subtract 1 from result, to return post-decrement value
|
||||||
|
TString name("atomicAdd");
|
||||||
|
TType uintType(EbtUint);
|
||||||
|
|
||||||
|
TFunction realFunc(&name, function->getType());
|
||||||
|
|
||||||
|
for (int i = 0; i < function->getParamCount(); ++i) {
|
||||||
|
realFunc.addParameter((*function)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TParameter tmpP = { 0, &uintType };
|
||||||
|
realFunc.addParameter(tmpP);
|
||||||
|
arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true));
|
||||||
|
|
||||||
|
result = handleFunctionCall(loc, &realFunc, arguments);
|
||||||
|
|
||||||
|
// post decrement, so that it matches AtomicCounterDecrement semantics
|
||||||
|
if (result) {
|
||||||
|
result = handleBinaryMath(loc, "-", EOpSub, result, intermediate.addConstantUnion(1, loc, true));
|
||||||
|
}
|
||||||
|
} else if (function->getName() == "atomicCounter") {
|
||||||
|
// change atomicCounter into a direct read of the variable
|
||||||
|
if (arguments->getAsTyped()) {
|
||||||
|
result = arguments->getAsTyped();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// When a declaration includes a type, but not a variable name, it can be used
|
// When a declaration includes a type, but not a variable name, it can be used
|
||||||
// to establish defaults.
|
// to establish defaults.
|
||||||
void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
|
void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType)
|
||||||
@@ -6535,18 +6790,105 @@ void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType
|
|||||||
error(loc, "atomic_uint binding is too large", "binding", "");
|
error(loc, "atomic_uint binding is too large", "binding", "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (publicType.qualifier.hasOffset())
|
||||||
if(publicType.qualifier.hasOffset()) {
|
|
||||||
atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
|
atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset;
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (publicType.arraySizes) {
|
||||||
|
error(loc, "expect an array name", "", "");
|
||||||
|
}
|
||||||
|
|
||||||
if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
|
if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference())
|
||||||
warn(loc, "useless application of layout qualifier", "layout", "");
|
warn(loc, "useless application of layout qualifier", "layout", "");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType&,
|
||||||
|
TArraySizes*, TIntermTyped* initializer, TType& type)
|
||||||
|
{
|
||||||
|
if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() ||
|
||||||
|
type.getQualifier().storage != EvqUniform ||
|
||||||
|
!(type.containsNonOpaque()
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
|| type.getBasicType() == EbtAtomicUint
|
||||||
|
#endif
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.getQualifier().hasLocation()) {
|
||||||
|
warn(loc, "ignoring layout qualifier for uniform", identifier.c_str(), "location");
|
||||||
|
type.getQualifier().layoutLocation = TQualifier::layoutLocationEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initializer) {
|
||||||
|
warn(loc, "Ignoring initializer for uniform", identifier.c_str(), "");
|
||||||
|
initializer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isArray()) {
|
||||||
|
// do array size checks here
|
||||||
|
arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false);
|
||||||
|
|
||||||
|
if (arrayQualifierError(loc, type.getQualifier()) || arrayError(loc, type)) {
|
||||||
|
error(loc, "array param error", identifier.c_str(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do some checking on the type as it was declared
|
||||||
|
layoutTypeCheck(loc, type);
|
||||||
|
|
||||||
|
int bufferBinding = TQualifier::layoutBindingEnd;
|
||||||
|
TVariable* updatedBlock = nullptr;
|
||||||
|
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
// Convert atomic_uint into members of a buffer block
|
||||||
|
if (type.isAtomic()) {
|
||||||
|
type.setBasicType(EbtUint);
|
||||||
|
type.getQualifier().storage = EvqBuffer;
|
||||||
|
|
||||||
|
type.getQualifier().volatil = true;
|
||||||
|
type.getQualifier().coherent = true;
|
||||||
|
|
||||||
|
// xxTODO: use logic from fixOffset() to apply explicit member offset
|
||||||
|
bufferBinding = type.getQualifier().layoutBinding;
|
||||||
|
type.getQualifier().layoutBinding = TQualifier::layoutBindingEnd;
|
||||||
|
type.getQualifier().explicitOffset = false;
|
||||||
|
growAtomicCounterBlock(bufferBinding, loc, type, identifier, nullptr);
|
||||||
|
updatedBlock = atomicCounterBuffers[bufferBinding];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!updatedBlock) {
|
||||||
|
growGlobalUniformBlock(loc, type, identifier, nullptr);
|
||||||
|
updatedBlock = globalUniformBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// don't assign explicit member offsets here
|
||||||
|
// if any are assigned, need to be updated here and in the merge/link step
|
||||||
|
// fixBlockUniformOffsets(updatedBlock->getWritableType().getQualifier(), *updatedBlock->getWritableType().getWritableStruct());
|
||||||
|
|
||||||
|
// checks on update buffer object
|
||||||
|
layoutObjectCheck(loc, *updatedBlock);
|
||||||
|
|
||||||
|
TSymbol* symbol = symbolTable.find(identifier);
|
||||||
|
|
||||||
|
if (!symbol) {
|
||||||
|
if (updatedBlock == globalUniformBlock)
|
||||||
|
error(loc, "error adding uniform to default uniform block", identifier.c_str(), "");
|
||||||
|
else
|
||||||
|
error(loc, "error adding atomic counter to atomic counter block", identifier.c_str(), "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge qualifiers
|
||||||
|
mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do everything necessary to handle a variable (non-block) declaration.
|
// Do everything necessary to handle a variable (non-block) declaration.
|
||||||
// Either redeclaring a variable, or making a new one, updating the symbol
|
// Either redeclaring a variable, or making a new one, updating the symbol
|
||||||
@@ -6632,6 +6974,22 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
|
|||||||
if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
|
if (type.getQualifier().storage == EvqShared && type.containsCoopMat())
|
||||||
error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
|
error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
|
||||||
|
|
||||||
|
if (profile == EEsProfile) {
|
||||||
|
if (type.getQualifier().isPipeInput() && type.getBasicType() == EbtStruct) {
|
||||||
|
if (type.getQualifier().isArrayedIo(language)) {
|
||||||
|
TType perVertexType(type, 0);
|
||||||
|
if (perVertexType.containsArray() && perVertexType.containsBuiltIn() == false) {
|
||||||
|
error(loc, "A per vertex structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.containsArray() && type.containsBuiltIn() == false) {
|
||||||
|
error(loc, "A structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), "");
|
||||||
|
}
|
||||||
|
if (type.containsStructure())
|
||||||
|
error(loc, "A structure containing an struct is not allowed as input in ES", type.getTypeName().c_str(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
|
if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
|
||||||
error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
|
error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
|
||||||
if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
|
if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone)
|
||||||
@@ -6642,6 +7000,14 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
|
|||||||
if (symbol == nullptr)
|
if (symbol == nullptr)
|
||||||
reservedErrorCheck(loc, identifier);
|
reservedErrorCheck(loc, identifier);
|
||||||
|
|
||||||
|
if (symbol == nullptr && spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) {
|
||||||
|
bool remapped = vkRelaxedRemapUniformVariable(loc, identifier, publicType, arraySizes, initializer, type);
|
||||||
|
|
||||||
|
if (remapped) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inheritGlobalDefaults(type.getQualifier());
|
inheritGlobalDefaults(type.getQualifier());
|
||||||
|
|
||||||
// Declare the variable
|
// Declare the variable
|
||||||
@@ -6749,6 +7115,11 @@ TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString&
|
|||||||
//
|
//
|
||||||
TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
|
TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
|
||||||
{
|
{
|
||||||
|
// A null initializer is an aggregate that hasn't had an op assigned yet
|
||||||
|
// (still EOpNull, no relation to nullInit), and has no children.
|
||||||
|
bool nullInit = initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull &&
|
||||||
|
initializer->getAsAggregate()->getSequence().size() == 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Identifier must be of type constant, a global, or a temporary, and
|
// Identifier must be of type constant, a global, or a temporary, and
|
||||||
// starting at version 120, desktop allows uniforms to have initializers.
|
// starting at version 120, desktop allows uniforms to have initializers.
|
||||||
@@ -6756,9 +7127,36 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||||||
TStorageQualifier qualifier = variable->getType().getQualifier().storage;
|
TStorageQualifier qualifier = variable->getType().getQualifier().storage;
|
||||||
if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
|
if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
|
||||||
(qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
|
(qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
|
||||||
error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
|
if (qualifier == EvqShared) {
|
||||||
|
// GL_EXT_null_initializer allows this for shared, if it's a null initializer
|
||||||
|
if (nullInit) {
|
||||||
|
const char* feature = "initialization with shared qualifier";
|
||||||
|
profileRequires(loc, EEsProfile, 0, E_GL_EXT_null_initializer, feature);
|
||||||
|
profileRequires(loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, feature);
|
||||||
|
} else {
|
||||||
|
error(loc, "initializer can only be a null initializer ('{}')", "shared", "");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(loc, " cannot initialize this type of qualifier ",
|
||||||
|
variable->getType().getStorageQualifierString(), "");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullInit) {
|
||||||
|
// only some types can be null initialized
|
||||||
|
if (variable->getType().containsUnsizedArray()) {
|
||||||
|
error(loc, "null initializers can't size unsized arrays", "{}", "");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (variable->getType().containsOpaque()) {
|
||||||
|
error(loc, "null initializers can't be used on opaque values", "{}", "");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
variable->getWritableType().getQualifier().setNullInit();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
arrayObjectCheck(loc, variable->getType(), "array initializer");
|
arrayObjectCheck(loc, variable->getType(), "array initializer");
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -6802,13 +7200,15 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||||||
|
|
||||||
// Uniforms require a compile-time constant initializer
|
// Uniforms require a compile-time constant initializer
|
||||||
if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
|
if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
|
||||||
error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
error(loc, "uniform initializers must be constant", "=", "'%s'",
|
||||||
|
variable->getType().getCompleteString().c_str());
|
||||||
variable->getWritableType().getQualifier().makeTemporary();
|
variable->getWritableType().getQualifier().makeTemporary();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// Global consts require a constant initializer (specialization constant is okay)
|
// Global consts require a constant initializer (specialization constant is okay)
|
||||||
if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
||||||
error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
error(loc, "global const initializers must be constant", "=", "'%s'",
|
||||||
|
variable->getType().getCompleteString().c_str());
|
||||||
variable->getWritableType().getQualifier().makeTemporary();
|
variable->getWritableType().getQualifier().makeTemporary();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -6828,7 +7228,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||||||
// "In declarations of global variables with no storage qualifier or with a const
|
// "In declarations of global variables with no storage qualifier or with a const
|
||||||
// qualifier any initializer must be a constant expression."
|
// qualifier any initializer must be a constant expression."
|
||||||
if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
||||||
const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
|
const char* initFeature =
|
||||||
|
"non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
|
||||||
if (isEsProfile()) {
|
if (isEsProfile()) {
|
||||||
if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
|
if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
|
||||||
warn(loc, "not allowed in this version", initFeature, "");
|
warn(loc, "not allowed in this version", initFeature, "");
|
||||||
@@ -6842,7 +7243,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||||||
// Compile-time tagging of the variable with its constant value...
|
// Compile-time tagging of the variable with its constant value...
|
||||||
|
|
||||||
initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
|
initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
|
||||||
if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) {
|
if (! initializer || ! initializer->getType().getQualifier().isConstant() ||
|
||||||
|
variable->getType() != initializer->getType()) {
|
||||||
error(loc, "non-matching or non-convertible constant type for const initializer",
|
error(loc, "non-matching or non-convertible constant type for const initializer",
|
||||||
variable->getType().getStorageQualifierString(), "");
|
variable->getType().getStorageQualifierString(), "");
|
||||||
variable->getWritableType().getQualifier().makeTemporary();
|
variable->getWritableType().getQualifier().makeTemporary();
|
||||||
@@ -6954,6 +7356,15 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
|
|||||||
error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
|
error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString().c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
TBasicType destType = type.getBasicType();
|
||||||
|
for (int i = 0; i < type.getVectorSize(); ++i) {
|
||||||
|
TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType();
|
||||||
|
if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) {
|
||||||
|
error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString().c_str());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
|
error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -7410,6 +7821,19 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
|
case EOpConstructAccStruct:
|
||||||
|
if ((node->getType().isScalar() && node->getType().getBasicType() == EbtUint64)) {
|
||||||
|
// construct acceleration structure from uint64
|
||||||
|
requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "uint64_t conversion to acclerationStructureEXT");
|
||||||
|
return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToAccStruct, true, node,
|
||||||
|
type);
|
||||||
|
} else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint && node->getVectorSize() == 2) {
|
||||||
|
// construct acceleration structure from uint64
|
||||||
|
requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "uvec2 conversion to accelerationStructureEXT");
|
||||||
|
return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToAccStruct, true, node,
|
||||||
|
type);
|
||||||
|
} else
|
||||||
|
return nullptr;
|
||||||
#endif // GLSLANG_WEB
|
#endif // GLSLANG_WEB
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -7476,6 +7900,8 @@ void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier&
|
|||||||
void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
|
void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName,
|
||||||
TArraySizes* arraySizes)
|
TArraySizes* arraySizes)
|
||||||
{
|
{
|
||||||
|
if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed)
|
||||||
|
blockStorageRemap(loc, blockName, currentBlockQualifier);
|
||||||
blockStageIoCheck(loc, currentBlockQualifier);
|
blockStageIoCheck(loc, currentBlockQualifier);
|
||||||
blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
|
blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
|
||||||
if (arraySizes != nullptr) {
|
if (arraySizes != nullptr) {
|
||||||
@@ -7490,10 +7916,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
|
|||||||
TType& memberType = *typeList[member].type;
|
TType& memberType = *typeList[member].type;
|
||||||
TQualifier& memberQualifier = memberType.getQualifier();
|
TQualifier& memberQualifier = memberType.getQualifier();
|
||||||
const TSourceLoc& memberLoc = typeList[member].loc;
|
const TSourceLoc& memberLoc = typeList[member].loc;
|
||||||
globalQualifierFixCheck(memberLoc, memberQualifier);
|
|
||||||
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
|
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
|
||||||
error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
|
error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), "");
|
||||||
memberQualifier.storage = currentBlockQualifier.storage;
|
memberQualifier.storage = currentBlockQualifier.storage;
|
||||||
|
globalQualifierFixCheck(memberLoc, memberQualifier);
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
|
inheritMemoryQualifiers(currentBlockQualifier, memberQualifier);
|
||||||
if (currentBlockQualifier.perPrimitiveNV)
|
if (currentBlockQualifier.perPrimitiveNV)
|
||||||
@@ -7543,6 +7969,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
|
|||||||
case EvqBuffer: defaultQualification = globalBufferDefaults; break;
|
case EvqBuffer: defaultQualification = globalBufferDefaults; break;
|
||||||
case EvqVaryingIn: defaultQualification = globalInputDefaults; break;
|
case EvqVaryingIn: defaultQualification = globalInputDefaults; break;
|
||||||
case EvqVaryingOut: defaultQualification = globalOutputDefaults; break;
|
case EvqVaryingOut: defaultQualification = globalOutputDefaults; break;
|
||||||
|
case EvqShared: defaultQualification = globalSharedDefaults; break;
|
||||||
default: defaultQualification.clear(); break;
|
default: defaultQualification.clear(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7764,6 +8191,17 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
|
|||||||
trackLinkage(variable);
|
trackLinkage(variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// allow storage type of block to be remapped at compile time
|
||||||
|
//
|
||||||
|
void TParseContext::blockStorageRemap(const TSourceLoc&, const TString* instanceName, TQualifier& qualifier)
|
||||||
|
{
|
||||||
|
TBlockStorageClass type = intermediate.getBlockStorageOverride(instanceName->c_str());
|
||||||
|
if (type != EbsNone) {
|
||||||
|
qualifier.setBlockStorage(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Do all block-declaration checking regarding the combination of in/out/uniform/buffer
|
// Do all block-declaration checking regarding the combination of in/out/uniform/buffer
|
||||||
// with a particular stage.
|
// with a particular stage.
|
||||||
void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
|
void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
|
||||||
@@ -7806,6 +8244,12 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
|
|||||||
error(loc, "output blocks cannot be used in a task shader", "out", "");
|
error(loc, "output blocks cannot be used in a task shader", "out", "");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EvqShared:
|
||||||
|
if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) {
|
||||||
|
error(loc, "shared block requires at least SPIR-V 1.4", "shared block", "");
|
||||||
|
}
|
||||||
|
profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block");
|
||||||
|
break;
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
case EvqPayload:
|
case EvqPayload:
|
||||||
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
|
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
|
||||||
@@ -7964,7 +8408,7 @@ void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList)
|
|||||||
//
|
//
|
||||||
void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
|
void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
|
||||||
{
|
{
|
||||||
if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory())
|
if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory())
|
||||||
return;
|
return;
|
||||||
if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
|
if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
|
||||||
return;
|
return;
|
||||||
@@ -8191,7 +8635,7 @@ void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qual
|
|||||||
|
|
||||||
bool pipeOut = qualifier.isPipeOutput();
|
bool pipeOut = qualifier.isPipeOutput();
|
||||||
bool pipeIn = qualifier.isPipeInput();
|
bool pipeIn = qualifier.isPipeInput();
|
||||||
if (version >= 300 || (!isEsProfile() && version >= 420)) {
|
if ((version >= 300 && isEsProfile()) || (!isEsProfile() && version >= 420)) {
|
||||||
if (! pipeOut)
|
if (! pipeOut)
|
||||||
error(loc, "can only apply to an output", "invariant", "");
|
error(loc, "can only apply to an output", "invariant", "");
|
||||||
} else {
|
} else {
|
||||||
@@ -8478,8 +8922,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case EvqShared:
|
||||||
|
if (qualifier.hasMatrix())
|
||||||
|
globalSharedDefaults.layoutMatrix = qualifier.layoutMatrix;
|
||||||
|
if (qualifier.hasPacking())
|
||||||
|
globalSharedDefaults.layoutPacking = qualifier.layoutPacking;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", "");
|
error(loc, "default qualifier requires 'uniform', 'buffer', 'in', 'out' or 'shared' storage qualification", "", "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ struct TPragma {
|
|||||||
class TScanContext;
|
class TScanContext;
|
||||||
class TPpContext;
|
class TPpContext;
|
||||||
|
|
||||||
typedef std::set<int> TIdSetType;
|
typedef std::set<long long> TIdSetType;
|
||||||
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
|
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
|
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
|
||||||
scopeMangler("::"),
|
scopeMangler("::"),
|
||||||
symbolTable(symbolTable),
|
symbolTable(symbolTable),
|
||||||
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
|
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
|
||||||
currentFunctionType(nullptr),
|
currentFunctionType(nullptr),
|
||||||
postEntryPointReturn(false),
|
postEntryPointReturn(false),
|
||||||
contextPragma(true, false),
|
contextPragma(true, false),
|
||||||
@@ -92,7 +92,8 @@ public:
|
|||||||
limits(resources.limits),
|
limits(resources.limits),
|
||||||
globalUniformBlock(nullptr),
|
globalUniformBlock(nullptr),
|
||||||
globalUniformBinding(TQualifier::layoutBindingEnd),
|
globalUniformBinding(TQualifier::layoutBindingEnd),
|
||||||
globalUniformSet(TQualifier::layoutSetEnd)
|
globalUniformSet(TQualifier::layoutSetEnd),
|
||||||
|
atomicCounterBlockSet(TQualifier::layoutSetEnd)
|
||||||
{
|
{
|
||||||
if (entryPoint != nullptr)
|
if (entryPoint != nullptr)
|
||||||
sourceEntryPointName = *entryPoint;
|
sourceEntryPointName = *entryPoint;
|
||||||
@@ -154,10 +155,11 @@ public:
|
|||||||
extensionCallback(line, extension, behavior);
|
extensionCallback(line, extension, behavior);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_HLSL
|
|
||||||
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
|
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
|
||||||
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
|
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
|
||||||
#endif
|
|
||||||
|
// Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
|
||||||
|
virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
|
||||||
|
|
||||||
// Potentially rename shader entry point function
|
// Potentially rename shader entry point function
|
||||||
void renameShaderFunction(TString*& name) const
|
void renameShaderFunction(TString*& name) const
|
||||||
@@ -178,7 +180,8 @@ public:
|
|||||||
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
||||||
int statementNestingLevel; // 0 if outside all flow control or compound statements
|
int statementNestingLevel; // 0 if outside all flow control or compound statements
|
||||||
int loopNestingLevel; // 0 if outside all loops
|
int loopNestingLevel; // 0 if outside all loops
|
||||||
int structNestingLevel; // 0 if outside blocks and structures
|
int structNestingLevel; // 0 if outside structures
|
||||||
|
int blockNestingLevel; // 0 if outside blocks
|
||||||
int controlFlowNestingLevel; // 0 if outside all flow control
|
int controlFlowNestingLevel; // 0 if outside all flow control
|
||||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
||||||
bool functionReturnsValue; // true if a non-void function has a return
|
bool functionReturnsValue; // true if a non-void function has a return
|
||||||
@@ -229,7 +232,24 @@ protected:
|
|||||||
// override this to set the language-specific name
|
// override this to set the language-specific name
|
||||||
virtual const char* getGlobalUniformBlockName() const { return ""; }
|
virtual const char* getGlobalUniformBlockName() const { return ""; }
|
||||||
virtual void setUniformBlockDefaults(TType&) const { }
|
virtual void setUniformBlockDefaults(TType&) const { }
|
||||||
virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
|
virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
|
||||||
|
|
||||||
|
// Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
|
||||||
|
TMap<int, TVariable*> atomicCounterBuffers;
|
||||||
|
unsigned int atomicCounterBlockSet;
|
||||||
|
TMap<int, int> atomicCounterBlockFirstNewMember;
|
||||||
|
// override this to set the language-specific name
|
||||||
|
virtual const char* getAtomicCounterBlockName() const { return ""; }
|
||||||
|
virtual void setAtomicCounterBlockDefaults(TType&) const {}
|
||||||
|
virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
|
||||||
|
bool isAtomicCounterBlock(const TSymbol& symbol) {
|
||||||
|
const TVariable* var = symbol.getAsVariable();
|
||||||
|
if (!var)
|
||||||
|
return false;
|
||||||
|
const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
|
||||||
|
return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||||
va_list args);
|
va_list args);
|
||||||
@@ -292,6 +312,9 @@ public:
|
|||||||
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
|
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
|
||||||
void parserError(const char* s); // for bison's yyerror
|
void parserError(const char* s); // for bison's yyerror
|
||||||
|
|
||||||
|
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
|
||||||
|
virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
|
||||||
|
|
||||||
void reservedErrorCheck(const TSourceLoc&, const TString&);
|
void reservedErrorCheck(const TSourceLoc&, const TString&);
|
||||||
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
|
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
|
||||||
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
|
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
|
||||||
@@ -339,6 +362,10 @@ public:
|
|||||||
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
|
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
|
||||||
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
|
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
|
||||||
|
|
||||||
|
TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||||
|
// returns true if the variable was remapped to something else
|
||||||
|
bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
|
||||||
|
|
||||||
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
||||||
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||||
@@ -365,7 +392,7 @@ public:
|
|||||||
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
|
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
|
||||||
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
||||||
void memberQualifierCheck(glslang::TPublicType&);
|
void memberQualifierCheck(glslang::TPublicType&);
|
||||||
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
|
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
|
||||||
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
|
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
|
||||||
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
||||||
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
|
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
|
||||||
@@ -391,7 +418,7 @@ public:
|
|||||||
void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
|
void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
|
||||||
void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
|
void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
|
||||||
|
|
||||||
void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
|
void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
|
||||||
void constantIndexExpressionCheck(TIntermNode*);
|
void constantIndexExpressionCheck(TIntermNode*);
|
||||||
|
|
||||||
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
|
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
|
||||||
@@ -416,6 +443,7 @@ public:
|
|||||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
||||||
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
|
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
|
||||||
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||||
|
void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
|
||||||
void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
|
void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
|
||||||
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
|
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
|
||||||
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
||||||
@@ -460,6 +488,14 @@ protected:
|
|||||||
void finish() override;
|
void finish() override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual const char* getGlobalUniformBlockName() const override;
|
||||||
|
virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
|
||||||
|
virtual void setUniformBlockDefaults(TType& block) const override;
|
||||||
|
|
||||||
|
virtual const char* getAtomicCounterBlockName() const override;
|
||||||
|
virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
|
||||||
|
virtual void setAtomicCounterBlockDefaults(TType& block) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//
|
//
|
||||||
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
|
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
|
||||||
@@ -484,6 +520,7 @@ protected:
|
|||||||
TQualifier globalUniformDefaults;
|
TQualifier globalUniformDefaults;
|
||||||
TQualifier globalInputDefaults;
|
TQualifier globalInputDefaults;
|
||||||
TQualifier globalOutputDefaults;
|
TQualifier globalOutputDefaults;
|
||||||
|
TQualifier globalSharedDefaults;
|
||||||
TString currentCaller; // name of last function body entered (not valid when at global scope)
|
TString currentCaller; // name of last function body entered (not valid when at global scope)
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
|
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
|
||||||
|
|||||||
@@ -365,6 +365,9 @@ void TScanContext::fillInKeywordMap()
|
|||||||
(*KeywordMap)["if"] = IF;
|
(*KeywordMap)["if"] = IF;
|
||||||
(*KeywordMap)["else"] = ELSE;
|
(*KeywordMap)["else"] = ELSE;
|
||||||
(*KeywordMap)["discard"] = DISCARD;
|
(*KeywordMap)["discard"] = DISCARD;
|
||||||
|
(*KeywordMap)["terminateInvocation"] = TERMINATE_INVOCATION;
|
||||||
|
(*KeywordMap)["terminateRayEXT"] = TERMINATE_RAY;
|
||||||
|
(*KeywordMap)["ignoreIntersectionEXT"] = IGNORE_INTERSECTION;
|
||||||
(*KeywordMap)["return"] = RETURN;
|
(*KeywordMap)["return"] = RETURN;
|
||||||
(*KeywordMap)["void"] = VOID;
|
(*KeywordMap)["void"] = VOID;
|
||||||
(*KeywordMap)["bool"] = BOOL;
|
(*KeywordMap)["bool"] = BOOL;
|
||||||
@@ -471,6 +474,28 @@ void TScanContext::fillInKeywordMap()
|
|||||||
(*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
|
(*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
|
||||||
(*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
|
(*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
|
||||||
(*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY;
|
(*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY;
|
||||||
|
(*KeywordMap)["i64image1D"] = I64IMAGE1D;
|
||||||
|
(*KeywordMap)["u64image1D"] = U64IMAGE1D;
|
||||||
|
(*KeywordMap)["i64image2D"] = I64IMAGE2D;
|
||||||
|
(*KeywordMap)["u64image2D"] = U64IMAGE2D;
|
||||||
|
(*KeywordMap)["i64image3D"] = I64IMAGE3D;
|
||||||
|
(*KeywordMap)["u64image3D"] = U64IMAGE3D;
|
||||||
|
(*KeywordMap)["i64image2DRect"] = I64IMAGE2DRECT;
|
||||||
|
(*KeywordMap)["u64image2DRect"] = U64IMAGE2DRECT;
|
||||||
|
(*KeywordMap)["i64imageCube"] = I64IMAGECUBE;
|
||||||
|
(*KeywordMap)["u64imageCube"] = U64IMAGECUBE;
|
||||||
|
(*KeywordMap)["i64imageBuffer"] = I64IMAGEBUFFER;
|
||||||
|
(*KeywordMap)["u64imageBuffer"] = U64IMAGEBUFFER;
|
||||||
|
(*KeywordMap)["i64image1DArray"] = I64IMAGE1DARRAY;
|
||||||
|
(*KeywordMap)["u64image1DArray"] = U64IMAGE1DARRAY;
|
||||||
|
(*KeywordMap)["i64image2DArray"] = I64IMAGE2DARRAY;
|
||||||
|
(*KeywordMap)["u64image2DArray"] = U64IMAGE2DARRAY;
|
||||||
|
(*KeywordMap)["i64imageCubeArray"] = I64IMAGECUBEARRAY;
|
||||||
|
(*KeywordMap)["u64imageCubeArray"] = U64IMAGECUBEARRAY;
|
||||||
|
(*KeywordMap)["i64image2DMS"] = I64IMAGE2DMS;
|
||||||
|
(*KeywordMap)["u64image2DMS"] = U64IMAGE2DMS;
|
||||||
|
(*KeywordMap)["i64image2DMSArray"] = I64IMAGE2DMSARRAY;
|
||||||
|
(*KeywordMap)["u64image2DMSArray"] = U64IMAGE2DMSARRAY;
|
||||||
(*KeywordMap)["double"] = DOUBLE;
|
(*KeywordMap)["double"] = DOUBLE;
|
||||||
(*KeywordMap)["dvec2"] = DVEC2;
|
(*KeywordMap)["dvec2"] = DVEC2;
|
||||||
(*KeywordMap)["dvec3"] = DVEC3;
|
(*KeywordMap)["dvec3"] = DVEC3;
|
||||||
@@ -914,6 +939,17 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
case CASE:
|
case CASE:
|
||||||
return keyword;
|
return keyword;
|
||||||
|
|
||||||
|
case TERMINATE_INVOCATION:
|
||||||
|
if (!parseContext.extensionTurnedOn(E_GL_EXT_terminate_invocation))
|
||||||
|
return identifierOrType();
|
||||||
|
return keyword;
|
||||||
|
|
||||||
|
case TERMINATE_RAY:
|
||||||
|
case IGNORE_INTERSECTION:
|
||||||
|
if (!parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing))
|
||||||
|
return identifierOrType();
|
||||||
|
return keyword;
|
||||||
|
|
||||||
case BUFFER:
|
case BUFFER:
|
||||||
afterBuffer = true;
|
afterBuffer = true;
|
||||||
if ((parseContext.isEsProfile() && parseContext.version < 310) ||
|
if ((parseContext.isEsProfile() && parseContext.version < 310) ||
|
||||||
@@ -982,7 +1018,7 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
return keyword;
|
return keyword;
|
||||||
case PACKED:
|
case PACKED:
|
||||||
if ((parseContext.isEsProfile() && parseContext.version < 300) ||
|
if ((parseContext.isEsProfile() && parseContext.version < 300) ||
|
||||||
(!parseContext.isEsProfile() && parseContext.version < 330))
|
(!parseContext.isEsProfile() && parseContext.version < 140))
|
||||||
return reservedWord();
|
return reservedWord();
|
||||||
return identifierOrType();
|
return identifierOrType();
|
||||||
|
|
||||||
@@ -1147,6 +1183,19 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
afterType = true;
|
afterType = true;
|
||||||
return firstGenerationImage(false);
|
return firstGenerationImage(false);
|
||||||
|
|
||||||
|
case I64IMAGE1D:
|
||||||
|
case U64IMAGE1D:
|
||||||
|
case I64IMAGE1DARRAY:
|
||||||
|
case U64IMAGE1DARRAY:
|
||||||
|
case I64IMAGE2DRECT:
|
||||||
|
case U64IMAGE2DRECT:
|
||||||
|
afterType = true;
|
||||||
|
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||||
|
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
|
||||||
|
return firstGenerationImage(false);
|
||||||
|
}
|
||||||
|
return identifierOrType();
|
||||||
|
|
||||||
case IMAGEBUFFER:
|
case IMAGEBUFFER:
|
||||||
case IIMAGEBUFFER:
|
case IIMAGEBUFFER:
|
||||||
case UIMAGEBUFFER:
|
case UIMAGEBUFFER:
|
||||||
@@ -1155,6 +1204,18 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
|
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
|
||||||
return keyword;
|
return keyword;
|
||||||
return firstGenerationImage(false);
|
return firstGenerationImage(false);
|
||||||
|
|
||||||
|
case I64IMAGEBUFFER:
|
||||||
|
case U64IMAGEBUFFER:
|
||||||
|
afterType = true;
|
||||||
|
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||||
|
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
|
||||||
|
if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
|
||||||
|
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
|
||||||
|
return keyword;
|
||||||
|
return firstGenerationImage(false);
|
||||||
|
}
|
||||||
|
return identifierOrType();
|
||||||
|
|
||||||
case IMAGE2D:
|
case IMAGE2D:
|
||||||
case IIMAGE2D:
|
case IIMAGE2D:
|
||||||
@@ -1171,6 +1232,20 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
afterType = true;
|
afterType = true;
|
||||||
return firstGenerationImage(true);
|
return firstGenerationImage(true);
|
||||||
|
|
||||||
|
case I64IMAGE2D:
|
||||||
|
case U64IMAGE2D:
|
||||||
|
case I64IMAGE3D:
|
||||||
|
case U64IMAGE3D:
|
||||||
|
case I64IMAGECUBE:
|
||||||
|
case U64IMAGECUBE:
|
||||||
|
case I64IMAGE2DARRAY:
|
||||||
|
case U64IMAGE2DARRAY:
|
||||||
|
afterType = true;
|
||||||
|
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||||
|
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64))
|
||||||
|
return firstGenerationImage(true);
|
||||||
|
return identifierOrType();
|
||||||
|
|
||||||
case IMAGECUBEARRAY:
|
case IMAGECUBEARRAY:
|
||||||
case IIMAGECUBEARRAY:
|
case IIMAGECUBEARRAY:
|
||||||
case UIMAGECUBEARRAY:
|
case UIMAGECUBEARRAY:
|
||||||
@@ -1179,6 +1254,18 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
|
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
|
||||||
return keyword;
|
return keyword;
|
||||||
return secondGenerationImage();
|
return secondGenerationImage();
|
||||||
|
|
||||||
|
case I64IMAGECUBEARRAY:
|
||||||
|
case U64IMAGECUBEARRAY:
|
||||||
|
afterType = true;
|
||||||
|
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||||
|
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
|
||||||
|
if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
|
||||||
|
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
|
||||||
|
return keyword;
|
||||||
|
return secondGenerationImage();
|
||||||
|
}
|
||||||
|
return identifierOrType();
|
||||||
|
|
||||||
case IMAGE2DMS:
|
case IMAGE2DMS:
|
||||||
case IIMAGE2DMS:
|
case IIMAGE2DMS:
|
||||||
@@ -1188,6 +1275,17 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
case UIMAGE2DMSARRAY:
|
case UIMAGE2DMSARRAY:
|
||||||
afterType = true;
|
afterType = true;
|
||||||
return secondGenerationImage();
|
return secondGenerationImage();
|
||||||
|
|
||||||
|
case I64IMAGE2DMS:
|
||||||
|
case U64IMAGE2DMS:
|
||||||
|
case I64IMAGE2DMSARRAY:
|
||||||
|
case U64IMAGE2DMSARRAY:
|
||||||
|
afterType = true;
|
||||||
|
if (parseContext.symbolTable.atBuiltInLevel() ||
|
||||||
|
parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) {
|
||||||
|
return secondGenerationImage();
|
||||||
|
}
|
||||||
|
return identifierOrType();
|
||||||
|
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
case DVEC2:
|
case DVEC2:
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ int MapVersionToIndex(int version)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex
|
const int SpvVersionCount = 4; // index range in MapSpvVersionToIndex
|
||||||
|
|
||||||
int MapSpvVersionToIndex(const SpvVersion& spvVersion)
|
int MapSpvVersionToIndex(const SpvVersion& spvVersion)
|
||||||
{
|
{
|
||||||
@@ -167,8 +167,12 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion)
|
|||||||
|
|
||||||
if (spvVersion.openGl > 0)
|
if (spvVersion.openGl > 0)
|
||||||
index = 1;
|
index = 1;
|
||||||
else if (spvVersion.vulkan > 0)
|
else if (spvVersion.vulkan > 0) {
|
||||||
index = 2;
|
if (!spvVersion.vulkanRelaxed)
|
||||||
|
index = 2;
|
||||||
|
else
|
||||||
|
index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
assert(index < SpvVersionCount);
|
assert(index < SpvVersionCount);
|
||||||
|
|
||||||
@@ -723,6 +727,7 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
|
|||||||
break;
|
break;
|
||||||
case EShClientVulkan:
|
case EShClientVulkan:
|
||||||
spvVersion.vulkanGlsl = environment->input.dialectVersion;
|
spvVersion.vulkanGlsl = environment->input.dialectVersion;
|
||||||
|
spvVersion.vulkanRelaxed = environment->input.vulkanRulesRelaxed;
|
||||||
break;
|
break;
|
||||||
case EShClientOpenGL:
|
case EShClientOpenGL:
|
||||||
spvVersion.openGl = environment->input.dialectVersion;
|
spvVersion.openGl = environment->input.dialectVersion;
|
||||||
@@ -949,6 +954,9 @@ bool ProcessDeferred(
|
|||||||
if (cachedTable)
|
if (cachedTable)
|
||||||
symbolTable->adoptLevels(*cachedTable);
|
symbolTable->adoptLevels(*cachedTable);
|
||||||
|
|
||||||
|
if (intermediate.getUniqueId() != 0)
|
||||||
|
symbolTable->overwriteUniqueId(intermediate.getUniqueId());
|
||||||
|
|
||||||
// Add built-in symbols that are potentially context dependent;
|
// Add built-in symbols that are potentially context dependent;
|
||||||
// they get popped again further down.
|
// they get popped again further down.
|
||||||
if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
|
if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
|
||||||
@@ -1011,6 +1019,7 @@ bool ProcessDeferred(
|
|||||||
bool success = processingContext(*parseContext, ppContext, fullInput,
|
bool success = processingContext(*parseContext, ppContext, fullInput,
|
||||||
versionWillBeError, *symbolTable,
|
versionWillBeError, *symbolTable,
|
||||||
intermediate, optLevel, messages);
|
intermediate, optLevel, messages);
|
||||||
|
intermediate.setUniqueId(symbolTable->getMaxSymbolId());
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,14 +1279,15 @@ bool PreprocessDeferred(
|
|||||||
EShMessages messages, // warnings/errors/AST; things to print out
|
EShMessages messages, // warnings/errors/AST; things to print out
|
||||||
TShader::Includer& includer,
|
TShader::Includer& includer,
|
||||||
TIntermediate& intermediate, // returned tree, etc.
|
TIntermediate& intermediate, // returned tree, etc.
|
||||||
std::string* outputString)
|
std::string* outputString,
|
||||||
|
TEnvironment* environment = nullptr)
|
||||||
{
|
{
|
||||||
DoPreprocessing parser(outputString);
|
DoPreprocessing parser(outputString);
|
||||||
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
|
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
|
||||||
preamble, optLevel, resources, defaultVersion,
|
preamble, optLevel, resources, defaultVersion,
|
||||||
defaultProfile, forceDefaultVersionAndProfile,
|
defaultProfile, forceDefaultVersionAndProfile,
|
||||||
forwardCompatible, messages, intermediate, parser,
|
forwardCompatible, messages, intermediate, parser,
|
||||||
false, includer);
|
false, includer, "", environment);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1757,6 +1767,7 @@ TShader::TShader(EShLanguage s)
|
|||||||
// clear environment (avoid constructors in them for use in a C interface)
|
// clear environment (avoid constructors in them for use in a C interface)
|
||||||
environment.input.languageFamily = EShSourceNone;
|
environment.input.languageFamily = EShSourceNone;
|
||||||
environment.input.dialect = EShClientNone;
|
environment.input.dialect = EShClientNone;
|
||||||
|
environment.input.vulkanRulesRelaxed = false;
|
||||||
environment.client.client = EShClientNone;
|
environment.client.client = EShClientNone;
|
||||||
environment.target.language = EShTargetNone;
|
environment.target.language = EShTargetNone;
|
||||||
environment.target.hlslFunctionality1 = false;
|
environment.target.hlslFunctionality1 = false;
|
||||||
@@ -1810,6 +1821,11 @@ void TShader::addProcesses(const std::vector<std::string>& p)
|
|||||||
intermediate->addProcesses(p);
|
intermediate->addProcesses(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TShader::setUniqueId(unsigned long long id)
|
||||||
|
{
|
||||||
|
intermediate->setUniqueId(id);
|
||||||
|
}
|
||||||
|
|
||||||
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
|
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
|
||||||
void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
|
void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
|
||||||
|
|
||||||
@@ -1858,6 +1874,15 @@ void TShader::setResourceSetBinding(const std::vector<std::string>& base) { in
|
|||||||
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
|
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void TShader::addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) { intermediate->addBlockStorageOverride(nameStr, backing); }
|
||||||
|
|
||||||
|
void TShader::setGlobalUniformBlockName(const char* name) { intermediate->setGlobalUniformBlockName(name); }
|
||||||
|
void TShader::setGlobalUniformSet(unsigned int set) { intermediate->setGlobalUniformSet(set); }
|
||||||
|
void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setGlobalUniformBinding(binding); }
|
||||||
|
|
||||||
|
void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); }
|
||||||
|
void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); }
|
||||||
|
|
||||||
#ifdef ENABLE_HLSL
|
#ifdef ENABLE_HLSL
|
||||||
// See comment above TDefaultHlslIoMapper in iomapper.cpp:
|
// See comment above TDefaultHlslIoMapper in iomapper.cpp:
|
||||||
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
|
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
|
||||||
@@ -1909,7 +1934,8 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources,
|
|||||||
return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
|
return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
|
||||||
EShOptNone, builtInResources, defaultVersion,
|
EShOptNone, builtInResources, defaultVersion,
|
||||||
defaultProfile, forceDefaultVersionAndProfile,
|
defaultProfile, forceDefaultVersionAndProfile,
|
||||||
forwardCompatible, message, includer, *intermediate, output_string);
|
forwardCompatible, message, includer, *intermediate, output_string,
|
||||||
|
&environment);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1972,7 +1998,10 @@ bool TProgram::link(EShMessages messages)
|
|||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Link: cross-stage error checking
|
if (!error) {
|
||||||
|
if (! crossStageCheck(messages))
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
return ! error;
|
return ! error;
|
||||||
}
|
}
|
||||||
@@ -2016,7 +2045,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
|
|||||||
intermediate[stage] = new TIntermediate(stage,
|
intermediate[stage] = new TIntermediate(stage,
|
||||||
firstIntermediate->getVersion(),
|
firstIntermediate->getVersion(),
|
||||||
firstIntermediate->getProfile());
|
firstIntermediate->getProfile());
|
||||||
|
intermediate[stage]->setLimits(firstIntermediate->getLimits());
|
||||||
|
|
||||||
// The new TIntermediate must use the same origin as the original TIntermediates.
|
// The new TIntermediate must use the same origin as the original TIntermediates.
|
||||||
// Otherwise linking will fail due to different coordinate systems.
|
// Otherwise linking will fail due to different coordinate systems.
|
||||||
@@ -2049,6 +2078,69 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
|
|||||||
return intermediate[stage]->getNumErrors() == 0;
|
return intermediate[stage]->getNumErrors() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check that there are no errors in linker objects accross stages
|
||||||
|
//
|
||||||
|
// Return true if no errors.
|
||||||
|
//
|
||||||
|
bool TProgram::crossStageCheck(EShMessages) {
|
||||||
|
|
||||||
|
// make temporary intermediates to hold the linkage symbols for each linking interface
|
||||||
|
// while we do the checks
|
||||||
|
// Independent interfaces are:
|
||||||
|
// all uniform variables and blocks
|
||||||
|
// all buffer blocks
|
||||||
|
// all in/out on a stage boundary
|
||||||
|
|
||||||
|
TVector<TIntermediate*> activeStages;
|
||||||
|
for (int s = 0; s < EShLangCount; ++s) {
|
||||||
|
if (intermediate[s])
|
||||||
|
activeStages.push_back(intermediate[s]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no extra linking if there is only one stage
|
||||||
|
if (! (activeStages.size() > 1))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// setup temporary tree to hold unfirom objects from different stages
|
||||||
|
TIntermediate* firstIntermediate = activeStages.front();
|
||||||
|
TIntermediate uniforms(EShLangCount,
|
||||||
|
firstIntermediate->getVersion(),
|
||||||
|
firstIntermediate->getProfile());
|
||||||
|
uniforms.setSpv(firstIntermediate->getSpv());
|
||||||
|
|
||||||
|
TIntermAggregate uniformObjects(EOpLinkerObjects);
|
||||||
|
TIntermAggregate root(EOpSequence);
|
||||||
|
root.getSequence().push_back(&uniformObjects);
|
||||||
|
uniforms.setTreeRoot(&root);
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
// merge uniforms from all stages into a single intermediate
|
||||||
|
for (unsigned int i = 0; i < activeStages.size(); ++i) {
|
||||||
|
uniforms.mergeUniformObjects(*infoSink, *activeStages[i]);
|
||||||
|
}
|
||||||
|
error |= uniforms.getNumErrors() != 0;
|
||||||
|
|
||||||
|
// copy final definition of global block back into each stage
|
||||||
|
for (unsigned int i = 0; i < activeStages.size(); ++i) {
|
||||||
|
// We only want to merge into already existing global uniform blocks.
|
||||||
|
// A stage that doesn't already know about the global doesn't care about it's content.
|
||||||
|
// Otherwise we end up pointing to the same object between different stages
|
||||||
|
// and that will break binding/set remappings
|
||||||
|
bool mergeExistingOnly = true;
|
||||||
|
activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms, mergeExistingOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare cross stage symbols for each stage boundary
|
||||||
|
for (unsigned int i = 1; i < activeStages.size(); ++i) {
|
||||||
|
activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]);
|
||||||
|
error |= (activeStages[i - 1]->getNumErrors() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !error;
|
||||||
|
}
|
||||||
|
|
||||||
const char* TProgram::getInfoLog()
|
const char* TProgram::getInfoLog()
|
||||||
{
|
{
|
||||||
return infoSink->info.c_str();
|
return infoSink->info.c_str();
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ void TType::buildMangledName(TString& mangledName) const
|
|||||||
#endif
|
#endif
|
||||||
case EbtInt: mangledName += "i"; break;
|
case EbtInt: mangledName += "i"; break;
|
||||||
case EbtUint: mangledName += "u"; break;
|
case EbtUint: mangledName += "u"; break;
|
||||||
|
case EbtInt64: mangledName += "i64"; break;
|
||||||
|
case EbtUint64: mangledName += "u64"; break;
|
||||||
default: break; // some compilers want this
|
default: break; // some compilers want this
|
||||||
}
|
}
|
||||||
if (sampler.isImageClass())
|
if (sampler.isImageClass())
|
||||||
@@ -146,6 +148,8 @@ void TType::buildMangledName(TString& mangledName) const
|
|||||||
if (typeName)
|
if (typeName)
|
||||||
mangledName += *typeName;
|
mangledName += *typeName;
|
||||||
for (unsigned int i = 0; i < structure->size(); ++i) {
|
for (unsigned int i = 0; i < structure->size(); ++i) {
|
||||||
|
if ((*structure)[i].type->getBasicType() == EbtVoid)
|
||||||
|
continue;
|
||||||
mangledName += '-';
|
mangledName += '-';
|
||||||
(*structure)[i].type->buildMangledName(mangledName);
|
(*structure)[i].type->buildMangledName(mangledName);
|
||||||
}
|
}
|
||||||
@@ -166,7 +170,7 @@ void TType::buildMangledName(TString& mangledName) const
|
|||||||
for (int i = 0; i < arraySizes->getNumDims(); ++i) {
|
for (int i = 0; i < arraySizes->getNumDims(); ++i) {
|
||||||
if (arraySizes->getDimNode(i)) {
|
if (arraySizes->getDimNode(i)) {
|
||||||
if (arraySizes->getDimNode(i)->getAsSymbolNode())
|
if (arraySizes->getDimNode(i)->getAsSymbolNode())
|
||||||
snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
|
snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
|
||||||
else
|
else
|
||||||
snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
|
snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ public:
|
|||||||
virtual const TAnonMember* getAsAnonMember() const { return 0; }
|
virtual const TAnonMember* getAsAnonMember() const { return 0; }
|
||||||
virtual const TType& getType() const = 0;
|
virtual const TType& getType() const = 0;
|
||||||
virtual TType& getWritableType() = 0;
|
virtual TType& getWritableType() = 0;
|
||||||
virtual void setUniqueId(int id) { uniqueId = id; }
|
virtual void setUniqueId(long long id) { uniqueId = id; }
|
||||||
virtual int getUniqueId() const { return uniqueId; }
|
virtual long long getUniqueId() const { return uniqueId; }
|
||||||
virtual void setExtensions(int numExts, const char* const exts[])
|
virtual void setExtensions(int numExts, const char* const exts[])
|
||||||
{
|
{
|
||||||
assert(extensions == 0);
|
assert(extensions == 0);
|
||||||
@@ -130,7 +130,7 @@ protected:
|
|||||||
TSymbol& operator=(const TSymbol&);
|
TSymbol& operator=(const TSymbol&);
|
||||||
|
|
||||||
const TString *name;
|
const TString *name;
|
||||||
unsigned int uniqueId; // For cross-scope comparing during code generation
|
unsigned long long uniqueId; // For cross-scope comparing during code generation
|
||||||
|
|
||||||
// For tracking what extensions must be present
|
// For tracking what extensions must be present
|
||||||
// (don't use if correct version/profile is present).
|
// (don't use if correct version/profile is present).
|
||||||
@@ -612,21 +612,28 @@ public:
|
|||||||
// 3: user-shader globals
|
// 3: user-shader globals
|
||||||
//
|
//
|
||||||
protected:
|
protected:
|
||||||
|
static const uint32_t LevelFlagBitOffset = 56;
|
||||||
static const int globalLevel = 3;
|
static const int globalLevel = 3;
|
||||||
bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
|
static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
|
||||||
bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
|
static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
|
||||||
bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
|
static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
|
||||||
public:
|
public:
|
||||||
bool isEmpty() { return table.size() == 0; }
|
bool isEmpty() { return table.size() == 0; }
|
||||||
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
|
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
|
||||||
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
|
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
|
||||||
|
static bool isBuiltInSymbol(long long uniqueId) {
|
||||||
|
int level = static_cast<int>(uniqueId >> LevelFlagBitOffset);
|
||||||
|
return isBuiltInLevel(level);
|
||||||
|
}
|
||||||
|
static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1;
|
||||||
|
static const uint32_t MaxLevelInUniqueID = 127;
|
||||||
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
|
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
|
||||||
void setSeparateNameSpaces() { separateNameSpaces = true; }
|
void setSeparateNameSpaces() { separateNameSpaces = true; }
|
||||||
|
|
||||||
void push()
|
void push()
|
||||||
{
|
{
|
||||||
table.push_back(new TSymbolTableLevel);
|
table.push_back(new TSymbolTableLevel);
|
||||||
|
updateUniqueIdLevelFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a new symbol-table level to represent the scope introduced by a structure
|
// Make a new symbol-table level to represent the scope introduced by a structure
|
||||||
@@ -639,6 +646,7 @@ public:
|
|||||||
{
|
{
|
||||||
assert(thisSymbol.getName().size() == 0);
|
assert(thisSymbol.getName().size() == 0);
|
||||||
table.push_back(new TSymbolTableLevel);
|
table.push_back(new TSymbolTableLevel);
|
||||||
|
updateUniqueIdLevelFlag();
|
||||||
table.back()->setThisLevel();
|
table.back()->setThisLevel();
|
||||||
insert(thisSymbol);
|
insert(thisSymbol);
|
||||||
}
|
}
|
||||||
@@ -648,6 +656,7 @@ public:
|
|||||||
table[currentLevel()]->getPreviousDefaultPrecisions(p);
|
table[currentLevel()]->getPreviousDefaultPrecisions(p);
|
||||||
delete table.back();
|
delete table.back();
|
||||||
table.pop_back();
|
table.pop_back();
|
||||||
|
updateUniqueIdLevelFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -685,6 +694,16 @@ public:
|
|||||||
return table[currentLevel()]->amend(symbol, firstNewMember);
|
return table[currentLevel()]->amend(symbol, firstNewMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the level info in symbol's unique ID to current level
|
||||||
|
void amendSymbolIdLevel(TSymbol& symbol)
|
||||||
|
{
|
||||||
|
// clamp level to avoid overflow
|
||||||
|
uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
|
||||||
|
uint64_t symbolId = symbol.getUniqueId();
|
||||||
|
symbolId &= uniqueIdMask;
|
||||||
|
symbolId |= (level << LevelFlagBitOffset);
|
||||||
|
symbol.setUniqueId(symbolId);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// To allocate an internal temporary, which will need to be uniquely
|
// To allocate an internal temporary, which will need to be uniquely
|
||||||
// identified by the consumer of the AST, but never need to
|
// identified by the consumer of the AST, but never need to
|
||||||
@@ -853,7 +872,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getMaxSymbolId() { return uniqueId; }
|
long long getMaxSymbolId() { return uniqueId; }
|
||||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||||
void dump(TInfoSink& infoSink, bool complete = false) const;
|
void dump(TInfoSink& infoSink, bool complete = false) const;
|
||||||
#endif
|
#endif
|
||||||
@@ -867,14 +886,27 @@ public:
|
|||||||
table[level]->readOnly();
|
table[level]->readOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add current level in the high-bits of unique id
|
||||||
|
void updateUniqueIdLevelFlag() {
|
||||||
|
// clamp level to avoid overflow
|
||||||
|
uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
|
||||||
|
uniqueId &= uniqueIdMask;
|
||||||
|
uniqueId |= (level << LevelFlagBitOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void overwriteUniqueId(long long id)
|
||||||
|
{
|
||||||
|
uniqueId = id;
|
||||||
|
updateUniqueIdLevelFlag();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TSymbolTable(TSymbolTable&);
|
TSymbolTable(TSymbolTable&);
|
||||||
TSymbolTable& operator=(TSymbolTableLevel&);
|
TSymbolTable& operator=(TSymbolTableLevel&);
|
||||||
|
|
||||||
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
||||||
|
|
||||||
std::vector<TSymbolTableLevel*> table;
|
std::vector<TSymbolTableLevel*> table;
|
||||||
int uniqueId; // for unique identification in code generation
|
long long uniqueId; // for unique identification in code generation
|
||||||
bool noBuiltInRedeclarations;
|
bool noBuiltInRedeclarations;
|
||||||
bool separateNameSpaces;
|
bool separateNameSpaces;
|
||||||
unsigned int adoptedLevels;
|
unsigned int adoptedLevels;
|
||||||
|
|||||||
@@ -306,6 +306,7 @@ void TParseVersions::initializeExtensionBehavior()
|
|||||||
extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
|
extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
|
||||||
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;
|
||||||
|
|
||||||
// OES matching AEP
|
// OES matching AEP
|
||||||
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
|
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
|
||||||
@@ -328,6 +329,10 @@ void TParseVersions::initializeExtensionBehavior()
|
|||||||
extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
|
extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
|
||||||
extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable;
|
extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable;
|
||||||
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
|
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
|
||||||
|
extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable;
|
||||||
|
extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable;
|
||||||
|
extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable;
|
||||||
|
extensionBehavior[E_GL_EXT_shared_memory_block] = EBhDisable;
|
||||||
|
|
||||||
// OVR extensions
|
// OVR extensions
|
||||||
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
|
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
|
||||||
@@ -373,6 +378,7 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_EXT_YUV_target 1\n"
|
"#define GL_EXT_YUV_target 1\n"
|
||||||
"#define GL_EXT_shader_texture_lod 1\n"
|
"#define GL_EXT_shader_texture_lod 1\n"
|
||||||
"#define GL_EXT_shadow_samplers 1\n"
|
"#define GL_EXT_shadow_samplers 1\n"
|
||||||
|
"#define GL_EXT_fragment_shading_rate 1\n"
|
||||||
|
|
||||||
// AEP
|
// AEP
|
||||||
"#define GL_ANDROID_extension_pack_es31a 1\n"
|
"#define GL_ANDROID_extension_pack_es31a 1\n"
|
||||||
@@ -406,11 +412,14 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
|
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
if (isEsProfile() && version >= 300) {
|
if (version >= 300) {
|
||||||
preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
|
preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
|
||||||
}
|
}
|
||||||
|
if (version >= 310) {
|
||||||
|
preamble += "#define GL_EXT_null_initializer 1\n";
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else { // !isEsProfile()
|
||||||
preamble =
|
preamble =
|
||||||
"#define GL_FRAGMENT_PRECISION_HIGH 1\n"
|
"#define GL_FRAGMENT_PRECISION_HIGH 1\n"
|
||||||
"#define GL_EXT_texture_array 1\n"
|
"#define GL_EXT_texture_array 1\n"
|
||||||
@@ -466,6 +475,8 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_EXT_buffer_reference_uvec2 1\n"
|
"#define GL_EXT_buffer_reference_uvec2 1\n"
|
||||||
"#define GL_EXT_demote_to_helper_invocation 1\n"
|
"#define GL_EXT_demote_to_helper_invocation 1\n"
|
||||||
"#define GL_EXT_debug_printf 1\n"
|
"#define GL_EXT_debug_printf 1\n"
|
||||||
|
"#define GL_EXT_fragment_shading_rate 1\n"
|
||||||
|
"#define GL_EXT_shared_memory_block 1\n"
|
||||||
|
|
||||||
// GL_KHR_shader_subgroup
|
// GL_KHR_shader_subgroup
|
||||||
"#define GL_KHR_shader_subgroup_basic 1\n"
|
"#define GL_KHR_shader_subgroup_basic 1\n"
|
||||||
@@ -477,6 +488,7 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_KHR_shader_subgroup_clustered 1\n"
|
"#define GL_KHR_shader_subgroup_clustered 1\n"
|
||||||
"#define GL_KHR_shader_subgroup_quad 1\n"
|
"#define GL_KHR_shader_subgroup_quad 1\n"
|
||||||
|
|
||||||
|
"#define GL_EXT_shader_image_int64 1\n"
|
||||||
"#define GL_EXT_shader_atomic_int64 1\n"
|
"#define GL_EXT_shader_atomic_int64 1\n"
|
||||||
"#define GL_EXT_shader_realtime_clock 1\n"
|
"#define GL_EXT_shader_realtime_clock 1\n"
|
||||||
"#define GL_EXT_ray_tracing 1\n"
|
"#define GL_EXT_ray_tracing 1\n"
|
||||||
@@ -535,6 +547,9 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
if (profile == ECompatibilityProfile)
|
if (profile == ECompatibilityProfile)
|
||||||
preamble += "#define GL_compatibility_profile 1\n";
|
preamble += "#define GL_compatibility_profile 1\n";
|
||||||
}
|
}
|
||||||
|
if (version >= 140) {
|
||||||
|
preamble += "#define GL_EXT_null_initializer 1\n";
|
||||||
|
}
|
||||||
#endif // GLSLANG_WEB
|
#endif // GLSLANG_WEB
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,6 +576,11 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_GOOGLE_include_directive 1\n"
|
"#define GL_GOOGLE_include_directive 1\n"
|
||||||
"#define GL_KHR_blend_equation_advanced 1\n"
|
"#define GL_KHR_blend_equation_advanced 1\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
// other general extensions
|
||||||
|
preamble +=
|
||||||
|
"#define GL_EXT_terminate_invocation 1\n"
|
||||||
|
;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #define VULKAN XXXX
|
// #define VULKAN XXXX
|
||||||
@@ -1256,7 +1276,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
|
|||||||
// Call for any operation removed because Vulkan SPIR-V is being generated.
|
// Call for any operation removed because Vulkan SPIR-V is being generated.
|
||||||
void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
|
void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
|
||||||
{
|
{
|
||||||
if (spvVersion.vulkan > 0)
|
if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
|
||||||
error(loc, "not allowed when using GLSL for Vulkan", op, "");
|
error(loc, "not allowed when using GLSL for Vulkan", op, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,11 +87,12 @@ inline const char* ProfileName(EProfile profile)
|
|||||||
// The union of all requested rule sets will be applied.
|
// The union of all requested rule sets will be applied.
|
||||||
//
|
//
|
||||||
struct SpvVersion {
|
struct SpvVersion {
|
||||||
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
|
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {}
|
||||||
unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
|
unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
|
||||||
int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
|
int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
|
||||||
int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use
|
int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use
|
||||||
int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
|
int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
|
||||||
|
bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -200,6 +201,10 @@ const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"
|
|||||||
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
|
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
|
||||||
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
|
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
|
||||||
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
|
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
|
||||||
|
const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate";
|
||||||
|
const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64";
|
||||||
|
const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer";
|
||||||
|
const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block";
|
||||||
|
|
||||||
// Arrays of extensions for the above viewportEXTs duplications
|
// Arrays of extensions for the above viewportEXTs duplications
|
||||||
|
|
||||||
@@ -298,6 +303,7 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shad
|
|||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
|
const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
|
||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
|
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
|
||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
|
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
|
||||||
|
const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation";
|
||||||
|
|
||||||
const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
|
const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,9 @@
|
|||||||
#define GL_INT64_VEC4_ARB 0x8FEB
|
#define GL_INT64_VEC4_ARB 0x8FEB
|
||||||
|
|
||||||
#define GL_UNSIGNED_INT64_ARB 0x140F
|
#define GL_UNSIGNED_INT64_ARB 0x140F
|
||||||
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5
|
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
|
||||||
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6
|
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
|
||||||
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7
|
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
|
||||||
#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
|
#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
|
||||||
#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
|
#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
|
||||||
#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
|
#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
|||||||
/* A Bison parser, made by GNU Bison 3.0.4. */
|
/* A Bison parser, made by GNU Bison 3.7.4. */
|
||||||
|
|
||||||
/* Bison interface for Yacc-like parsers in C
|
/* Bison interface for Yacc-like parsers in C
|
||||||
|
|
||||||
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
|
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
|
||||||
|
Inc.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,6 +31,10 @@
|
|||||||
This special exception was added by the Free Software Foundation in
|
This special exception was added by the Free Software Foundation in
|
||||||
version 2.2 of Bison. */
|
version 2.2 of Bison. */
|
||||||
|
|
||||||
|
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
|
||||||
|
especially those whose name start with YY_ or yy_. They are
|
||||||
|
private implementation details that can be changed or removed. */
|
||||||
|
|
||||||
#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
||||||
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
|
||||||
/* Debug traces. */
|
/* Debug traces. */
|
||||||
@@ -40,437 +45,466 @@
|
|||||||
extern int yydebug;
|
extern int yydebug;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Token type. */
|
/* Token kinds. */
|
||||||
#ifndef YYTOKENTYPE
|
#ifndef YYTOKENTYPE
|
||||||
# define YYTOKENTYPE
|
# define YYTOKENTYPE
|
||||||
enum yytokentype
|
enum yytokentype
|
||||||
{
|
{
|
||||||
CONST = 258,
|
YYEMPTY = -2,
|
||||||
BOOL = 259,
|
YYEOF = 0, /* "end of file" */
|
||||||
INT = 260,
|
YYerror = 256, /* error */
|
||||||
UINT = 261,
|
YYUNDEF = 257, /* "invalid token" */
|
||||||
FLOAT = 262,
|
CONST = 258, /* CONST */
|
||||||
BVEC2 = 263,
|
BOOL = 259, /* BOOL */
|
||||||
BVEC3 = 264,
|
INT = 260, /* INT */
|
||||||
BVEC4 = 265,
|
UINT = 261, /* UINT */
|
||||||
IVEC2 = 266,
|
FLOAT = 262, /* FLOAT */
|
||||||
IVEC3 = 267,
|
BVEC2 = 263, /* BVEC2 */
|
||||||
IVEC4 = 268,
|
BVEC3 = 264, /* BVEC3 */
|
||||||
UVEC2 = 269,
|
BVEC4 = 265, /* BVEC4 */
|
||||||
UVEC3 = 270,
|
IVEC2 = 266, /* IVEC2 */
|
||||||
UVEC4 = 271,
|
IVEC3 = 267, /* IVEC3 */
|
||||||
VEC2 = 272,
|
IVEC4 = 268, /* IVEC4 */
|
||||||
VEC3 = 273,
|
UVEC2 = 269, /* UVEC2 */
|
||||||
VEC4 = 274,
|
UVEC3 = 270, /* UVEC3 */
|
||||||
MAT2 = 275,
|
UVEC4 = 271, /* UVEC4 */
|
||||||
MAT3 = 276,
|
VEC2 = 272, /* VEC2 */
|
||||||
MAT4 = 277,
|
VEC3 = 273, /* VEC3 */
|
||||||
MAT2X2 = 278,
|
VEC4 = 274, /* VEC4 */
|
||||||
MAT2X3 = 279,
|
MAT2 = 275, /* MAT2 */
|
||||||
MAT2X4 = 280,
|
MAT3 = 276, /* MAT3 */
|
||||||
MAT3X2 = 281,
|
MAT4 = 277, /* MAT4 */
|
||||||
MAT3X3 = 282,
|
MAT2X2 = 278, /* MAT2X2 */
|
||||||
MAT3X4 = 283,
|
MAT2X3 = 279, /* MAT2X3 */
|
||||||
MAT4X2 = 284,
|
MAT2X4 = 280, /* MAT2X4 */
|
||||||
MAT4X3 = 285,
|
MAT3X2 = 281, /* MAT3X2 */
|
||||||
MAT4X4 = 286,
|
MAT3X3 = 282, /* MAT3X3 */
|
||||||
SAMPLER2D = 287,
|
MAT3X4 = 283, /* MAT3X4 */
|
||||||
SAMPLER3D = 288,
|
MAT4X2 = 284, /* MAT4X2 */
|
||||||
SAMPLERCUBE = 289,
|
MAT4X3 = 285, /* MAT4X3 */
|
||||||
SAMPLER2DSHADOW = 290,
|
MAT4X4 = 286, /* MAT4X4 */
|
||||||
SAMPLERCUBESHADOW = 291,
|
SAMPLER2D = 287, /* SAMPLER2D */
|
||||||
SAMPLER2DARRAY = 292,
|
SAMPLER3D = 288, /* SAMPLER3D */
|
||||||
SAMPLER2DARRAYSHADOW = 293,
|
SAMPLERCUBE = 289, /* SAMPLERCUBE */
|
||||||
ISAMPLER2D = 294,
|
SAMPLER2DSHADOW = 290, /* SAMPLER2DSHADOW */
|
||||||
ISAMPLER3D = 295,
|
SAMPLERCUBESHADOW = 291, /* SAMPLERCUBESHADOW */
|
||||||
ISAMPLERCUBE = 296,
|
SAMPLER2DARRAY = 292, /* SAMPLER2DARRAY */
|
||||||
ISAMPLER2DARRAY = 297,
|
SAMPLER2DARRAYSHADOW = 293, /* SAMPLER2DARRAYSHADOW */
|
||||||
USAMPLER2D = 298,
|
ISAMPLER2D = 294, /* ISAMPLER2D */
|
||||||
USAMPLER3D = 299,
|
ISAMPLER3D = 295, /* ISAMPLER3D */
|
||||||
USAMPLERCUBE = 300,
|
ISAMPLERCUBE = 296, /* ISAMPLERCUBE */
|
||||||
USAMPLER2DARRAY = 301,
|
ISAMPLER2DARRAY = 297, /* ISAMPLER2DARRAY */
|
||||||
SAMPLER = 302,
|
USAMPLER2D = 298, /* USAMPLER2D */
|
||||||
SAMPLERSHADOW = 303,
|
USAMPLER3D = 299, /* USAMPLER3D */
|
||||||
TEXTURE2D = 304,
|
USAMPLERCUBE = 300, /* USAMPLERCUBE */
|
||||||
TEXTURE3D = 305,
|
USAMPLER2DARRAY = 301, /* USAMPLER2DARRAY */
|
||||||
TEXTURECUBE = 306,
|
SAMPLER = 302, /* SAMPLER */
|
||||||
TEXTURE2DARRAY = 307,
|
SAMPLERSHADOW = 303, /* SAMPLERSHADOW */
|
||||||
ITEXTURE2D = 308,
|
TEXTURE2D = 304, /* TEXTURE2D */
|
||||||
ITEXTURE3D = 309,
|
TEXTURE3D = 305, /* TEXTURE3D */
|
||||||
ITEXTURECUBE = 310,
|
TEXTURECUBE = 306, /* TEXTURECUBE */
|
||||||
ITEXTURE2DARRAY = 311,
|
TEXTURE2DARRAY = 307, /* TEXTURE2DARRAY */
|
||||||
UTEXTURE2D = 312,
|
ITEXTURE2D = 308, /* ITEXTURE2D */
|
||||||
UTEXTURE3D = 313,
|
ITEXTURE3D = 309, /* ITEXTURE3D */
|
||||||
UTEXTURECUBE = 314,
|
ITEXTURECUBE = 310, /* ITEXTURECUBE */
|
||||||
UTEXTURE2DARRAY = 315,
|
ITEXTURE2DARRAY = 311, /* ITEXTURE2DARRAY */
|
||||||
ATTRIBUTE = 316,
|
UTEXTURE2D = 312, /* UTEXTURE2D */
|
||||||
VARYING = 317,
|
UTEXTURE3D = 313, /* UTEXTURE3D */
|
||||||
FLOAT16_T = 318,
|
UTEXTURECUBE = 314, /* UTEXTURECUBE */
|
||||||
FLOAT32_T = 319,
|
UTEXTURE2DARRAY = 315, /* UTEXTURE2DARRAY */
|
||||||
DOUBLE = 320,
|
ATTRIBUTE = 316, /* ATTRIBUTE */
|
||||||
FLOAT64_T = 321,
|
VARYING = 317, /* VARYING */
|
||||||
INT64_T = 322,
|
FLOAT16_T = 318, /* FLOAT16_T */
|
||||||
UINT64_T = 323,
|
FLOAT32_T = 319, /* FLOAT32_T */
|
||||||
INT32_T = 324,
|
DOUBLE = 320, /* DOUBLE */
|
||||||
UINT32_T = 325,
|
FLOAT64_T = 321, /* FLOAT64_T */
|
||||||
INT16_T = 326,
|
INT64_T = 322, /* INT64_T */
|
||||||
UINT16_T = 327,
|
UINT64_T = 323, /* UINT64_T */
|
||||||
INT8_T = 328,
|
INT32_T = 324, /* INT32_T */
|
||||||
UINT8_T = 329,
|
UINT32_T = 325, /* UINT32_T */
|
||||||
I64VEC2 = 330,
|
INT16_T = 326, /* INT16_T */
|
||||||
I64VEC3 = 331,
|
UINT16_T = 327, /* UINT16_T */
|
||||||
I64VEC4 = 332,
|
INT8_T = 328, /* INT8_T */
|
||||||
U64VEC2 = 333,
|
UINT8_T = 329, /* UINT8_T */
|
||||||
U64VEC3 = 334,
|
I64VEC2 = 330, /* I64VEC2 */
|
||||||
U64VEC4 = 335,
|
I64VEC3 = 331, /* I64VEC3 */
|
||||||
I32VEC2 = 336,
|
I64VEC4 = 332, /* I64VEC4 */
|
||||||
I32VEC3 = 337,
|
U64VEC2 = 333, /* U64VEC2 */
|
||||||
I32VEC4 = 338,
|
U64VEC3 = 334, /* U64VEC3 */
|
||||||
U32VEC2 = 339,
|
U64VEC4 = 335, /* U64VEC4 */
|
||||||
U32VEC3 = 340,
|
I32VEC2 = 336, /* I32VEC2 */
|
||||||
U32VEC4 = 341,
|
I32VEC3 = 337, /* I32VEC3 */
|
||||||
I16VEC2 = 342,
|
I32VEC4 = 338, /* I32VEC4 */
|
||||||
I16VEC3 = 343,
|
U32VEC2 = 339, /* U32VEC2 */
|
||||||
I16VEC4 = 344,
|
U32VEC3 = 340, /* U32VEC3 */
|
||||||
U16VEC2 = 345,
|
U32VEC4 = 341, /* U32VEC4 */
|
||||||
U16VEC3 = 346,
|
I16VEC2 = 342, /* I16VEC2 */
|
||||||
U16VEC4 = 347,
|
I16VEC3 = 343, /* I16VEC3 */
|
||||||
I8VEC2 = 348,
|
I16VEC4 = 344, /* I16VEC4 */
|
||||||
I8VEC3 = 349,
|
U16VEC2 = 345, /* U16VEC2 */
|
||||||
I8VEC4 = 350,
|
U16VEC3 = 346, /* U16VEC3 */
|
||||||
U8VEC2 = 351,
|
U16VEC4 = 347, /* U16VEC4 */
|
||||||
U8VEC3 = 352,
|
I8VEC2 = 348, /* I8VEC2 */
|
||||||
U8VEC4 = 353,
|
I8VEC3 = 349, /* I8VEC3 */
|
||||||
DVEC2 = 354,
|
I8VEC4 = 350, /* I8VEC4 */
|
||||||
DVEC3 = 355,
|
U8VEC2 = 351, /* U8VEC2 */
|
||||||
DVEC4 = 356,
|
U8VEC3 = 352, /* U8VEC3 */
|
||||||
DMAT2 = 357,
|
U8VEC4 = 353, /* U8VEC4 */
|
||||||
DMAT3 = 358,
|
DVEC2 = 354, /* DVEC2 */
|
||||||
DMAT4 = 359,
|
DVEC3 = 355, /* DVEC3 */
|
||||||
F16VEC2 = 360,
|
DVEC4 = 356, /* DVEC4 */
|
||||||
F16VEC3 = 361,
|
DMAT2 = 357, /* DMAT2 */
|
||||||
F16VEC4 = 362,
|
DMAT3 = 358, /* DMAT3 */
|
||||||
F16MAT2 = 363,
|
DMAT4 = 359, /* DMAT4 */
|
||||||
F16MAT3 = 364,
|
F16VEC2 = 360, /* F16VEC2 */
|
||||||
F16MAT4 = 365,
|
F16VEC3 = 361, /* F16VEC3 */
|
||||||
F32VEC2 = 366,
|
F16VEC4 = 362, /* F16VEC4 */
|
||||||
F32VEC3 = 367,
|
F16MAT2 = 363, /* F16MAT2 */
|
||||||
F32VEC4 = 368,
|
F16MAT3 = 364, /* F16MAT3 */
|
||||||
F32MAT2 = 369,
|
F16MAT4 = 365, /* F16MAT4 */
|
||||||
F32MAT3 = 370,
|
F32VEC2 = 366, /* F32VEC2 */
|
||||||
F32MAT4 = 371,
|
F32VEC3 = 367, /* F32VEC3 */
|
||||||
F64VEC2 = 372,
|
F32VEC4 = 368, /* F32VEC4 */
|
||||||
F64VEC3 = 373,
|
F32MAT2 = 369, /* F32MAT2 */
|
||||||
F64VEC4 = 374,
|
F32MAT3 = 370, /* F32MAT3 */
|
||||||
F64MAT2 = 375,
|
F32MAT4 = 371, /* F32MAT4 */
|
||||||
F64MAT3 = 376,
|
F64VEC2 = 372, /* F64VEC2 */
|
||||||
F64MAT4 = 377,
|
F64VEC3 = 373, /* F64VEC3 */
|
||||||
DMAT2X2 = 378,
|
F64VEC4 = 374, /* F64VEC4 */
|
||||||
DMAT2X3 = 379,
|
F64MAT2 = 375, /* F64MAT2 */
|
||||||
DMAT2X4 = 380,
|
F64MAT3 = 376, /* F64MAT3 */
|
||||||
DMAT3X2 = 381,
|
F64MAT4 = 377, /* F64MAT4 */
|
||||||
DMAT3X3 = 382,
|
DMAT2X2 = 378, /* DMAT2X2 */
|
||||||
DMAT3X4 = 383,
|
DMAT2X3 = 379, /* DMAT2X3 */
|
||||||
DMAT4X2 = 384,
|
DMAT2X4 = 380, /* DMAT2X4 */
|
||||||
DMAT4X3 = 385,
|
DMAT3X2 = 381, /* DMAT3X2 */
|
||||||
DMAT4X4 = 386,
|
DMAT3X3 = 382, /* DMAT3X3 */
|
||||||
F16MAT2X2 = 387,
|
DMAT3X4 = 383, /* DMAT3X4 */
|
||||||
F16MAT2X3 = 388,
|
DMAT4X2 = 384, /* DMAT4X2 */
|
||||||
F16MAT2X4 = 389,
|
DMAT4X3 = 385, /* DMAT4X3 */
|
||||||
F16MAT3X2 = 390,
|
DMAT4X4 = 386, /* DMAT4X4 */
|
||||||
F16MAT3X3 = 391,
|
F16MAT2X2 = 387, /* F16MAT2X2 */
|
||||||
F16MAT3X4 = 392,
|
F16MAT2X3 = 388, /* F16MAT2X3 */
|
||||||
F16MAT4X2 = 393,
|
F16MAT2X4 = 389, /* F16MAT2X4 */
|
||||||
F16MAT4X3 = 394,
|
F16MAT3X2 = 390, /* F16MAT3X2 */
|
||||||
F16MAT4X4 = 395,
|
F16MAT3X3 = 391, /* F16MAT3X3 */
|
||||||
F32MAT2X2 = 396,
|
F16MAT3X4 = 392, /* F16MAT3X4 */
|
||||||
F32MAT2X3 = 397,
|
F16MAT4X2 = 393, /* F16MAT4X2 */
|
||||||
F32MAT2X4 = 398,
|
F16MAT4X3 = 394, /* F16MAT4X3 */
|
||||||
F32MAT3X2 = 399,
|
F16MAT4X4 = 395, /* F16MAT4X4 */
|
||||||
F32MAT3X3 = 400,
|
F32MAT2X2 = 396, /* F32MAT2X2 */
|
||||||
F32MAT3X4 = 401,
|
F32MAT2X3 = 397, /* F32MAT2X3 */
|
||||||
F32MAT4X2 = 402,
|
F32MAT2X4 = 398, /* F32MAT2X4 */
|
||||||
F32MAT4X3 = 403,
|
F32MAT3X2 = 399, /* F32MAT3X2 */
|
||||||
F32MAT4X4 = 404,
|
F32MAT3X3 = 400, /* F32MAT3X3 */
|
||||||
F64MAT2X2 = 405,
|
F32MAT3X4 = 401, /* F32MAT3X4 */
|
||||||
F64MAT2X3 = 406,
|
F32MAT4X2 = 402, /* F32MAT4X2 */
|
||||||
F64MAT2X4 = 407,
|
F32MAT4X3 = 403, /* F32MAT4X3 */
|
||||||
F64MAT3X2 = 408,
|
F32MAT4X4 = 404, /* F32MAT4X4 */
|
||||||
F64MAT3X3 = 409,
|
F64MAT2X2 = 405, /* F64MAT2X2 */
|
||||||
F64MAT3X4 = 410,
|
F64MAT2X3 = 406, /* F64MAT2X3 */
|
||||||
F64MAT4X2 = 411,
|
F64MAT2X4 = 407, /* F64MAT2X4 */
|
||||||
F64MAT4X3 = 412,
|
F64MAT3X2 = 408, /* F64MAT3X2 */
|
||||||
F64MAT4X4 = 413,
|
F64MAT3X3 = 409, /* F64MAT3X3 */
|
||||||
ATOMIC_UINT = 414,
|
F64MAT3X4 = 410, /* F64MAT3X4 */
|
||||||
ACCSTRUCTNV = 415,
|
F64MAT4X2 = 411, /* F64MAT4X2 */
|
||||||
ACCSTRUCTEXT = 416,
|
F64MAT4X3 = 412, /* F64MAT4X3 */
|
||||||
RAYQUERYEXT = 417,
|
F64MAT4X4 = 413, /* F64MAT4X4 */
|
||||||
FCOOPMATNV = 418,
|
ATOMIC_UINT = 414, /* ATOMIC_UINT */
|
||||||
ICOOPMATNV = 419,
|
ACCSTRUCTNV = 415, /* ACCSTRUCTNV */
|
||||||
UCOOPMATNV = 420,
|
ACCSTRUCTEXT = 416, /* ACCSTRUCTEXT */
|
||||||
SAMPLERCUBEARRAY = 421,
|
RAYQUERYEXT = 417, /* RAYQUERYEXT */
|
||||||
SAMPLERCUBEARRAYSHADOW = 422,
|
FCOOPMATNV = 418, /* FCOOPMATNV */
|
||||||
ISAMPLERCUBEARRAY = 423,
|
ICOOPMATNV = 419, /* ICOOPMATNV */
|
||||||
USAMPLERCUBEARRAY = 424,
|
UCOOPMATNV = 420, /* UCOOPMATNV */
|
||||||
SAMPLER1D = 425,
|
SAMPLERCUBEARRAY = 421, /* SAMPLERCUBEARRAY */
|
||||||
SAMPLER1DARRAY = 426,
|
SAMPLERCUBEARRAYSHADOW = 422, /* SAMPLERCUBEARRAYSHADOW */
|
||||||
SAMPLER1DARRAYSHADOW = 427,
|
ISAMPLERCUBEARRAY = 423, /* ISAMPLERCUBEARRAY */
|
||||||
ISAMPLER1D = 428,
|
USAMPLERCUBEARRAY = 424, /* USAMPLERCUBEARRAY */
|
||||||
SAMPLER1DSHADOW = 429,
|
SAMPLER1D = 425, /* SAMPLER1D */
|
||||||
SAMPLER2DRECT = 430,
|
SAMPLER1DARRAY = 426, /* SAMPLER1DARRAY */
|
||||||
SAMPLER2DRECTSHADOW = 431,
|
SAMPLER1DARRAYSHADOW = 427, /* SAMPLER1DARRAYSHADOW */
|
||||||
ISAMPLER2DRECT = 432,
|
ISAMPLER1D = 428, /* ISAMPLER1D */
|
||||||
USAMPLER2DRECT = 433,
|
SAMPLER1DSHADOW = 429, /* SAMPLER1DSHADOW */
|
||||||
SAMPLERBUFFER = 434,
|
SAMPLER2DRECT = 430, /* SAMPLER2DRECT */
|
||||||
ISAMPLERBUFFER = 435,
|
SAMPLER2DRECTSHADOW = 431, /* SAMPLER2DRECTSHADOW */
|
||||||
USAMPLERBUFFER = 436,
|
ISAMPLER2DRECT = 432, /* ISAMPLER2DRECT */
|
||||||
SAMPLER2DMS = 437,
|
USAMPLER2DRECT = 433, /* USAMPLER2DRECT */
|
||||||
ISAMPLER2DMS = 438,
|
SAMPLERBUFFER = 434, /* SAMPLERBUFFER */
|
||||||
USAMPLER2DMS = 439,
|
ISAMPLERBUFFER = 435, /* ISAMPLERBUFFER */
|
||||||
SAMPLER2DMSARRAY = 440,
|
USAMPLERBUFFER = 436, /* USAMPLERBUFFER */
|
||||||
ISAMPLER2DMSARRAY = 441,
|
SAMPLER2DMS = 437, /* SAMPLER2DMS */
|
||||||
USAMPLER2DMSARRAY = 442,
|
ISAMPLER2DMS = 438, /* ISAMPLER2DMS */
|
||||||
SAMPLEREXTERNALOES = 443,
|
USAMPLER2DMS = 439, /* USAMPLER2DMS */
|
||||||
SAMPLEREXTERNAL2DY2YEXT = 444,
|
SAMPLER2DMSARRAY = 440, /* SAMPLER2DMSARRAY */
|
||||||
ISAMPLER1DARRAY = 445,
|
ISAMPLER2DMSARRAY = 441, /* ISAMPLER2DMSARRAY */
|
||||||
USAMPLER1D = 446,
|
USAMPLER2DMSARRAY = 442, /* USAMPLER2DMSARRAY */
|
||||||
USAMPLER1DARRAY = 447,
|
SAMPLEREXTERNALOES = 443, /* SAMPLEREXTERNALOES */
|
||||||
F16SAMPLER1D = 448,
|
SAMPLEREXTERNAL2DY2YEXT = 444, /* SAMPLEREXTERNAL2DY2YEXT */
|
||||||
F16SAMPLER2D = 449,
|
ISAMPLER1DARRAY = 445, /* ISAMPLER1DARRAY */
|
||||||
F16SAMPLER3D = 450,
|
USAMPLER1D = 446, /* USAMPLER1D */
|
||||||
F16SAMPLER2DRECT = 451,
|
USAMPLER1DARRAY = 447, /* USAMPLER1DARRAY */
|
||||||
F16SAMPLERCUBE = 452,
|
F16SAMPLER1D = 448, /* F16SAMPLER1D */
|
||||||
F16SAMPLER1DARRAY = 453,
|
F16SAMPLER2D = 449, /* F16SAMPLER2D */
|
||||||
F16SAMPLER2DARRAY = 454,
|
F16SAMPLER3D = 450, /* F16SAMPLER3D */
|
||||||
F16SAMPLERCUBEARRAY = 455,
|
F16SAMPLER2DRECT = 451, /* F16SAMPLER2DRECT */
|
||||||
F16SAMPLERBUFFER = 456,
|
F16SAMPLERCUBE = 452, /* F16SAMPLERCUBE */
|
||||||
F16SAMPLER2DMS = 457,
|
F16SAMPLER1DARRAY = 453, /* F16SAMPLER1DARRAY */
|
||||||
F16SAMPLER2DMSARRAY = 458,
|
F16SAMPLER2DARRAY = 454, /* F16SAMPLER2DARRAY */
|
||||||
F16SAMPLER1DSHADOW = 459,
|
F16SAMPLERCUBEARRAY = 455, /* F16SAMPLERCUBEARRAY */
|
||||||
F16SAMPLER2DSHADOW = 460,
|
F16SAMPLERBUFFER = 456, /* F16SAMPLERBUFFER */
|
||||||
F16SAMPLER1DARRAYSHADOW = 461,
|
F16SAMPLER2DMS = 457, /* F16SAMPLER2DMS */
|
||||||
F16SAMPLER2DARRAYSHADOW = 462,
|
F16SAMPLER2DMSARRAY = 458, /* F16SAMPLER2DMSARRAY */
|
||||||
F16SAMPLER2DRECTSHADOW = 463,
|
F16SAMPLER1DSHADOW = 459, /* F16SAMPLER1DSHADOW */
|
||||||
F16SAMPLERCUBESHADOW = 464,
|
F16SAMPLER2DSHADOW = 460, /* F16SAMPLER2DSHADOW */
|
||||||
F16SAMPLERCUBEARRAYSHADOW = 465,
|
F16SAMPLER1DARRAYSHADOW = 461, /* F16SAMPLER1DARRAYSHADOW */
|
||||||
IMAGE1D = 466,
|
F16SAMPLER2DARRAYSHADOW = 462, /* F16SAMPLER2DARRAYSHADOW */
|
||||||
IIMAGE1D = 467,
|
F16SAMPLER2DRECTSHADOW = 463, /* F16SAMPLER2DRECTSHADOW */
|
||||||
UIMAGE1D = 468,
|
F16SAMPLERCUBESHADOW = 464, /* F16SAMPLERCUBESHADOW */
|
||||||
IMAGE2D = 469,
|
F16SAMPLERCUBEARRAYSHADOW = 465, /* F16SAMPLERCUBEARRAYSHADOW */
|
||||||
IIMAGE2D = 470,
|
IMAGE1D = 466, /* IMAGE1D */
|
||||||
UIMAGE2D = 471,
|
IIMAGE1D = 467, /* IIMAGE1D */
|
||||||
IMAGE3D = 472,
|
UIMAGE1D = 468, /* UIMAGE1D */
|
||||||
IIMAGE3D = 473,
|
IMAGE2D = 469, /* IMAGE2D */
|
||||||
UIMAGE3D = 474,
|
IIMAGE2D = 470, /* IIMAGE2D */
|
||||||
IMAGE2DRECT = 475,
|
UIMAGE2D = 471, /* UIMAGE2D */
|
||||||
IIMAGE2DRECT = 476,
|
IMAGE3D = 472, /* IMAGE3D */
|
||||||
UIMAGE2DRECT = 477,
|
IIMAGE3D = 473, /* IIMAGE3D */
|
||||||
IMAGECUBE = 478,
|
UIMAGE3D = 474, /* UIMAGE3D */
|
||||||
IIMAGECUBE = 479,
|
IMAGE2DRECT = 475, /* IMAGE2DRECT */
|
||||||
UIMAGECUBE = 480,
|
IIMAGE2DRECT = 476, /* IIMAGE2DRECT */
|
||||||
IMAGEBUFFER = 481,
|
UIMAGE2DRECT = 477, /* UIMAGE2DRECT */
|
||||||
IIMAGEBUFFER = 482,
|
IMAGECUBE = 478, /* IMAGECUBE */
|
||||||
UIMAGEBUFFER = 483,
|
IIMAGECUBE = 479, /* IIMAGECUBE */
|
||||||
IMAGE1DARRAY = 484,
|
UIMAGECUBE = 480, /* UIMAGECUBE */
|
||||||
IIMAGE1DARRAY = 485,
|
IMAGEBUFFER = 481, /* IMAGEBUFFER */
|
||||||
UIMAGE1DARRAY = 486,
|
IIMAGEBUFFER = 482, /* IIMAGEBUFFER */
|
||||||
IMAGE2DARRAY = 487,
|
UIMAGEBUFFER = 483, /* UIMAGEBUFFER */
|
||||||
IIMAGE2DARRAY = 488,
|
IMAGE1DARRAY = 484, /* IMAGE1DARRAY */
|
||||||
UIMAGE2DARRAY = 489,
|
IIMAGE1DARRAY = 485, /* IIMAGE1DARRAY */
|
||||||
IMAGECUBEARRAY = 490,
|
UIMAGE1DARRAY = 486, /* UIMAGE1DARRAY */
|
||||||
IIMAGECUBEARRAY = 491,
|
IMAGE2DARRAY = 487, /* IMAGE2DARRAY */
|
||||||
UIMAGECUBEARRAY = 492,
|
IIMAGE2DARRAY = 488, /* IIMAGE2DARRAY */
|
||||||
IMAGE2DMS = 493,
|
UIMAGE2DARRAY = 489, /* UIMAGE2DARRAY */
|
||||||
IIMAGE2DMS = 494,
|
IMAGECUBEARRAY = 490, /* IMAGECUBEARRAY */
|
||||||
UIMAGE2DMS = 495,
|
IIMAGECUBEARRAY = 491, /* IIMAGECUBEARRAY */
|
||||||
IMAGE2DMSARRAY = 496,
|
UIMAGECUBEARRAY = 492, /* UIMAGECUBEARRAY */
|
||||||
IIMAGE2DMSARRAY = 497,
|
IMAGE2DMS = 493, /* IMAGE2DMS */
|
||||||
UIMAGE2DMSARRAY = 498,
|
IIMAGE2DMS = 494, /* IIMAGE2DMS */
|
||||||
F16IMAGE1D = 499,
|
UIMAGE2DMS = 495, /* UIMAGE2DMS */
|
||||||
F16IMAGE2D = 500,
|
IMAGE2DMSARRAY = 496, /* IMAGE2DMSARRAY */
|
||||||
F16IMAGE3D = 501,
|
IIMAGE2DMSARRAY = 497, /* IIMAGE2DMSARRAY */
|
||||||
F16IMAGE2DRECT = 502,
|
UIMAGE2DMSARRAY = 498, /* UIMAGE2DMSARRAY */
|
||||||
F16IMAGECUBE = 503,
|
F16IMAGE1D = 499, /* F16IMAGE1D */
|
||||||
F16IMAGE1DARRAY = 504,
|
F16IMAGE2D = 500, /* F16IMAGE2D */
|
||||||
F16IMAGE2DARRAY = 505,
|
F16IMAGE3D = 501, /* F16IMAGE3D */
|
||||||
F16IMAGECUBEARRAY = 506,
|
F16IMAGE2DRECT = 502, /* F16IMAGE2DRECT */
|
||||||
F16IMAGEBUFFER = 507,
|
F16IMAGECUBE = 503, /* F16IMAGECUBE */
|
||||||
F16IMAGE2DMS = 508,
|
F16IMAGE1DARRAY = 504, /* F16IMAGE1DARRAY */
|
||||||
F16IMAGE2DMSARRAY = 509,
|
F16IMAGE2DARRAY = 505, /* F16IMAGE2DARRAY */
|
||||||
TEXTURECUBEARRAY = 510,
|
F16IMAGECUBEARRAY = 506, /* F16IMAGECUBEARRAY */
|
||||||
ITEXTURECUBEARRAY = 511,
|
F16IMAGEBUFFER = 507, /* F16IMAGEBUFFER */
|
||||||
UTEXTURECUBEARRAY = 512,
|
F16IMAGE2DMS = 508, /* F16IMAGE2DMS */
|
||||||
TEXTURE1D = 513,
|
F16IMAGE2DMSARRAY = 509, /* F16IMAGE2DMSARRAY */
|
||||||
ITEXTURE1D = 514,
|
I64IMAGE1D = 510, /* I64IMAGE1D */
|
||||||
UTEXTURE1D = 515,
|
U64IMAGE1D = 511, /* U64IMAGE1D */
|
||||||
TEXTURE1DARRAY = 516,
|
I64IMAGE2D = 512, /* I64IMAGE2D */
|
||||||
ITEXTURE1DARRAY = 517,
|
U64IMAGE2D = 513, /* U64IMAGE2D */
|
||||||
UTEXTURE1DARRAY = 518,
|
I64IMAGE3D = 514, /* I64IMAGE3D */
|
||||||
TEXTURE2DRECT = 519,
|
U64IMAGE3D = 515, /* U64IMAGE3D */
|
||||||
ITEXTURE2DRECT = 520,
|
I64IMAGE2DRECT = 516, /* I64IMAGE2DRECT */
|
||||||
UTEXTURE2DRECT = 521,
|
U64IMAGE2DRECT = 517, /* U64IMAGE2DRECT */
|
||||||
TEXTUREBUFFER = 522,
|
I64IMAGECUBE = 518, /* I64IMAGECUBE */
|
||||||
ITEXTUREBUFFER = 523,
|
U64IMAGECUBE = 519, /* U64IMAGECUBE */
|
||||||
UTEXTUREBUFFER = 524,
|
I64IMAGEBUFFER = 520, /* I64IMAGEBUFFER */
|
||||||
TEXTURE2DMS = 525,
|
U64IMAGEBUFFER = 521, /* U64IMAGEBUFFER */
|
||||||
ITEXTURE2DMS = 526,
|
I64IMAGE1DARRAY = 522, /* I64IMAGE1DARRAY */
|
||||||
UTEXTURE2DMS = 527,
|
U64IMAGE1DARRAY = 523, /* U64IMAGE1DARRAY */
|
||||||
TEXTURE2DMSARRAY = 528,
|
I64IMAGE2DARRAY = 524, /* I64IMAGE2DARRAY */
|
||||||
ITEXTURE2DMSARRAY = 529,
|
U64IMAGE2DARRAY = 525, /* U64IMAGE2DARRAY */
|
||||||
UTEXTURE2DMSARRAY = 530,
|
I64IMAGECUBEARRAY = 526, /* I64IMAGECUBEARRAY */
|
||||||
F16TEXTURE1D = 531,
|
U64IMAGECUBEARRAY = 527, /* U64IMAGECUBEARRAY */
|
||||||
F16TEXTURE2D = 532,
|
I64IMAGE2DMS = 528, /* I64IMAGE2DMS */
|
||||||
F16TEXTURE3D = 533,
|
U64IMAGE2DMS = 529, /* U64IMAGE2DMS */
|
||||||
F16TEXTURE2DRECT = 534,
|
I64IMAGE2DMSARRAY = 530, /* I64IMAGE2DMSARRAY */
|
||||||
F16TEXTURECUBE = 535,
|
U64IMAGE2DMSARRAY = 531, /* U64IMAGE2DMSARRAY */
|
||||||
F16TEXTURE1DARRAY = 536,
|
TEXTURECUBEARRAY = 532, /* TEXTURECUBEARRAY */
|
||||||
F16TEXTURE2DARRAY = 537,
|
ITEXTURECUBEARRAY = 533, /* ITEXTURECUBEARRAY */
|
||||||
F16TEXTURECUBEARRAY = 538,
|
UTEXTURECUBEARRAY = 534, /* UTEXTURECUBEARRAY */
|
||||||
F16TEXTUREBUFFER = 539,
|
TEXTURE1D = 535, /* TEXTURE1D */
|
||||||
F16TEXTURE2DMS = 540,
|
ITEXTURE1D = 536, /* ITEXTURE1D */
|
||||||
F16TEXTURE2DMSARRAY = 541,
|
UTEXTURE1D = 537, /* UTEXTURE1D */
|
||||||
SUBPASSINPUT = 542,
|
TEXTURE1DARRAY = 538, /* TEXTURE1DARRAY */
|
||||||
SUBPASSINPUTMS = 543,
|
ITEXTURE1DARRAY = 539, /* ITEXTURE1DARRAY */
|
||||||
ISUBPASSINPUT = 544,
|
UTEXTURE1DARRAY = 540, /* UTEXTURE1DARRAY */
|
||||||
ISUBPASSINPUTMS = 545,
|
TEXTURE2DRECT = 541, /* TEXTURE2DRECT */
|
||||||
USUBPASSINPUT = 546,
|
ITEXTURE2DRECT = 542, /* ITEXTURE2DRECT */
|
||||||
USUBPASSINPUTMS = 547,
|
UTEXTURE2DRECT = 543, /* UTEXTURE2DRECT */
|
||||||
F16SUBPASSINPUT = 548,
|
TEXTUREBUFFER = 544, /* TEXTUREBUFFER */
|
||||||
F16SUBPASSINPUTMS = 549,
|
ITEXTUREBUFFER = 545, /* ITEXTUREBUFFER */
|
||||||
LEFT_OP = 550,
|
UTEXTUREBUFFER = 546, /* UTEXTUREBUFFER */
|
||||||
RIGHT_OP = 551,
|
TEXTURE2DMS = 547, /* TEXTURE2DMS */
|
||||||
INC_OP = 552,
|
ITEXTURE2DMS = 548, /* ITEXTURE2DMS */
|
||||||
DEC_OP = 553,
|
UTEXTURE2DMS = 549, /* UTEXTURE2DMS */
|
||||||
LE_OP = 554,
|
TEXTURE2DMSARRAY = 550, /* TEXTURE2DMSARRAY */
|
||||||
GE_OP = 555,
|
ITEXTURE2DMSARRAY = 551, /* ITEXTURE2DMSARRAY */
|
||||||
EQ_OP = 556,
|
UTEXTURE2DMSARRAY = 552, /* UTEXTURE2DMSARRAY */
|
||||||
NE_OP = 557,
|
F16TEXTURE1D = 553, /* F16TEXTURE1D */
|
||||||
AND_OP = 558,
|
F16TEXTURE2D = 554, /* F16TEXTURE2D */
|
||||||
OR_OP = 559,
|
F16TEXTURE3D = 555, /* F16TEXTURE3D */
|
||||||
XOR_OP = 560,
|
F16TEXTURE2DRECT = 556, /* F16TEXTURE2DRECT */
|
||||||
MUL_ASSIGN = 561,
|
F16TEXTURECUBE = 557, /* F16TEXTURECUBE */
|
||||||
DIV_ASSIGN = 562,
|
F16TEXTURE1DARRAY = 558, /* F16TEXTURE1DARRAY */
|
||||||
ADD_ASSIGN = 563,
|
F16TEXTURE2DARRAY = 559, /* F16TEXTURE2DARRAY */
|
||||||
MOD_ASSIGN = 564,
|
F16TEXTURECUBEARRAY = 560, /* F16TEXTURECUBEARRAY */
|
||||||
LEFT_ASSIGN = 565,
|
F16TEXTUREBUFFER = 561, /* F16TEXTUREBUFFER */
|
||||||
RIGHT_ASSIGN = 566,
|
F16TEXTURE2DMS = 562, /* F16TEXTURE2DMS */
|
||||||
AND_ASSIGN = 567,
|
F16TEXTURE2DMSARRAY = 563, /* F16TEXTURE2DMSARRAY */
|
||||||
XOR_ASSIGN = 568,
|
SUBPASSINPUT = 564, /* SUBPASSINPUT */
|
||||||
OR_ASSIGN = 569,
|
SUBPASSINPUTMS = 565, /* SUBPASSINPUTMS */
|
||||||
SUB_ASSIGN = 570,
|
ISUBPASSINPUT = 566, /* ISUBPASSINPUT */
|
||||||
STRING_LITERAL = 571,
|
ISUBPASSINPUTMS = 567, /* ISUBPASSINPUTMS */
|
||||||
LEFT_PAREN = 572,
|
USUBPASSINPUT = 568, /* USUBPASSINPUT */
|
||||||
RIGHT_PAREN = 573,
|
USUBPASSINPUTMS = 569, /* USUBPASSINPUTMS */
|
||||||
LEFT_BRACKET = 574,
|
F16SUBPASSINPUT = 570, /* F16SUBPASSINPUT */
|
||||||
RIGHT_BRACKET = 575,
|
F16SUBPASSINPUTMS = 571, /* F16SUBPASSINPUTMS */
|
||||||
LEFT_BRACE = 576,
|
LEFT_OP = 572, /* LEFT_OP */
|
||||||
RIGHT_BRACE = 577,
|
RIGHT_OP = 573, /* RIGHT_OP */
|
||||||
DOT = 578,
|
INC_OP = 574, /* INC_OP */
|
||||||
COMMA = 579,
|
DEC_OP = 575, /* DEC_OP */
|
||||||
COLON = 580,
|
LE_OP = 576, /* LE_OP */
|
||||||
EQUAL = 581,
|
GE_OP = 577, /* GE_OP */
|
||||||
SEMICOLON = 582,
|
EQ_OP = 578, /* EQ_OP */
|
||||||
BANG = 583,
|
NE_OP = 579, /* NE_OP */
|
||||||
DASH = 584,
|
AND_OP = 580, /* AND_OP */
|
||||||
TILDE = 585,
|
OR_OP = 581, /* OR_OP */
|
||||||
PLUS = 586,
|
XOR_OP = 582, /* XOR_OP */
|
||||||
STAR = 587,
|
MUL_ASSIGN = 583, /* MUL_ASSIGN */
|
||||||
SLASH = 588,
|
DIV_ASSIGN = 584, /* DIV_ASSIGN */
|
||||||
PERCENT = 589,
|
ADD_ASSIGN = 585, /* ADD_ASSIGN */
|
||||||
LEFT_ANGLE = 590,
|
MOD_ASSIGN = 586, /* MOD_ASSIGN */
|
||||||
RIGHT_ANGLE = 591,
|
LEFT_ASSIGN = 587, /* LEFT_ASSIGN */
|
||||||
VERTICAL_BAR = 592,
|
RIGHT_ASSIGN = 588, /* RIGHT_ASSIGN */
|
||||||
CARET = 593,
|
AND_ASSIGN = 589, /* AND_ASSIGN */
|
||||||
AMPERSAND = 594,
|
XOR_ASSIGN = 590, /* XOR_ASSIGN */
|
||||||
QUESTION = 595,
|
OR_ASSIGN = 591, /* OR_ASSIGN */
|
||||||
INVARIANT = 596,
|
SUB_ASSIGN = 592, /* SUB_ASSIGN */
|
||||||
HIGH_PRECISION = 597,
|
STRING_LITERAL = 593, /* STRING_LITERAL */
|
||||||
MEDIUM_PRECISION = 598,
|
LEFT_PAREN = 594, /* LEFT_PAREN */
|
||||||
LOW_PRECISION = 599,
|
RIGHT_PAREN = 595, /* RIGHT_PAREN */
|
||||||
PRECISION = 600,
|
LEFT_BRACKET = 596, /* LEFT_BRACKET */
|
||||||
PACKED = 601,
|
RIGHT_BRACKET = 597, /* RIGHT_BRACKET */
|
||||||
RESOURCE = 602,
|
LEFT_BRACE = 598, /* LEFT_BRACE */
|
||||||
SUPERP = 603,
|
RIGHT_BRACE = 599, /* RIGHT_BRACE */
|
||||||
FLOATCONSTANT = 604,
|
DOT = 600, /* DOT */
|
||||||
INTCONSTANT = 605,
|
COMMA = 601, /* COMMA */
|
||||||
UINTCONSTANT = 606,
|
COLON = 602, /* COLON */
|
||||||
BOOLCONSTANT = 607,
|
EQUAL = 603, /* EQUAL */
|
||||||
IDENTIFIER = 608,
|
SEMICOLON = 604, /* SEMICOLON */
|
||||||
TYPE_NAME = 609,
|
BANG = 605, /* BANG */
|
||||||
CENTROID = 610,
|
DASH = 606, /* DASH */
|
||||||
IN = 611,
|
TILDE = 607, /* TILDE */
|
||||||
OUT = 612,
|
PLUS = 608, /* PLUS */
|
||||||
INOUT = 613,
|
STAR = 609, /* STAR */
|
||||||
STRUCT = 614,
|
SLASH = 610, /* SLASH */
|
||||||
VOID = 615,
|
PERCENT = 611, /* PERCENT */
|
||||||
WHILE = 616,
|
LEFT_ANGLE = 612, /* LEFT_ANGLE */
|
||||||
BREAK = 617,
|
RIGHT_ANGLE = 613, /* RIGHT_ANGLE */
|
||||||
CONTINUE = 618,
|
VERTICAL_BAR = 614, /* VERTICAL_BAR */
|
||||||
DO = 619,
|
CARET = 615, /* CARET */
|
||||||
ELSE = 620,
|
AMPERSAND = 616, /* AMPERSAND */
|
||||||
FOR = 621,
|
QUESTION = 617, /* QUESTION */
|
||||||
IF = 622,
|
INVARIANT = 618, /* INVARIANT */
|
||||||
DISCARD = 623,
|
HIGH_PRECISION = 619, /* HIGH_PRECISION */
|
||||||
RETURN = 624,
|
MEDIUM_PRECISION = 620, /* MEDIUM_PRECISION */
|
||||||
SWITCH = 625,
|
LOW_PRECISION = 621, /* LOW_PRECISION */
|
||||||
CASE = 626,
|
PRECISION = 622, /* PRECISION */
|
||||||
DEFAULT = 627,
|
PACKED = 623, /* PACKED */
|
||||||
UNIFORM = 628,
|
RESOURCE = 624, /* RESOURCE */
|
||||||
SHARED = 629,
|
SUPERP = 625, /* SUPERP */
|
||||||
BUFFER = 630,
|
FLOATCONSTANT = 626, /* FLOATCONSTANT */
|
||||||
FLAT = 631,
|
INTCONSTANT = 627, /* INTCONSTANT */
|
||||||
SMOOTH = 632,
|
UINTCONSTANT = 628, /* UINTCONSTANT */
|
||||||
LAYOUT = 633,
|
BOOLCONSTANT = 629, /* BOOLCONSTANT */
|
||||||
DOUBLECONSTANT = 634,
|
IDENTIFIER = 630, /* IDENTIFIER */
|
||||||
INT16CONSTANT = 635,
|
TYPE_NAME = 631, /* TYPE_NAME */
|
||||||
UINT16CONSTANT = 636,
|
CENTROID = 632, /* CENTROID */
|
||||||
FLOAT16CONSTANT = 637,
|
IN = 633, /* IN */
|
||||||
INT32CONSTANT = 638,
|
OUT = 634, /* OUT */
|
||||||
UINT32CONSTANT = 639,
|
INOUT = 635, /* INOUT */
|
||||||
INT64CONSTANT = 640,
|
STRUCT = 636, /* STRUCT */
|
||||||
UINT64CONSTANT = 641,
|
VOID = 637, /* VOID */
|
||||||
SUBROUTINE = 642,
|
WHILE = 638, /* WHILE */
|
||||||
DEMOTE = 643,
|
BREAK = 639, /* BREAK */
|
||||||
PAYLOADNV = 644,
|
CONTINUE = 640, /* CONTINUE */
|
||||||
PAYLOADINNV = 645,
|
DO = 641, /* DO */
|
||||||
HITATTRNV = 646,
|
ELSE = 642, /* ELSE */
|
||||||
CALLDATANV = 647,
|
FOR = 643, /* FOR */
|
||||||
CALLDATAINNV = 648,
|
IF = 644, /* IF */
|
||||||
PAYLOADEXT = 649,
|
DISCARD = 645, /* DISCARD */
|
||||||
PAYLOADINEXT = 650,
|
RETURN = 646, /* RETURN */
|
||||||
HITATTREXT = 651,
|
SWITCH = 647, /* SWITCH */
|
||||||
CALLDATAEXT = 652,
|
CASE = 648, /* CASE */
|
||||||
CALLDATAINEXT = 653,
|
DEFAULT = 649, /* DEFAULT */
|
||||||
PATCH = 654,
|
TERMINATE_INVOCATION = 650, /* TERMINATE_INVOCATION */
|
||||||
SAMPLE = 655,
|
TERMINATE_RAY = 651, /* TERMINATE_RAY */
|
||||||
NONUNIFORM = 656,
|
IGNORE_INTERSECTION = 652, /* IGNORE_INTERSECTION */
|
||||||
COHERENT = 657,
|
UNIFORM = 653, /* UNIFORM */
|
||||||
VOLATILE = 658,
|
SHARED = 654, /* SHARED */
|
||||||
RESTRICT = 659,
|
BUFFER = 655, /* BUFFER */
|
||||||
READONLY = 660,
|
FLAT = 656, /* FLAT */
|
||||||
WRITEONLY = 661,
|
SMOOTH = 657, /* SMOOTH */
|
||||||
DEVICECOHERENT = 662,
|
LAYOUT = 658, /* LAYOUT */
|
||||||
QUEUEFAMILYCOHERENT = 663,
|
DOUBLECONSTANT = 659, /* DOUBLECONSTANT */
|
||||||
WORKGROUPCOHERENT = 664,
|
INT16CONSTANT = 660, /* INT16CONSTANT */
|
||||||
SUBGROUPCOHERENT = 665,
|
UINT16CONSTANT = 661, /* UINT16CONSTANT */
|
||||||
NONPRIVATE = 666,
|
FLOAT16CONSTANT = 662, /* FLOAT16CONSTANT */
|
||||||
SHADERCALLCOHERENT = 667,
|
INT32CONSTANT = 663, /* INT32CONSTANT */
|
||||||
NOPERSPECTIVE = 668,
|
UINT32CONSTANT = 664, /* UINT32CONSTANT */
|
||||||
EXPLICITINTERPAMD = 669,
|
INT64CONSTANT = 665, /* INT64CONSTANT */
|
||||||
PERVERTEXNV = 670,
|
UINT64CONSTANT = 666, /* UINT64CONSTANT */
|
||||||
PERPRIMITIVENV = 671,
|
SUBROUTINE = 667, /* SUBROUTINE */
|
||||||
PERVIEWNV = 672,
|
DEMOTE = 668, /* DEMOTE */
|
||||||
PERTASKNV = 673,
|
PAYLOADNV = 669, /* PAYLOADNV */
|
||||||
PRECISE = 674
|
PAYLOADINNV = 670, /* PAYLOADINNV */
|
||||||
|
HITATTRNV = 671, /* HITATTRNV */
|
||||||
|
CALLDATANV = 672, /* CALLDATANV */
|
||||||
|
CALLDATAINNV = 673, /* CALLDATAINNV */
|
||||||
|
PAYLOADEXT = 674, /* PAYLOADEXT */
|
||||||
|
PAYLOADINEXT = 675, /* PAYLOADINEXT */
|
||||||
|
HITATTREXT = 676, /* HITATTREXT */
|
||||||
|
CALLDATAEXT = 677, /* CALLDATAEXT */
|
||||||
|
CALLDATAINEXT = 678, /* CALLDATAINEXT */
|
||||||
|
PATCH = 679, /* PATCH */
|
||||||
|
SAMPLE = 680, /* SAMPLE */
|
||||||
|
NONUNIFORM = 681, /* NONUNIFORM */
|
||||||
|
COHERENT = 682, /* COHERENT */
|
||||||
|
VOLATILE = 683, /* VOLATILE */
|
||||||
|
RESTRICT = 684, /* RESTRICT */
|
||||||
|
READONLY = 685, /* READONLY */
|
||||||
|
WRITEONLY = 686, /* WRITEONLY */
|
||||||
|
DEVICECOHERENT = 687, /* DEVICECOHERENT */
|
||||||
|
QUEUEFAMILYCOHERENT = 688, /* QUEUEFAMILYCOHERENT */
|
||||||
|
WORKGROUPCOHERENT = 689, /* WORKGROUPCOHERENT */
|
||||||
|
SUBGROUPCOHERENT = 690, /* SUBGROUPCOHERENT */
|
||||||
|
NONPRIVATE = 691, /* NONPRIVATE */
|
||||||
|
SHADERCALLCOHERENT = 692, /* SHADERCALLCOHERENT */
|
||||||
|
NOPERSPECTIVE = 693, /* NOPERSPECTIVE */
|
||||||
|
EXPLICITINTERPAMD = 694, /* EXPLICITINTERPAMD */
|
||||||
|
PERVERTEXNV = 695, /* PERVERTEXNV */
|
||||||
|
PERPRIMITIVENV = 696, /* PERPRIMITIVENV */
|
||||||
|
PERVIEWNV = 697, /* PERVIEWNV */
|
||||||
|
PERTASKNV = 698, /* PERTASKNV */
|
||||||
|
PRECISE = 699 /* PRECISE */
|
||||||
};
|
};
|
||||||
|
typedef enum yytokentype yytoken_kind_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Value type. */
|
/* Value type. */
|
||||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||||
|
|
||||||
union YYSTYPE
|
union YYSTYPE
|
||||||
{
|
{
|
||||||
#line 97 "MachineIndependent/glslang.y" /* yacc.c:1909 */
|
#line 97 "MachineIndependent/glslang.y"
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
glslang::TSourceLoc loc;
|
glslang::TSourceLoc loc;
|
||||||
@@ -506,9 +540,9 @@ union YYSTYPE
|
|||||||
glslang::TArraySizes* typeParameters;
|
glslang::TArraySizes* typeParameters;
|
||||||
} interm;
|
} interm;
|
||||||
|
|
||||||
#line 510 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
|
#line 544 "MachineIndependent/glslang_tab.cpp.h"
|
||||||
};
|
|
||||||
|
|
||||||
|
};
|
||||||
typedef union YYSTYPE YYSTYPE;
|
typedef union YYSTYPE YYSTYPE;
|
||||||
# define YYSTYPE_IS_TRIVIAL 1
|
# define YYSTYPE_IS_TRIVIAL 1
|
||||||
# define YYSTYPE_IS_DECLARED 1
|
# define YYSTYPE_IS_DECLARED 1
|
||||||
|
|||||||
@@ -438,6 +438,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
|||||||
case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break;
|
case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break;
|
||||||
case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break;
|
case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break;
|
||||||
|
|
||||||
|
case EOpConvUint64ToAccStruct: out.debug << "Convert uint64_t to acceleration structure"; break;
|
||||||
|
case EOpConvUvec2ToAccStruct: out.debug << "Convert uvec2 to acceleration strucuture "; break;
|
||||||
|
|
||||||
case EOpRadians: out.debug << "radians"; break;
|
case EOpRadians: out.debug << "radians"; break;
|
||||||
case EOpDegrees: out.debug << "degrees"; break;
|
case EOpDegrees: out.debug << "degrees"; break;
|
||||||
case EOpSin: out.debug << "sine"; break;
|
case EOpSin: out.debug << "sine"; break;
|
||||||
@@ -829,6 +832,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
|
|||||||
case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
|
case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
|
||||||
case EOpConstructReference: out.debug << "Construct reference"; break;
|
case EOpConstructReference: out.debug << "Construct reference"; break;
|
||||||
case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break;
|
case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break;
|
||||||
|
case EOpConstructAccStruct: out.debug << "Construct acceleration structure"; break;
|
||||||
|
|
||||||
case EOpLessThan: out.debug << "Compare Less Than"; break;
|
case EOpLessThan: out.debug << "Compare Less Than"; break;
|
||||||
case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
|
case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
|
||||||
@@ -882,6 +886,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
|
|||||||
case EOpTime: out.debug << "time"; break;
|
case EOpTime: out.debug << "time"; break;
|
||||||
|
|
||||||
case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
|
case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
|
||||||
|
case EOpAtomicSubtract: out.debug << "AtomicSubtract"; break;
|
||||||
case EOpAtomicMin: out.debug << "AtomicMin"; break;
|
case EOpAtomicMin: out.debug << "AtomicMin"; break;
|
||||||
case EOpAtomicMax: out.debug << "AtomicMax"; break;
|
case EOpAtomicMax: out.debug << "AtomicMax"; break;
|
||||||
case EOpAtomicAnd: out.debug << "AtomicAnd"; break;
|
case EOpAtomicAnd: out.debug << "AtomicAnd"; break;
|
||||||
@@ -1079,11 +1084,15 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
|
|||||||
case EOpSubpassLoad: out.debug << "subpassLoad"; break;
|
case EOpSubpassLoad: out.debug << "subpassLoad"; break;
|
||||||
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
|
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
|
||||||
|
|
||||||
case EOpTrace: out.debug << "traceNV"; break;
|
case EOpTraceNV: out.debug << "traceNV"; break;
|
||||||
|
case EOpTraceKHR: out.debug << "traceRayKHR"; break;
|
||||||
case EOpReportIntersection: out.debug << "reportIntersectionNV"; break;
|
case EOpReportIntersection: out.debug << "reportIntersectionNV"; break;
|
||||||
case EOpIgnoreIntersection: out.debug << "ignoreIntersectionNV"; break;
|
case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break;
|
||||||
case EOpTerminateRay: out.debug << "terminateRayNV"; break;
|
case EOpIgnoreIntersectionKHR: out.debug << "ignoreIntersectionKHR"; break;
|
||||||
case EOpExecuteCallable: out.debug << "executeCallableNV"; break;
|
case EOpTerminateRayNV: out.debug << "terminateRayNV"; break;
|
||||||
|
case EOpTerminateRayKHR: out.debug << "terminateRayKHR"; break;
|
||||||
|
case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break;
|
||||||
|
case EOpExecuteCallableKHR: out.debug << "executeCallableKHR"; break;
|
||||||
case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
|
case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
|
||||||
|
|
||||||
case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break;
|
case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break;
|
||||||
@@ -1321,6 +1330,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
|
|||||||
out.debug << buf << "\n";
|
out.debug << buf << "\n";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EbtString:
|
||||||
|
out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
|
out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
|
||||||
break;
|
break;
|
||||||
@@ -1406,14 +1418,17 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
|
|||||||
OutputTreeText(out, node, depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
switch (node->getFlowOp()) {
|
switch (node->getFlowOp()) {
|
||||||
case EOpKill: out.debug << "Branch: Kill"; break;
|
case EOpKill: out.debug << "Branch: Kill"; break;
|
||||||
case EOpBreak: out.debug << "Branch: Break"; break;
|
case EOpTerminateInvocation: out.debug << "Branch: TerminateInvocation"; break;
|
||||||
case EOpContinue: out.debug << "Branch: Continue"; break;
|
case EOpIgnoreIntersectionKHR: out.debug << "Branch: IgnoreIntersectionKHR"; break;
|
||||||
case EOpReturn: out.debug << "Branch: Return"; break;
|
case EOpTerminateRayKHR: out.debug << "Branch: TerminateRayKHR"; break;
|
||||||
case EOpCase: out.debug << "case: "; break;
|
case EOpBreak: out.debug << "Branch: Break"; break;
|
||||||
case EOpDemote: out.debug << "Demote"; break;
|
case EOpContinue: out.debug << "Branch: Continue"; break;
|
||||||
case EOpDefault: out.debug << "default: "; break;
|
case EOpReturn: out.debug << "Branch: Return"; break;
|
||||||
default: out.debug << "Branch: Unknown Branch"; break;
|
case EOpCase: out.debug << "case: "; break;
|
||||||
|
case EOpDemote: out.debug << "Demote"; break;
|
||||||
|
case EOpDefault: out.debug << "default: "; break;
|
||||||
|
default: out.debug << "Branch: Unknown Branch"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getExpression()) {
|
if (node->getExpression()) {
|
||||||
|
|||||||
@@ -37,9 +37,11 @@
|
|||||||
|
|
||||||
#include "../Include/Common.h"
|
#include "../Include/Common.h"
|
||||||
#include "../Include/InfoSink.h"
|
#include "../Include/InfoSink.h"
|
||||||
|
#include "../Include/Types.h"
|
||||||
|
|
||||||
#include "gl_types.h"
|
#include "gl_types.h"
|
||||||
#include "iomapper.h"
|
#include "iomapper.h"
|
||||||
|
#include "SymbolTable.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Map IO bindings.
|
// Map IO bindings.
|
||||||
@@ -82,17 +84,17 @@ public:
|
|||||||
// If a global is being visited, then we should also traverse it incase it's evaluation
|
// If a global is being visited, then we should also traverse it incase it's evaluation
|
||||||
// ends up visiting inputs we want to tag as live
|
// ends up visiting inputs we want to tag as live
|
||||||
else if (base->getQualifier().storage == EvqGlobal)
|
else if (base->getQualifier().storage == EvqGlobal)
|
||||||
addGlobalReference(base->getName());
|
addGlobalReference(base->getAccessName());
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
|
TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
|
||||||
ent.stage = intermediate.getStage();
|
ent.stage = intermediate.getStage();
|
||||||
TVarLiveMap::iterator at = target->find(
|
TVarLiveMap::iterator at = target->find(
|
||||||
ent.symbol->getName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
|
ent.symbol->getAccessName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
|
||||||
if (at != target->end() && at->second.id == ent.id)
|
if (at != target->end() && at->second.id == ent.id)
|
||||||
at->second.live = at->second.live || ! traverseAll; // update live state
|
at->second.live = at->second.live || ! traverseAll; // update live state
|
||||||
else
|
else
|
||||||
(*target)[ent.symbol->getName()] = ent;
|
(*target)[ent.symbol->getAccessName()] = ent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +127,8 @@ public:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
TVarEntryInfo ent = { base->getId() };
|
TVarEntryInfo ent = { base->getId() };
|
||||||
TVarLiveMap::const_iterator at = source->find(base->getName());
|
// Fix a defect, when block has no instance name, we need to find its block name
|
||||||
|
TVarLiveMap::const_iterator at = source->find(base->getAccessName());
|
||||||
if (at == source->end())
|
if (at == source->end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -181,7 +184,7 @@ struct TNotifyInOutAdaptor
|
|||||||
|
|
||||||
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
|
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
|
||||||
{
|
{
|
||||||
resolver.notifyInOut(stage, entKey.second);
|
resolver.notifyInOut(entKey.second.stage, entKey.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -189,12 +192,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TResolverUniformAdaptor {
|
struct TResolverUniformAdaptor {
|
||||||
TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
|
TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TVarLiveMap* uniform[EShLangCount], TInfoSink& i, bool& e)
|
||||||
: stage(s)
|
: stage(s)
|
||||||
, resolver(r)
|
, resolver(r)
|
||||||
, infoSink(i)
|
, infoSink(i)
|
||||||
, error(e)
|
, error(e)
|
||||||
{
|
{
|
||||||
|
memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
|
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
|
||||||
@@ -206,9 +210,9 @@ struct TResolverUniformAdaptor {
|
|||||||
ent.newIndex = -1;
|
ent.newIndex = -1;
|
||||||
const bool isValid = resolver.validateBinding(stage, ent);
|
const bool isValid = resolver.validateBinding(stage, ent);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
resolver.resolveBinding(stage, ent);
|
resolver.resolveSet(ent.stage, ent);
|
||||||
resolver.resolveSet(stage, ent);
|
resolver.resolveBinding(ent.stage, ent);
|
||||||
resolver.resolveUniformLocation(stage, ent);
|
resolver.resolveUniformLocation(ent.stage, ent);
|
||||||
|
|
||||||
if (ent.newBinding != -1) {
|
if (ent.newBinding != -1) {
|
||||||
if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
|
if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
|
||||||
@@ -217,6 +221,17 @@ struct TResolverUniformAdaptor {
|
|||||||
infoSink.info.message(EPrefixInternalError, err.c_str());
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ent.symbol->getQualifier().hasBinding()) {
|
||||||
|
for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
|
||||||
|
if (idx == ent.stage || uniformVarMap[idx] == nullptr)
|
||||||
|
continue;
|
||||||
|
auto entKey2 = uniformVarMap[idx]->find(entKey.first);
|
||||||
|
if (entKey2 != uniformVarMap[idx]->end()) {
|
||||||
|
entKey2->second.newBinding = ent.newBinding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ent.newSet != -1) {
|
if (ent.newSet != -1) {
|
||||||
if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
|
if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
|
||||||
@@ -225,6 +240,16 @@ struct TResolverUniformAdaptor {
|
|||||||
infoSink.info.message(EPrefixInternalError, err.c_str());
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
if (ent.symbol->getQualifier().hasSet()) {
|
||||||
|
for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
|
||||||
|
if ((idx == stage) || (uniformVarMap[idx] == nullptr))
|
||||||
|
continue;
|
||||||
|
auto entKey2 = uniformVarMap[idx]->find(entKey.first);
|
||||||
|
if (entKey2 != uniformVarMap[idx]->end()) {
|
||||||
|
entKey2->second.newSet = ent.newSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TString errorMsg = "Invalid binding: " + entKey.first;
|
TString errorMsg = "Invalid binding: " + entKey.first;
|
||||||
@@ -239,7 +264,7 @@ struct TResolverUniformAdaptor {
|
|||||||
TIoMapResolver& resolver;
|
TIoMapResolver& resolver;
|
||||||
TInfoSink& infoSink;
|
TInfoSink& infoSink;
|
||||||
bool& error;
|
bool& error;
|
||||||
|
TVarLiveMap* uniformVarMap[EShLangCount];
|
||||||
private:
|
private:
|
||||||
TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
|
TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
|
||||||
};
|
};
|
||||||
@@ -261,7 +286,7 @@ struct TResolverInOutAdaptor {
|
|||||||
ent.newBinding = -1;
|
ent.newBinding = -1;
|
||||||
ent.newSet = -1;
|
ent.newSet = -1;
|
||||||
ent.newIndex = -1;
|
ent.newIndex = -1;
|
||||||
const bool isValid = resolver.validateInOut(stage, ent);
|
const bool isValid = resolver.validateInOut(ent.stage, ent);
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
resolver.resolveInOutLocation(stage, ent);
|
resolver.resolveInOutLocation(stage, ent);
|
||||||
resolver.resolveInOutComponent(stage, ent);
|
resolver.resolveInOutComponent(stage, ent);
|
||||||
@@ -292,21 +317,118 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
|
// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
|
||||||
|
// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform"
|
||||||
|
|
||||||
struct TSymbolValidater
|
struct TSymbolValidater
|
||||||
{
|
{
|
||||||
TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
|
TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
|
||||||
TVarLiveMap* uniform[EShLangCount], bool& hadError)
|
TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version)
|
||||||
: preStage(EShLangCount)
|
: resolver(r)
|
||||||
, currentStage(EShLangCount)
|
|
||||||
, nextStage(EShLangCount)
|
|
||||||
, resolver(r)
|
|
||||||
, infoSink(i)
|
, infoSink(i)
|
||||||
, hadError(hadError)
|
, hadError(hadError)
|
||||||
|
, profile(profile)
|
||||||
|
, version(version)
|
||||||
{
|
{
|
||||||
memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
|
memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
|
||||||
memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
|
memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
|
||||||
memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
|
memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
|
||||||
|
|
||||||
|
std::map<TString, TString> anonymousMemberMap;
|
||||||
|
std::vector<TRange> usedUniformLocation;
|
||||||
|
std::vector<TString> usedUniformName;
|
||||||
|
usedUniformLocation.clear();
|
||||||
|
usedUniformName.clear();
|
||||||
|
for (int i = 0; i < EShLangCount; i++) {
|
||||||
|
if (uniformVarMap[i]) {
|
||||||
|
for (auto uniformVar : *uniformVarMap[i])
|
||||||
|
{
|
||||||
|
TIntermSymbol* pSymbol = uniformVar.second.symbol;
|
||||||
|
TQualifier qualifier = uniformVar.second.symbol->getQualifier();
|
||||||
|
TString symbolName = pSymbol->getAccessName();
|
||||||
|
|
||||||
|
// All the uniform needs multi-stage location check (block/default)
|
||||||
|
int uniformLocation = qualifier.layoutLocation;
|
||||||
|
|
||||||
|
if (uniformLocation != TQualifier::layoutLocationEnd) {
|
||||||
|
// Total size of current uniform, could be block, struct or other types.
|
||||||
|
int size = TIntermediate::computeTypeUniformLocationSize(pSymbol->getType());
|
||||||
|
|
||||||
|
TRange locationRange(uniformLocation, uniformLocation + size - 1);
|
||||||
|
|
||||||
|
// Combine location and component ranges
|
||||||
|
int overlapLocation = -1;
|
||||||
|
bool diffLocation = false;
|
||||||
|
|
||||||
|
// Check for collisions, except for vertex inputs on desktop targeting OpenGL
|
||||||
|
overlapLocation = checkLocationOverlap(locationRange, usedUniformLocation, symbolName, usedUniformName, diffLocation);
|
||||||
|
|
||||||
|
// Overlap locations of uniforms, regardless of components (multi stages)
|
||||||
|
if (overlapLocation == -1) {
|
||||||
|
usedUniformLocation.push_back(locationRange);
|
||||||
|
usedUniformName.push_back(symbolName);
|
||||||
|
}
|
||||||
|
else if (overlapLocation >= 0) {
|
||||||
|
if (diffLocation == true) {
|
||||||
|
TString err = ("Uniform location should be equal for same uniforms: " +std::to_string(overlapLocation)).c_str();
|
||||||
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
|
hadError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TString err = ("Uniform location overlaps across stages: " + std::to_string(overlapLocation)).c_str();
|
||||||
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
|
hadError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uniformVar.second.symbol->getBasicType() == EbtBlock) &&
|
||||||
|
IsAnonymous(uniformVar.second.symbol->getName()))
|
||||||
|
{
|
||||||
|
auto blockType = uniformVar.second.symbol->getType().getStruct();
|
||||||
|
for (size_t memberIdx = 0; memberIdx < blockType->size(); ++memberIdx) {
|
||||||
|
auto memberName = (*blockType)[memberIdx].type->getFieldName();
|
||||||
|
if (anonymousMemberMap.find(memberName) != anonymousMemberMap.end())
|
||||||
|
{
|
||||||
|
if (anonymousMemberMap[memberName] != uniformVar.second.symbol->getType().getTypeName())
|
||||||
|
{
|
||||||
|
TString err = "Invalid block member name: " + memberName;
|
||||||
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
|
hadError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
anonymousMemberMap[memberName] = uniformVar.second.symbol->getType().getTypeName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hadError)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case we need to new an intermediate, which costs too much
|
||||||
|
int checkLocationOverlap(const TRange& locationRange, std::vector<TRange>& usedUniformLocation, const TString symbolName, std::vector<TString>& usedUniformName, bool& diffLocation)
|
||||||
|
{
|
||||||
|
for (size_t r = 0; r < usedUniformLocation.size(); ++r) {
|
||||||
|
if (usedUniformName[r] == symbolName) {
|
||||||
|
diffLocation = true;
|
||||||
|
return (usedUniformLocation[r].start == locationRange.start &&
|
||||||
|
usedUniformLocation[r].last == locationRange.last)
|
||||||
|
? -2 : std::max(locationRange.start, usedUniformLocation[r].start);
|
||||||
|
}
|
||||||
|
if (locationRange.overlap(usedUniformLocation[r])) {
|
||||||
|
// there is a collision; pick one
|
||||||
|
return std::max(locationRange.start, usedUniformLocation[r].start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1; // no collision
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
|
inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
|
||||||
@@ -314,17 +436,23 @@ struct TSymbolValidater
|
|||||||
TIntermSymbol* base = ent1.symbol;
|
TIntermSymbol* base = ent1.symbol;
|
||||||
const TType& type = ent1.symbol->getType();
|
const TType& type = ent1.symbol->getType();
|
||||||
const TString& name = entKey.first;
|
const TString& name = entKey.first;
|
||||||
EShLanguage stage = ent1.stage;
|
|
||||||
TString mangleName1, mangleName2;
|
TString mangleName1, mangleName2;
|
||||||
if (currentStage != stage) {
|
EShLanguage stage = ent1.stage;
|
||||||
preStage = currentStage;
|
EShLanguage preStage, currentStage, nextStage;
|
||||||
currentStage = stage;
|
|
||||||
nextStage = EShLangCount;
|
preStage = EShLangCount;
|
||||||
for (int i = currentStage + 1; i < EShLangCount; i++) {
|
for (int i = stage - 1; i >= 0; i--) {
|
||||||
if (inVarMaps[i] != nullptr) {
|
if (inVarMaps[i] != nullptr) {
|
||||||
nextStage = static_cast<EShLanguage>(i);
|
preStage = static_cast<EShLanguage>(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
currentStage = stage;
|
||||||
|
nextStage = EShLangCount;
|
||||||
|
for (int i = stage + 1; i < EShLangCount; i++) {
|
||||||
|
if (inVarMaps[i] != nullptr) {
|
||||||
|
nextStage = static_cast<EShLanguage>(i);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,46 +463,86 @@ struct TSymbolValidater
|
|||||||
type.appendMangledName(mangleName1);
|
type.appendMangledName(mangleName1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// basic checking that symbols match
|
||||||
|
// more extensive checking in the link stage
|
||||||
if (base->getQualifier().storage == EvqVaryingIn) {
|
if (base->getQualifier().storage == EvqVaryingIn) {
|
||||||
// validate stage in;
|
// validate stage in;
|
||||||
if (preStage == EShLangCount)
|
if (preStage == EShLangCount)
|
||||||
return;
|
return;
|
||||||
if (name == "gl_PerVertex")
|
if (TSymbolTable::isBuiltInSymbol(base->getId()))
|
||||||
return;
|
return;
|
||||||
if (outVarMaps[preStage] != nullptr) {
|
if (outVarMaps[preStage] != nullptr) {
|
||||||
auto ent2 = outVarMaps[preStage]->find(name);
|
auto ent2 = outVarMaps[preStage]->find(name);
|
||||||
|
uint32_t location = base->getType().getQualifier().layoutLocation;
|
||||||
|
if (ent2 == outVarMaps[preStage]->end() &&
|
||||||
|
location != glslang::TQualifier::layoutLocationEnd) {
|
||||||
|
for (auto var = outVarMaps[preStage]->begin(); var != ent2; var++) {
|
||||||
|
if (var->second.symbol->getType().getQualifier().layoutLocation == location) {
|
||||||
|
ent2 = var;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ent2 != outVarMaps[preStage]->end()) {
|
if (ent2 != outVarMaps[preStage]->end()) {
|
||||||
|
auto& type1 = base->getType();
|
||||||
|
auto& type2 = ent2->second.symbol->getType();
|
||||||
|
hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
|
||||||
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
|
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
|
||||||
TType subType(ent2->second.symbol->getType(), 0);
|
TType subType(ent2->second.symbol->getType(), 0);
|
||||||
subType.appendMangledName(mangleName2);
|
subType.appendMangledName(mangleName2);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
||||||
}
|
}
|
||||||
if (mangleName1 == mangleName2)
|
|
||||||
|
if (mangleName1 == mangleName2) {
|
||||||
|
// For ES 3.0 only, other versions have no such restrictions
|
||||||
|
// According to ES 3.0 spec: The type and presence of the interpolation qualifiers and
|
||||||
|
// storage qualifiers of variables with the same name declared in all linked shaders must
|
||||||
|
// match, otherwise the link command will fail.
|
||||||
|
if (profile == EEsProfile && version == 300) {
|
||||||
|
// Don't need to check smooth qualifier, as it uses the default interpolation mode
|
||||||
|
if (ent1.stage == EShLangFragment && type1.isBuiltIn() == false) {
|
||||||
|
if (type1.getQualifier().flat != type2.getQualifier().flat ||
|
||||||
|
type1.getQualifier().nopersp != type2.getQualifier().nopersp) {
|
||||||
|
TString err = "Interpolation qualifier mismatch : " + entKey.first;
|
||||||
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
|
hadError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
TString err = "Invalid In/Out variable type : " + entKey.first;
|
TString err = "Invalid In/Out variable type : " + entKey.first;
|
||||||
infoSink.info.message(EPrefixInternalError, err.c_str());
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
hadError = true;
|
hadError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!base->getType().isBuiltIn()) {
|
||||||
|
// According to spec: A link error is generated if any statically referenced input variable
|
||||||
|
// or block does not have a matching output
|
||||||
|
if (profile == EEsProfile && ent1.live) {
|
||||||
|
hadError = true;
|
||||||
|
TString errorStr = name + ": not been declare as a output variable in pre shader stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (base->getQualifier().storage == EvqVaryingOut) {
|
} else if (base->getQualifier().storage == EvqVaryingOut) {
|
||||||
// validate stage out;
|
// validate stage out;
|
||||||
if (nextStage == EShLangCount)
|
if (nextStage == EShLangCount)
|
||||||
return;
|
return;
|
||||||
if (name == "gl_PerVertex")
|
if (TSymbolTable::isBuiltInSymbol(base->getId()))
|
||||||
return;
|
return;
|
||||||
if (outVarMaps[nextStage] != nullptr) {
|
if (inVarMaps[nextStage] != nullptr) {
|
||||||
auto ent2 = inVarMaps[nextStage]->find(name);
|
auto ent2 = inVarMaps[nextStage]->find(name);
|
||||||
if (ent2 != inVarMaps[nextStage]->end()) {
|
if (ent2 != inVarMaps[nextStage]->end()) {
|
||||||
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
|
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
|
||||||
TType subType(ent2->second.symbol->getType(), 0);
|
TType subType(ent2->second.symbol->getType(), 0);
|
||||||
subType.appendMangledName(mangleName2);
|
subType.appendMangledName(mangleName2);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
||||||
}
|
}
|
||||||
if (mangleName1 == mangleName2)
|
if (mangleName1 == mangleName2)
|
||||||
@@ -387,7 +555,7 @@ struct TSymbolValidater
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (base->getQualifier().isUniformOrBuffer() && ! base->getQualifier().isPushConstant()) {
|
} else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) {
|
||||||
// validate uniform type;
|
// validate uniform type;
|
||||||
for (int i = 0; i < EShLangCount; i++) {
|
for (int i = 0; i < EShLangCount; i++) {
|
||||||
if (i != currentStage && outVarMaps[i] != nullptr) {
|
if (i != currentStage && outVarMaps[i] != nullptr) {
|
||||||
@@ -395,26 +563,174 @@ struct TSymbolValidater
|
|||||||
if (ent2 != uniformVarMap[i]->end()) {
|
if (ent2 != uniformVarMap[i]->end()) {
|
||||||
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
ent2->second.symbol->getType().appendMangledName(mangleName2);
|
||||||
if (mangleName1 != mangleName2) {
|
if (mangleName1 != mangleName2) {
|
||||||
|
ent2->second.symbol->getType().sameElementType(type);
|
||||||
TString err = "Invalid Uniform variable type : " + entKey.first;
|
TString err = "Invalid Uniform variable type : " + entKey.first;
|
||||||
infoSink.info.message(EPrefixInternalError, err.c_str());
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
hadError = true;
|
hadError = true;
|
||||||
}
|
}
|
||||||
mangleName2.clear();
|
mangleName2.clear();
|
||||||
|
|
||||||
|
// validate instance name of blocks
|
||||||
|
if (hadError == false &&
|
||||||
|
base->getType().getBasicType() == EbtBlock &&
|
||||||
|
IsAnonymous(base->getName()) != IsAnonymous(ent2->second.symbol->getName())) {
|
||||||
|
TString err = "Matched uniform block names must also either all be lacking "
|
||||||
|
"an instance name or all having an instance name: " + entKey.first;
|
||||||
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
|
hadError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate uniform block member qualifier and member names
|
||||||
|
auto& type1 = base->getType();
|
||||||
|
auto& type2 = ent2->second.symbol->getType();
|
||||||
|
if (hadError == false && base->getType().getBasicType() == EbtBlock) {
|
||||||
|
hadError = hadError || typeCheck(&type1, &type2, name.c_str(), true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (base->getBasicType() == EbtBlock)
|
||||||
|
{
|
||||||
|
if (IsAnonymous(base->getName()))
|
||||||
|
{
|
||||||
|
// The name of anonymous block member can't same with default uniform variable.
|
||||||
|
auto blockType1 = base->getType().getStruct();
|
||||||
|
for (size_t memberIdx = 0; memberIdx < blockType1->size(); ++memberIdx) {
|
||||||
|
auto memberName = (*blockType1)[memberIdx].type->getFieldName();
|
||||||
|
if (uniformVarMap[i]->find(memberName) != uniformVarMap[i]->end())
|
||||||
|
{
|
||||||
|
TString err = "Invalid Uniform variable name : " + memberName;
|
||||||
|
infoSink.info.message(EPrefixInternalError, err.c_str());
|
||||||
|
hadError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
|
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];
|
||||||
// Use for mark pre stage, to get more interface symbol information.
|
|
||||||
EShLanguage preStage, currentStage, nextStage;
|
|
||||||
// Use for mark current shader stage for resolver
|
// Use for mark current shader stage for resolver
|
||||||
TIoMapResolver& resolver;
|
TIoMapResolver& resolver;
|
||||||
TInfoSink& infoSink;
|
TInfoSink& infoSink;
|
||||||
bool& hadError;
|
bool& hadError;
|
||||||
|
EProfile profile;
|
||||||
|
int version;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSymbolValidater& operator=(TSymbolValidater&) = delete;
|
TSymbolValidater& operator=(TSymbolValidater&) = delete;
|
||||||
|
|
||||||
|
bool qualifierCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
|
||||||
|
{
|
||||||
|
bool hasError = false;
|
||||||
|
const TQualifier& qualifier1 = type1->getQualifier();
|
||||||
|
const TQualifier& qualifier2 = type2->getQualifier();
|
||||||
|
|
||||||
|
if (((isBlock == false) &&
|
||||||
|
(type1->getQualifier().storage == EvqUniform && type2->getQualifier().storage == EvqUniform)) ||
|
||||||
|
(type1->getQualifier().storage == EvqGlobal && type2->getQualifier().storage == EvqGlobal)) {
|
||||||
|
if (qualifier1.precision != qualifier2.precision) {
|
||||||
|
hasError = true;
|
||||||
|
std::string errorStr = name + ": have precision conflict cross stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
if (qualifier1.hasFormat() && qualifier2.hasFormat()) {
|
||||||
|
if (qualifier1.layoutFormat != qualifier2.layoutFormat) {
|
||||||
|
hasError = true;
|
||||||
|
std::string errorStr = name + ": have layout format conflict cross stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlock == true) {
|
||||||
|
if (qualifier1.layoutPacking != qualifier2.layoutPacking) {
|
||||||
|
hasError = true;
|
||||||
|
std::string errorStr = name + ": have layoutPacking conflict cross stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
if (qualifier1.layoutMatrix != qualifier2.layoutMatrix) {
|
||||||
|
hasError = true;
|
||||||
|
std::string errorStr = name + ": have layoutMatrix conflict cross stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
if (qualifier1.layoutOffset != qualifier2.layoutOffset) {
|
||||||
|
hasError = true;
|
||||||
|
std::string errorStr = name + ": have layoutOffset conflict cross stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
if (qualifier1.layoutAlign != qualifier2.layoutAlign) {
|
||||||
|
hasError = true;
|
||||||
|
std::string errorStr = name + ": have layoutAlign conflict cross stage.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasError;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool typeCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
|
||||||
|
{
|
||||||
|
bool hasError = false;
|
||||||
|
if (!(type1->isStruct() && type2->isStruct())) {
|
||||||
|
hasError = hasError || qualifierCheck(type1, type2, name, isBlock);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (type1->getBasicType() == EbtBlock && type2->getBasicType() == EbtBlock)
|
||||||
|
isBlock = true;
|
||||||
|
const TTypeList* typeList1 = type1->getStruct();
|
||||||
|
const TTypeList* typeList2 = type2->getStruct();
|
||||||
|
|
||||||
|
std::string newName = name;
|
||||||
|
size_t memberCount = typeList1->size();
|
||||||
|
size_t index2 = 0;
|
||||||
|
for (size_t index = 0; index < memberCount; index++, index2++) {
|
||||||
|
// Skip inactive member
|
||||||
|
if (typeList1->at(index).type->getBasicType() == EbtVoid)
|
||||||
|
continue;
|
||||||
|
while (index2 < typeList2->size() && typeList2->at(index2).type->getBasicType() == EbtVoid) {
|
||||||
|
++index2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeList1 has more members in list
|
||||||
|
if (index2 == typeList2->size()) {
|
||||||
|
std::string errorStr = name + ": struct mismatch.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
hasError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeList1->at(index).type->getFieldName() != typeList2->at(index2).type->getFieldName()) {
|
||||||
|
std::string errorStr = name + ": member name mismatch.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
hasError = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newName = typeList1->at(index).type->getFieldName().c_str();
|
||||||
|
}
|
||||||
|
hasError = hasError || typeCheck(typeList1->at(index).type, typeList2->at(index2).type, newName, isBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index2 < typeList2->size())
|
||||||
|
{
|
||||||
|
// TypeList2 has more members
|
||||||
|
if (typeList2->at(index2).type->getBasicType() != EbtVoid) {
|
||||||
|
std::string errorStr = name + ": struct mismatch.";
|
||||||
|
infoSink.info.message(EPrefixError, errorStr.c_str());
|
||||||
|
hasError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++index2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasError;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TSlotCollector {
|
struct TSlotCollector {
|
||||||
@@ -438,14 +754,18 @@ TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate
|
|||||||
, nextOutputLocation(0)
|
, nextOutputLocation(0)
|
||||||
{
|
{
|
||||||
memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
|
memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
|
||||||
|
memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount));
|
||||||
|
stageIntermediates[intermediate.getStage()] = &intermediate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TDefaultIoResolverBase::getBaseBinding(TResourceType res, unsigned int set) const {
|
int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const {
|
||||||
return selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
|
return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set))
|
||||||
|
: selectBaseBinding(intermediate.getShiftBinding(res), intermediate.getShiftBindingForSet(res, set));
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding() const {
|
const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const {
|
||||||
return intermediate.getResourceSetBinding();
|
return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding()
|
||||||
|
: intermediate.getResourceSetBinding();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
|
bool TDefaultIoResolverBase::doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
|
||||||
@@ -486,21 +806,21 @@ int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) {
|
|||||||
return reserveSlot(set, base, size);
|
return reserveSlot(set, base, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TDefaultIoResolverBase::resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
if (type.getQualifier().hasSet()) {
|
if (type.getQualifier().hasSet()) {
|
||||||
return ent.newSet = type.getQualifier().layoutSet;
|
return ent.newSet = type.getQualifier().layoutSet;
|
||||||
}
|
}
|
||||||
// If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
|
// If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
|
||||||
if (getResourceSetBinding().size() == 1) {
|
if (getResourceSetBinding(stage).size() == 1) {
|
||||||
return ent.newSet = atoi(getResourceSetBinding()[0].c_str());
|
return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str());
|
||||||
}
|
}
|
||||||
return ent.newSet = 0;
|
return ent.newSet = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const char* name = ent.symbol->getName().c_str();
|
const char* name = ent.symbol->getAccessName().c_str();
|
||||||
// kick out of not doing this
|
// kick out of not doing this
|
||||||
if (! doAutoLocationMapping()) {
|
if (! doAutoLocationMapping()) {
|
||||||
return ent.newLocation = -1;
|
return ent.newLocation = -1;
|
||||||
@@ -609,12 +929,12 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
|
|||||||
|
|
||||||
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
|
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = getAccessName(ent.symbol);
|
const TString& name = ent.symbol->getAccessName();
|
||||||
if (currentStage != stage) {
|
if (currentStage != stage) {
|
||||||
preStage = currentStage;
|
preStage = currentStage;
|
||||||
currentStage = stage;
|
currentStage = stage;
|
||||||
}
|
}
|
||||||
// kick out of not doing this
|
// kick out if not doing this
|
||||||
if (! doAutoLocationMapping()) {
|
if (! doAutoLocationMapping()) {
|
||||||
return ent.newLocation = -1;
|
return ent.newLocation = -1;
|
||||||
}
|
}
|
||||||
@@ -693,7 +1013,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
|
|||||||
|
|
||||||
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = getAccessName(ent.symbol);
|
const TString& name = ent.symbol->getAccessName();
|
||||||
// kick out of not doing this
|
// kick out of not doing this
|
||||||
if (! doAutoLocationMapping()) {
|
if (! doAutoLocationMapping()) {
|
||||||
return ent.newLocation = -1;
|
return ent.newLocation = -1;
|
||||||
@@ -762,9 +1082,9 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
|
|||||||
return ent.newLocation = location;
|
return ent.newLocation = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = getAccessName(ent.symbol);
|
const TString& name = ent.symbol->getAccessName();
|
||||||
// On OpenGL arrays of opaque types take a separate binding for each element
|
// On OpenGL arrays of opaque types take a separate binding for each element
|
||||||
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
||||||
TResourceType resource = getResourceType(type);
|
TResourceType resource = getResourceType(type);
|
||||||
@@ -775,30 +1095,32 @@ int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo&
|
|||||||
// 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 = resource;
|
int set = intermediate.getSpv().openGl != 0 ? resource : ent.newSet;
|
||||||
|
int resourceKey = set;
|
||||||
if (resource < EResCount) {
|
if (resource < EResCount) {
|
||||||
if (type.getQualifier().hasBinding()) {
|
if (type.getQualifier().hasBinding()) {
|
||||||
ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
|
int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
|
||||||
return ent.newBinding;
|
return ent.newBinding = newBinding;
|
||||||
} else if (ent.live && doAutoBindingMapping()) {
|
|
||||||
|
} 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
|
||||||
// the resource has binding, don't need to allocate if it already has a binding
|
// the resource has binding, don't need to allocate if it already has a binding
|
||||||
bool hasBinding = false;
|
bool hasBinding = false;
|
||||||
if (! resourceSlotMap[resource].empty()) {
|
ent.newBinding = -1; // leave as -1 if it isn't set below
|
||||||
TVarSlotMap::iterator iter = resourceSlotMap[resource].find(name);
|
|
||||||
if (iter != resourceSlotMap[resource].end()) {
|
if (! resourceSlotMap[resourceKey].empty()) {
|
||||||
|
TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name);
|
||||||
|
if (iter != resourceSlotMap[resourceKey].end()) {
|
||||||
hasBinding = true;
|
hasBinding = true;
|
||||||
ent.newBinding = iter->second;
|
ent.newBinding = iter->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! hasBinding) {
|
if (!hasBinding && (ent.live && doAutoBindingMapping())) {
|
||||||
TVarSlotMap varSlotMap;
|
|
||||||
// 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(resource, getBaseBinding(resource, set), numBindings);
|
int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings);
|
||||||
varSlotMap[name] = binding;
|
resourceSlotMap[resourceKey][name] = binding;
|
||||||
resourceSlotMap[resource] = varSlotMap;
|
|
||||||
ent.newBinding = binding;
|
ent.newBinding = binding;
|
||||||
}
|
}
|
||||||
return ent.newBinding;
|
return ent.newBinding;
|
||||||
@@ -839,7 +1161,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
|
|||||||
|
|
||||||
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = getAccessName(ent.symbol);
|
const TString& name = ent.symbol->getAccessName();
|
||||||
TStorageQualifier storage = type.getQualifier().storage;
|
TStorageQualifier storage = type.getQualifier().storage;
|
||||||
EShLanguage stage(EShLangCount);
|
EShLanguage stage(EShLangCount);
|
||||||
switch (storage) {
|
switch (storage) {
|
||||||
@@ -899,17 +1221,21 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
|
|||||||
|
|
||||||
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = getAccessName(ent.symbol);
|
const TString& name = ent.symbol->getAccessName();
|
||||||
int resource = getResourceType(type);
|
TResourceType resource = getResourceType(type);
|
||||||
|
int set = intermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent);
|
||||||
|
int resourceKey = set;
|
||||||
|
|
||||||
if (type.getQualifier().hasBinding()) {
|
if (type.getQualifier().hasBinding()) {
|
||||||
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
|
TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey];
|
||||||
TVarSlotMap::iterator iter = varSlotMap.find(name);
|
TVarSlotMap::iterator iter = varSlotMap.find(name);
|
||||||
int binding = type.getQualifier().layoutBinding;
|
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 = type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
||||||
varSlotMap[name] = binding;
|
varSlotMap[name] = binding;
|
||||||
reserveSlot(resource, binding, numBindings);
|
reserveSlot(resourceKey, 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
|
||||||
@@ -922,13 +1248,6 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
|
|
||||||
{
|
|
||||||
return symbol->getBasicType() == EbtBlock ?
|
|
||||||
symbol->getType().getTypeName() :
|
|
||||||
symbol->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
//TDefaultGlslIoResolver end
|
//TDefaultGlslIoResolver end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -965,7 +1284,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
|
|||||||
return EResCount;
|
return EResCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
|
int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const int set = getLayoutSet(type);
|
const int set = getLayoutSet(type);
|
||||||
// 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
|
||||||
@@ -974,11 +1293,11 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase {
|
|||||||
if (resource < EResCount) {
|
if (resource < EResCount) {
|
||||||
if (type.getQualifier().hasBinding()) {
|
if (type.getQualifier().hasBinding()) {
|
||||||
return ent.newBinding = reserveSlot(
|
return ent.newBinding = reserveSlot(
|
||||||
set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding, numBindings);
|
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(resource, set), numBindings);
|
return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ent.newBinding = -1;
|
return ent.newBinding = -1;
|
||||||
@@ -1050,17 +1369,17 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
|
|||||||
return EResCount;
|
return EResCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override {
|
int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
|
||||||
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);
|
||||||
if (resource < EResCount) {
|
if (resource < EResCount) {
|
||||||
if (type.getQualifier().hasBinding()) {
|
if (type.getQualifier().hasBinding()) {
|
||||||
return ent.newBinding = reserveSlot(set, getBaseBinding(resource, set) + type.getQualifier().layoutBinding);
|
return ent.newBinding = reserveSlot(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(resource, set));
|
return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ent.newBinding = -1;
|
return ent.newBinding = -1;
|
||||||
@@ -1099,10 +1418,10 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
|
|||||||
else
|
else
|
||||||
resolver = &defaultResolver;
|
resolver = &defaultResolver;
|
||||||
}
|
}
|
||||||
resolver->addStage(stage);
|
|
||||||
#else
|
#else
|
||||||
resolver = &defaultResolver;
|
resolver = &defaultResolver;
|
||||||
#endif
|
#endif
|
||||||
|
resolver->addStage(stage, intermediate);
|
||||||
|
|
||||||
TVarLiveMap inVarMap, outVarMap, uniformVarMap;
|
TVarLiveMap inVarMap, outVarMap, uniformVarMap;
|
||||||
TVarLiveVector inVector, outVector, uniformVector;
|
TVarLiveVector inVector, outVector, uniformVector;
|
||||||
@@ -1117,25 +1436,23 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
|
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
|
||||||
std::for_each(inVarMap.begin(), inVarMap.end(),
|
for (auto& var : inVarMap) { inVector.push_back(var); }
|
||||||
[&inVector](TVarLivePair p) { inVector.push_back(p); });
|
|
||||||
std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||||
});
|
});
|
||||||
std::for_each(outVarMap.begin(), outVarMap.end(),
|
for (auto& var : outVarMap) { outVector.push_back(var); }
|
||||||
[&outVector](TVarLivePair p) { outVector.push_back(p); });
|
|
||||||
std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||||
});
|
});
|
||||||
std::for_each(uniformVarMap.begin(), uniformVarMap.end(),
|
for (auto& var : uniformVarMap) { uniformVector.push_back(var); }
|
||||||
[&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
|
|
||||||
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||||
});
|
});
|
||||||
bool hadError = false;
|
bool hadError = false;
|
||||||
|
TVarLiveMap* dummyUniformVarMap[EShLangCount] = {};
|
||||||
TNotifyInOutAdaptor inOutNotify(stage, *resolver);
|
TNotifyInOutAdaptor inOutNotify(stage, *resolver);
|
||||||
TNotifyUniformAdaptor uniformNotify(stage, *resolver);
|
TNotifyUniformAdaptor uniformNotify(stage, *resolver);
|
||||||
TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError);
|
TResolverUniformAdaptor uniformResolve(stage, *resolver, dummyUniformVarMap, infoSink, hadError);
|
||||||
TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
|
TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
|
||||||
resolver->beginNotifications(stage);
|
resolver->beginNotifications(stage);
|
||||||
std::for_each(inVector.begin(), inVector.end(), inOutNotify);
|
std::for_each(inVector.begin(), inVector.end(), inOutNotify);
|
||||||
@@ -1143,22 +1460,22 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
|
|||||||
std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
|
std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
|
||||||
resolver->endNotifications(stage);
|
resolver->endNotifications(stage);
|
||||||
resolver->beginResolve(stage);
|
resolver->beginResolve(stage);
|
||||||
std::for_each(inVector.begin(), inVector.end(), inOutResolve);
|
for (auto& var : inVector) { inOutResolve(var); }
|
||||||
std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
|
std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
|
||||||
auto at = inVarMap.find(p.second.symbol->getName());
|
auto at = inVarMap.find(p.second.symbol->getAccessName());
|
||||||
if (at != inVarMap.end())
|
if (at != inVarMap.end() && p.second.id == at->second.id)
|
||||||
at->second = p.second;
|
at->second = p.second;
|
||||||
});
|
});
|
||||||
std::for_each(outVector.begin(), outVector.end(), inOutResolve);
|
for (auto& var : outVector) { inOutResolve(var); }
|
||||||
std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
|
std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
|
||||||
auto at = outVarMap.find(p.second.symbol->getName());
|
auto at = outVarMap.find(p.second.symbol->getAccessName());
|
||||||
if (at != outVarMap.end())
|
if (at != outVarMap.end() && p.second.id == at->second.id)
|
||||||
at->second = p.second;
|
at->second = p.second;
|
||||||
});
|
});
|
||||||
std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
|
std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
|
||||||
std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
|
std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
|
||||||
auto at = uniformVarMap.find(p.second.symbol->getName());
|
auto at = uniformVarMap.find(p.second.symbol->getAccessName());
|
||||||
if (at != uniformVarMap.end())
|
if (at != uniformVarMap.end() && p.second.id == at->second.id)
|
||||||
at->second = p.second;
|
at->second = p.second;
|
||||||
});
|
});
|
||||||
resolver->endResolve(stage);
|
resolver->endResolve(stage);
|
||||||
@@ -1174,9 +1491,14 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
|
|||||||
//
|
//
|
||||||
// Returns false if the input is too malformed to do this.
|
// Returns false if the input is too malformed to do this.
|
||||||
bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
|
bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
|
||||||
|
bool somethingToDo = !intermediate.getResourceSetBinding().empty() ||
|
||||||
|
intermediate.getAutoMapBindings() ||
|
||||||
|
intermediate.getAutoMapLocations();
|
||||||
|
|
||||||
|
// Profile and version are use for symbol validate.
|
||||||
|
profile = intermediate.getProfile();
|
||||||
|
version = intermediate.getVersion();
|
||||||
|
|
||||||
bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() ||
|
|
||||||
intermediate.getAutoMapLocations();
|
|
||||||
// Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
|
// Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
|
||||||
// unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
|
// unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
|
||||||
for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
|
for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
|
||||||
@@ -1195,10 +1517,21 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn
|
|||||||
}
|
}
|
||||||
// if no resolver is provided, use the default resolver with the given shifts and auto map settings
|
// if no resolver is provided, use the default resolver with the given shifts and auto map settings
|
||||||
TDefaultGlslIoResolver defaultResolver(intermediate);
|
TDefaultGlslIoResolver defaultResolver(intermediate);
|
||||||
|
#ifdef ENABLE_HLSL
|
||||||
|
TDefaultHlslIoResolver defaultHlslResolver(intermediate);
|
||||||
|
if (resolver == nullptr) {
|
||||||
|
// TODO: use a passed in IO mapper for this
|
||||||
|
if (intermediate.usingHlslIoMapping())
|
||||||
|
resolver = &defaultHlslResolver;
|
||||||
|
else
|
||||||
|
resolver = &defaultResolver;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (resolver == nullptr) {
|
if (resolver == nullptr) {
|
||||||
resolver = &defaultResolver;
|
resolver = &defaultResolver;
|
||||||
}
|
}
|
||||||
resolver->addStage(stage);
|
#endif
|
||||||
|
resolver->addStage(stage, intermediate);
|
||||||
inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
|
inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
|
||||||
TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
|
TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
|
||||||
*uniformVarMap[stage]);
|
*uniformVarMap[stage]);
|
||||||
@@ -1236,31 +1569,66 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
|
|||||||
resolver->endResolve(EShLangCount);
|
resolver->endResolve(EShLangCount);
|
||||||
if (!hadError) {
|
if (!hadError) {
|
||||||
//Resolve uniform location, ubo/ssbo/opaque bindings across stages
|
//Resolve uniform location, ubo/ssbo/opaque bindings across stages
|
||||||
TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, infoSink, hadError);
|
TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, uniformVarMap, infoSink, hadError);
|
||||||
TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
|
TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
|
||||||
TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, outVarMaps, uniformVarMap, hadError);
|
TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps,
|
||||||
|
outVarMaps, uniformVarMap, hadError, profile, version);
|
||||||
|
|
||||||
|
TVarLiveVector inVectors[EShLangCount];
|
||||||
|
TVarLiveVector outVectors[EShLangCount];
|
||||||
TVarLiveVector uniformVector;
|
TVarLiveVector uniformVector;
|
||||||
|
|
||||||
resolver->beginResolve(EShLangCount);
|
resolver->beginResolve(EShLangCount);
|
||||||
for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
|
for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
|
||||||
if (inVarMaps[stage] != nullptr) {
|
if (inVarMaps[stage] != nullptr) {
|
||||||
inOutResolve.setStage(EShLanguage(stage));
|
inOutResolve.setStage(EShLanguage(stage));
|
||||||
std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), symbolValidater);
|
|
||||||
std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutResolve);
|
// copy vars into a sorted list
|
||||||
std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), symbolValidater);
|
std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(),
|
||||||
std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutResolve);
|
[&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); });
|
||||||
|
std::sort(inVectors[stage].begin(), inVectors[stage].end(),
|
||||||
|
[](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
|
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(),
|
||||||
|
[&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); });
|
||||||
|
std::sort(outVectors[stage].begin(), outVectors[stage].end(),
|
||||||
|
[](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
|
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto& var : inVectors[stage]) { symbolValidater(var); }
|
||||||
|
for (auto& var : inVectors[stage]) { inOutResolve(var); }
|
||||||
|
for (auto& var : outVectors[stage]) { symbolValidater(var); }
|
||||||
|
for (auto& var : outVectors[stage]) { inOutResolve(var); }
|
||||||
|
|
||||||
|
// copy results back into maps
|
||||||
|
std::for_each(inVectors[stage].begin(), inVectors[stage].end(),
|
||||||
|
[this, stage](TVarLivePair p) {
|
||||||
|
auto at = inVarMaps[stage]->find(p.first);
|
||||||
|
if (at != inVarMaps[stage]->end())
|
||||||
|
at->second = p.second;
|
||||||
|
});
|
||||||
|
|
||||||
|
std::for_each(outVectors[stage].begin(), outVectors[stage].end(),
|
||||||
|
[this, stage](TVarLivePair p) {
|
||||||
|
auto at = outVarMaps[stage]->find(p.first);
|
||||||
|
if (at != outVarMaps[stage]->end())
|
||||||
|
at->second = p.second;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
if (uniformVarMap[stage] != nullptr) {
|
if (uniformVarMap[stage] != nullptr) {
|
||||||
uniformResolve.setStage(EShLanguage(stage));
|
uniformResolve.setStage(EShLanguage(stage));
|
||||||
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
|
for (auto& var : *(uniformVarMap[stage])) { uniformVector.push_back(var); }
|
||||||
std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(),
|
|
||||||
[&uniformVector](TVarLivePair p) { uniformVector.push_back(p); });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second);
|
||||||
});
|
});
|
||||||
std::for_each(uniformVector.begin(), uniformVector.end(), symbolValidater);
|
for (auto& var : uniformVector) { symbolValidater(var); }
|
||||||
std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
|
for (auto& var : uniformVector) { uniformResolve(var); }
|
||||||
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
|
||||||
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
|
||||||
});
|
});
|
||||||
@@ -1269,14 +1637,18 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
|
|||||||
if (intermediates[stage] != nullptr) {
|
if (intermediates[stage] != nullptr) {
|
||||||
// traverse each stage, set new location to each input/output and unifom symbol, set new binding to
|
// traverse each stage, set new location to each input/output and unifom symbol, set new binding to
|
||||||
// ubo, ssbo and opaque symbols
|
// ubo, ssbo and opaque symbols
|
||||||
TVarLiveMap** pUniformVarMap = uniformVarMap;
|
TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap;
|
||||||
std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
|
std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
|
||||||
auto at = pUniformVarMap[stage]->find(p.second.symbol->getName());
|
auto at = pUniformVarMap[stage]->find(p.second.symbol->getAccessName());
|
||||||
if (at != pUniformVarMap[stage]->end())
|
if (at != pUniformVarMap[stage]->end() && at->second.id == p.second.id){
|
||||||
|
int resolvedBinding = at->second.newBinding;
|
||||||
at->second = p.second;
|
at->second = p.second;
|
||||||
|
if (resolvedBinding > 0)
|
||||||
|
at->second.newBinding = resolvedBinding;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
|
TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
|
||||||
*uniformVarMap[stage]);
|
*uniformResolve.uniformVarMap[stage]);
|
||||||
intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
|
intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace glslang {
|
|||||||
|
|
||||||
class TIntermediate;
|
class TIntermediate;
|
||||||
struct TVarEntryInfo {
|
struct TVarEntryInfo {
|
||||||
int id;
|
long long id;
|
||||||
TIntermSymbol* symbol;
|
TIntermSymbol* symbol;
|
||||||
bool live;
|
bool live;
|
||||||
int newBinding;
|
int newBinding;
|
||||||
@@ -87,6 +87,35 @@ struct TVarEntryInfo {
|
|||||||
return lPoints > rPoints;
|
return lPoints > rPoints;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TOrderByPriorityAndLive {
|
||||||
|
// ordering:
|
||||||
|
// 1) do live variables first
|
||||||
|
// 2) has both binding and set
|
||||||
|
// 3) has binding but no set
|
||||||
|
// 4) has no binding but set
|
||||||
|
// 5) has no binding and no set
|
||||||
|
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
|
||||||
|
|
||||||
|
const TQualifier& lq = l.symbol->getQualifier();
|
||||||
|
const TQualifier& rq = r.symbol->getQualifier();
|
||||||
|
|
||||||
|
// simple rules:
|
||||||
|
// has binding gives 2 points
|
||||||
|
// has set gives 1 point
|
||||||
|
// who has the most points is more important.
|
||||||
|
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
|
||||||
|
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
|
||||||
|
|
||||||
|
if (l.live != r.live)
|
||||||
|
return l.live > r.live;
|
||||||
|
|
||||||
|
if (lPoints != rPoints)
|
||||||
|
return lPoints > rPoints;
|
||||||
|
|
||||||
|
return l.id < r.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base class for shared TIoMapResolver services, used by several derivations.
|
// Base class for shared TIoMapResolver services, used by several derivations.
|
||||||
@@ -107,8 +136,8 @@ public:
|
|||||||
void endCollect(EShLanguage) override {}
|
void endCollect(EShLanguage) override {}
|
||||||
void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
||||||
void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
||||||
int getBaseBinding(TResourceType res, unsigned int set) const;
|
int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
|
||||||
const std::vector<std::string>& getResourceSetBinding() const;
|
const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
|
||||||
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;
|
||||||
@@ -122,9 +151,11 @@ public:
|
|||||||
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
|
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
|
||||||
int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||||
int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
||||||
void addStage(EShLanguage stage) override {
|
void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
|
||||||
if (stage < EShLangCount)
|
if (stage < EShLangCount) {
|
||||||
stageMask[stage] = true;
|
stageMask[stage] = true;
|
||||||
|
stageIntermediates[stage] = &stageIntermediate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
|
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
|
||||||
|
|
||||||
@@ -139,6 +170,8 @@ protected:
|
|||||||
int nextInputLocation;
|
int nextInputLocation;
|
||||||
int nextOutputLocation;
|
int nextOutputLocation;
|
||||||
bool stageMask[EShLangCount + 1];
|
bool stageMask[EShLangCount + 1];
|
||||||
|
const TIntermediate* stageIntermediates[EShLangCount];
|
||||||
|
|
||||||
// Return descriptor set specific base if there is one, and the generic base otherwise.
|
// Return descriptor set specific base if there is one, and the generic base otherwise.
|
||||||
int selectBaseBinding(int base, int descriptorSetBase) const {
|
int selectBaseBinding(int base, int descriptorSetBase) const {
|
||||||
return descriptorSetBase != -1 ? descriptorSetBase : base;
|
return descriptorSetBase != -1 ? descriptorSetBase : base;
|
||||||
@@ -203,7 +236,6 @@ public:
|
|||||||
void endCollect(EShLanguage) override;
|
void endCollect(EShLanguage) override;
|
||||||
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||||
void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||||
const TString& getAccessName(const TIntermSymbol*);
|
|
||||||
// in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
|
// in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
|
||||||
// We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
|
// We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
|
||||||
// if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
|
// if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
|
||||||
@@ -263,10 +295,12 @@ public:
|
|||||||
class TGlslIoMapper : public TIoMapper {
|
class TGlslIoMapper : public TIoMapper {
|
||||||
public:
|
public:
|
||||||
TGlslIoMapper() {
|
TGlslIoMapper() {
|
||||||
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
|
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
|
||||||
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
|
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
|
||||||
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount);
|
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
|
||||||
memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
|
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
|
||||||
|
profile = ENoProfile;
|
||||||
|
version = 0;
|
||||||
}
|
}
|
||||||
virtual ~TGlslIoMapper() {
|
virtual ~TGlslIoMapper() {
|
||||||
for (size_t stage = 0; stage < EShLangCount; stage++) {
|
for (size_t stage = 0; stage < EShLangCount; stage++) {
|
||||||
@@ -293,6 +327,8 @@ public:
|
|||||||
*uniformVarMap[EShLangCount];
|
*uniformVarMap[EShLangCount];
|
||||||
TIntermediate* intermediates[EShLangCount];
|
TIntermediate* intermediates[EShLangCount];
|
||||||
bool hadError = false;
|
bool hadError = false;
|
||||||
|
EProfile profile;
|
||||||
|
int version;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
|||||||
@@ -63,14 +63,14 @@ namespace glslang {
|
|||||||
|
|
||||||
class TInductiveTraverser : public TIntermTraverser {
|
class TInductiveTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TInductiveTraverser(int id, TSymbolTable& st)
|
TInductiveTraverser(long long id, TSymbolTable& st)
|
||||||
: loopId(id), symbolTable(st), bad(false) { }
|
: loopId(id), symbolTable(st), bad(false) { }
|
||||||
|
|
||||||
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
||||||
virtual bool visitUnary(TVisit, TIntermUnary* node);
|
virtual bool visitUnary(TVisit, TIntermUnary* node);
|
||||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||||
|
|
||||||
int loopId; // unique ID of the symbol that's the loop inductive variable
|
long long loopId; // unique ID of the symbol that's the loop inductive variable
|
||||||
TSymbolTable& symbolTable;
|
TSymbolTable& symbolTable;
|
||||||
bool bad;
|
bool bad;
|
||||||
TSourceLoc badLoc;
|
TSourceLoc badLoc;
|
||||||
@@ -129,7 +129,7 @@ bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* n
|
|||||||
//
|
//
|
||||||
// External function to call for loop check.
|
// External function to call for loop check.
|
||||||
//
|
//
|
||||||
void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
|
void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, long long loopId, TSymbolTable& symbolTable)
|
||||||
{
|
{
|
||||||
TInductiveTraverser it(loopId, symbolTable);
|
TInductiveTraverser it(loopId, symbolTable);
|
||||||
|
|
||||||
|
|||||||
Executable → Regular
+433
-44
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include "localintermediate.h"
|
#include "localintermediate.h"
|
||||||
#include "../Include/InfoSink.h"
|
#include "../Include/InfoSink.h"
|
||||||
|
#include "SymbolTable.h"
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
@@ -89,6 +90,56 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// check that link objects between stages
|
||||||
|
//
|
||||||
|
void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit) {
|
||||||
|
if (unit.treeRoot == nullptr || treeRoot == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the linker-object lists
|
||||||
|
TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
|
||||||
|
TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence();
|
||||||
|
|
||||||
|
// filter unitLinkerObjects to only contain uniforms
|
||||||
|
auto end = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(),
|
||||||
|
[](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqUniform &&
|
||||||
|
node->getAsSymbolNode()->getQualifier().storage != EvqBuffer; });
|
||||||
|
unitLinkerObjects.resize(end - unitLinkerObjects.begin());
|
||||||
|
|
||||||
|
// merge uniforms and do error checking
|
||||||
|
bool mergeExistingOnly = false;
|
||||||
|
mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly);
|
||||||
|
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// do error checking on the shader boundary in / out vars
|
||||||
|
//
|
||||||
|
void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) {
|
||||||
|
if (unit.treeRoot == nullptr || treeRoot == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get copies of the linker-object lists
|
||||||
|
TIntermSequence linkerObjects = findLinkerObjects()->getSequence();
|
||||||
|
TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence();
|
||||||
|
|
||||||
|
// filter linkerObjects to only contain out variables
|
||||||
|
auto end = std::remove_if(linkerObjects.begin(), linkerObjects.end(),
|
||||||
|
[](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingOut; });
|
||||||
|
linkerObjects.resize(end - linkerObjects.begin());
|
||||||
|
|
||||||
|
// filter unitLinkerObjects to only contain in variables
|
||||||
|
auto unitEnd = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(),
|
||||||
|
[](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingIn; });
|
||||||
|
unitLinkerObjects.resize(unitEnd - unitLinkerObjects.begin());
|
||||||
|
|
||||||
|
// do matching and error checking
|
||||||
|
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
|
||||||
|
|
||||||
|
// TODO: final check; make sure that any statically used `in` have matching `out` written to
|
||||||
|
}
|
||||||
|
|
||||||
void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
|
void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
|
||||||
{
|
{
|
||||||
if (unit.getNumEntryPoints() > 0) {
|
if (unit.getNumEntryPoints() > 0) {
|
||||||
@@ -136,6 +187,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
MERGE_MAX(spvVersion.vulkanGlsl);
|
MERGE_MAX(spvVersion.vulkanGlsl);
|
||||||
MERGE_MAX(spvVersion.vulkan);
|
MERGE_MAX(spvVersion.vulkan);
|
||||||
MERGE_MAX(spvVersion.openGl);
|
MERGE_MAX(spvVersion.openGl);
|
||||||
|
MERGE_TRUE(spvVersion.vulkanRelaxed);
|
||||||
|
|
||||||
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
|
||||||
@@ -196,12 +248,14 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
MERGE_TRUE(pointMode);
|
MERGE_TRUE(pointMode);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
if (!localSizeNotDefault[i] && unit.localSizeNotDefault[i]) {
|
if (unit.localSizeNotDefault[i]) {
|
||||||
localSize[i] = unit.localSize[i];
|
if (!localSizeNotDefault[i]) {
|
||||||
localSizeNotDefault[i] = true;
|
localSize[i] = unit.localSize[i];
|
||||||
|
localSizeNotDefault[i] = true;
|
||||||
|
}
|
||||||
|
else if (localSize[i] != unit.localSize[i])
|
||||||
|
error(infoSink, "Contradictory local size");
|
||||||
}
|
}
|
||||||
else if (localSize[i] != unit.localSize[i])
|
|
||||||
error(infoSink, "Contradictory local size");
|
|
||||||
|
|
||||||
if (localSizeSpecId[i] == TQualifier::layoutNotSet)
|
if (localSizeSpecId[i] == TQualifier::layoutNotSet)
|
||||||
localSizeSpecId[i] = unit.localSizeSpecId[i];
|
localSizeSpecId[i] = unit.localSizeSpecId[i];
|
||||||
@@ -304,12 +358,14 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
// Map by global name to unique ID to rationalize the same object having
|
// Map by global name to unique ID to rationalize the same object having
|
||||||
// differing IDs in different trees.
|
// differing IDs in different trees.
|
||||||
TIdMaps idMaps;
|
TIdMaps idMaps;
|
||||||
int maxId;
|
long long idShift;
|
||||||
seedIdMap(idMaps, maxId);
|
seedIdMap(idMaps, idShift);
|
||||||
remapIds(idMaps, maxId + 1, unit);
|
remapIds(idMaps, idShift + 1, unit);
|
||||||
|
|
||||||
mergeBodies(infoSink, globals, unitGlobals);
|
mergeBodies(infoSink, globals, unitGlobals);
|
||||||
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
|
bool mergeExistingOnly = false;
|
||||||
|
mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly);
|
||||||
|
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
|
||||||
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
|
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,14 +383,14 @@ static const TString& getNameForIdMap(TIntermSymbol* symbol)
|
|||||||
|
|
||||||
|
|
||||||
// Traverser that seeds an ID map with all built-ins, and tracks the
|
// Traverser that seeds an ID map with all built-ins, and tracks the
|
||||||
// maximum ID used.
|
// maximum ID used, currently using (maximum ID + 1) as new symbol id shift seed.
|
||||||
|
// Level id will keep same after shifting.
|
||||||
// (It would be nice to put this in a function, but that causes warnings
|
// (It would be nice to put this in a function, but that causes warnings
|
||||||
// on having no bodies for the copy-constructor/operator=.)
|
// on having no bodies for the copy-constructor/operator=.)
|
||||||
class TBuiltInIdTraverser : public TIntermTraverser {
|
class TBuiltInIdTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), maxId(0) { }
|
TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), idShift(0) { }
|
||||||
// If it's a built in, add it to the map.
|
// If it's a built in, add it to the map.
|
||||||
// Track the max ID.
|
|
||||||
virtual void visitSymbol(TIntermSymbol* symbol)
|
virtual void visitSymbol(TIntermSymbol* symbol)
|
||||||
{
|
{
|
||||||
const TQualifier& qualifier = symbol->getType().getQualifier();
|
const TQualifier& qualifier = symbol->getType().getQualifier();
|
||||||
@@ -342,14 +398,16 @@ public:
|
|||||||
TShaderInterface si = symbol->getType().getShaderInterface();
|
TShaderInterface si = symbol->getType().getShaderInterface();
|
||||||
idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
|
idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
|
||||||
}
|
}
|
||||||
maxId = std::max(maxId, symbol->getId());
|
idShift = (symbol->getId() & ~TSymbolTable::uniqueIdMask) |
|
||||||
|
std::max(idShift & TSymbolTable::uniqueIdMask,
|
||||||
|
symbol->getId() & TSymbolTable::uniqueIdMask);
|
||||||
}
|
}
|
||||||
int getMaxId() const { return maxId; }
|
long long getIdShift() const { return idShift; }
|
||||||
protected:
|
protected:
|
||||||
TBuiltInIdTraverser(TBuiltInIdTraverser&);
|
TBuiltInIdTraverser(TBuiltInIdTraverser&);
|
||||||
TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
|
TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
|
||||||
TIdMaps& idMaps;
|
TIdMaps& idMaps;
|
||||||
int maxId;
|
long long idShift;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Traverser that seeds an ID map with non-builtins.
|
// Traverser that seeds an ID map with non-builtins.
|
||||||
@@ -375,12 +433,12 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the the ID map with what we know of 'this' AST.
|
// Initialize the the ID map with what we know of 'this' AST.
|
||||||
void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
|
void TIntermediate::seedIdMap(TIdMaps& idMaps, long long& idShift)
|
||||||
{
|
{
|
||||||
// all built-ins everywhere need to align on IDs and contribute to the max ID
|
// all built-ins everywhere need to align on IDs and contribute to the max ID
|
||||||
TBuiltInIdTraverser builtInIdTraverser(idMaps);
|
TBuiltInIdTraverser builtInIdTraverser(idMaps);
|
||||||
treeRoot->traverse(&builtInIdTraverser);
|
treeRoot->traverse(&builtInIdTraverser);
|
||||||
maxId = builtInIdTraverser.getMaxId();
|
idShift = builtInIdTraverser.getIdShift() & TSymbolTable::uniqueIdMask;
|
||||||
|
|
||||||
// user variables in the linker object list need to align on ids
|
// user variables in the linker object list need to align on ids
|
||||||
TUserIdTraverser userIdTraverser(idMaps);
|
TUserIdTraverser userIdTraverser(idMaps);
|
||||||
@@ -392,7 +450,7 @@ void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
|
|||||||
// on having no bodies for the copy-constructor/operator=.)
|
// on having no bodies for the copy-constructor/operator=.)
|
||||||
class TRemapIdTraverser : public TIntermTraverser {
|
class TRemapIdTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TRemapIdTraverser(const TIdMaps& idMaps, int idShift) : idMaps(idMaps), idShift(idShift) { }
|
TRemapIdTraverser(const TIdMaps& idMaps, long long idShift) : idMaps(idMaps), idShift(idShift) { }
|
||||||
// Do the mapping:
|
// Do the mapping:
|
||||||
// - if the same symbol, adopt the 'this' ID
|
// - if the same symbol, adopt the 'this' ID
|
||||||
// - otherwise, ensure a unique ID by shifting to a new space
|
// - otherwise, ensure a unique ID by shifting to a new space
|
||||||
@@ -404,7 +462,9 @@ public:
|
|||||||
TShaderInterface si = symbol->getType().getShaderInterface();
|
TShaderInterface si = symbol->getType().getShaderInterface();
|
||||||
auto it = idMaps[si].find(getNameForIdMap(symbol));
|
auto it = idMaps[si].find(getNameForIdMap(symbol));
|
||||||
if (it != idMaps[si].end()) {
|
if (it != idMaps[si].end()) {
|
||||||
symbol->changeId(it->second);
|
uint64_t id = (symbol->getId() & ~TSymbolTable::uniqueIdMask) |
|
||||||
|
(it->second & TSymbolTable::uniqueIdMask);
|
||||||
|
symbol->changeId(id);
|
||||||
remapped = true;
|
remapped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,10 +475,10 @@ protected:
|
|||||||
TRemapIdTraverser(TRemapIdTraverser&);
|
TRemapIdTraverser(TRemapIdTraverser&);
|
||||||
TRemapIdTraverser& operator=(TRemapIdTraverser&);
|
TRemapIdTraverser& operator=(TRemapIdTraverser&);
|
||||||
const TIdMaps& idMaps;
|
const TIdMaps& idMaps;
|
||||||
int idShift;
|
long long idShift;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TIntermediate::remapIds(const TIdMaps& idMaps, int idShift, TIntermediate& unit)
|
void TIntermediate::remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate& unit)
|
||||||
{
|
{
|
||||||
// Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
|
// Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
|
||||||
TRemapIdTraverser idTraverser(idMaps, idShift);
|
TRemapIdTraverser idTraverser(idMaps, idShift);
|
||||||
@@ -449,11 +509,193 @@ void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, c
|
|||||||
globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
|
globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) {
|
||||||
|
return // 1) same stage and same shader interface
|
||||||
|
(stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) ||
|
||||||
|
// 2) accross stages and both are uniform or buffer
|
||||||
|
(symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) ||
|
||||||
|
(symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) ||
|
||||||
|
// 3) in/out matched across stage boundary
|
||||||
|
(stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) ||
|
||||||
|
(unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Global Unfiform block stores any default uniforms (i.e. uniforms without a block)
|
||||||
|
// If two linked stages declare the same member, they are meant to be the same uniform
|
||||||
|
// and need to be in the same block
|
||||||
|
// merge the members of different stages to allow them to be linked properly
|
||||||
|
// as a single block
|
||||||
|
//
|
||||||
|
void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly)
|
||||||
|
{
|
||||||
|
TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
|
||||||
|
TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
|
||||||
|
|
||||||
|
// build lists of default blocks from the intermediates
|
||||||
|
TIntermSequence defaultBlocks;
|
||||||
|
TIntermSequence unitDefaultBlocks;
|
||||||
|
|
||||||
|
auto filter = [](TIntermSequence& list, TIntermNode* node) {
|
||||||
|
if (node->getAsSymbolNode()->getQualifier().defaultBlock) {
|
||||||
|
list.push_back(node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::for_each(linkerObjects.begin(), linkerObjects.end(),
|
||||||
|
[&defaultBlocks, &filter](TIntermNode* node) {
|
||||||
|
filter(defaultBlocks, node);
|
||||||
|
});
|
||||||
|
std::for_each(unitLinkerObjects.begin(), unitLinkerObjects.end(),
|
||||||
|
[&unitDefaultBlocks, &filter](TIntermNode* node) {
|
||||||
|
filter(unitDefaultBlocks, node);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto itUnitBlock = unitDefaultBlocks.begin();
|
||||||
|
for (; itUnitBlock != unitDefaultBlocks.end(); itUnitBlock++) {
|
||||||
|
|
||||||
|
bool add = !mergeExistingOnly;
|
||||||
|
auto itBlock = defaultBlocks.begin();
|
||||||
|
|
||||||
|
for (; itBlock != defaultBlocks.end(); itBlock++) {
|
||||||
|
TIntermSymbol* block = (*itBlock)->getAsSymbolNode();
|
||||||
|
TIntermSymbol* unitBlock = (*itUnitBlock)->getAsSymbolNode();
|
||||||
|
|
||||||
|
assert(block && unitBlock);
|
||||||
|
|
||||||
|
// if the two default blocks match, then merge their definitions
|
||||||
|
if (block->getType().getTypeName() == unitBlock->getType().getTypeName() &&
|
||||||
|
block->getQualifier().storage == unitBlock->getQualifier().storage) {
|
||||||
|
add = false;
|
||||||
|
mergeBlockDefinitions(infoSink, block, unitBlock, &unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (add) {
|
||||||
|
// push back on original list; won't change the size of the list we're iterating over
|
||||||
|
linkerObjects.push_back(*itUnitBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) {
|
||||||
|
if (block->getType() == unitBlock->getType()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->getType().getTypeName() != unitBlock->getType().getTypeName() ||
|
||||||
|
block->getType().getBasicType() != unitBlock->getType().getBasicType() ||
|
||||||
|
block->getQualifier().storage != unitBlock->getQualifier().storage ||
|
||||||
|
block->getQualifier().layoutSet != unitBlock->getQualifier().layoutSet) {
|
||||||
|
// different block names likely means different blocks
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge the struct
|
||||||
|
// order of declarations doesn't matter and they matched based on member name
|
||||||
|
TTypeList* memberList = block->getType().getWritableStruct();
|
||||||
|
TTypeList* unitMemberList = unitBlock->getType().getWritableStruct();
|
||||||
|
|
||||||
|
// keep track of which members have changed position
|
||||||
|
// so we don't have to search the array again
|
||||||
|
std::map<unsigned int, unsigned int> memberIndexUpdates;
|
||||||
|
|
||||||
|
size_t memberListStartSize = memberList->size();
|
||||||
|
for (unsigned int i = 0; i < unitMemberList->size(); ++i) {
|
||||||
|
bool merge = true;
|
||||||
|
for (unsigned int j = 0; j < memberListStartSize; ++j) {
|
||||||
|
if ((*memberList)[j].type->getFieldName() == (*unitMemberList)[i].type->getFieldName()) {
|
||||||
|
merge = false;
|
||||||
|
const TType* memberType = (*memberList)[j].type;
|
||||||
|
const TType* unitMemberType = (*unitMemberList)[i].type;
|
||||||
|
|
||||||
|
// compare types
|
||||||
|
// don't need as many checks as when merging symbols, since
|
||||||
|
// initializers and most qualifiers are stripped when the member is moved into the block
|
||||||
|
if ((*memberType) != (*unitMemberType)) {
|
||||||
|
error(infoSink, "Types must match:");
|
||||||
|
infoSink.info << " " << memberType->getFieldName() << ": ";
|
||||||
|
infoSink.info << "\"" << memberType->getCompleteString() << "\" versus ";
|
||||||
|
infoSink.info << "\"" << unitMemberType->getCompleteString() << "\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
memberIndexUpdates[i] = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (merge) {
|
||||||
|
memberList->push_back((*unitMemberList)[i]);
|
||||||
|
memberIndexUpdates[i] = (unsigned int)memberList->size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TType unitType;
|
||||||
|
unitType.shallowCopy(unitBlock->getType());
|
||||||
|
|
||||||
|
// update symbol node in unit tree,
|
||||||
|
// and other nodes that may reference it
|
||||||
|
class TMergeBlockTraverser : public TIntermTraverser {
|
||||||
|
public:
|
||||||
|
TMergeBlockTraverser(const glslang::TType &type, const glslang::TType& unitType,
|
||||||
|
glslang::TIntermediate& unit,
|
||||||
|
const std::map<unsigned int, unsigned int>& memberIdxUpdates) :
|
||||||
|
newType(type), unitType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates)
|
||||||
|
{ }
|
||||||
|
virtual ~TMergeBlockTraverser() { }
|
||||||
|
|
||||||
|
const glslang::TType& newType; // type with modifications
|
||||||
|
const glslang::TType& unitType; // copy of original type
|
||||||
|
glslang::TIntermediate& unit; // intermediate that is being updated
|
||||||
|
const std::map<unsigned int, unsigned int>& memberIndexUpdates;
|
||||||
|
|
||||||
|
virtual void visitSymbol(TIntermSymbol* symbol)
|
||||||
|
{
|
||||||
|
glslang::TType& symType = symbol->getWritableType();
|
||||||
|
|
||||||
|
if (symType == unitType) {
|
||||||
|
// each symbol node has a local copy of the unitType
|
||||||
|
// if merging involves changing properties that aren't shared objects
|
||||||
|
// they should be updated in all instances
|
||||||
|
|
||||||
|
// e.g. the struct list is a ptr to an object, so it can be updated
|
||||||
|
// once, outside the traverser
|
||||||
|
//*symType.getWritableStruct() = *newType.getStruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visitBinary(TVisit, glslang::TIntermBinary* node)
|
||||||
|
{
|
||||||
|
if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == unitType) {
|
||||||
|
// this is a dereference to a member of the block since the
|
||||||
|
// member list changed, need to update this to point to the
|
||||||
|
// right index
|
||||||
|
assert(node->getRight()->getAsConstantUnion());
|
||||||
|
|
||||||
|
glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion();
|
||||||
|
unsigned int memberIdx = constNode->getConstArray()[0].getUConst();
|
||||||
|
unsigned int newIdx = memberIndexUpdates.at(memberIdx);
|
||||||
|
TIntermTyped* newConstNode = unit.addConstantUnion(newIdx, node->getRight()->getLoc());
|
||||||
|
|
||||||
|
node->setRight(newConstNode);
|
||||||
|
delete constNode;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} finalLinkTraverser(block->getType(), unitType, *unit, memberIndexUpdates);
|
||||||
|
|
||||||
|
// update the tree to use the new type
|
||||||
|
unit->getTreeRoot()->traverse(&finalLinkTraverser);
|
||||||
|
|
||||||
|
// update the member list
|
||||||
|
(*unitMemberList) = (*memberList);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Merge the linker objects from unitLinkerObjects into linkerObjects.
|
// Merge the linker objects from unitLinkerObjects into linkerObjects.
|
||||||
// Duplication is expected and filtered out, but contradictions are an error.
|
// Duplication is expected and filtered out, but contradictions are an error.
|
||||||
//
|
//
|
||||||
void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects)
|
void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage unitStage)
|
||||||
{
|
{
|
||||||
// Error check and merge the linker objects (duplicates should not be created)
|
// Error check and merge the linker objects (duplicates should not be created)
|
||||||
std::size_t initialNumLinkerObjects = linkerObjects.size();
|
std::size_t initialNumLinkerObjects = linkerObjects.size();
|
||||||
@@ -468,7 +710,7 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
|
|||||||
// If they are both blocks in the same shader interface,
|
// If they are both blocks in the same shader interface,
|
||||||
// match by the block-name, not the identifier name.
|
// match by the block-name, not the identifier name.
|
||||||
if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
|
if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
|
||||||
if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
|
if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
|
||||||
isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
|
isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -488,18 +730,54 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
|
|||||||
if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
|
if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
|
||||||
symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
|
symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;
|
||||||
|
|
||||||
|
// Similarly for location
|
||||||
|
if (!symbol->getQualifier().hasLocation() && unitSymbol->getQualifier().hasLocation()) {
|
||||||
|
symbol->getQualifier().layoutLocation = unitSymbol->getQualifier().layoutLocation;
|
||||||
|
}
|
||||||
|
|
||||||
// Update implicit array sizes
|
// Update implicit array sizes
|
||||||
mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
|
mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());
|
||||||
|
|
||||||
// Check for consistent types/qualification/initializers etc.
|
// Check for consistent types/qualification/initializers etc.
|
||||||
mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
|
mergeErrorCheck(infoSink, *symbol, *unitSymbol, unitStage);
|
||||||
}
|
}
|
||||||
// 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())
|
else if (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");
|
||||||
}
|
}
|
||||||
if (merge)
|
if (merge) {
|
||||||
linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
|
linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
|
||||||
|
|
||||||
|
// for anonymous blocks, check that their members don't conflict with other names
|
||||||
|
if (unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getBasicType() == EbtBlock &&
|
||||||
|
IsAnonymous(unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getName())) {
|
||||||
|
for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
|
||||||
|
TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
|
||||||
|
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
|
||||||
|
assert(symbol && unitSymbol);
|
||||||
|
|
||||||
|
auto checkName = [this, unitSymbol, &infoSink](const TString& name) {
|
||||||
|
for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) {
|
||||||
|
if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()) {
|
||||||
|
error(infoSink, "Anonymous member name used for global variable or other anonymous member: ");
|
||||||
|
infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) {
|
||||||
|
checkName(symbol->getName());
|
||||||
|
|
||||||
|
// check members of other anonymous blocks
|
||||||
|
if (symbol->getBasicType() == EbtBlock && IsAnonymous(symbol->getName())) {
|
||||||
|
for (unsigned int i = 0; i < symbol->getType().getStruct()->size(); ++i) {
|
||||||
|
checkName((*symbol->getType().getStruct())[i].type->getFieldName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,26 +809,75 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
|
|||||||
//
|
//
|
||||||
// This function only does one of intra- or cross-stage matching per call.
|
// This function only does one of intra- or cross-stage matching per call.
|
||||||
//
|
//
|
||||||
void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
|
void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, EShLanguage unitStage)
|
||||||
{
|
{
|
||||||
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
|
||||||
|
bool crossStage = getStage() != unitStage;
|
||||||
bool writeTypeComparison = false;
|
bool writeTypeComparison = false;
|
||||||
|
|
||||||
// Types have to match
|
// Types have to match
|
||||||
if (symbol.getType() != unitSymbol.getType()) {
|
{
|
||||||
// but, we make an exception if one is an implicit array and the other is sized
|
// but, we make an exception if one is an implicit array and the other is sized
|
||||||
if (! (symbol.getType().isArray() && unitSymbol.getType().isArray() &&
|
// or if the array sizes differ because of the extra array dimension on some in/out boundaries
|
||||||
symbol.getType().sameElementType(unitSymbol.getType()) &&
|
bool arraysMatch = false;
|
||||||
(symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()))) {
|
if (isIoResizeArray(symbol.getType(), getStage()) || isIoResizeArray(unitSymbol.getType(), unitStage)) {
|
||||||
error(infoSink, "Types must match:");
|
// if the arrays have an extra dimension because of the stage.
|
||||||
|
// compare dimensions while ignoring the outer dimension
|
||||||
|
unsigned int firstDim = isIoResizeArray(symbol.getType(), getStage()) ? 1 : 0;
|
||||||
|
unsigned int numDim = symbol.getArraySizes()
|
||||||
|
? symbol.getArraySizes()->getNumDims() : 0;
|
||||||
|
unsigned int unitFirstDim = isIoResizeArray(unitSymbol.getType(), unitStage) ? 1 : 0;
|
||||||
|
unsigned int unitNumDim = unitSymbol.getArraySizes()
|
||||||
|
? unitSymbol.getArraySizes()->getNumDims() : 0;
|
||||||
|
arraysMatch = (numDim - firstDim) == (unitNumDim - unitFirstDim);
|
||||||
|
// check that array sizes match as well
|
||||||
|
for (unsigned int i = 0; i < (numDim - firstDim) && arraysMatch; i++) {
|
||||||
|
if (symbol.getArraySizes()->getDimSize(firstDim + i) !=
|
||||||
|
unitSymbol.getArraySizes()->getDimSize(unitFirstDim + i)) {
|
||||||
|
arraysMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arraysMatch = symbol.getType().sameArrayness(unitSymbol.getType()) ||
|
||||||
|
(symbol.getType().isArray() && unitSymbol.getType().isArray() &&
|
||||||
|
(symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!symbol.getType().sameElementType(unitSymbol.getType()) ||
|
||||||
|
!symbol.getType().sameTypeParameters(unitSymbol.getType()) ||
|
||||||
|
!arraysMatch ) {
|
||||||
writeTypeComparison = true;
|
writeTypeComparison = true;
|
||||||
|
error(infoSink, "Types must match:");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Qualifiers have to (almost) match
|
// Interface block member-wise layout qualifiers have to match
|
||||||
|
if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
|
||||||
|
symbol.getType().getStruct() && unitSymbol.getType().getStruct() &&
|
||||||
|
symbol.getType().sameStructType(unitSymbol.getType())) {
|
||||||
|
for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) {
|
||||||
|
const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier();
|
||||||
|
const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier();
|
||||||
|
if (qualifier.layoutMatrix != unitQualifier.layoutMatrix ||
|
||||||
|
qualifier.layoutOffset != unitQualifier.layoutOffset ||
|
||||||
|
qualifier.layoutAlign != unitQualifier.layoutAlign ||
|
||||||
|
qualifier.layoutLocation != unitQualifier.layoutLocation ||
|
||||||
|
qualifier.layoutComponent != unitQualifier.layoutComponent) {
|
||||||
|
error(infoSink, "Interface block member layout qualifiers must match:");
|
||||||
|
writeTypeComparison = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInOut = crossStage &&
|
||||||
|
((symbol.getQualifier().storage == EvqVaryingIn && unitSymbol.getQualifier().storage == EvqVaryingOut) ||
|
||||||
|
(symbol.getQualifier().storage == EvqVaryingOut && unitSymbol.getQualifier().storage == EvqVaryingIn));
|
||||||
|
|
||||||
|
// Qualifiers have to (almost) match
|
||||||
// Storage...
|
// Storage...
|
||||||
if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
|
if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) {
|
||||||
error(infoSink, "Storage qualifiers must match:");
|
error(infoSink, "Storage qualifiers must match:");
|
||||||
writeTypeComparison = true;
|
writeTypeComparison = true;
|
||||||
}
|
}
|
||||||
@@ -572,7 +899,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Precision...
|
// Precision...
|
||||||
if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
|
if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
|
||||||
error(infoSink, "Precision qualifiers must match:");
|
error(infoSink, "Precision qualifiers must match:");
|
||||||
writeTypeComparison = true;
|
writeTypeComparison = true;
|
||||||
}
|
}
|
||||||
@@ -590,12 +917,16 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auxiliary and interpolation...
|
// Auxiliary and interpolation...
|
||||||
if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid ||
|
// "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ.
|
||||||
|
// These mismatches are allowed between any pair of stages ...
|
||||||
|
// those provided in the fragment shader supersede those provided in previous stages."
|
||||||
|
if (!crossStage &&
|
||||||
|
(symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid ||
|
||||||
symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth ||
|
symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth ||
|
||||||
symbol.getQualifier().flat != unitSymbol.getQualifier().flat ||
|
symbol.getQualifier().flat != unitSymbol.getQualifier().flat ||
|
||||||
symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
|
symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() ||
|
||||||
symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
|
symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() ||
|
||||||
symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective()) {
|
symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) {
|
||||||
error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
|
error(infoSink, "Interpolation and auxiliary storage qualifiers must match:");
|
||||||
writeTypeComparison = true;
|
writeTypeComparison = true;
|
||||||
}
|
}
|
||||||
@@ -651,6 +982,25 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TIntermediate::sharedBlockCheck(TInfoSink& infoSink)
|
||||||
|
{
|
||||||
|
bool has_shared_block = false;
|
||||||
|
bool has_shared_non_block = false;
|
||||||
|
TIntermSequence& linkObjects = findLinkerObjects()->getSequence();
|
||||||
|
for (size_t i = 0; i < linkObjects.size(); ++i) {
|
||||||
|
const TType& type = linkObjects[i]->getAsTyped()->getType();
|
||||||
|
const TQualifier& qualifier = type.getQualifier();
|
||||||
|
if (qualifier.storage == glslang::EvqShared) {
|
||||||
|
if (type.getBasicType() == glslang::EbtBlock)
|
||||||
|
has_shared_block = true;
|
||||||
|
else
|
||||||
|
has_shared_non_block = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_shared_block && has_shared_non_block)
|
||||||
|
error(infoSink, "cannot mix use of shared variables inside and outside blocks");
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do final link-time error checking of a complete (merged) intermediate representation.
|
// Do final link-time error checking of a complete (merged) intermediate representation.
|
||||||
// (Much error checking was done during merging).
|
// (Much error checking was done during merging).
|
||||||
@@ -736,10 +1086,10 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
|
|||||||
|
|
||||||
// "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
|
// "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
|
||||||
// implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
|
// implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
|
||||||
if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) {
|
if (xfbBuffers[b].stride > (unsigned int)(4 * resources->maxTransformFeedbackInterleavedComponents)) {
|
||||||
error(infoSink, "xfb_stride is too large:");
|
error(infoSink, "xfb_stride is too large:");
|
||||||
infoSink.info.prefix(EPrefixError);
|
infoSink.info.prefix(EPrefixError);
|
||||||
infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources.maxTransformFeedbackInterleavedComponents << "\n";
|
infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources->maxTransformFeedbackInterleavedComponents << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,6 +1126,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
|
|||||||
error(infoSink, "post_depth_coverage requires early_fragment_tests");
|
error(infoSink, "post_depth_coverage requires early_fragment_tests");
|
||||||
break;
|
break;
|
||||||
case EShLangCompute:
|
case EShLangCompute:
|
||||||
|
sharedBlockCheck(infoSink);
|
||||||
break;
|
break;
|
||||||
case EShLangRayGen:
|
case EShLangRayGen:
|
||||||
case EShLangIntersect:
|
case EShLangIntersect:
|
||||||
@@ -808,6 +1159,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
|
|||||||
case EShLangTaskNV:
|
case EShLangTaskNV:
|
||||||
if (numTaskNVBlocks > 1)
|
if (numTaskNVBlocks > 1)
|
||||||
error(infoSink, "Only one taskNV interface block is allowed per shader");
|
error(infoSink, "Only one taskNV interface block is allowed per shader");
|
||||||
|
sharedBlockCheck(infoSink);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error(infoSink, "Unknown Stage.");
|
error(infoSink, "Unknown Stage.");
|
||||||
@@ -1055,8 +1407,8 @@ bool TIntermediate::userOutputUsed() const
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
|
// Accumulate locations used for inputs, outputs, and uniforms, payload and callable data
|
||||||
// as the accumulation is done.
|
// and check for collisions as the accumulation is done.
|
||||||
//
|
//
|
||||||
// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
|
// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
|
||||||
//
|
//
|
||||||
@@ -1068,6 +1420,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
|||||||
typeCollision = false;
|
typeCollision = false;
|
||||||
|
|
||||||
int set;
|
int set;
|
||||||
|
int setRT;
|
||||||
if (qualifier.isPipeInput())
|
if (qualifier.isPipeInput())
|
||||||
set = 0;
|
set = 0;
|
||||||
else if (qualifier.isPipeOutput())
|
else if (qualifier.isPipeOutput())
|
||||||
@@ -1076,11 +1429,17 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
|||||||
set = 2;
|
set = 2;
|
||||||
else if (qualifier.storage == EvqBuffer)
|
else if (qualifier.storage == EvqBuffer)
|
||||||
set = 3;
|
set = 3;
|
||||||
|
else if (qualifier.isAnyPayload())
|
||||||
|
setRT = 0;
|
||||||
|
else if (qualifier.isAnyCallable())
|
||||||
|
setRT = 1;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
|
if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) {
|
||||||
|
size = 1;
|
||||||
|
} else if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
|
||||||
if (type.isSizedArray())
|
if (type.isSizedArray())
|
||||||
size = type.getCumulativeArraySize();
|
size = type.getCumulativeArraySize();
|
||||||
else
|
else
|
||||||
@@ -1108,10 +1467,17 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
|
|||||||
// (A vertex shader input will show using only one location, even for a dvec3/4.)
|
// (A vertex shader input will show using only one location, even for a dvec3/4.)
|
||||||
//
|
//
|
||||||
// So, for the case of dvec3, we need two independent ioRanges.
|
// So, for the case of dvec3, we need two independent ioRanges.
|
||||||
|
//
|
||||||
|
// For raytracing IO (payloads and callabledata) each declaration occupies a single
|
||||||
|
// slot irrespective of type.
|
||||||
int collision = -1; // no collision
|
int collision = -1; // no collision
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 &&
|
if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) {
|
||||||
|
TRange range(qualifier.layoutLocation, qualifier.layoutLocation);
|
||||||
|
collision = checkLocationRT(setRT, qualifier.layoutLocation);
|
||||||
|
if (collision < 0)
|
||||||
|
usedIoRT[setRT].push_back(range);
|
||||||
|
} else if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 &&
|
||||||
(qualifier.isPipeInput() || qualifier.isPipeOutput())) {
|
(qualifier.isPipeInput() || qualifier.isPipeOutput())) {
|
||||||
// Dealing with dvec3 in/out split across two locations.
|
// Dealing with dvec3 in/out split across two locations.
|
||||||
// Need two io-ranges.
|
// Need two io-ranges.
|
||||||
@@ -1187,6 +1553,16 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
|
|||||||
return -1; // no collision
|
return -1; // no collision
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TIntermediate::checkLocationRT(int set, int location) {
|
||||||
|
TRange range(location, location);
|
||||||
|
for (size_t r = 0; r < usedIoRT[set].size(); ++r) {
|
||||||
|
if (range.overlap(usedIoRT[set][r])) {
|
||||||
|
return range.start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; // no collision
|
||||||
|
}
|
||||||
|
|
||||||
// Accumulate bindings and offsets, and check for collisions
|
// Accumulate bindings and offsets, and check for collisions
|
||||||
// as the accumulation is done.
|
// as the accumulation is done.
|
||||||
//
|
//
|
||||||
@@ -1778,4 +2154,17 @@ int TIntermediate::computeBufferReferenceTypeSize(const TType& type)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef GLSLANG_WEB
|
||||||
|
bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) {
|
||||||
|
return type.isArray() &&
|
||||||
|
((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) ||
|
||||||
|
(language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut &&
|
||||||
|
! type.getQualifier().patch) ||
|
||||||
|
(language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn &&
|
||||||
|
type.getQualifier().pervertexNV) ||
|
||||||
|
(language == EShLangMeshNV && type.getQualifier().storage == EvqVaryingOut &&
|
||||||
|
!type.getQualifier().perTaskNV));
|
||||||
|
}
|
||||||
|
#endif // not GLSLANG_WEB
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
|||||||
@@ -227,10 +227,10 @@ enum ComputeDerivativeMode {
|
|||||||
|
|
||||||
class TIdMaps {
|
class TIdMaps {
|
||||||
public:
|
public:
|
||||||
TMap<TString, int>& operator[](int i) { return maps[i]; }
|
TMap<TString, long long>& operator[](long long i) { return maps[i]; }
|
||||||
const TMap<TString, int>& operator[](int i) const { return maps[i]; }
|
const TMap<TString, long long>& operator[](long long i) const { return maps[i]; }
|
||||||
private:
|
private:
|
||||||
TMap<TString, int> maps[EsiCount];
|
TMap<TString, long long> maps[EsiCount];
|
||||||
};
|
};
|
||||||
|
|
||||||
class TNumericFeatures {
|
class TNumericFeatures {
|
||||||
@@ -259,6 +259,23 @@ private:
|
|||||||
unsigned int features;
|
unsigned int features;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// MustBeAssigned wraps a T, asserting that it has been assigned with
|
||||||
|
// operator =() before attempting to read with operator T() or operator ->().
|
||||||
|
// Used to catch cases where fields are read before they have been assigned.
|
||||||
|
template<typename T>
|
||||||
|
class MustBeAssigned
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MustBeAssigned() = default;
|
||||||
|
MustBeAssigned(const T& v) : value(v) {}
|
||||||
|
operator const T&() const { assert(isSet); return value; }
|
||||||
|
const T* operator ->() const { assert(isSet); return &value; }
|
||||||
|
MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; }
|
||||||
|
private:
|
||||||
|
T value;
|
||||||
|
bool isSet = false;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set of helper functions to help parse and build the tree.
|
// Set of helper functions to help parse and build the tree.
|
||||||
//
|
//
|
||||||
@@ -270,11 +287,18 @@ public:
|
|||||||
profile(p), version(v),
|
profile(p), version(v),
|
||||||
#endif
|
#endif
|
||||||
treeRoot(0),
|
treeRoot(0),
|
||||||
|
resources(TBuiltInResource{}),
|
||||||
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
|
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
|
||||||
invertY(false),
|
invertY(false),
|
||||||
useStorageBuffer(false),
|
useStorageBuffer(false),
|
||||||
nanMinMaxClamp(false),
|
nanMinMaxClamp(false),
|
||||||
depthReplacing(false)
|
depthReplacing(false),
|
||||||
|
uniqueId(0),
|
||||||
|
globalUniformBlockName(""),
|
||||||
|
atomicCounterBlockName(""),
|
||||||
|
globalUniformBlockSet(TQualifier::layoutSetEnd),
|
||||||
|
globalUniformBlockBinding(TQualifier::layoutBindingEnd),
|
||||||
|
atomicCounterBlockSet(TQualifier::layoutSetEnd)
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
,
|
,
|
||||||
implicitThisName("@this"), implicitCounterName("@count"),
|
implicitThisName("@this"), implicitCounterName("@count"),
|
||||||
@@ -398,6 +422,9 @@ public:
|
|||||||
EShLanguage getStage() const { return language; }
|
EShLanguage getStage() const { return language; }
|
||||||
void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
|
void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
|
||||||
const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
|
const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
|
||||||
|
bool isRayTracingStage() const {
|
||||||
|
return language >= EShLangRayGen && language <= EShLangCallableNV;
|
||||||
|
}
|
||||||
|
|
||||||
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
|
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
|
||||||
TIntermNode* getTreeRoot() const { return treeRoot; }
|
TIntermNode* getTreeRoot() const { return treeRoot; }
|
||||||
@@ -406,6 +433,7 @@ public:
|
|||||||
int getNumErrors() const { return numErrors; }
|
int getNumErrors() const { return numErrors; }
|
||||||
void addPushConstantCount() { ++numPushConstants; }
|
void addPushConstantCount() { ++numPushConstants; }
|
||||||
void setLimits(const TBuiltInResource& r) { resources = r; }
|
void setLimits(const TBuiltInResource& r) { resources = r; }
|
||||||
|
const TBuiltInResource& getLimits() const { return resources; }
|
||||||
|
|
||||||
bool postProcess(TIntermNode*, EShLanguage);
|
bool postProcess(TIntermNode*, EShLanguage);
|
||||||
void removeTree();
|
void removeTree();
|
||||||
@@ -512,6 +540,20 @@ public:
|
|||||||
// Linkage related
|
// Linkage related
|
||||||
void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
|
void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
|
||||||
void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
|
void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
|
||||||
|
TIntermAggregate* findLinkerObjects() const;
|
||||||
|
|
||||||
|
void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
|
||||||
|
const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
|
||||||
|
void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
|
||||||
|
unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
|
||||||
|
void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
|
||||||
|
unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
|
||||||
|
|
||||||
|
void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
|
||||||
|
const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
|
||||||
|
void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
|
||||||
|
unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
|
||||||
|
|
||||||
|
|
||||||
void setUseStorageBuffer() { useStorageBuffer = true; }
|
void setUseStorageBuffer() { useStorageBuffer = true; }
|
||||||
bool usingStorageBuffer() const { return useStorageBuffer; }
|
bool usingStorageBuffer() const { return useStorageBuffer; }
|
||||||
@@ -526,6 +568,11 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
unsigned int getLocalSize(int dim) const { return localSize[dim]; }
|
unsigned int getLocalSize(int dim) const { return localSize[dim]; }
|
||||||
|
bool isLocalSizeSet() const
|
||||||
|
{
|
||||||
|
// Return true if any component has been set (i.e. any component is not default).
|
||||||
|
return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
|
||||||
|
}
|
||||||
bool setLocalSizeSpecId(int dim, int id)
|
bool setLocalSizeSpecId(int dim, int id)
|
||||||
{
|
{
|
||||||
if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
|
if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
|
||||||
@@ -534,6 +581,13 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
|
int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
|
||||||
|
bool isLocalSizeSpecialized() const
|
||||||
|
{
|
||||||
|
// Return true if any component has been specialized.
|
||||||
|
return localSizeSpecId[0] != TQualifier::layoutNotSet ||
|
||||||
|
localSizeSpecId[1] != TQualifier::layoutNotSet ||
|
||||||
|
localSizeSpecId[2] != TQualifier::layoutNotSet;
|
||||||
|
}
|
||||||
#ifdef GLSLANG_WEB
|
#ifdef GLSLANG_WEB
|
||||||
void output(TInfoSink&, bool tree) { }
|
void output(TInfoSink&, bool tree) { }
|
||||||
|
|
||||||
@@ -812,6 +866,20 @@ public:
|
|||||||
bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
|
bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
|
||||||
#endif // GLSLANG_WEB
|
#endif // GLSLANG_WEB
|
||||||
|
|
||||||
|
void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
|
||||||
|
{
|
||||||
|
std::string name(nameStr);
|
||||||
|
blockBackingOverrides[name] = backing;
|
||||||
|
}
|
||||||
|
TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
|
||||||
|
{
|
||||||
|
std::string name = nameStr;
|
||||||
|
auto pos = blockBackingOverrides.find(name);
|
||||||
|
if (pos == blockBackingOverrides.end())
|
||||||
|
return EbsNone;
|
||||||
|
else
|
||||||
|
return pos->second;
|
||||||
|
}
|
||||||
#ifdef ENABLE_HLSL
|
#ifdef ENABLE_HLSL
|
||||||
void setHlslFunctionality1() { hlslFunctionality1 = true; }
|
void setHlslFunctionality1() { hlslFunctionality1 = true; }
|
||||||
bool getHlslFunctionality1() const { return hlslFunctionality1; }
|
bool getHlslFunctionality1() const { return hlslFunctionality1; }
|
||||||
@@ -835,10 +903,22 @@ public:
|
|||||||
bool usingHlslIoMapping() { return false; }
|
bool usingHlslIoMapping() { return false; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool usingScalarBlockLayout() const {
|
||||||
|
for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
|
||||||
|
if (*extIt == E_GL_EXT_scalar_block_layout)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
|
void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
|
||||||
void merge(TInfoSink&, TIntermediate&);
|
void merge(TInfoSink&, TIntermediate&);
|
||||||
void finalCheck(TInfoSink&, bool keepUncalled);
|
void finalCheck(TInfoSink&, bool keepUncalled);
|
||||||
|
|
||||||
|
void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
|
||||||
|
void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
|
||||||
|
void checkStageIO(TInfoSink&, TIntermediate&);
|
||||||
|
|
||||||
bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
|
bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
|
||||||
TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
|
TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
|
||||||
|
|
||||||
@@ -847,6 +927,7 @@ public:
|
|||||||
|
|
||||||
int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
|
int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
|
||||||
int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
|
int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
|
||||||
|
int checkLocationRT(int set, int location);
|
||||||
int addUsedOffsets(int binding, int offset, int numOffsets);
|
int addUsedOffsets(int binding, int offset, int numOffsets);
|
||||||
bool addUsedConstantId(int id);
|
bool addUsedConstantId(int id);
|
||||||
static int computeTypeLocationSize(const TType&, EShLanguage);
|
static int computeTypeLocationSize(const TType&, EShLanguage);
|
||||||
@@ -861,6 +942,8 @@ public:
|
|||||||
static int getOffset(const TType& type, int index);
|
static int getOffset(const TType& type, int index);
|
||||||
static int getBlockSize(const TType& blockType);
|
static int getBlockSize(const TType& blockType);
|
||||||
static int computeBufferReferenceTypeSize(const TType&);
|
static int computeBufferReferenceTypeSize(const TType&);
|
||||||
|
static bool isIoResizeArray(const TType& type, EShLanguage language);
|
||||||
|
|
||||||
bool promote(TIntermOperator*);
|
bool promote(TIntermOperator*);
|
||||||
void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
|
void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
|
||||||
bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
|
bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
|
||||||
@@ -879,6 +962,8 @@ public:
|
|||||||
void addProcess(const std::string& process) { processes.addProcess(process); }
|
void addProcess(const std::string& process) { processes.addProcess(process); }
|
||||||
void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
|
void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
|
||||||
const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
|
const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
|
||||||
|
unsigned long long getUniqueId() const { return uniqueId; }
|
||||||
|
void setUniqueId(unsigned long long id) { uniqueId = id; }
|
||||||
|
|
||||||
// Certain explicit conversions are allowed conditionally
|
// Certain explicit conversions are allowed conditionally
|
||||||
#ifdef GLSLANG_WEB
|
#ifdef GLSLANG_WEB
|
||||||
@@ -907,22 +992,23 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
|
TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
|
||||||
void error(TInfoSink& infoSink, const char*);
|
void error(TInfoSink& infoSink, const char*);
|
||||||
void warn(TInfoSink& infoSink, const char*);
|
void warn(TInfoSink& infoSink, const char*);
|
||||||
void mergeCallGraphs(TInfoSink&, TIntermediate&);
|
void mergeCallGraphs(TInfoSink&, TIntermediate&);
|
||||||
void mergeModes(TInfoSink&, TIntermediate&);
|
void mergeModes(TInfoSink&, TIntermediate&);
|
||||||
void mergeTrees(TInfoSink&, TIntermediate&);
|
void mergeTrees(TInfoSink&, TIntermediate&);
|
||||||
void seedIdMap(TIdMaps& idMaps, int& maxId);
|
void seedIdMap(TIdMaps& idMaps, long long& IdShift);
|
||||||
void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&);
|
void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
|
||||||
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
|
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
|
||||||
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
|
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
|
||||||
|
void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
|
||||||
void mergeImplicitArraySizes(TType&, const TType&);
|
void mergeImplicitArraySizes(TType&, const TType&);
|
||||||
void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
|
void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
|
||||||
void checkCallGraphCycles(TInfoSink&);
|
void checkCallGraphCycles(TInfoSink&);
|
||||||
void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
|
void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
|
||||||
void inOutLocationCheck(TInfoSink&);
|
void inOutLocationCheck(TInfoSink&);
|
||||||
TIntermAggregate* findLinkerObjects() const;
|
void sharedBlockCheck(TInfoSink&);
|
||||||
bool userOutputUsed() const;
|
bool userOutputUsed() const;
|
||||||
bool isSpecializationOperation(const TIntermOperator&) const;
|
bool isSpecializationOperation(const TIntermOperator&) const;
|
||||||
bool isNonuniformPropagating(TOperator) const;
|
bool isNonuniformPropagating(TOperator) const;
|
||||||
@@ -955,7 +1041,7 @@ protected:
|
|||||||
SpvVersion spvVersion;
|
SpvVersion spvVersion;
|
||||||
TIntermNode* treeRoot;
|
TIntermNode* treeRoot;
|
||||||
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
|
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
|
||||||
TBuiltInResource resources;
|
MustBeAssigned<TBuiltInResource> resources;
|
||||||
int numEntryPoints;
|
int numEntryPoints;
|
||||||
int numErrors;
|
int numErrors;
|
||||||
int numPushConstants;
|
int numPushConstants;
|
||||||
@@ -967,6 +1053,14 @@ protected:
|
|||||||
int localSize[3];
|
int localSize[3];
|
||||||
bool localSizeNotDefault[3];
|
bool localSizeNotDefault[3];
|
||||||
int localSizeSpecId[3];
|
int localSizeSpecId[3];
|
||||||
|
unsigned long long uniqueId;
|
||||||
|
|
||||||
|
std::string globalUniformBlockName;
|
||||||
|
std::string atomicCounterBlockName;
|
||||||
|
unsigned int globalUniformBlockSet;
|
||||||
|
unsigned int globalUniformBlockBinding;
|
||||||
|
unsigned int atomicCounterBlockSet;
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
public:
|
public:
|
||||||
const char* const implicitThisName;
|
const char* const implicitThisName;
|
||||||
@@ -1027,10 +1121,13 @@ protected:
|
|||||||
int uniformLocationBase;
|
int uniformLocationBase;
|
||||||
TNumericFeatures numericFeatures;
|
TNumericFeatures numericFeatures;
|
||||||
#endif
|
#endif
|
||||||
|
std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
|
||||||
|
|
||||||
std::unordered_set<int> usedConstantId; // specialization constant ids used
|
std::unordered_set<int> usedConstantId; // specialization constant ids used
|
||||||
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
|
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
|
||||||
std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
|
std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
|
||||||
|
std::vector<TRange> usedIoRT[2]; // sets of used location, one for rayPayload/rayPayloadIN and other
|
||||||
|
// for callableData/callableDataIn
|
||||||
// set of names of statically read/written I/O that might need extra checking
|
// set of names of statically read/written I/O that might need extra checking
|
||||||
std::set<TString> ioAccessed;
|
std::set<TString> ioAccessed;
|
||||||
// source code of shader, useful as part of debug information
|
// source code of shader, useful as part of debug information
|
||||||
|
|||||||
@@ -455,6 +455,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||||||
token = scanToken(ppToken);
|
token = scanToken(ppToken);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
token = tokenPaste(token, *ppToken);
|
||||||
token = evalToToken(token, shortCircuit, res, err, ppToken);
|
token = evalToToken(token, shortCircuit, res, err, ppToken);
|
||||||
return eval(token, precedence, shortCircuit, res, err, ppToken);
|
return eval(token, precedence, shortCircuit, res, err, ppToken);
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
@@ -658,14 +658,17 @@ public:
|
|||||||
|
|
||||||
blocks.back().numMembers = countAggregateMembers(type);
|
blocks.back().numMembers = countAggregateMembers(type);
|
||||||
|
|
||||||
EShLanguageMask& stages = blocks.back().stages;
|
if (updateStageMasks) {
|
||||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
EShLanguageMask& stages = blocks.back().stages;
|
||||||
|
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
blockIndex = it->second;
|
blockIndex = it->second;
|
||||||
|
if (updateStageMasks) {
|
||||||
EShLanguageMask& stages = blocks[blockIndex].stages;
|
EShLanguageMask& stages = blocks[blockIndex].stages;
|
||||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -904,8 +907,8 @@ public:
|
|||||||
case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset;
|
case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset;
|
||||||
case EbtInt: return GL_INT_VEC2 + offset;
|
case EbtInt: return GL_INT_VEC2 + offset;
|
||||||
case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset;
|
case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset;
|
||||||
case EbtInt64: return GL_INT64_ARB + offset;
|
case EbtInt64: return GL_INT64_VEC2_ARB + offset;
|
||||||
case EbtUint64: return GL_UNSIGNED_INT64_ARB + offset;
|
case EbtUint64: return GL_UNSIGNED_INT64_VEC2_ARB + offset;
|
||||||
case EbtBool: return GL_BOOL_VEC2 + offset;
|
case EbtBool: return GL_BOOL_VEC2 + offset;
|
||||||
case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
|
case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
@@ -1135,6 +1138,8 @@ void TReflection::buildCounterIndices(const TIntermediate& intermediate)
|
|||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
indexToUniformBlock[i].counterIndex = index;
|
indexToUniformBlock[i].counterIndex = index;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(void)intermediate;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ typedef enum {
|
|||||||
EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
|
EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
|
||||||
EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
|
EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
|
||||||
EShTargetOpenGL_450 = 450, // OpenGL
|
EShTargetOpenGL_450 = 450, // OpenGL
|
||||||
LAST_ELEMENT_MARKER(EShTargetClientVersionCount),
|
LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 4),
|
||||||
} EShTargetClientVersion;
|
} EShTargetClientVersion;
|
||||||
|
|
||||||
typedef EShTargetClientVersion EshTargetClientVersion;
|
typedef EShTargetClientVersion EshTargetClientVersion;
|
||||||
@@ -179,7 +179,7 @@ typedef enum {
|
|||||||
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
|
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
|
||||||
EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
|
EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
|
||||||
EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
|
EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
|
||||||
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount),
|
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 6),
|
||||||
} EShTargetLanguageVersion;
|
} EShTargetLanguageVersion;
|
||||||
|
|
||||||
struct TInputLanguage {
|
struct TInputLanguage {
|
||||||
@@ -187,6 +187,7 @@ struct TInputLanguage {
|
|||||||
EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone
|
EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone
|
||||||
EShClient dialect;
|
EShClient dialect;
|
||||||
int dialectVersion; // version of client's language definition, not the client (when not EShClientNone)
|
int dialectVersion; // version of client's language definition, not the client (when not EShClientNone)
|
||||||
|
bool vulkanRulesRelaxed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TClient {
|
struct TClient {
|
||||||
@@ -427,6 +428,14 @@ enum TResourceType {
|
|||||||
EResCount
|
EResCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TBlockStorageClass
|
||||||
|
{
|
||||||
|
EbsUniform = 0,
|
||||||
|
EbsStorageBuffer,
|
||||||
|
EbsPushConstant,
|
||||||
|
EbsNone, // not a uniform or buffer variable
|
||||||
|
EbsCount,
|
||||||
|
};
|
||||||
|
|
||||||
// Make one TShader per shader that you will link into a program. Then
|
// Make one TShader per shader that you will link into a program. Then
|
||||||
// - provide the shader through setStrings() or setStringsWithLengths()
|
// - provide the shader through setStrings() or setStringsWithLengths()
|
||||||
@@ -458,6 +467,7 @@ public:
|
|||||||
GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
|
GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
|
||||||
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
|
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
|
||||||
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
|
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
|
||||||
|
GLSLANG_EXPORT void setUniqueId(unsigned long long id);
|
||||||
|
|
||||||
// IO resolver binding data: see comments in ShaderLang.cpp
|
// IO resolver binding data: see comments in ShaderLang.cpp
|
||||||
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
|
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
|
||||||
@@ -482,6 +492,14 @@ public:
|
|||||||
GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
|
GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
|
||||||
GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
|
GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
|
||||||
GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
|
GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
|
||||||
|
GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing);
|
||||||
|
|
||||||
|
GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name);
|
||||||
|
GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name);
|
||||||
|
GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set);
|
||||||
|
GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding);
|
||||||
|
GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set);
|
||||||
|
GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding);
|
||||||
|
|
||||||
// For setting up the environment (cleared to nothingness in the constructor).
|
// For setting up the environment (cleared to nothingness in the constructor).
|
||||||
// These must be called so that parsing is done for the right source language and
|
// These must be called so that parsing is done for the right source language and
|
||||||
@@ -538,6 +556,9 @@ public:
|
|||||||
bool getEnvTargetHlslFunctionality1() const { return false; }
|
bool getEnvTargetHlslFunctionality1() const { return false; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; }
|
||||||
|
bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; }
|
||||||
|
|
||||||
// Interface to #include handlers.
|
// Interface to #include handlers.
|
||||||
//
|
//
|
||||||
// To support #include, a client of Glslang does the following:
|
// To support #include, a client of Glslang does the following:
|
||||||
@@ -805,7 +826,7 @@ public:
|
|||||||
// Called by TSlotCollector to resolve resource locations or bindings
|
// Called by TSlotCollector to resolve resource locations or bindings
|
||||||
virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
|
virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0;
|
||||||
// Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
|
// Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline
|
||||||
virtual void addStage(EShLanguage stage) = 0;
|
virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
|
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
|
||||||
@@ -927,6 +948,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
|
GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
|
||||||
|
GLSLANG_EXPORT bool crossStageCheck(EShMessages);
|
||||||
|
|
||||||
TPoolAllocator* pool;
|
TPoolAllocator* pool;
|
||||||
std::list<TShader*> stages[EShLangCount];
|
std::list<TShader*> stages[EShLangCount];
|
||||||
|
|||||||
Reference in New Issue
Block a user