• 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 ShaderVariable
59 	{
60 		ShaderVariable(const TType& type, const std::string& name, int registerIndex);
61 
62 		GLenum type;
63 		GLenum precision;
64 		std::string name;
65 		int arraySize;
66 
67 		int registerIndex;
68 
69 		std::vector<ShaderVariable> fields;
70 	};
71 
72 	struct Uniform : public ShaderVariable
73 	{
74 		Uniform(const TType& type, const std::string &name, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo);
75 
76 		int blockId;
77 		BlockMemberInfo blockInfo;
78 	};
79 
80 	typedef std::vector<Uniform> ActiveUniforms;
81 
82 	struct UniformBlock
83 	{
84 		UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize,
85 		             TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId);
86 
87 		std::string name;
88 		unsigned int dataSize;
89 		unsigned int arraySize;
90 		TLayoutBlockStorage layout;
91 		bool isRowMajorLayout;
92 		std::vector<int> fields;
93 
94 		int registerIndex;
95 
96 		int blockId;
97 	};
98 
99 	class BlockLayoutEncoder
100 	{
101 	public:
102 		BlockLayoutEncoder();
~BlockLayoutEncoder()103 		virtual ~BlockLayoutEncoder() {}
104 
105 		BlockMemberInfo encodeType(const TType &type);
106 
getBlockSize()107 		size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
108 
109 		virtual void enterAggregateType() = 0;
110 		virtual void exitAggregateType() = 0;
111 
112 		static const size_t BytesPerComponent = 4u;
113 		static const unsigned int ComponentsPerRegister = 4u;
114 
115 		static size_t getBlockRegister(const BlockMemberInfo &info);
116 		static size_t getBlockRegisterElement(const BlockMemberInfo &info);
117 
118 	protected:
119 		size_t mCurrentOffset;
120 
121 		void nextRegister();
122 
123 		virtual void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
124 		virtual void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
125 	};
126 
127 	// Block layout according to the std140 block layout
128 	// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
129 	class Std140BlockEncoder : public BlockLayoutEncoder
130 	{
131 	public:
132 		Std140BlockEncoder();
133 
134 		void enterAggregateType() override;
135 		void exitAggregateType() override;
136 
137 	protected:
138 		void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override;
139 		void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) override;
140 	};
141 
142 	typedef std::vector<UniformBlock> ActiveUniformBlocks;
143 
144 	struct Attribute
145 	{
146 		Attribute();
147 		Attribute(GLenum type, const std::string &name, int arraySize, int layoutLocation, int registerIndex);
148 
149 		GLenum type;
150 		std::string name;
151 		int arraySize;
152 		int layoutLocation;
153 
154 		int registerIndex;
155 	};
156 
157 	typedef std::vector<Attribute> ActiveAttributes;
158 
159 	struct Varying : public ShaderVariable
160 	{
161 		Varying(const TType& type, const std::string &name, int reg = -1, int col = -1)
ShaderVariableVarying162 			: ShaderVariable(type, name, reg), qualifier(type.getQualifier()), column(col)
163 		{
164 		}
165 
isArrayVarying166 		bool isArray() const
167 		{
168 			return arraySize >= 1;
169 		}
170 
sizeVarying171 		int size() const   // Unify with es2::Uniform?
172 		{
173 			return arraySize > 0 ? arraySize : 1;
174 		}
175 
176 		TQualifier qualifier;
177 		int column;    // First register element, assigned during link
178 	};
179 
180 	typedef std::list<Varying> VaryingList;
181 
182 	class Shader
183 	{
184 		friend class OutputASM;
185 	public:
~Shader()186 		virtual ~Shader() {}
187 		virtual sw::Shader *getShader() const = 0;
188 		virtual sw::PixelShader *getPixelShader() const;
189 		virtual sw::VertexShader *getVertexShader() const;
getShaderVersion()190 		int getShaderVersion() const { return shaderVersion; }
191 
192 	protected:
193 		VaryingList varyings;
194 		ActiveUniforms activeUniforms;
195 		ActiveUniforms activeUniformStructs;
196 		ActiveAttributes activeAttributes;
197 		ActiveUniformBlocks activeUniformBlocks;
198 		int shaderVersion;
199 	};
200 
201 	struct Function
202 	{
FunctionFunction203 		Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
204 		{
205 		}
206 
FunctionFunction207 		Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
208 		{
209 		}
210 
211 		int label;
212 		TString name;
213 		TIntermSequence *arg;
214 		TIntermTyped *ret;
215 	};
216 
217 	typedef sw::Shader::Instruction Instruction;
218 
219 	class Temporary;
220 
221 	class OutputASM : public TIntermTraverser
222 	{
223 	public:
224 		explicit OutputASM(TParseContext &context, Shader *shaderObject);
225 		~OutputASM();
226 
227 		void output();
228 
229 		void freeTemporary(Temporary *temporary);
230 
231 	private:
232 		enum Scope
233 		{
234 			GLOBAL,
235 			FUNCTION
236 		};
237 
238 		struct TextureFunction
239 		{
240 			TextureFunction(const TString& name);
241 
242 			enum Method
243 			{
244 				IMPLICIT,   // Mipmap LOD determined implicitly (standard lookup)
245 				LOD,
246 				SIZE,   // textureSize()
247 				FETCH,
248 				GRAD,
249 			};
250 
251 			Method method;
252 			bool proj;
253 			bool offset;
254 		};
255 
256 		void emitShader(Scope scope);
257 
258 		// Visit AST nodes and output their code to the body stream
259 		void visitSymbol(TIntermSymbol*) override;
260 		bool visitBinary(Visit visit, TIntermBinary*) override;
261 		bool visitUnary(Visit visit, TIntermUnary*) override;
262 		bool visitSelection(Visit visit, TIntermSelection*) override;
263 		bool visitAggregate(Visit visit, TIntermAggregate*) override;
264 		bool visitLoop(Visit visit, TIntermLoop*) override;
265 		bool visitBranch(Visit visit, TIntermBranch*) override;
266 		bool visitSwitch(Visit, TIntermSwitch*) override;
267 
268 		sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const;
269 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0);
270 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0 = 0, int index0 = 0, TIntermNode *src1 = 0, int index1 = 0,
271 		                  TIntermNode *src2 = 0, int index2 = 0, TIntermNode *src3 = 0, int index3 = 0, TIntermNode *src4 = 0, int index4 = 0);
272 		Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src);
273 		Instruction *emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex);
274 		void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);
275 		void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);
276 		void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0);
277 		void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0);
278 		void source(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);
279 		void destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *argument, int index = 0);
280 		void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
281 		void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
282 		void evaluateRvalue(TIntermTyped *node);
283 		int lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node);
284 		int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node);
285 		sw::Shader::ParameterType registerType(TIntermTyped *operand);
286 		bool hasFlatQualifier(TIntermTyped *operand);
287 		unsigned int registerIndex(TIntermTyped *operand);
288 		int writeMask(TIntermTyped *destination, int index = 0);
289 		int readSwizzle(TIntermTyped *argument, int size);
290 		bool trivial(TIntermTyped *expression, int budget);   // Fast to compute and no side effects
291 		int cost(TIntermNode *expression, int budget);
292 		const Function *findFunction(const TString &name);
293 
294 		int temporaryRegister(TIntermTyped *temporary);
295 		int varyingRegister(TIntermTyped *varying);
296 		void setPixelShaderInputs(const TType& type, int var, bool flat);
297 		void declareVarying(TIntermTyped *varying, int reg);
298 		void declareVarying(const TType &type, const TString &name, int registerIndex);
299 		void declareFragmentOutput(TIntermTyped *fragmentOutput);
300 		int uniformRegister(TIntermTyped *uniform);
301 		int attributeRegister(TIntermTyped *attribute);
302 		int fragmentOutputRegister(TIntermTyped *fragmentOutput);
303 		int samplerRegister(TIntermTyped *sampler);
304 		int samplerRegister(TIntermSymbol *sampler);
305 		bool isSamplerRegister(TIntermTyped *operand);
306 		bool arrayExceedsLimits(TIntermTyped *operand);
307 
308 		typedef std::vector<TIntermTyped*> VariableArray;
309 
310 		int lookup(VariableArray &list, TIntermTyped *variable);
311 		int lookup(VariableArray &list, TInterfaceBlock *block);
312 		int blockMemberLookup(const TType &type, const TString &name, int registerIndex);
313 		// Returns -1 if it fails to allocate variable.
314 		int allocate(VariableArray &list, TIntermTyped *variable, bool samplersOnly = false);
315 		void free(VariableArray &list, TIntermTyped *variable);
316 
317 		void declareUniform(const TType &type, const TString &name, int registerIndex, bool samplersOnly, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
318 
319 		static int dim(TIntermNode *v);
320 		static int dim2(TIntermNode *m);
321 
322 		struct LoopInfo
323 		{
324 			LoopInfo(TIntermLoop *node);
325 
isDeterministicLoopInfo326 			bool isDeterministic()
327 			{
328 				return (iterations != ~0u);
329 			}
330 
331 			unsigned int iterations = ~0u;
332 
333 			TIntermSymbol *index = nullptr;
334 			TOperator comparator = EOpNull;
335 			int initial = 0;
336 			int limit = 0;
337 			int increment = 0;
338 		};
339 
340 		Shader *const shaderObject;
341 		sw::Shader *shader;
342 		sw::PixelShader *pixelShader;
343 		sw::VertexShader *vertexShader;
344 
345 		VariableArray temporaries;
346 		VariableArray uniforms;
347 		VariableArray varyings;
348 		VariableArray attributes;
349 		VariableArray samplers;
350 		VariableArray fragmentOutputs;
351 
352 		struct TypedMemberInfo : public BlockMemberInfo
353 		{
TypedMemberInfoTypedMemberInfo354 			TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {}
355 			TType type;
356 		};
357 		struct ArgumentInfo
358 		{
ArgumentInfoArgumentInfo359 			ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) :
360 			    typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {}
361 			TypedMemberInfo typedMemberInfo;
362 			int clampedIndex;
363 			int bufferIndex;
364 		};
365 		int getBlockId(TIntermTyped *argument);
366 		ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index);
367 
368 		typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap;
369 		std::vector<BlockDefinitionIndexMap> blockDefinitions;
370 
371 		Scope emitScope;
372 		Scope currentScope;
373 
374 		int currentFunction;
375 		std::vector<Function> functionArray;
376 
377 		TQualifier outputQualifier;
378 
379 		std::set<int> deterministicVariables;
380 
381 		TParseContext &mContext;
382 	};
383 
384 	class LoopUnrollable : public TIntermTraverser
385 	{
386 	public:
387 		bool traverse(TIntermLoop *loop, int loopIndexId);
388 
389 	private:
390 		void visitSymbol(TIntermSymbol *node) override;
391 		bool visitBinary(Visit visit, TIntermBinary *node) override;
392 		bool visitUnary(Visit visit, TIntermUnary *node) override;
393 		bool visitBranch(Visit visit, TIntermBranch *node) override;
394 		bool visitAggregate(Visit visit, TIntermAggregate *node) override;
395 
396 		bool loopUnrollable;
397 
398 		int loopIndexId;
399 	};
400 }
401 
402 #endif   // COMPILER_OUTPUTASM_H_
403