• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef COMPILER_OUTPUTASM_H_
16 #define COMPILER_OUTPUTASM_H_
17 
18 #include "intermediate.h"
19 #include "ParseHelper.h"
20 #include "Shader/PixelShader.hpp"
21 #include "Shader/VertexShader.hpp"
22 
23 #include <list>
24 #include <set>
25 #include <map>
26 
27 namespace es2
28 {
29 	class Shader;
30 }
31 
32 typedef unsigned int GLenum;
33 
34 namespace glsl
35 {
36 	struct BlockMemberInfo
37 	{
BlockMemberInfoBlockMemberInfo38 		BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
39 
BlockMemberInfoBlockMemberInfo40 		BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
41 			: offset(offset),
42 			arrayStride(arrayStride),
43 			matrixStride(matrixStride),
44 			isRowMajorMatrix(isRowMajorMatrix)
45 		{}
46 
getDefaultBlockInfoBlockMemberInfo47 		static BlockMemberInfo getDefaultBlockInfo()
48 		{
49 			return BlockMemberInfo(-1, -1, -1, false);
50 		}
51 
52 		int offset;
53 		int arrayStride;
54 		int matrixStride;
55 		bool isRowMajorMatrix;
56 	};
57 
58 	struct Uniform
59 	{
60 		Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo);
61 
62 		GLenum type;
63 		GLenum precision;
64 		std::string name;
65 		int arraySize;
66 
67 		int registerIndex;
68 
69 		int blockId;
70 		BlockMemberInfo blockInfo;
71 	};
72 
73 	typedef std::vector<Uniform> ActiveUniforms;
74 
75 	struct UniformBlock
76 	{
77 		UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize,
78 		             TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId);
79 
80 		std::string name;
81 		unsigned int dataSize;
82 		unsigned int arraySize;
83 		TLayoutBlockStorage layout;
84 		bool isRowMajorLayout;
85 		std::vector<int> fields;
86 
87 		int registerIndex;
88 
89 		int blockId;
90 	};
91 
92 	class BlockLayoutEncoder
93 	{
94 	public:
95 		BlockLayoutEncoder(bool rowMajor);
~BlockLayoutEncoder()96 		virtual ~BlockLayoutEncoder() {}
97 
98 		BlockMemberInfo encodeType(const TType &type);
99 
getBlockSize()100 		size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
101 
102 		virtual void enterAggregateType() = 0;
103 		virtual void exitAggregateType() = 0;
104 
105 		static const size_t BytesPerComponent = 4u;
106 		static const unsigned int ComponentsPerRegister = 4u;
107 
108 		static size_t getBlockRegister(const BlockMemberInfo &info);
109 		static size_t getBlockRegisterElement(const BlockMemberInfo &info);
110 
111 	protected:
112 		size_t mCurrentOffset;
113 		bool isRowMajor;
114 
115 		void nextRegister();
116 
117 		virtual void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
118 		virtual void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
119 	};
120 
121 	// Block layout according to the std140 block layout
122 	// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
123 	class Std140BlockEncoder : public BlockLayoutEncoder
124 	{
125 	public:
126 		Std140BlockEncoder(bool rowMajor);
127 
128 		void enterAggregateType() override;
129 		void exitAggregateType() override;
130 
131 	protected:
132 		void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override;
133 		void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) override;
134 	};
135 
136 	typedef std::vector<UniformBlock> ActiveUniformBlocks;
137 
138 	struct Attribute
139 	{
140 		Attribute();
141 		Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex);
142 
143 		GLenum type;
144 		std::string name;
145 		int arraySize;
146 		int location;
147 
148 		int registerIndex;
149 	};
150 
151 	typedef std::vector<Attribute> ActiveAttributes;
152 
153 	struct Varying
154 	{
155 		Varying(GLenum type, const std::string &name, int arraySize, int reg = -1, int col = -1)
typeVarying156 			: type(type), name(name), arraySize(arraySize), reg(reg), col(col)
157 		{
158 		}
159 
isArrayVarying160 		bool isArray() const
161 		{
162 			return arraySize >= 1;
163 		}
164 
sizeVarying165 		int size() const   // Unify with es2::Uniform?
166 		{
167 			return arraySize > 0 ? arraySize : 1;
168 		}
169 
170 		GLenum type;
171 		std::string name;
172 		int arraySize;
173 
174 		int reg;    // First varying register, assigned during link
175 		int col;    // First register element, assigned during link
176 	};
177 
178 	typedef std::list<Varying> VaryingList;
179 
180 	class Shader
181 	{
182 		friend class OutputASM;
183 	public:
~Shader()184 		virtual ~Shader() {};
185 		virtual sw::Shader *getShader() const = 0;
186 		virtual sw::PixelShader *getPixelShader() const;
187 		virtual sw::VertexShader *getVertexShader() const;
188 
189 	protected:
190 		VaryingList varyings;
191 		ActiveUniforms activeUniforms;
192 		ActiveAttributes activeAttributes;
193 		ActiveUniformBlocks activeUniformBlocks;
194 	};
195 
196 	struct Function
197 	{
FunctionFunction198 		Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
199 		{
200 		}
201 
FunctionFunction202 		Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
203 		{
204 		}
205 
206 		int label;
207 		TString name;
208 		TIntermSequence *arg;
209 		TIntermTyped *ret;
210 	};
211 
212 	typedef sw::Shader::Instruction Instruction;
213 
214 	class Temporary;
215 
216 	class OutputASM : public TIntermTraverser
217 	{
218 	public:
219 		explicit OutputASM(TParseContext &context, Shader *shaderObject);
220 		~OutputASM();
221 
222 		void output();
223 
224 		void freeTemporary(Temporary *temporary);
225 
226 	private:
227 		enum Scope
228 		{
229 			GLOBAL,
230 			FUNCTION
231 		};
232 
233 		struct TextureFunction
234 		{
235 			TextureFunction(const TString& name);
236 
237 			enum Method
238 			{
239 				IMPLICIT,   // Mipmap LOD determined implicitly (standard lookup)
240 				LOD,
241 				SIZE,   // textureSize()
242 				FETCH,
243 				GRAD
244 			};
245 
246 			Method method;
247 			bool proj;
248 			bool offset;
249 		};
250 
251 		void emitShader(Scope scope);
252 
253 		// Visit AST nodes and output their code to the body stream
254 		virtual void visitSymbol(TIntermSymbol*);
255 		virtual bool visitBinary(Visit visit, TIntermBinary*);
256 		virtual bool visitUnary(Visit visit, TIntermUnary*);
257 		virtual bool visitSelection(Visit visit, TIntermSelection*);
258 		virtual bool visitAggregate(Visit visit, TIntermAggregate*);
259 		virtual bool visitLoop(Visit visit, TIntermLoop*);
260 		virtual bool visitBranch(Visit visit, TIntermBranch*);
261 		virtual bool visitSwitch(Visit, TIntermSwitch*);
262 
263 		sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const;
264 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0);
265 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0 = 0, int index0 = 0, TIntermNode *src1 = 0, int index1 = 0,
266 		                  TIntermNode *src2 = 0, int index2 = 0, TIntermNode *src3 = 0, int index3 = 0, TIntermNode *src4 = 0, int index4 = 0);
267 		Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src);
268 		Instruction *emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex);
269 		void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);
270 		void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);
271 		void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0);
272 		void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0);
273 		void argument(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);
274 		void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
275 		void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
276 		int lvalue(sw::Shader::DestinationParameter &dst, Temporary &address, TIntermTyped *node);
277 		sw::Shader::ParameterType registerType(TIntermTyped *operand);
278 		bool hasFlatQualifier(TIntermTyped *operand);
279 		unsigned int registerIndex(TIntermTyped *operand);
280 		int writeMask(TIntermTyped *destination, int index = 0);
281 		int readSwizzle(TIntermTyped *argument, int size);
282 		bool trivial(TIntermTyped *expression, int budget);   // Fast to compute and no side effects
283 		int cost(TIntermNode *expression, int budget);
284 		const Function *findFunction(const TString &name);
285 
286 		int temporaryRegister(TIntermTyped *temporary);
287 		int varyingRegister(TIntermTyped *varying);
288 		void declareVarying(TIntermTyped *varying, int reg);
289 		int uniformRegister(TIntermTyped *uniform);
290 		int attributeRegister(TIntermTyped *attribute);
291 		int fragmentOutputRegister(TIntermTyped *fragmentOutput);
292 		int samplerRegister(TIntermTyped *sampler);
293 		int samplerRegister(TIntermSymbol *sampler);
294 		bool isSamplerRegister(TIntermTyped *operand);
295 
296 		typedef std::vector<TIntermTyped*> VariableArray;
297 
298 		int lookup(VariableArray &list, TIntermTyped *variable);
299 		int lookup(VariableArray &list, TInterfaceBlock *block);
300 		int blockMemberLookup(const TType &type, const TString &name, int registerIndex);
301 		int allocate(VariableArray &list, TIntermTyped *variable);
302 		void free(VariableArray &list, TIntermTyped *variable);
303 
304 		void declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
305 		GLenum glVariableType(const TType &type);
306 		GLenum glVariablePrecision(const TType &type);
307 
308 		static int dim(TIntermNode *v);
309 		static int dim2(TIntermNode *m);
310 		static unsigned int loopCount(TIntermLoop *node);
311 
312 		Shader *const shaderObject;
313 		sw::Shader *shader;
314 		sw::PixelShader *pixelShader;
315 		sw::VertexShader *vertexShader;
316 
317 		VariableArray temporaries;
318 		VariableArray uniforms;
319 		VariableArray varyings;
320 		VariableArray attributes;
321 		VariableArray samplers;
322 		VariableArray fragmentOutputs;
323 
324 		struct TypedMemberInfo : public BlockMemberInfo
325 		{
TypedMemberInfoTypedMemberInfo326 			TypedMemberInfo() {}
TypedMemberInfoTypedMemberInfo327 			TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {}
328 			TType type;
329 		};
330 		struct ArgumentInfo
331 		{
ArgumentInfoArgumentInfo332 			ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) :
333 			    typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {}
334 			TypedMemberInfo typedMemberInfo;
335 			int clampedIndex;
336 			int bufferIndex;
337 		};
338 		int getBlockId(TIntermTyped *argument);
339 		ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index);
340 
341 		typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap;
342 		std::vector<BlockDefinitionIndexMap> blockDefinitions;
343 
344 		Scope emitScope;
345 		Scope currentScope;
346 
347 		int currentFunction;
348 		std::vector<Function> functionArray;
349 
350 		TQualifier outputQualifier;
351 
352 		TParseContext &mContext;
353 	};
354 
355 	class LoopUnrollable : public TIntermTraverser
356 	{
357 	public:
358 		bool traverse(TIntermNode *node);
359 
360 	private:
361 		bool visitBranch(Visit visit, TIntermBranch *node);
362 		bool visitLoop(Visit visit, TIntermLoop *loop);
363 		bool visitAggregate(Visit visit, TIntermAggregate *node);
364 
365 		int loopDepth;
366 		bool loopUnrollable;
367 	};
368 }
369 
370 #endif   // COMPILER_OUTPUTASM_H_
371