2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
9 // Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
12 // Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
17 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
35 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_
36 #define _LOCAL_INTERMEDIATE_INCLUDED_
38 #include "../Include/intermediate.h"
39 #include "../Public/ShaderLang.h"
49 struct TVectorFields {
55 // Some helper structures for TIntermediate. Their contents are encapsulated
59 // Used for detecting recursion: A "call" is a pair: <caller, callee>.
61 TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
69 // A generic 1-D range.
71 TRange(int start, int last) : start(start), last(last) { }
72 bool overlap(const TRange& rhs) const
74 return last >= rhs.start && start <= rhs.last;
80 // An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
81 // within the same location range, component range, and index value. Locations don't alias unless
82 // all other dimensions of their range overlap.
84 TIoRange(TRange location, TRange component, TBasicType basicType, int index)
85 : location(location), component(component), basicType(basicType), index(index) { }
86 bool overlap(const TIoRange& rhs) const
88 return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
96 // An IO range is a 2-D rectangle; the set of (binding, offset) pairs all lying
97 // within the same binding and offset range.
99 TOffsetRange(TRange binding, TRange offset)
100 : binding(binding), offset(offset) { }
101 bool overlap(const TOffsetRange& rhs) const
103 return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
109 // Things that need to be tracked per xfb buffer.
111 TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { }
112 std::vector<TRange> ranges; // byte offsets that have already been assigned
114 unsigned int implicitStride;
123 // Set of helper functions to help parse and build the tree.
125 class TIntermediate {
127 explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v),
128 numMains(0), numErrors(0), recursive(false),
129 invocations(0), vertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),
130 vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), xfbMode(false)
135 xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
137 void setLimits(const TBuiltInResource& r) { resources = r; }
139 bool postProcess(TIntermNode*, EShLanguage);
140 void output(TInfoSink&, bool tree);
143 void setVersion(int v) { version = v; }
144 int getVersion() const { return version; }
145 void setProfile(EProfile p) { profile = p; }
146 EProfile getProfile() const { return profile; }
147 EShLanguage getStage() const { return language; }
148 void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
149 const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
151 void setTreeRoot(TIntermNode* r) { treeRoot = r; }
152 TIntermNode* getTreeRoot() const { return treeRoot; }
153 void addMainCount() { ++numMains; }
154 int getNumMains() const { return numMains; }
155 int getNumErrors() const { return numErrors; }
156 bool isRecursive() const { return recursive; }
158 TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
159 TIntermSymbol* addSymbol(const TVariable&, TSourceLoc);
160 TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
161 TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
162 TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
163 TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
164 TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
165 TIntermTyped* addBuiltInFunctionCall(TSourceLoc line, TOperator, bool unary, TIntermNode*, const TType& returnType);
166 bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
167 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
168 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
169 TIntermAggregate* makeAggregate(TIntermNode* node);
170 TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
171 TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
172 bool areAllChildConst(TIntermAggregate* aggrNode);
173 TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
174 TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
175 TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
176 TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
177 TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc, bool literal = false) const;
178 TIntermConstantUnion* addConstantUnion(int, TSourceLoc, bool literal = false) const;
179 TIntermConstantUnion* addConstantUnion(unsigned int, TSourceLoc, bool literal = false) const;
180 TIntermConstantUnion* addConstantUnion(bool, TSourceLoc, bool literal = false) const;
181 TIntermConstantUnion* addConstantUnion(double, TBasicType, TSourceLoc, bool literal = false) const;
182 TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
183 bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
184 TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
185 TIntermBranch* addBranch(TOperator, TSourceLoc);
186 TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
187 TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
189 // Constant folding (in Constant.cpp)
190 TIntermTyped* fold(TIntermAggregate* aggrNode);
191 TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
192 TIntermTyped* foldDereference(TIntermTyped* node, int index, TSourceLoc);
193 TIntermTyped* foldSwizzle(TIntermTyped* node, TVectorFields& fields, TSourceLoc);
196 void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
197 void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
198 void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
200 bool setInvocations(int i)
203 return invocations == i;
207 int getInvocations() const { return invocations; }
208 bool setVertices(int m)
211 return vertices == m;
215 int getVertices() const { return vertices; }
216 bool setInputPrimitive(TLayoutGeometry p)
218 if (inputPrimitive != ElgNone)
219 return inputPrimitive == p;
223 TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
224 bool setVertexSpacing(TVertexSpacing s)
226 if (vertexSpacing != EvsNone)
227 return vertexSpacing == s;
231 TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
232 bool setVertexOrder(TVertexOrder o)
234 if (vertexOrder != EvoNone)
235 return vertexOrder == o;
239 TVertexOrder getVertexOrder() const { return vertexOrder; }
240 void setPointMode() { pointMode = true; }
241 bool getPointMode() const { return pointMode; }
243 bool setLocalSize(int dim, int size)
245 if (localSize[dim] > 1)
246 return size == localSize[dim];
247 localSize[dim] = size;
250 unsigned int getLocalSize(int dim) const { return localSize[dim]; }
252 void setXfbMode() { xfbMode = true; }
253 bool getXfbMode() const { return xfbMode; }
254 bool setOutputPrimitive(TLayoutGeometry p)
256 if (outputPrimitive != ElgNone)
257 return outputPrimitive == p;
261 TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
262 void setOriginUpperLeft() { originUpperLeft = true; }
263 bool getOriginUpperLeft() const { return originUpperLeft; }
264 void setPixelCenterInteger() { pixelCenterInteger = true; }
265 bool getPixelCenterInteger() const { return pixelCenterInteger; }
266 void setEarlyFragmentTests() { earlyFragmentTests = true; }
267 bool getEarlyFragmentTests() const { return earlyFragmentTests; }
268 bool setDepth(TLayoutDepth d)
270 if (depthLayout != EldNone)
271 return depthLayout == d;
275 TLayoutDepth getDepth() const { return depthLayout; }
277 void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
278 void merge(TInfoSink&, TIntermediate&);
279 void finalCheck(TInfoSink&);
281 void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
282 bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
284 int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
285 int addUsedOffsets(int binding, int offset, int numOffsets);
286 int computeTypeLocationSize(const TType&) const;
288 bool setXfbBufferStride(int buffer, unsigned stride)
290 if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
291 return xfbBuffers[buffer].stride == stride;
292 xfbBuffers[buffer].stride = stride;
295 int addXfbBufferOffset(const TType&);
296 unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
297 static int getBaseAlignment(const TType&, int& size, bool std140);
300 void error(TInfoSink& infoSink, const char*);
301 void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
302 void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
303 void mergeImplicitArraySizes(TType&, const TType&);
304 void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
305 void checkCallGraphCycles(TInfoSink&);
306 void inOutLocationCheck(TInfoSink&);
307 TIntermSequence& findLinkerObjects() const;
308 bool userOutputUsed() const;
309 static int getBaseAlignmentScalar(const TType&, int& size);
311 const EShLanguage language;
312 TIntermNode* treeRoot;
315 std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
316 TBuiltInResource resources;
322 TLayoutGeometry inputPrimitive;
323 TLayoutGeometry outputPrimitive;
324 bool pixelCenterInteger;
325 bool originUpperLeft;
326 TVertexSpacing vertexSpacing;
327 TVertexOrder vertexOrder;
330 bool earlyFragmentTests;
331 TLayoutDepth depthLayout;
334 typedef std::list<TCall> TGraph;
337 std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
338 std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
339 std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
340 std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
343 void operator=(TIntermediate&); // prevent assignments
346 } // end namespace glslang
348 #endif // _LOCAL_INTERMEDIATE_INCLUDED_