SPV 1.4: Lookup tables: Use variable initializer and NonWritable...
...when doing a variable lookup on an array of constants.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index c12f5bf..f5cbb88 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1711,6 +1711,7 @@
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);
@@ -1765,8 +1766,8 @@
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.
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 6eb18d0..773e5f1 100644
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1306,11 +1306,13 @@
}
// 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:
@@ -2649,12 +2651,19 @@
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;
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 72018a3..aee9781 100644
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -61,6 +61,14 @@
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);
@@ -300,7 +308,7 @@
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);
diff --git a/Test/baseResults/spv.1.4.NonWritable.frag.out b/Test/baseResults/spv.1.4.NonWritable.frag.out
new file mode 100755
index 0000000..4f92426
--- /dev/null
+++ b/Test/baseResults/spv.1.4.NonWritable.frag.out
@@ -0,0 +1,59 @@
+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
diff --git a/Test/spv.1.4.NonWritable.frag b/Test/spv.1.4.NonWritable.frag
new file mode 100755
index 0000000..386b446
--- /dev/null
+++ b/Test/spv.1.4.NonWritable.frag
@@ -0,0 +1,13 @@
+#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];
+}
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index 25abf3a..308bab6 100755
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -465,9 +465,10 @@
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",