blob: 118b8b41e4221798e8ea0929a0adaaf8ec85f4e8 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// 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
27namespace es2
28{
29 class Shader;
30}
31
32typedef unsigned int GLenum;
33
34namespace glsl
35{
36 struct BlockMemberInfo
37 {
38 BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
39
40 BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
41 : offset(offset),
42 arrayStride(arrayStride),
43 matrixStride(matrixStride),
44 isRowMajorMatrix(isRowMajorMatrix)
45 {}
46
47 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);
96 virtual ~BlockLayoutEncoder() {}
97
98 BlockMemberInfo encodeType(const TType &type);
99
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)
156 : type(type), name(name), arraySize(arraySize), reg(reg), col(col)
157 {
158 }
159
160 bool isArray() const
161 {
162 return arraySize >= 1;
163 }
164
165 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:
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 {
198 Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
199 {
200 }
201
202 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
Nicolas Capens0530b452017-11-15 16:39:47 -0500254 void visitSymbol(TIntermSymbol*) override;
255 bool visitBinary(Visit visit, TIntermBinary*) override;
256 bool visitUnary(Visit visit, TIntermUnary*) override;
257 bool visitSelection(Visit visit, TIntermSelection*) override;
258 bool visitAggregate(Visit visit, TIntermAggregate*) override;
259 bool visitLoop(Visit visit, TIntermLoop*) override;
260 bool visitBranch(Visit visit, TIntermBranch*) override;
261 bool visitSwitch(Visit, TIntermSwitch*) override;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400262
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);
Nicolas Capens0530b452017-11-15 16:39:47 -0500273 void source(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);
274 void destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *argument, int index = 0);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400275 void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
276 void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
Nicolas Capens6986b282017-11-16 10:38:19 -0500277 int lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node);
Nicolas Capens0530b452017-11-15 16:39:47 -0500278 int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400279 sw::Shader::ParameterType registerType(TIntermTyped *operand);
Alexis Hetu12b00502016-05-20 13:01:11 -0400280 bool hasFlatQualifier(TIntermTyped *operand);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400281 unsigned int registerIndex(TIntermTyped *operand);
282 int writeMask(TIntermTyped *destination, int index = 0);
283 int readSwizzle(TIntermTyped *argument, int size);
284 bool trivial(TIntermTyped *expression, int budget); // Fast to compute and no side effects
285 int cost(TIntermNode *expression, int budget);
286 const Function *findFunction(const TString &name);
287
288 int temporaryRegister(TIntermTyped *temporary);
289 int varyingRegister(TIntermTyped *varying);
Alexis Hetu49351232017-11-02 16:00:32 -0400290 void setPixelShaderInputs(const TType& type, int var, bool flat);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400291 void declareVarying(TIntermTyped *varying, int reg);
Alexis Hetu49351232017-11-02 16:00:32 -0400292 void declareVarying(const TType &type, const TString &name, int registerIndex);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400293 int uniformRegister(TIntermTyped *uniform);
294 int attributeRegister(TIntermTyped *attribute);
295 int fragmentOutputRegister(TIntermTyped *fragmentOutput);
296 int samplerRegister(TIntermTyped *sampler);
297 int samplerRegister(TIntermSymbol *sampler);
298 bool isSamplerRegister(TIntermTyped *operand);
299
300 typedef std::vector<TIntermTyped*> VariableArray;
301
302 int lookup(VariableArray &list, TIntermTyped *variable);
303 int lookup(VariableArray &list, TInterfaceBlock *block);
304 int blockMemberLookup(const TType &type, const TString &name, int registerIndex);
305 int allocate(VariableArray &list, TIntermTyped *variable);
306 void free(VariableArray &list, TIntermTyped *variable);
307
308 void declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
309 GLenum glVariableType(const TType &type);
310 GLenum glVariablePrecision(const TType &type);
311
312 static int dim(TIntermNode *v);
313 static int dim2(TIntermNode *m);
314 static unsigned int loopCount(TIntermLoop *node);
315
316 Shader *const shaderObject;
317 sw::Shader *shader;
318 sw::PixelShader *pixelShader;
319 sw::VertexShader *vertexShader;
320
321 VariableArray temporaries;
322 VariableArray uniforms;
323 VariableArray varyings;
324 VariableArray attributes;
325 VariableArray samplers;
326 VariableArray fragmentOutputs;
327
328 struct TypedMemberInfo : public BlockMemberInfo
329 {
330 TypedMemberInfo() {}
331 TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {}
332 TType type;
333 };
334 struct ArgumentInfo
335 {
336 ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) :
337 typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {}
338 TypedMemberInfo typedMemberInfo;
339 int clampedIndex;
340 int bufferIndex;
341 };
342 int getBlockId(TIntermTyped *argument);
343 ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index);
344
345 typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap;
346 std::vector<BlockDefinitionIndexMap> blockDefinitions;
347
348 Scope emitScope;
349 Scope currentScope;
350
351 int currentFunction;
352 std::vector<Function> functionArray;
353
354 TQualifier outputQualifier;
355
356 TParseContext &mContext;
357 };
358
359 class LoopUnrollable : public TIntermTraverser
360 {
361 public:
362 bool traverse(TIntermNode *node);
363
364 private:
365 bool visitBranch(Visit visit, TIntermBranch *node);
366 bool visitLoop(Visit visit, TIntermLoop *loop);
367 bool visitAggregate(Visit visit, TIntermAggregate *node);
368
369 int loopDepth;
370 bool loopUnrollable;
371 };
372}
373
374#endif // COMPILER_OUTPUTASM_H_