@@ -149,6 +149,7 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
149
149
spv::Decoration TranslateInterpolationDecoration (const glslang::TQualifier& qualifier);
150
150
spv::Decoration TranslateAuxiliaryStorageDecoration (const glslang::TQualifier& qualifier);
151
151
spv::Decoration TranslateNonUniformDecoration (const glslang::TQualifier& qualifier);
152
+ spv::Decoration TranslateNonUniformDecoration (const spv::Builder::AccessChain::CoherentFlags& coherentFlags);
152
153
spv::Builder::AccessChain::CoherentFlags TranslateCoherent (const glslang::TType& type);
153
154
spv::MemoryAccessMask TranslateMemoryAccess (const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
154
155
spv::ImageOperandsMask TranslateImageOperands (const spv::Builder::AccessChain::CoherentFlags &coherentFlags);
@@ -539,6 +540,20 @@ spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glsl
539
540
return spv::DecorationMax;
540
541
}
541
542
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
+
542
557
spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess (
543
558
const spv::Builder::AccessChain::CoherentFlags &coherentFlags)
544
559
{
@@ -614,6 +629,7 @@ spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCohere
614
629
flags.volatil ;
615
630
flags.isImage = type.getBasicType () == glslang::EbtSampler;
616
631
#endif
632
+ flags.nonUniform = type.getQualifier ().nonUniform ;
617
633
return flags;
618
634
}
619
635
@@ -1376,6 +1392,8 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa
1376
1392
if (parent.writeonly )
1377
1393
child.writeonly = true ;
1378
1394
#endif
1395
+ if (parent.nonUniform )
1396
+ child.nonUniform = true ;
1379
1397
}
1380
1398
1381
1399
bool HasNonLayoutQualifiers (const glslang::TType& type, const glslang::TQualifier& qualifier)
@@ -1881,9 +1899,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
1881
1899
spv::Id leftRValue = accessChainLoad (node->getLeft ()->getType ());
1882
1900
1883
1901
// do the operation
1902
+ spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent (node->getLeft ()->getType ());
1903
+ coherentFlags |= TranslateCoherent (node->getRight ()->getType ());
1884
1904
OpDecorations decorations = { TranslatePrecisionDecoration (node->getOperationPrecision ()),
1885
1905
TranslateNoContractionDecoration (node->getType ().getQualifier ()),
1886
- TranslateNonUniformDecoration (node-> getType (). getQualifier () ) };
1906
+ TranslateNonUniformDecoration (coherentFlags ) };
1887
1907
rValue = createBinaryOperation (node->getOp (), decorations,
1888
1908
convertGlslangToSpvType (node->getType ()), leftRValue, rValue,
1889
1909
node->getType ().getBasicType ());
@@ -1914,13 +1934,16 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
1914
1934
if (! node->getLeft ()->getType ().isArray () &&
1915
1935
node->getLeft ()->getType ().isVector () &&
1916
1936
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 ;
1917
1940
// This is essentially a hard-coded vector swizzle of size 1,
1918
1941
// so short circuit the access-chain stuff with a swizzle.
1919
1942
std::vector<unsigned > swizzle;
1920
1943
swizzle.push_back (glslangIndex);
1921
1944
int dummySize;
1922
1945
builder.accessChainPushSwizzle (swizzle, convertGlslangToSpvType (node->getLeft ()->getType ()),
1923
- TranslateCoherent (node-> getLeft ()-> getType ()) ,
1946
+ coherentFlags ,
1924
1947
glslangIntermediate->getBaseAlignmentScalar (
1925
1948
node->getLeft ()->getType (), dummySize));
1926
1949
} else {
@@ -1951,9 +1974,14 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
1951
1974
}
1952
1975
}
1953
1976
1977
+ // Struct reference propagates uniform lvalue
1978
+ spv::Builder::AccessChain::CoherentFlags coherentFlags =
1979
+ TranslateCoherent (node->getLeft ()->getType ());
1980
+ coherentFlags.nonUniform = 0 ;
1981
+
1954
1982
// normal case for indexing array or structure or block
1955
1983
builder.accessChainPush (builder.makeIntConstant (spvIndex),
1956
- TranslateCoherent (node-> getLeft ()-> getType ()) ,
1984
+ coherentFlags ,
1957
1985
node->getLeft ()->getType ().getBufferReferenceAlignment ());
1958
1986
1959
1987
// Add capabilities here for accessing PointSize and clip/cull distance.
@@ -1987,15 +2015,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
1987
2015
// restore the saved access chain
1988
2016
builder.setAccessChain (partial);
1989
2017
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
+
1990
2023
if (! node->getLeft ()->getType ().isArray () && node->getLeft ()->getType ().isVector ()) {
1991
2024
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 ,
1994
2027
glslangIntermediate->getBaseAlignmentScalar (node->getLeft ()->getType (),
1995
2028
dummySize));
1996
2029
} 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 ());
1999
2032
}
2000
2033
return false ;
2001
2034
case glslang::EOpVectorSwizzle:
@@ -2119,7 +2152,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
2119
2152
// handle 32-bit v.xy* -> 64-bit
2120
2153
builder.clearAccessChain ();
2121
2154
builder.setAccessChainLValue (object);
2122
- object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, objectTypeId);
2155
+ object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
2123
2156
std::vector<spv::Id> components;
2124
2157
components.push_back (builder.createCompositeExtract (object, builder.getContainedTypeId (objectTypeId), 0 ));
2125
2158
components.push_back (builder.createCompositeExtract (object, builder.getContainedTypeId (objectTypeId), 1 ));
@@ -2135,7 +2168,7 @@ spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object)
2135
2168
// and we insert a transpose after loading the original non-transposed builtins
2136
2169
builder.clearAccessChain ();
2137
2170
builder.setAccessChainLValue (object);
2138
- object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, objectTypeId);
2171
+ object = builder.accessChainLoad (spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId);
2139
2172
return builder.createUnaryOp (spv::OpTranspose, desiredTypeId, object);
2140
2173
2141
2174
} else {
@@ -2322,7 +2355,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
2322
2355
// The result of operation is always stored, but conditionally the
2323
2356
// consumed result. The consumed result is always an r-value.
2324
2357
builder.accessChainStore (result,
2325
- TranslateNonUniformDecoration (node-> getOperand ()-> getType (). getQualifier () ));
2358
+ TranslateNonUniformDecoration (builder. getAccessChain (). coherentFlags ));
2326
2359
builder.clearAccessChain ();
2327
2360
if (node->getOp () == glslang::EOpPreIncrement ||
2328
2361
node->getOp () == glslang::EOpPreDecrement)
@@ -2398,7 +2431,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
2398
2431
spv::Id invertedType = spv::NoType; // to use to override the natural type of the node
2399
2432
std::vector<spv::Builder::AccessChain> complexLvalues; // for holding swizzling l-values too complex for
2400
2433
// SPIR-V, for an out parameter
2401
- std::vector<glslang::TQualifier> complexLValueQualifiers;
2402
2434
std::vector<spv::Id> temporaryLvalues; // temporaries to pass, as proxies for complexLValues
2403
2435
2404
2436
auto resultType = [&invertedType, &node, this ](){ return invertedType != spv::NoType ?
@@ -3020,7 +3052,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
3020
3052
// receive the result, and must later swizzle that into the original
3021
3053
// l-value.
3022
3054
complexLvalues.push_back (builder.getAccessChain ());
3023
- complexLValueQualifiers.push_back (glslangOperands[arg]->getAsTyped ()->getType ().getQualifier ());
3024
3055
temporaryLvalues.push_back (builder.createVariable (
3025
3056
spv::NoPrecision, spv::StorageClassFunction,
3026
3057
builder.accessChainGetInferredType (), " swizzleTemp" ));
@@ -3125,7 +3156,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
3125
3156
3126
3157
for (unsigned int i = 0 ; i < temporaryLvalues.size (); ++i) {
3127
3158
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 ));
3129
3161
}
3130
3162
}
3131
3163
@@ -4135,6 +4167,7 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
4135
4167
alignment |= type.getBufferReferenceAlignment ();
4136
4168
4137
4169
spv::Id loadedId = builder.accessChainLoad (TranslatePrecisionDecoration (type),
4170
+ TranslateNonUniformDecoration (builder.getAccessChain ().coherentFlags ),
4138
4171
TranslateNonUniformDecoration (type.getQualifier ()),
4139
4172
nominalTypeId,
4140
4173
spv::MemoryAccessMask (TranslateMemoryAccess (coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
@@ -4202,7 +4235,7 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
4202
4235
unsigned int alignment = builder.getAccessChain ().alignment ;
4203
4236
alignment |= type.getBufferReferenceAlignment ();
4204
4237
4205
- builder.accessChainStore (rvalue, TranslateNonUniformDecoration (type. getQualifier () ),
4238
+ builder.accessChainStore (rvalue, TranslateNonUniformDecoration (builder. getAccessChain (). coherentFlags ),
4206
4239
spv::MemoryAccessMask (TranslateMemoryAccess (coherentFlags) &
4207
4240
~spv::MemoryAccessMakePointerVisibleKHRMask),
4208
4241
TranslateMemoryScope (coherentFlags), alignment);
@@ -4734,8 +4767,10 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
4734
4767
}
4735
4768
4736
4769
if (lvalue) {
4737
- arguments.push_back (builder.accessChainGetLValue ());
4770
+ spv::Id lvalue_id = builder.accessChainGetLValue ();
4771
+ arguments.push_back (lvalue_id);
4738
4772
lvalueCoherentFlags = builder.getAccessChain ().coherentFlags ;
4773
+ builder.addDecoration (lvalue_id, TranslateNonUniformDecoration (lvalueCoherentFlags));
4739
4774
lvalueCoherentFlags |= TranslateCoherent (glslangArguments[i]->getAsTyped ()->getType ());
4740
4775
} else
4741
4776
#endif
@@ -5415,6 +5450,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
5415
5450
// 3. Make the call.
5416
5451
spv::Id result = builder.createFunctionCall (function, spvArgs);
5417
5452
builder.setPrecision (result, TranslatePrecisionDecoration (node->getType ()));
5453
+ builder.addDecoration (result, TranslateNonUniformDecoration (node->getType ().getQualifier ()));
5418
5454
5419
5455
// 4. Copy back out an "out" arguments.
5420
5456
lValueCount = 0 ;
@@ -5424,6 +5460,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
5424
5460
else if (writableParam (qualifiers[a])) {
5425
5461
if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
5426
5462
spv::Id copy = builder.createLoad (spvArgs[a], spv::NoPrecision);
5463
+ builder.addDecoration (copy, TranslateNonUniformDecoration (argTypes[a]->getQualifier ()));
5427
5464
builder.setAccessChain (lValues[lValueCount]);
5428
5465
multiTypeStore (*argTypes[a], copy);
5429
5466
}
@@ -8228,9 +8265,6 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
8228
8265
builder.addDecoration (id, memory[i]);
8229
8266
}
8230
8267
8231
- // nonuniform
8232
- builder.addDecoration (id, TranslateNonUniformDecoration (symbol->getType ().getQualifier ()));
8233
-
8234
8268
if (builtIn == spv::BuiltInSampleMask) {
8235
8269
spv::Decoration decoration;
8236
8270
// GL_NV_sample_mask_override_coverage extension
0 commit comments