Commit b617e14a by John Kessenich

Link: Merge all the settings in TIntermediate.

Fixes #1309.
parent 5d6b5679
...@@ -5,6 +5,8 @@ float a1; ...@@ -5,6 +5,8 @@ float a1;
float foo(); float foo();
out float cout;
void main() void main()
{ {
f = 10; f = 10;
......
...@@ -6,9 +6,12 @@ float f; ...@@ -6,9 +6,12 @@ float f;
float bar(); float bar();
out float cout;
in float cin;
float foo() float foo()
{ {
float h2 = 2 * f; float h2 = 2 * f + cin;
float g2 = bar(); float g2 = bar();
return h2 + g2 + gl_FragCoord.y; return h2 + g2 + gl_FragCoord.y;
} }
\ No newline at end of file
...@@ -3,9 +3,13 @@ ...@@ -3,9 +3,13 @@
float f; float f;
float h3 = 3.0; float h3 = 3.0;
out float cout;
in float cin;
float bar() float bar()
{ {
h3 *= f; h3 *= f;
float g3 = 2 * h3; float g3 = 2 * h3;
cout = g3;
return h3 + g3 + gl_FragCoord.y; return h3 + g3 + gl_FragCoord.y;
} }
...@@ -616,6 +616,22 @@ public: ...@@ -616,6 +616,22 @@ public:
} }
} }
// non-built-in symbols that might link between compilation units
bool isLinkable() const
{
switch (storage) {
case EvqGlobal:
case EvqVaryingIn:
case EvqVaryingOut:
case EvqUniform:
case EvqBuffer:
case EvqShared:
return true;
default:
return false;
}
}
// True if this type of IO is supposed to be arrayed with extra level for per-vertex data // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
bool isArrayedIo(EShLanguage language) const bool isArrayedIo(EShLanguage language) const
{ {
......
...@@ -77,12 +77,13 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message) ...@@ -77,12 +77,13 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message)
// //
void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
{ {
if (source == EShSourceNone) mergeCallGraphs(infoSink, unit);
source = unit.source; mergeModes(infoSink, unit);
mergeTrees(infoSink, unit);
if (source != unit.source) }
error(infoSink, "can't link compilation units from different source languages");
void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
{
if (unit.getNumEntryPoints() > 0) { if (unit.getNumEntryPoints() > 0) {
if (getNumEntryPoints() > 0) if (getNumEntryPoints() > 0)
error(infoSink, "can't handle multiple entry points per stage"); error(infoSink, "can't handle multiple entry points per stage");
...@@ -92,35 +93,50 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) ...@@ -92,35 +93,50 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
} }
} }
numEntryPoints += unit.getNumEntryPoints(); numEntryPoints += unit.getNumEntryPoints();
numErrors += unit.getNumErrors();
numPushConstants += unit.numPushConstants;
callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end()); callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
}
if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) #define MERGE_MAX(member) member = std::max(member, unit.member)
error(infoSink, "gl_FragCoord redeclarations must match across shaders"); #define MERGE_TRUE(member) if (unit.member) member = unit.member;
if (! earlyFragmentTests) void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
earlyFragmentTests = unit.earlyFragmentTests; {
if (language != unit.language)
error(infoSink, "stages must match when linking into a single stage");
if (!postDepthCoverage) if (source == EShSourceNone)
postDepthCoverage = unit.postDepthCoverage; source = unit.source;
if (source != unit.source)
error(infoSink, "can't link compilation units from different source languages");
if (depthLayout == EldNone) if (treeRoot == nullptr) {
depthLayout = unit.depthLayout; profile = unit.profile;
else if (depthLayout != unit.depthLayout) version = unit.version;
error(infoSink, "Contradictory depth layouts"); requestedExtensions = unit.requestedExtensions;
} else {
if ((profile == EEsProfile) != (unit.profile == EEsProfile))
error(infoSink, "Cannot cross link ES and desktop profiles");
else if (unit.profile == ECompatibilityProfile)
profile = ECompatibilityProfile;
version = std::max(version, unit.version);
requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
}
blendEquations |= unit.blendEquations; MERGE_MAX(spvVersion.spv);
MERGE_MAX(spvVersion.vulkanGlsl);
MERGE_MAX(spvVersion.vulkan);
MERGE_MAX(spvVersion.openGl);
if (inputPrimitive == ElgNone) numErrors += unit.getNumErrors();
inputPrimitive = unit.inputPrimitive; numPushConstants += unit.numPushConstants;
else if (inputPrimitive != unit.inputPrimitive)
error(infoSink, "Contradictory input layout primitives");
if (outputPrimitive == ElgNone) if (unit.invocations != TQualifier::layoutNotSet) {
outputPrimitive = unit.outputPrimitive; if (invocations == TQualifier::layoutNotSet)
else if (outputPrimitive != unit.outputPrimitive) invocations = unit.invocations;
error(infoSink, "Contradictory output layout primitives"); else if (invocations != unit.invocations)
error(infoSink, "number of invocations must match between compilation units");
}
if (vertices == TQualifier::layoutNotSet) if (vertices == TQualifier::layoutNotSet)
vertices = unit.vertices; vertices = unit.vertices;
...@@ -133,6 +149,19 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) ...@@ -133,6 +149,19 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
assert(0); assert(0);
} }
if (inputPrimitive == ElgNone)
inputPrimitive = unit.inputPrimitive;
else if (inputPrimitive != unit.inputPrimitive)
error(infoSink, "Contradictory input layout primitives");
if (outputPrimitive == ElgNone)
outputPrimitive = unit.outputPrimitive;
else if (outputPrimitive != unit.outputPrimitive)
error(infoSink, "Contradictory output layout primitives");
if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
error(infoSink, "gl_FragCoord redeclarations must match across shaders");
if (vertexSpacing == EvsNone) if (vertexSpacing == EvsNone)
vertexSpacing = unit.vertexSpacing; vertexSpacing = unit.vertexSpacing;
else if (vertexSpacing != unit.vertexSpacing) else if (vertexSpacing != unit.vertexSpacing)
...@@ -143,8 +172,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) ...@@ -143,8 +172,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
else if (vertexOrder != unit.vertexOrder) else if (vertexOrder != unit.vertexOrder)
error(infoSink, "Contradictory triangle ordering"); error(infoSink, "Contradictory triangle ordering");
if (unit.pointMode) MERGE_TRUE(pointMode);
pointMode = true;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if (localSize[i] > 1) if (localSize[i] > 1)
...@@ -158,8 +186,21 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) ...@@ -158,8 +186,21 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
error(infoSink, "Contradictory local size specialization ids"); error(infoSink, "Contradictory local size specialization ids");
} }
if (unit.xfbMode) MERGE_TRUE(earlyFragmentTests);
xfbMode = true; MERGE_TRUE(postDepthCoverage);
if (depthLayout == EldNone)
depthLayout = unit.depthLayout;
else if (depthLayout != unit.depthLayout)
error(infoSink, "Contradictory depth layouts");
MERGE_TRUE(depthReplacing);
MERGE_TRUE(hlslFunctionality1);
blendEquations |= unit.blendEquations;
MERGE_TRUE(xfbMode);
for (size_t b = 0; b < xfbBuffers.size(); ++b) { for (size_t b = 0; b < xfbBuffers.size(); ++b) {
if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd) if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
xfbBuffers[b].stride = unit.xfbBuffers[b].stride; xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
...@@ -171,22 +212,40 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) ...@@ -171,22 +212,40 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
// TODO: 4.4 link: enhanced layouts: compare ranges // TODO: 4.4 link: enhanced layouts: compare ranges
} }
if (unit.treeRoot == 0) MERGE_TRUE(multiStream);
return;
if (treeRoot == 0) { #ifdef NV_EXTENSIONS
treeRoot = unit.treeRoot; MERGE_TRUE(layoutOverrideCoverage);
version = unit.version; MERGE_TRUE(geoPassthroughEXT);
requestedExtensions = unit.requestedExtensions; #endif
return;
for (unsigned int i = 0; i < unit.shiftBinding.size(); ++i) {
if (unit.shiftBinding[i] > 0)
setShiftBinding((TResourceType)i, unit.shiftBinding[i]);
} }
// Getting this far means we have two existing trees to merge... for (unsigned int i = 0; i < unit.shiftBindingForSet.size(); ++i) {
mergeTree(infoSink, unit); for (auto it = unit.shiftBindingForSet[i].begin(); it != unit.shiftBindingForSet[i].end(); ++it)
setShiftBindingForSet((TResourceType)i, it->second, it->first);
}
version = std::max(version, unit.version); resourceSetBinding.insert(resourceSetBinding.end(), unit.resourceSetBinding.begin(), unit.resourceSetBinding.end());
requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end()); MERGE_TRUE(autoMapBindings);
MERGE_TRUE(autoMapLocations);
MERGE_TRUE(invertY);
MERGE_TRUE(flattenUniformArrays);
MERGE_TRUE(useUnknownFormat);
MERGE_TRUE(hlslOffsets);
MERGE_TRUE(useStorageBuffer);
MERGE_TRUE(hlslIoMapping);
// TODO: sourceFile
// TODO: sourceText
// TODO: processes
MERGE_TRUE(needToLegalize);
MERGE_TRUE(binaryDoubleOutput);
} }
// //
...@@ -195,8 +254,18 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) ...@@ -195,8 +254,18 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
// and might have overlaps that are not the same symbol, or might have different // and might have overlaps that are not the same symbol, or might have different
// IDs for what should be the same shared symbol. // IDs for what should be the same shared symbol.
// //
void TIntermediate::mergeTree(TInfoSink& infoSink, TIntermediate& unit) void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
{ {
if (unit.treeRoot == nullptr)
return;
if (treeRoot == nullptr) {
treeRoot = unit.treeRoot;
return;
}
// Getting this far means we have two existing trees to merge...
// Get the top-level globals of each unit // Get the top-level globals of each unit
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence(); TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
...@@ -214,6 +283,7 @@ void TIntermediate::mergeTree(TInfoSink& infoSink, TIntermediate& unit) ...@@ -214,6 +283,7 @@ void TIntermediate::mergeTree(TInfoSink& infoSink, TIntermediate& unit)
mergeBodies(infoSink, globals, unitGlobals); mergeBodies(infoSink, globals, unitGlobals);
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects); mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
} }
// 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
...@@ -240,7 +310,7 @@ protected: ...@@ -240,7 +310,7 @@ protected:
int maxId; int maxId;
}; };
// Traverser that seeds an ID map with non-builtin globals. // Traverser that seeds an ID map with non-builtins.
// (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 TUserIdTraverser : public TIntermTraverser { class TUserIdTraverser : public TIntermTraverser {
...@@ -250,7 +320,7 @@ public: ...@@ -250,7 +320,7 @@ public:
virtual void visitSymbol(TIntermSymbol* symbol) virtual void visitSymbol(TIntermSymbol* symbol)
{ {
const TQualifier& qualifier = symbol->getType().getQualifier(); const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.storage == EvqGlobal && qualifier.builtIn == EbvNone) if (qualifier.builtIn == EbvNone)
idMap[symbol->getName()] = symbol->getId(); idMap[symbol->getName()] = symbol->getId();
} }
...@@ -286,7 +356,7 @@ public: ...@@ -286,7 +356,7 @@ public:
{ {
const TQualifier& qualifier = symbol->getType().getQualifier(); const TQualifier& qualifier = symbol->getType().getQualifier();
bool remapped = false; bool remapped = false;
if (qualifier.storage == EvqGlobal || qualifier.builtIn != EbvNone) { if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
auto it = idMap.find(symbol->getName()); auto it = idMap.find(symbol->getName());
if (it != idMap.end()) { if (it != idMap.end()) {
symbol->changeId(it->second); symbol->changeId(it->second);
......
...@@ -645,7 +645,9 @@ protected: ...@@ -645,7 +645,9 @@ protected:
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*); void error(TInfoSink& infoSink, const char*);
void warn(TInfoSink& infoSink, const char*); void warn(TInfoSink& infoSink, const char*);
void mergeTree(TInfoSink&, TIntermediate&); void mergeCallGraphs(TInfoSink&, TIntermediate&);
void mergeModes(TInfoSink&, TIntermediate&);
void mergeTrees(TInfoSink&, TIntermediate&);
void seedIdMap(TMap<TString, int>& idMap, int& maxId); void seedIdMap(TMap<TString, int>& idMap, int& maxId);
void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&); void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
...@@ -677,6 +679,8 @@ protected: ...@@ -677,6 +679,8 @@ protected:
EShSource source; // source language, known a bit later EShSource source; // source language, known a bit later
std::string entryPointName; std::string entryPointName;
std::string entryPointMangledName; std::string entryPointMangledName;
typedef std::list<TCall> TGraph;
TGraph callGraph;
EProfile profile; // source profile EProfile profile; // source profile
int version; // source version int version; // source version
...@@ -706,6 +710,7 @@ protected: ...@@ -706,6 +710,7 @@ protected:
bool hlslFunctionality1; bool hlslFunctionality1;
int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift
bool xfbMode; bool xfbMode;
std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
bool multiStream; bool multiStream;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
...@@ -717,7 +722,7 @@ protected: ...@@ -717,7 +722,7 @@ protected:
std::array<unsigned int, EResCount> shiftBinding; std::array<unsigned int, EResCount> shiftBinding;
// Per-descriptor-set shift values // Per-descriptor-set shift values
std::array<std::map<int, int>, EResCount> shiftBindingForSet; std::array<std::map<int, int>, EResCount> shiftBindingForSet;
std::vector<std::string> resourceSetBinding; std::vector<std::string> resourceSetBinding;
bool autoMapBindings; bool autoMapBindings;
...@@ -729,13 +734,9 @@ protected: ...@@ -729,13 +734,9 @@ protected:
bool useStorageBuffer; bool useStorageBuffer;
bool hlslIoMapping; bool hlslIoMapping;
typedef std::list<TCall> TGraph;
TGraph callGraph;
std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
std::unordered_set<int> usedConstantId; // specialization constant ids used std::unordered_set<int> usedConstantId; // specialization constant ids used
std::set<TString> semanticNameSet; std::set<TString> semanticNameSet;
......
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