From 61a5ce190a02491fb45718b5e050e86ef732bbcd Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Thu, 7 Feb 2019 08:04:12 -0700 Subject: [PATCH] SPV 1.4: Lookup tables: Use variable initializer and NonWritable... ...when doing a variable lookup on an array of constants. --- SPIRV/GlslangToSpv.cpp | 5 ++- SPIRV/SpvBuilder.cpp | 23 +++++++---- SPIRV/SpvBuilder.h | 10 ++++- Test/baseResults/spv.1.4.NonWritable.frag.out | 59 +++++++++++++++++++++++++++ Test/spv.1.4.NonWritable.frag | 13 ++++++ gtests/Spv.FromFile.cpp | 3 +- 6 files changed, 102 insertions(+), 11 deletions(-) create mode 100755 Test/baseResults/spv.1.4.NonWritable.frag.out create mode 100755 Test/spv.1.4.NonWritable.frag 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 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T 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 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T 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 @@ void Builder::makeDiscard() } // 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 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu 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 @@ public: 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( INSTANTIATE_TEST_CASE_P( Glsl, CompileToSpirv14Test, ::testing::ValuesIn(std::vector({ + "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", -- 2.7.4