Unverified Commit 0b66fa3b by Malcolm Bechard Committed by GitHub

Shader interface matching rework to fix #2136 (#2156)

* rework how shader interface block naming rules are handled * Fixes 2136 According to the spec, shader interfaces (uniform blocks, buffer blocks, input blocks, output blocks) all should be matched up via their block names across all compilation units, not instance names. Also, all block names can be re-used between all 4 interface types without conflict. This change makes it so all of these blocks are matched and remapped using block name and not by instance name. Additional the rule that matched uniform and buffer blocks must either be anonymous or named (but not nessearily the same name) is now imposed. * add warning if instance names differ between matched shader interfaces * Add test cases from #2137 which is now fixed as well. * replace some tab characters with spaces * buffer blocks and uniform blocks now share the same block namespace
parent 1fff3623
#version 430
// Error: Block has different members
layout (std140) uniform Block
{
mat4 uProj;
};
// Error: BufferBlock has different members
buffer BufferBlock
{
vec4 b;
};
// Error: Vertex has different members
out Vertex
{
vec4 v1;
};
// Error: ColorBlock has different members
layout (std140) uniform ColorBlock
{
vec4 color1;
vec4 color2;
// Error, redeclare varaible in another anonymous block
vec4 v1;
};
// Error: NamedBlock is anonymous in other compilation unit
layout (std140) uniform NamedBlock
{
mat4 m;
} myName;
vec4 getWorld();
vec4 getColor2();
out vec4 oColor;
// Error: redeclare varaibles that are in anonymous blocks
out vec4 v1;
uniform mat4 uProj;
void
main()
{
oColor = color1 * getColor2();
v1 = color1;
gl_Position = uProj * getWorld();
}
#version 430
// Error: ColorBlock has different members
layout (std140) uniform ColorBlock
{
vec4 color2;
};
// Error: Block has different members
layout (std140) uniform Block
{
mat4 uProj;
mat4 uWorld;
};
// Error: Vertex has different members
out Vertex
{
vec4 v1;
vec4 v2;
};
// Error BufferBlock has different members
buffer BufferBlock
{
vec4 a;
};
// Error: NamedBlock is anonymous in other compilation unit
layout (std140) uniform NamedBlock
{
mat4 m;
};
in vec4 P;
vec4 getColor2()
{
return color2;
}
vec4 getWorld()
{
return uWorld * P;
v2 = vec4(1);
}
#version 430
// Verify that matching by block name is working, not
// instance name, which was at one point failing on this
// test due to E.g anon@1 being different blocks for
// different compilation units
layout (std140) uniform Block
{
mat4 uProj;
mat4 uWorld;
};
out Vertex
{
vec4 v1;
vec4 v2;
};
layout (std140) uniform ColorBlock
{
vec4 color1;
vec4 color2;
};
vec4 getWorld();
vec4 getColor2();
out vec4 oColor;
void
main()
{
oColor = color1 * getColor2();
v1 = color1;
gl_Position = uProj * getWorld();
}
#version 430
layout (std140) uniform ColorBlock
{
vec4 color1;
vec4 color2;
};
layout (std140) uniform Block
{
mat4 uProj;
mat4 uWorld;
};
out Vertex
{
vec4 v1;
vec4 v2;
};
in vec4 P;
vec4 getColor2()
{
return color2;
}
vec4 getWorld()
{
return uWorld * P;
v2 = vec4(1);
}
#version 430
// Verify that blocks with different instance names
// are correctly detected as invalid non-matching blocks
// when they are matched up by block name
layout (std140) uniform Block
{
mat4 uProj;
} uD;
out Vertex
{
vec4 v1;
} oV;
layout (std140) uniform ColorBlock
{
vec4 color1;
} uC;
// Error, buffer blocks and uniform blocks share the
// same namespace for their block name
layout (std430) buffer ColorBlock
{
vec4 color1;
} uBufC;
vec4 getWorld();
vec4 getColor2();
out vec4 oColor;
void
main()
{
oColor = uC.color1 * getColor2();
oV.v1 = uC.color1 + uBufC.color1;
gl_Position = uD.uProj * getWorld();
}
#version 430
layout (std140) uniform ColorBlock
{
vec4 color2;
} uColorB;
layout (std140) uniform Block
{
mat4 uWorld;
} uDefaultB;
out Vertex
{
vec4 v2;
} oVert;
in vec4 P;
vec4 getColor2()
{
return uColorB.color2;
}
vec4 getWorld()
{
return uDefaultB.uWorld * P;
oVert.v2 = vec4(1);
}
#version 430
layout (std140) uniform Block
{
mat4 uProj;
mat4 uWorld;
} a;
out Vertex
{
vec4 v1;
vec4 v2;
} b;
layout (std140) uniform ColorBlock
{
vec4 color1;
vec4 color2;
} c;
vec4 getWorld();
vec4 getColor2();
out vec4 oColor;
void
main()
{
oColor = c.color1 * getColor2();
b.v1 = c.color1;
gl_Position = a.uProj * getWorld();
}
#version 430
layout (std140) uniform ColorBlock
{
vec4 color1;
vec4 color2;
} a;
layout (std140) uniform Block
{
mat4 uProj;
mat4 uWorld;
} b;
out Vertex
{
vec4 v1;
vec4 v2;
} c;
in vec4 P;
vec4 getColor2()
{
return a.color2;
}
vec4 getWorld()
{
return b.uWorld * P;
c.v2 = vec4(1);
}
#version 430
// OK: different instance names is allowed in other unit
layout (std140, binding = 0) uniform MatrixBlock
{
mat4 uProj;
mat4 uWorld;
} uM;
// OK: other unit has it as anonymous, but that is allowed
out Vertex
{
vec4 v1;
vec4 v2;
} oV;
// OK: different instance names is allowed in other unit
layout (std140, binding = 1) uniform ColorBlock
{
vec4 color1;
bool b;
vec4 color2;
vec4 color3;
} uC;
// OK: different instance names is allowed in other unit
layout (std430, binding = 1) buffer BufferBlock
{
mat4 p;
} uBuf;
layout (std430, binding = 0) buffer SecondaryColorBlock
{
vec4 c;
} uColorBuf;
vec4 getWorld();
vec4 getColor2();
out vec4 oColor;
void
main()
{
oColor = uC.color1 * getColor2() * uColorBuf.c;
oV.v1 = uC.color1;
gl_Position = uM.uProj * getWorld();
}
#version 430
// OK: different instance names is allowed in other unit
layout (std140, binding = 1) uniform ColorBlock
{
vec4 color1;
bool b;
vec4 color2;
vec4 color3;
} uColor;
// OK: different instance names is allowed in other unit
layout (std430, binding = 1) buffer BufferBlock
{
mat4 p;
} uBuffer;
// OK: different instance names is allowed in other unit
layout (std140, binding = 0) uniform MatrixBlock
{
mat4 uProj;
mat4 uWorld;
} uMatrix;
// OK, it's allowed for input/output interfaces to
// be anonymous is one unit and not in another
out Vertex
{
vec4 v1;
vec4 v2;
};
in vec4 P;
vec4 getColor2()
{
return uColor.color2;
}
vec4 getWorld()
{
v1 = vec4(1);
return uMatrix.uWorld * P;
}
#version 430
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
// OK: different instance names is allowed
layout (std140, binding = 0) uniform MatrixBlock
{
mat4 uProj;
mat4 uWorld;
} uM;
// Verify that in/out blocks with same block name work
in Vertex
{
vec4 v1;
vec4 v2;
} iV[3];
out Vertex
{
vec4 val1;
} oV;
// OK: different instance names is allowed
layout (std140, binding = 1) uniform ColorBlock
{
vec4 color1;
bool b;
vec4 color2;
vec4 color3;
} uC;
// OK: different instance names is allowed
layout (std430, binding = 1) buffer BufferBlock
{
mat4 p;
} uBuf;
vec4 getWorld(int i);
vec4 getColor2();
out vec4 oColor;
float globalF;
void
main()
{
oColor = uC.color1 * getColor2();
globalF = 1.0;
for (int i = 0; i < 3; i++)
{
gl_Position = uM.uProj * getWorld(i);
oV.val1 = uC.color1 + iV[i].v2 * globalF;
EmitVertex();
}
EndPrimitive();
}
#version 430
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
// OK: different instance names is allowed
layout (std140, binding = 1) uniform ColorBlock
{
vec4 color1;
bool b;
vec4 color2;
vec4 color3;
} uColor;
// OK: different instance names is allowed
layout (std430, binding = 1) buffer BufferBlock
{
mat4 p;
} uBuffer;
// OK: different instance names is allowed
layout (std140, binding = 0) uniform MatrixBlock
{
mat4 uProj;
mat4 uWorld;
} uMatrix;
// OK, it's allowed for input/output interfaces to
// be anonymous is one unit and not in another
out Vertex
{
vec4 val1;
};
in Vertex
{
vec4 v1;
vec4 v2;
} iVV[];
in vec4 P[3];
vec4 getColor2()
{
return uColor.color2;
}
vec4 getWorld(int i)
{
val1 = vec4(1);
return uMatrix.uWorld * iVV[i].v1;
}
#version 450
layout (push_constant) uniform Block
{
mat4 uWorld;
mat4 uProj;
vec4 color1;
vec4 color2;
} a;
vec4 getWorld();
vec4 getColor2();
out vec4 oColor;
void
main()
{
oColor = a.color1 * getColor2();
gl_Position = a.uProj * getWorld();
}
#version 450
layout (push_constant) uniform Block2
{
mat4 uWorld;
mat4 uProj;
vec4 color1;
vec4 color2;
} a;
in vec4 P;
vec4 getColor2()
{
return a.color2;
}
vec4 getWorld()
{
return a.uWorld * P;
}
#version 450
layout (push_constant) uniform PCBlock
{
mat4 uWorld;
mat4 uProj;
vec4 color1;
vec4 color2;
} a;
vec4 getWorld();
vec4 getColor2();
layout(location = 0) out vec4 oColor;
void
main()
{
oColor = a.color1 * getColor2();
gl_Position = a.uProj * getWorld();
}
#version 450
layout (push_constant) uniform PCBlock
{
mat4 uWorld;
mat4 uProj;
vec4 color1;
vec4 color2;
} b;
layout(location = 0) in vec4 P;
vec4 getColor2()
{
return b.color2;
}
vec4 getWorld()
{
return b.uWorld * P;
}
...@@ -473,6 +473,18 @@ enum TInterlockOrdering { ...@@ -473,6 +473,18 @@ enum TInterlockOrdering {
EioCount, EioCount,
}; };
enum TShaderInterface
{
// Includes both uniform blocks and buffer blocks
EsiUniform = 0,
EsiInput,
EsiOutput,
EsiNone,
EsiCount
};
class TQualifier { class TQualifier {
public: public:
static const int layoutNotSet = -1; static const int layoutNotSet = -1;
...@@ -1616,6 +1628,23 @@ public: ...@@ -1616,6 +1628,23 @@ public:
assert(fieldName); assert(fieldName);
return *fieldName; return *fieldName;
} }
TShaderInterface getShaderInterface() const
{
if (basicType != EbtBlock)
return EsiNone;
switch (qualifier.storage) {
default:
return EsiNone;
case EvqVaryingIn:
return EsiInput;
case EvqVaryingOut:
return EsiOutput;
case EvqUniform:
case EvqBuffer:
return EsiUniform;
}
}
virtual TBasicType getBasicType() const { return basicType; } virtual TBasicType getBasicType() const { return basicType; }
virtual const TSampler& getSampler() const { return sampler; } virtual const TSampler& getSampler() const { return sampler; }
......
...@@ -303,10 +303,10 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) ...@@ -303,10 +303,10 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
// Map by global name to unique ID to rationalize the same object having // Map by global name to unique ID to rationalize the same object having
// differing IDs in different trees. // differing IDs in different trees.
TMap<TString, int> idMap; TIdMaps idMaps;
int maxId; int maxId;
seedIdMap(idMap, maxId); seedIdMap(idMaps, maxId);
remapIds(idMap, maxId + 1, unit); remapIds(idMaps, maxId + 1, unit);
mergeBodies(infoSink, globals, unitGlobals); mergeBodies(infoSink, globals, unitGlobals);
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects); mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
...@@ -315,27 +315,40 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) ...@@ -315,27 +315,40 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
#endif #endif
static const TString& getNameForIdMap(TIntermSymbol* symbol)
{
TShaderInterface si = symbol->getType().getShaderInterface();
if (si == EsiNone)
return symbol->getName();
else
return symbol->getType().getTypeName();
}
// Traverser that seeds an ID map with all built-ins, and tracks the // Traverser that seeds an ID map with all built-ins, and tracks the
// maximum ID used. // maximum ID used.
// (It would be nice to put this in a function, but that causes warnings // (It would be nice to put this in a function, but that causes warnings
// on having no bodies for the copy-constructor/operator=.) // on having no bodies for the copy-constructor/operator=.)
class TBuiltInIdTraverser : public TIntermTraverser { class TBuiltInIdTraverser : public TIntermTraverser {
public: public:
TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { } TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), maxId(0) { }
// If it's a built in, add it to the map. // If it's a built in, add it to the map.
// Track the max ID. // Track the max ID.
virtual void visitSymbol(TIntermSymbol* symbol) virtual void visitSymbol(TIntermSymbol* symbol)
{ {
const TQualifier& qualifier = symbol->getType().getQualifier(); const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.builtIn != EbvNone) if (qualifier.builtIn != EbvNone) {
idMap[symbol->getName()] = symbol->getId(); TShaderInterface si = symbol->getType().getShaderInterface();
idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
}
maxId = std::max(maxId, symbol->getId()); maxId = std::max(maxId, symbol->getId());
} }
int getMaxId() const { return maxId; } int getMaxId() const { return maxId; }
protected: protected:
TBuiltInIdTraverser(TBuiltInIdTraverser&); TBuiltInIdTraverser(TBuiltInIdTraverser&);
TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&); TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
TMap<TString, int>& idMap; TIdMaps& idMaps;
int maxId; int maxId;
}; };
...@@ -344,31 +357,33 @@ protected: ...@@ -344,31 +357,33 @@ protected:
// on having no bodies for the copy-constructor/operator=.) // on having no bodies for the copy-constructor/operator=.)
class TUserIdTraverser : public TIntermTraverser { class TUserIdTraverser : public TIntermTraverser {
public: public:
TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { } TUserIdTraverser(TIdMaps& idMaps) : idMaps(idMaps) { }
// If its a non-built-in global, add it to the map. // If its a non-built-in global, add it to the map.
virtual void visitSymbol(TIntermSymbol* symbol) virtual void visitSymbol(TIntermSymbol* symbol)
{ {
const TQualifier& qualifier = symbol->getType().getQualifier(); const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.builtIn == EbvNone) if (qualifier.builtIn == EbvNone) {
idMap[symbol->getName()] = symbol->getId(); TShaderInterface si = symbol->getType().getShaderInterface();
idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
}
} }
protected: protected:
TUserIdTraverser(TUserIdTraverser&); TUserIdTraverser(TUserIdTraverser&);
TUserIdTraverser& operator=(TUserIdTraverser&); TUserIdTraverser& operator=(TUserIdTraverser&);
TMap<TString, int>& idMap; // over biggest id TIdMaps& idMaps; // over biggest id
}; };
// Initialize the the ID map with what we know of 'this' AST. // Initialize the the ID map with what we know of 'this' AST.
void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId) void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
{ {
// all built-ins everywhere need to align on IDs and contribute to the max ID // all built-ins everywhere need to align on IDs and contribute to the max ID
TBuiltInIdTraverser builtInIdTraverser(idMap); TBuiltInIdTraverser builtInIdTraverser(idMaps);
treeRoot->traverse(&builtInIdTraverser); treeRoot->traverse(&builtInIdTraverser);
maxId = builtInIdTraverser.getMaxId(); maxId = builtInIdTraverser.getMaxId();
// user variables in the linker object list need to align on ids // user variables in the linker object list need to align on ids
TUserIdTraverser userIdTraverser(idMap); TUserIdTraverser userIdTraverser(idMaps);
findLinkerObjects()->traverse(&userIdTraverser); findLinkerObjects()->traverse(&userIdTraverser);
} }
...@@ -377,7 +392,7 @@ void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId) ...@@ -377,7 +392,7 @@ void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
// on having no bodies for the copy-constructor/operator=.) // on having no bodies for the copy-constructor/operator=.)
class TRemapIdTraverser : public TIntermTraverser { class TRemapIdTraverser : public TIntermTraverser {
public: public:
TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { } TRemapIdTraverser(const TIdMaps& idMaps, int idShift) : idMaps(idMaps), idShift(idShift) { }
// Do the mapping: // Do the mapping:
// - if the same symbol, adopt the 'this' ID // - if the same symbol, adopt the 'this' ID
// - otherwise, ensure a unique ID by shifting to a new space // - otherwise, ensure a unique ID by shifting to a new space
...@@ -386,8 +401,9 @@ public: ...@@ -386,8 +401,9 @@ public:
const TQualifier& qualifier = symbol->getType().getQualifier(); const TQualifier& qualifier = symbol->getType().getQualifier();
bool remapped = false; bool remapped = false;
if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) { if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
auto it = idMap.find(symbol->getName()); TShaderInterface si = symbol->getType().getShaderInterface();
if (it != idMap.end()) { auto it = idMaps[si].find(getNameForIdMap(symbol));
if (it != idMaps[si].end()) {
symbol->changeId(it->second); symbol->changeId(it->second);
remapped = true; remapped = true;
} }
...@@ -398,14 +414,14 @@ public: ...@@ -398,14 +414,14 @@ public:
protected: protected:
TRemapIdTraverser(TRemapIdTraverser&); TRemapIdTraverser(TRemapIdTraverser&);
TRemapIdTraverser& operator=(TRemapIdTraverser&); TRemapIdTraverser& operator=(TRemapIdTraverser&);
const TMap<TString, int>& idMap; const TIdMaps& idMaps;
int idShift; int idShift;
}; };
void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit) void TIntermediate::remapIds(const TIdMaps& idMaps, int idShift, TIntermediate& unit)
{ {
// Remap all IDs to either share or be unique, as dictated by the idMap and idShift. // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
TRemapIdTraverser idTraverser(idMap, idShift); TRemapIdTraverser idTraverser(idMaps, idShift);
unit.getTreeRoot()->traverse(&idTraverser); unit.getTreeRoot()->traverse(&idTraverser);
} }
...@@ -447,7 +463,19 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin ...@@ -447,7 +463,19 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
assert(symbol && unitSymbol); assert(symbol && unitSymbol);
if (symbol->getName() == unitSymbol->getName()) {
bool isSameSymbol = false;
// If they are both blocks in the same shader interface,
// match by the block-name, not the identifier name.
if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
}
}
else if (symbol->getName() == unitSymbol->getName())
isSameSymbol = true;
if (isSameSymbol) {
// filter out copy // filter out copy
merge = false; merge = false;
...@@ -527,6 +555,22 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy ...@@ -527,6 +555,22 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
writeTypeComparison = true; writeTypeComparison = true;
} }
// Uniform and buffer blocks must either both have an instance name, or
// must both be anonymous. The names don't need to match though.
if (symbol.getQualifier().isUniformOrBuffer() &&
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) {
error(infoSink, "Matched Uniform or Storage blocks must all be anonymous,"
" or all be named:");
writeTypeComparison = true;
}
if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage &&
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) ||
(!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) {
warn(infoSink, "Matched shader interfaces are using different instance names.");
writeTypeComparison = true;
}
// Precision... // Precision...
if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
error(infoSink, "Precision qualifiers must match:"); error(infoSink, "Precision qualifiers must match:");
...@@ -597,9 +641,13 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy ...@@ -597,9 +641,13 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
} }
} }
if (writeTypeComparison) if (writeTypeComparison) {
infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" << infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus ";
unitSymbol.getType().getCompleteString() << "\"\n"; if (symbol.getName() != unitSymbol.getName())
infoSink.info << unitSymbol.getName() << ": ";
infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n";
}
#endif #endif
} }
......
...@@ -225,6 +225,15 @@ enum ComputeDerivativeMode { ...@@ -225,6 +225,15 @@ enum ComputeDerivativeMode {
LayoutDerivativeGroupLinear, // derivative_group_linearNV LayoutDerivativeGroupLinear, // derivative_group_linearNV
}; };
class TIdMaps {
public:
TMap<TString, int>& operator[](int i) { return maps[i]; };
const TMap<TString, int>& operator[](int i) const { return maps[i]; };
private:
TMap<TString, int> maps[EsiCount];
};
// //
// Set of helper functions to help parse and build the tree. // Set of helper functions to help parse and build the tree.
// //
...@@ -862,8 +871,8 @@ protected: ...@@ -862,8 +871,8 @@ protected:
void mergeCallGraphs(TInfoSink&, TIntermediate&); void mergeCallGraphs(TInfoSink&, TIntermediate&);
void mergeModes(TInfoSink&, TIntermediate&); void mergeModes(TInfoSink&, TIntermediate&);
void mergeTrees(TInfoSink&, TIntermediate&); void mergeTrees(TInfoSink&, TIntermediate&);
void seedIdMap(TMap<TString, int>& idMap, int& maxId); void seedIdMap(TIdMaps& idMaps, int& maxId);
void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&); void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&);
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
void mergeImplicitArraySizes(TType&, const TType&); void mergeImplicitArraySizes(TType&, const TType&);
......
...@@ -115,6 +115,10 @@ INSTANTIATE_TEST_CASE_P( ...@@ -115,6 +115,10 @@ INSTANTIATE_TEST_CASE_P(
"link.vk.differentPC.0.2.frag"}, "link.vk.differentPC.0.2.frag"},
{"link.vk.differentPC.1.0.frag", "link.vk.differentPC.1.1.frag", {"link.vk.differentPC.1.0.frag", "link.vk.differentPC.1.1.frag",
"link.vk.differentPC.1.2.frag"}, "link.vk.differentPC.1.2.frag"},
{"link.vk.pcNamingValid.0.0.vert", "link.vk.pcNamingValid.0.1.vert"},
{"link.vk.pcNamingInvalid.0.0.vert", "link.vk.pcNamingInvalid.0.1.vert"},
{"link.vk.multiBlocksValid.0.0.vert", "link.vk.multiBlocksValid.0.1.vert"},
{"link.vk.multiBlocksValid.1.0.geom", "link.vk.multiBlocksValid.1.1.geom"},
})) }))
); );
// clang-format on // clang-format on
......
...@@ -100,7 +100,11 @@ INSTANTIATE_TEST_CASE_P( ...@@ -100,7 +100,11 @@ INSTANTIATE_TEST_CASE_P(
{"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"}, {"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"},
{"max_vertices_0.geom"}, {"max_vertices_0.geom"},
{"es-link1.frag", "es-link2.frag"}, {"es-link1.frag", "es-link2.frag"},
{"missingBodies.vert"} {"missingBodies.vert"},
{"link.multiAnonBlocksInvalid.0.0.vert", "link.multiAnonBlocksInvalid.0.1.vert"},
{"link.multiAnonBlocksValid.0.0.vert", "link.multiAnonBlocksValid.0.1.vert"},
{"link.multiBlocksInvalid.0.0.vert", "link.multiBlocksInvalid.0.1.vert"},
{"link.multiBlocksValid.1.0.vert", "link.multiBlocksValid.1.1.vert"},
})) }))
); );
// clang-format on // clang-format on
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment