Reflection: Optimize leaf-array sizes for largest index used in a live path.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24073 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
12f9221e44
commit
c17dbd516f
@ -19,7 +19,7 @@ scalarAfterm23: offset 48, type 1404, size 1, index 0
|
|||||||
c_m23: offset 16, type 8b67, size 1, index 2
|
c_m23: offset 16, type 8b67, size 1, index 2
|
||||||
c_scalarAfterm23: offset 64, type 1404, size 1, index 2
|
c_scalarAfterm23: offset 64, type 1404, size 1, index 2
|
||||||
scalarBeforeArray: offset 96, type 1404, size 1, index 0
|
scalarBeforeArray: offset 96, type 1404, size 1, index 0
|
||||||
floatArray: offset 112, type 1406, size 5, index 0
|
floatArray: offset 112, type 1406, size 3, index 0
|
||||||
scalarAfterArray: offset 192, type 1404, size 1, index 0
|
scalarAfterArray: offset 192, type 1404, size 1, index 0
|
||||||
ablock.memvec2: offset 48, type 8b50, size 1, index 1
|
ablock.memvec2: offset 48, type 8b50, size 1, index 1
|
||||||
ablock.memf1: offset 56, type 1406, size 1, index 1
|
ablock.memf1: offset 56, type 1406, size 1, index 1
|
||||||
@ -27,8 +27,8 @@ ablock.memf2: offset 60, type 8b56, size 1, index 1
|
|||||||
ablock.memf3: offset 64, type 1404, size 1, index 1
|
ablock.memf3: offset 64, type 1404, size 1, index 1
|
||||||
ablock.memvec2a: offset 72, type 8b50, size 1, index 1
|
ablock.memvec2a: offset 72, type 8b50, size 1, index 1
|
||||||
ablock.m22: offset 80, type 8b5a, size 7, index 1
|
ablock.m22: offset 80, type 8b5a, size 7, index 1
|
||||||
dm22: offset -1, type 8b5a, size 10, index -1
|
dm22: offset -1, type 8b5a, size 4, index -1
|
||||||
m22: offset 208, type 8b5a, size 9, index 0
|
m22: offset 208, type 8b5a, size 3, index 0
|
||||||
nest.foo.n1.a: offset 0, type 1406, size 1, index 3
|
nest.foo.n1.a: offset 0, type 1406, size 1, index 3
|
||||||
nest.foo.n2.b: offset 16, type 1406, size 1, index 3
|
nest.foo.n2.b: offset 16, type 1406, size 1, index 3
|
||||||
nest.foo.n2.c: offset 20, type 1406, size 1, index 3
|
nest.foo.n2.c: offset 20, type 1406, size 1, index 3
|
||||||
|
@ -235,21 +235,41 @@ public:
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a complex uniform reference where blocks/struct/arrays are involved in the access.
|
// Add a uniform dereference where blocks/struct/arrays are involved in the access.
|
||||||
// Handles the situation where the left node is at too coarse a granularity to be a single
|
// Handles the situation where the left node is at the correct or too coarse a
|
||||||
// uniform, while the result of the operation at 'node' is at the right granuarity.
|
// granularity for reflection. (That is, further dereferences up the tree will be
|
||||||
|
// skipped.) Earlier dereferences, down the tree, will be handled
|
||||||
|
// at the same time, and logged to prevent reprocessing as the tree is traversed.
|
||||||
//
|
//
|
||||||
// Note: Simpler things like the following are already handled elsewhere:
|
// Note: Other things like the following must be caught elsewhere:
|
||||||
// - a simple non-array, non-struct variable
|
// - a simple non-array, non-struct variable (no dereference even conceivable)
|
||||||
// - a variable that's an array of non-struct
|
// - an aggregrate consumed en masse, without a dereference
|
||||||
//
|
//
|
||||||
// So, this code is for cases like
|
// So, this code is for cases like
|
||||||
// - a struct/block holding a member (member is array or not)
|
// - a struct/block dereferencing a member (whether the member is array or not)
|
||||||
// - an array of struct
|
// - an array of struct
|
||||||
// - structs/arrays containing the above
|
// - structs/arrays containing the above
|
||||||
//
|
//
|
||||||
void addDereferencedUniform(TIntermSymbol* base, TIntermBinary* topNode)
|
void addDereferencedUniform(TIntermBinary* topNode)
|
||||||
{
|
{
|
||||||
|
// See if too fine-grained to process (wait to get further down the tree)
|
||||||
|
const TType& leftType = topNode->getLeft()->getType();
|
||||||
|
if ((leftType.isVector() || leftType.isMatrix()) && ! leftType.isArray())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We have an array or structure or block dereference, see if it's a uniform
|
||||||
|
// based dereference (if not, skip it).
|
||||||
|
TIntermSymbol* base = findBase(topNode);
|
||||||
|
if (! base || base->getQualifier().storage != EvqUniform)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// See if we've already processed this (e.g., in the middle of something
|
||||||
|
// we did earlier), and if so skip it
|
||||||
|
if (processedDerefs.find(topNode) != processedDerefs.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Process this uniform dereference
|
||||||
|
|
||||||
int offset = -1;
|
int offset = -1;
|
||||||
int blockIndex = -1;
|
int blockIndex = -1;
|
||||||
bool anonymous = false;
|
bool anonymous = false;
|
||||||
@ -269,21 +289,49 @@ public:
|
|||||||
blockIndex = it->second;
|
blockIndex = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the dereference chain, backward, accumulating the pieces on a stack
|
// If the derefenced entity to record is an array, note the maximum array size.
|
||||||
|
int maxArraySize;
|
||||||
|
const TType* reflectionType;
|
||||||
|
if (isReflectionGranularity(topNode->getLeft()->getType()) && topNode->getLeft()->isArray()) {
|
||||||
|
reflectionType = &topNode->getLeft()->getType();
|
||||||
|
switch (topNode->getOp()) {
|
||||||
|
case EOpIndexIndirect:
|
||||||
|
maxArraySize = topNode->getLeft()->getType().getArraySize();
|
||||||
|
break;
|
||||||
|
case EOpIndexDirect:
|
||||||
|
maxArraySize = topNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst() + 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
maxArraySize = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reflectionType = &topNode->getType();
|
||||||
|
maxArraySize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: fully expand a partially dereferenced aggregate
|
||||||
|
|
||||||
|
// Process the dereference chain, backward, accumulating the pieces on a stack.
|
||||||
|
// If the topNode is a simple array dereference, don't include that.
|
||||||
if (block)
|
if (block)
|
||||||
offset = 0;
|
offset = 0;
|
||||||
std::list<TString> derefs;
|
std::list<TString> derefs;
|
||||||
for (TIntermBinary* visitNode = topNode; visitNode; visitNode = visitNode->getLeft()->getAsBinaryNode()) {
|
for (TIntermBinary* visitNode = topNode; visitNode; visitNode = visitNode->getLeft()->getAsBinaryNode()) {
|
||||||
|
processedDerefs.insert(visitNode);
|
||||||
int index;
|
int index;
|
||||||
switch (visitNode->getOp()) {
|
switch (visitNode->getOp()) {
|
||||||
case EOpIndexIndirect:
|
case EOpIndexIndirect:
|
||||||
// TODO handle indirect references in mid-chain: enumerate all possibilities?
|
// TODO handle indirect references in mid-chain: enumerate all possibilities?
|
||||||
derefs.push_back(TString("[") + String(0) + "]");
|
if (! isReflectionGranularity(visitNode->getLeft()->getType()))
|
||||||
|
derefs.push_back(TString("[") + String(0) + "]");
|
||||||
break;
|
break;
|
||||||
case EOpIndexDirect:
|
case EOpIndexDirect:
|
||||||
// TODO: reflection: track the highest used index for an array, to reduce the array's size
|
if (! isReflectionGranularity(visitNode->getLeft()->getType())) {
|
||||||
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||||
derefs.push_back(TString("[") + String(index) + "]");
|
derefs.push_back(TString("[") + String(index) + "]");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EOpIndexDirectStruct:
|
case EOpIndexDirectStruct:
|
||||||
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||||
@ -311,7 +359,7 @@ public:
|
|||||||
if (name.size() > 0) {
|
if (name.size() > 0) {
|
||||||
if (reflection.nameToIndex.find(name) == reflection.nameToIndex.end()) {
|
if (reflection.nameToIndex.find(name) == reflection.nameToIndex.end()) {
|
||||||
reflection.nameToIndex[name] = reflection.indexToUniform.size();
|
reflection.nameToIndex[name] = reflection.indexToUniform.size();
|
||||||
reflection.indexToUniform.push_back(TObjectReflection(name, offset, mapToGlType(topNode->getType()), mapToGlArraySize(topNode->getType()), blockIndex));
|
reflection.indexToUniform.push_back(TObjectReflection(name, offset, mapToGlType(*reflectionType), maxArraySize, blockIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,6 +643,7 @@ public:
|
|||||||
TFunctionStack functions;
|
TFunctionStack functions;
|
||||||
const TIntermediate& intermediate;
|
const TIntermediate& intermediate;
|
||||||
TReflection& reflection;
|
TReflection& reflection;
|
||||||
|
std::set<TIntermNode*> processedDerefs;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int TLiveTraverser::baseAlignmentVec4Std140 = 16;
|
const int TLiveTraverser::baseAlignmentVec4Std140 = 16;
|
||||||
@ -617,6 +666,7 @@ bool LiveAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser
|
|||||||
}
|
}
|
||||||
|
|
||||||
// To catch dereferenced aggregates that must be reflected.
|
// To catch dereferenced aggregates that must be reflected.
|
||||||
|
// This catches them at the highest level possible in the tree.
|
||||||
bool LiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
bool LiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
||||||
{
|
{
|
||||||
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
||||||
@ -625,24 +675,18 @@ bool LiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
|||||||
case EOpIndexDirect:
|
case EOpIndexDirect:
|
||||||
case EOpIndexIndirect:
|
case EOpIndexIndirect:
|
||||||
case EOpIndexDirectStruct:
|
case EOpIndexDirectStruct:
|
||||||
// If the left side is already small enough granularity to report, ignore
|
oit->addDereferencedUniform(node);
|
||||||
// this operation, and pick it up when the left side is visited.
|
break;
|
||||||
if (! oit->isReflectionGranularity(node->getLeft()->getType()) &&
|
|
||||||
oit->isReflectionGranularity(node->getType())) {
|
|
||||||
// right granularity; see if this really is a uniform-based dereference,
|
|
||||||
// and if so, process it
|
|
||||||
TIntermSymbol* base = oit->findBase(node);
|
|
||||||
if (base && base->getQualifier().storage == EvqUniform)
|
|
||||||
oit->addDereferencedUniform(base, node);
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // still need to visit everything below
|
// still need to visit everything below, which could contain sub-expressions
|
||||||
|
// containing different uniforms
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To catch non-dereferenced objects that must be reflected.
|
// To reflect non-dereferenced objects.
|
||||||
void LiveSymbol(TIntermSymbol* symbol, TIntermTraverser* it)
|
void LiveSymbol(TIntermSymbol* symbol, TIntermTraverser* it)
|
||||||
{
|
{
|
||||||
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user