...when doing a variable lookup on an array of constants.
case glslang::EOpIndexDirect:
case glslang::EOpIndexDirectStruct:
{
+ // Structure, array, matrix, or vector indirection with statically known index.
// Get the left part of the access chain.
node->getLeft()->traverse(this);
return false;
case glslang::EOpIndexIndirect:
{
- // Structure or array or vector indirection.
- // Will use native SPIR-V access-chain for struct and array indirection;
+ // Array, matrix, or vector indirection with variable index.
+ // Will use native SPIR-V access-chain for and array indirection;
// matrices are arrays of vectors, so will also work for a matrix.
// Will use the access chain's 'component' for variable index into a vector.
}
// Comments in header
-Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
+Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
{
Id pointerType = makePointer(storageClass, type);
Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
inst->addImmediateOperand(storageClass);
+ if (initializer != NoResult)
+ inst->addIdOperand(initializer);
switch (storageClass) {
case StorageClassFunction:
if (constant) {
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
} else {
- // make a new function variable for this r-value
- Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
-
- // store into it
- createStore(accessChain.base, lValue);
-
+ Id lValue = NoResult;
+ if (spvVersion >= Spv_1_4) {
+ // make a new function variable for this r-value, using an initializer,
+ // and mark it as NonWritable so that downstream it can be detected as a lookup
+ // table
+ lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
+ accessChain.base);
+ addDecoration(lValue, DecorationNonWritable);
+ } else {
+ lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
+ // store into it
+ createStore(accessChain.base, lValue);
+ }
// move base to the new variable
accessChain.base = lValue;
accessChain.isRValue = false;
namespace spv {
+typedef enum {
+ Spv_1_0 = (1 << 16),
+ Spv_1_1 = (1 << 16) | (1 << 8),
+ Spv_1_2 = (1 << 16) | (2 << 8),
+ Spv_1_3 = (1 << 16) | (3 << 8),
+ Spv_1_4 = (1 << 16) | (4 << 8),
+} SpvVersion;
+
class Builder {
public:
Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
void makeDiscard();
// Create a global or function local or IO variable.
- Id createVariable(StorageClass, Id type, const char* name = 0);
+ Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
// Create an intermediate with an undefined value.
Id createUndefined(Id type);
--- /dev/null
+spv.1.4.NonWritable.frag
+Validation failed
+// Module Version 10400
+// Generated by (magic number): 80007
+// Id's are bound by 38
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 8 31
+ ExecutionMode 4 OriginUpperLeft
+ Source GLSL 450
+ Name 4 "main"
+ Name 8 "color"
+ Name 31 "index"
+ Name 34 "indexable"
+ Decorate 8(color) Location 0
+ Decorate 31(index) Flat
+ Decorate 31(index) Location 0
+ Decorate 34(indexable) NonWritable
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypePointer Output 6(float)
+ 8(color): 7(ptr) Variable Output
+ 9: TypeInt 32 0
+ 10: 9(int) Constant 16
+ 11: TypeArray 6(float) 10
+ 12: 6(float) Constant 1065353216
+ 13: 6(float) Constant 1073741824
+ 14: 6(float) Constant 1077936128
+ 15: 6(float) Constant 1082130432
+ 16: 6(float) Constant 1084227584
+ 17: 6(float) Constant 1086324736
+ 18: 6(float) Constant 1088421888
+ 19: 6(float) Constant 1090519040
+ 20: 6(float) Constant 1091567616
+ 21: 6(float) Constant 1092616192
+ 22: 6(float) Constant 1093664768
+ 23: 6(float) Constant 1094713344
+ 24: 6(float) Constant 1095761920
+ 25: 6(float) Constant 1096810496
+ 26: 6(float) Constant 1097859072
+ 27: 6(float) Constant 1098907648
+ 28: 11 ConstantComposite 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
+ 29: TypeInt 32 1
+ 30: TypePointer Input 29(int)
+ 31(index): 30(ptr) Variable Input
+ 33: TypePointer Function 11
+ 35: TypePointer Function 6(float)
+ 4(main): 2 Function None 3
+ 5: Label
+ 34(indexable): 33(ptr) Variable Function 28
+ 32: 29(int) Load 31(index)
+ 36: 35(ptr) AccessChain 34(indexable) 32
+ 37: 6(float) Load 36
+ Store 8(color) 37
+ Return
+ FunctionEnd
--- /dev/null
+#version 450
+
+layout(location = 0) flat in int index;
+
+layout(location = 0) out float color;
+
+// lookup table
+const float table[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+void main()
+{
+ color = table[index];
+}
INSTANTIATE_TEST_CASE_P(
Glsl, CompileToSpirv14Test,
::testing::ValuesIn(std::vector<std::string>({
+ "spv.1.4.LoopControl.frag",
+ "spv.1.4.NonWritable.frag",
"spv.1.4.OpEntryPoint.frag",
"spv.1.4.OpSelect.frag",
- "spv.1.4.LoopControl.frag",
"spv.1.4.OpCopyLogical.comp",
"spv.1.4.OpCopyLogicalBool.comp",
"spv.1.4.OpCopyLogical.funcall.frag",