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

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