@@ -149,6 +149,7 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
149149 spv::Decoration TranslateInterpolationDecoration (const glslang::TQualifier& qualifier);
150150 spv::Decoration TranslateAuxiliaryStorageDecoration (const glslang::TQualifier& qualifier);
151151 spv::Decoration TranslateNonUniformDecoration (const glslang::TQualifier& qualifier);
152+ spv::Decoration TranslateNonUniformDecoration (const spv::Builder::AccessChain::CoherentFlags& coherentFlags);
152153 spv::Builder::AccessChain::CoherentFlags TranslateCoherent (const glslang::TType& type);
153154 spv::MemoryAccessMask TranslateMemoryAccess (const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
154155 spv::ImageOperandsMask TranslateImageOperands (const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
@@ -539,6 +540,20 @@ spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glsl
539540 return spv::DecorationMax;
540541}
541542
543+ // If lvalue flags contains nonUniform, return SPIR-V NonUniform decoration.
544+ spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration (
545+ const spv::Builder::AccessChain::CoherentFlags& coherentFlags)
546+ {
547+ #ifndef GLSLANG_WEB
548+ if (coherentFlags.isNonUniform ()) {
549+ builder.addIncorporatedExtension (" SPV_EXT_descriptor_indexing" , spv::Spv_1_5);
550+ builder.addCapability (spv::CapabilityShaderNonUniformEXT);
551+ return spv::DecorationNonUniformEXT;
552+ } else
553+ #endif
554+ return spv::DecorationMax;
555+ }
556+
542557spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess (
543558 const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
544559{
@@ -614,6 +629,7 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere
614629 flags.volatil ;
615630 flags.isImage = type.getBasicType () == glslang::EbtSampler;
616631#endif
632+ flags.nonUniform = type.getQualifier ().nonUniform ;
617633 return flags;
618634}
619635
@@ -1376,6 +1392,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa
13761392 if (parent.writeonly )
13771393 child.writeonly = true ;
13781394#endif
1395+ if (parent.nonUniform )
1396+ child.nonUniform = true ;
13791397}
13801398
13811399bool HasNonLayoutQualifiers (const glslang::TType& type, const glslang::TQualifier& qualifier)
@@ -1881,9 +1899,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
18811899 spv::Id leftRValue = accessChainLoad (node->getLeft ()->getType ());
18821900
18831901 // do the operation
1902+ spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent (node->getLeft ()->getType ());
1903+ coherentFlags |= TranslateCoherent (node->getRight ()->getType ());
18841904 OpDecorations decorations = { TranslatePrecisionDecoration (node->getOperationPrecision ()),
18851905 TranslateNoContractionDecoration (node->getType ().getQualifier ()),
1886- TranslateNonUniformDecoration (node-> getType (). getQualifier () ) };
1906+ TranslateNonUniformDecoration (coherentFlags ) };
18871907 rValue = createBinaryOperation (node->getOp (), decorations,
18881908 convertGlslangToSpvType (node->getType ()), leftRValue, rValue,
18891909 node->getType ().getBasicType ());
@@ -1914,13 +1934,16 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
19141934 if (! node->getLeft ()->getType ().isArray () &&
19151935 node->getLeft ()->getType ().isVector () &&
19161936 node->getOp () == glslang::EOpIndexDirect) {
1937+ // Swizzle is uniform so propagate uniform into access chain
1938+ spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent (node->getLeft ()->getType ());
1939+ coherentFlags.nonUniform = 0 ;
19171940 // This is essentially a hard-coded vector swizzle of size 1,
19181941 // so short circuit the access-chain stuff with a swizzle.
19191942 std::vector<unsigned > swizzle;
19201943 swizzle.push_back (glslangIndex);
19211944 int dummySize;
19221945 builder.accessChainPushSwizzle (swizzle, convertGlslangToSpvType (node->getLeft ()->getType ()),
1923- TranslateCoherent (node-> getLeft ()-> getType ()) ,
1946+ coherentFlags ,
19241947 glslangIntermediate->getBaseAlignmentScalar (
19251948 node->getLeft ()->getType (), dummySize));
19261949 } else {
@@ -1951,9 +1974,14 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
19511974 }
19521975 }
19531976
1977+ // Struct reference propagates uniform lvalue
1978+ spv::Builder::AccessChain::CoherentFlags coherentFlags =
1979+ TranslateCoherent (node->getLeft ()->getType ());
1980+ coherentFlags.nonUniform = 0 ;
1981+
19541982 // normal case for indexing array or structure or block
19551983 builder.accessChainPush (builder.makeIntConstant (spvIndex),
1956- TranslateCoherent (node-> getLeft ()-> getType ()) ,
1984+ coherentFlags ,
19571985 node->getLeft ()->getType ().getBufferReferenceAlignment ());
19581986
19591987 // Add capabilities here for accessing PointSize and clip/cull distance.
@@ -1987,15 +2015,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
19872015 // restore the saved access chain
19882016 builder.setAccessChain (partial);
19892017
2018+ // Only if index is nonUniform should we propagate nonUniform into access chain
2019+ spv::Builder::AccessChain::CoherentFlags index_flags = TranslateCoherent (node->getRight ()->getType ());
2020+ spv::Builder::AccessChain::CoherentFlags coherent_flags = TranslateCoherent (node->getLeft ()->getType ());
2021+ coherent_flags.nonUniform = index_flags.nonUniform ;
2022+
19902023 if (! node->getLeft ()->getType ().isArray () && node->getLeft ()->getType ().isVector ()) {
19912024 int dummySize;
1992- builder.accessChainPushComponent (index, convertGlslangToSpvType (node-> getLeft ()-> getType ()),
1993- TranslateCoherent (node->getLeft ()->getType ()),
2025+ builder.accessChainPushComponent (
2026+ index, convertGlslangToSpvType (node->getLeft ()->getType ()), coherent_flags ,
19942027 glslangIntermediate->getBaseAlignmentScalar (node->getLeft ()->getType (),
19952028 dummySize));
19962029 } else
1997- builder.accessChainPush (index, TranslateCoherent (node-> getLeft ()-> getType ()) ,
1998- node->getLeft ()->getType ().getBufferReferenceAlignment ());
2030+ builder.accessChainPush (index, coherent_flags ,
2031+ node->getLeft ()->getType ().getBufferReferenceAlignment ());
19992032 }
20002033 return false ;
20012034 case glslang::EOpVectorSwizzle:
@@ -2119,7 +2152,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
21192152 // handle 32-bit v.xy* -> 64-bit
21202153 builder.clearAccessChain ();
21212154 builder.setAccessChainLValue (object);
2122- object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, objectTypeId);
2155+ object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
21232156 std::vector<spv::Id> components;
21242157 components.push_back (builder.createCompositeExtract (object, builder.getContainedTypeId (objectTypeId), 0 ));
21252158 components.push_back (builder.createCompositeExtract (object, builder.getContainedTypeId (objectTypeId), 1 ));
@@ -2135,7 +2168,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
21352168 // and we insert a transpose after loading the original non-transposed builtins
21362169 builder.clearAccessChain ();
21372170 builder.setAccessChainLValue (object);
2138- object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, objectTypeId);
2171+ object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
21392172 return builder.createUnaryOp (spv::OpTranspose, desiredTypeId, object);
21402173
21412174 } else {
@@ -2322,7 +2355,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
23222355 // The result of operation is always stored, but conditionally the
23232356 // consumed result. The consumed result is always an r-value.
23242357 builder.accessChainStore (result,
2325- TranslateNonUniformDecoration (node-> getOperand ()-> getType (). getQualifier () ));
2358+ TranslateNonUniformDecoration (builder. getAccessChain (). coherentFlags ));
23262359 builder.clearAccessChain ();
23272360 if (node->getOp () == glslang::EOpPreIncrement ||
23282361 node->getOp () == glslang::EOpPreDecrement)
@@ -2398,7 +2431,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
23982431 spv::Id invertedType = spv::NoType; // to use to override the natural type of the node
23992432 std::vector<spv::Builder::AccessChain> complexLvalues; // for holding swizzling l-values too complex for
24002433 // SPIR-V, for an out parameter
2401- std::vector<glslang::TQualifier> complexLValueQualifiers;
24022434 std::vector<spv::Id> temporaryLvalues; // temporaries to pass, as proxies for complexLValues
24032435
24042436 auto resultType = [&invertedType, &node, this ](){ return invertedType != spv::NoType ?
@@ -3020,7 +3052,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
30203052 // receive the result, and must later swizzle that into the original
30213053 // l-value.
30223054 complexLvalues.push_back (builder.getAccessChain ());
3023- complexLValueQualifiers.push_back (glslangOperands[arg]->getAsTyped ()->getType ().getQualifier ());
30243055 temporaryLvalues.push_back (builder.createVariable (
30253056 spv::NoPrecision, spv::StorageClassFunction,
30263057 builder.accessChainGetInferredType (), " swizzleTemp" ));
@@ -3125,7 +3156,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
31253156
31263157 for (unsigned int i = 0 ; i < temporaryLvalues.size (); ++i) {
31273158 builder.setAccessChain (complexLvalues[i]);
3128- builder.accessChainStore (builder.createLoad (temporaryLvalues[i], spv::NoPrecision), TranslateNonUniformDecoration (complexLValueQualifiers[i]));
3159+ builder.accessChainStore (builder.createLoad (temporaryLvalues[i], spv::NoPrecision),
3160+ TranslateNonUniformDecoration (complexLvalues[i].coherentFlags ));
31293161 }
31303162 }
31313163
@@ -4135,6 +4167,7 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
41354167 alignment |= type.getBufferReferenceAlignment ();
41364168
41374169 spv::Id loadedId = builder.accessChainLoad (TranslatePrecisionDecoration (type),
4170+ TranslateNonUniformDecoration (builder.getAccessChain ().coherentFlags ),
41384171 TranslateNonUniformDecoration (type.getQualifier ()),
41394172 nominalTypeId,
41404173 spv::MemoryAccessMask (TranslateMemoryAccess (coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
@@ -4202,7 +4235,7 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
42024235 unsigned int alignment = builder.getAccessChain ().alignment ;
42034236 alignment |= type.getBufferReferenceAlignment ();
42044237
4205- builder.accessChainStore (rvalue, TranslateNonUniformDecoration (type. getQualifier () ),
4238+ builder.accessChainStore (rvalue, TranslateNonUniformDecoration (builder. getAccessChain (). coherentFlags ),
42064239 spv::MemoryAccessMask (TranslateMemoryAccess (coherentFlags) &
42074240 ~spv::MemoryAccessMakePointerVisibleKHRMask),
42084241 TranslateMemoryScope (coherentFlags), alignment);
@@ -4734,8 +4767,10 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
47344767 }
47354768
47364769 if (lvalue) {
4737- arguments.push_back (builder.accessChainGetLValue ());
4770+ spv::Id lvalue_id = builder.accessChainGetLValue ();
4771+ arguments.push_back (lvalue_id);
47384772 lvalueCoherentFlags = builder.getAccessChain ().coherentFlags ;
4773+ builder.addDecoration (lvalue_id, TranslateNonUniformDecoration (lvalueCoherentFlags));
47394774 lvalueCoherentFlags |= TranslateCoherent (glslangArguments[i]->getAsTyped ()->getType ());
47404775 } else
47414776#endif
@@ -5415,6 +5450,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
54155450 // 3. Make the call.
54165451 spv::Id result = builder.createFunctionCall (function, spvArgs);
54175452 builder.setPrecision (result, TranslatePrecisionDecoration (node->getType ()));
5453+ builder.addDecoration (result, TranslateNonUniformDecoration (node->getType ().getQualifier ()));
54185454
54195455 // 4. Copy back out an "out" arguments.
54205456 lValueCount = 0 ;
@@ -5424,6 +5460,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
54245460 else if (writableParam (qualifiers[a])) {
54255461 if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
54265462 spv::Id copy = builder.createLoad (spvArgs[a], spv::NoPrecision);
5463+ builder.addDecoration (copy, TranslateNonUniformDecoration (argTypes[a]->getQualifier ()));
54275464 builder.setAccessChain (lValues[lValueCount]);
54285465 multiTypeStore (*argTypes[a], copy);
54295466 }
@@ -8228,9 +8265,6 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
82288265 builder.addDecoration (id, memory[i]);
82298266 }
82308267
8231- // nonuniform
8232- builder.addDecoration (id, TranslateNonUniformDecoration (symbol->getType ().getQualifier ()));
8233-
82348268 if (builtIn == spv::BuiltInSampleMask) {
82358269 spv::Decoration decoration;
82368270 // GL_NV_sample_mask_override_coverage extension
0 commit comments