SPV 1.4: Lookup tables: Use variable initializer and NonWritable...

...when doing a variable lookup on an array of constants.
This commit is contained in:
John Kessenich 2019-02-07 08:04:12 -07:00
parent fbb6bdf046
commit 61a5ce190a
6 changed files with 102 additions and 11 deletions

View File

@ -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.

View File

@ -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");
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;

View File

@ -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);

View File

@ -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

13
Test/spv.1.4.NonWritable.frag Executable file
View File

@ -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];
}

View File

@ -465,9 +465,10 @@ INSTANTIATE_TEST_CASE_P(
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",