1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef COMPILER_OUTPUTASM_H_
16 #define COMPILER_OUTPUTASM_H_
18 #include "intermediate.h"
19 #include "ParseHelper.h"
20 #include "Shader/PixelShader.hpp"
21 #include "Shader/VertexShader.hpp"
32 typedef unsigned int GLenum;
36 struct BlockMemberInfo
38 BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
40 BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
42 arrayStride(arrayStride),
43 matrixStride(matrixStride),
44 isRowMajorMatrix(isRowMajorMatrix)
47 static BlockMemberInfo getDefaultBlockInfo()
49 return BlockMemberInfo(-1, -1, -1, false);
55 bool isRowMajorMatrix;
60 Uniform(GLenum type, GLenum precision, const std::string &name, int arraySize, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo);
70 BlockMemberInfo blockInfo;
73 typedef std::vector<Uniform> ActiveUniforms;
77 UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize,
78 TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId);
81 unsigned int dataSize;
82 unsigned int arraySize;
83 TLayoutBlockStorage layout;
84 bool isRowMajorLayout;
85 std::vector<int> fields;
92 class BlockLayoutEncoder
95 BlockLayoutEncoder(bool rowMajor);
96 virtual ~BlockLayoutEncoder() {}
98 BlockMemberInfo encodeType(const TType &type);
100 size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
102 virtual void enterAggregateType() = 0;
103 virtual void exitAggregateType() = 0;
105 static const size_t BytesPerComponent = 4u;
106 static const unsigned int ComponentsPerRegister = 4u;
108 static size_t getBlockRegister(const BlockMemberInfo &info);
109 static size_t getBlockRegisterElement(const BlockMemberInfo &info);
112 size_t mCurrentOffset;
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;
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
126 Std140BlockEncoder(bool rowMajor);
128 void enterAggregateType() override;
129 void exitAggregateType() override;
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;
136 typedef std::vector<UniformBlock> ActiveUniformBlocks;
141 Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex);
151 typedef std::vector<Attribute> ActiveAttributes;
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)
162 return arraySize >= 1;
165 int size() const // Unify with es2::Uniform?
167 return arraySize > 0 ? arraySize : 1;
174 int reg; // First varying register, assigned during link
175 int col; // First register element, assigned during link
178 typedef std::list<Varying> VaryingList;
182 friend class OutputASM;
184 virtual ~Shader() {};
185 virtual sw::Shader *getShader() const = 0;
186 virtual sw::PixelShader *getPixelShader() const;
187 virtual sw::VertexShader *getVertexShader() const;
188 int getShaderVersion() const { return shaderVersion; }
191 VaryingList varyings;
192 ActiveUniforms activeUniforms;
193 ActiveAttributes activeAttributes;
194 ActiveUniformBlocks activeUniformBlocks;
200 Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
204 Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
210 TIntermSequence *arg;
214 typedef sw::Shader::Instruction Instruction;
218 class OutputASM : public TIntermTraverser
221 explicit OutputASM(TParseContext &context, Shader *shaderObject);
226 void freeTemporary(Temporary *temporary);
235 struct TextureFunction
237 TextureFunction(const TString& name);
241 IMPLICIT, // Mipmap LOD determined implicitly (standard lookup)
243 SIZE, // textureSize()
253 void emitShader(Scope scope);
255 // Visit AST nodes and output their code to the body stream
256 void visitSymbol(TIntermSymbol*) override;
257 bool visitBinary(Visit visit, TIntermBinary*) override;
258 bool visitUnary(Visit visit, TIntermUnary*) override;
259 bool visitSelection(Visit visit, TIntermSelection*) override;
260 bool visitAggregate(Visit visit, TIntermAggregate*) override;
261 bool visitLoop(Visit visit, TIntermLoop*) override;
262 bool visitBranch(Visit visit, TIntermBranch*) override;
263 bool visitSwitch(Visit, TIntermSwitch*) override;
265 sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const;
266 Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0);
267 Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0 = 0, int index0 = 0, TIntermNode *src1 = 0, int index1 = 0,
268 TIntermNode *src2 = 0, int index2 = 0, TIntermNode *src3 = 0, int index3 = 0, TIntermNode *src4 = 0, int index4 = 0);
269 Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src);
270 Instruction *emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex);
271 void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);
272 void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);
273 void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0);
274 void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0);
275 void source(sw::Shader::SourceParameter ¶meter, TIntermNode *argument, int index = 0);
276 void destination(sw::Shader::DestinationParameter ¶meter, TIntermTyped *argument, int index = 0);
277 void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
278 void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
279 void evaluateRvalue(TIntermTyped *node);
280 int lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node);
281 int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node);
282 sw::Shader::ParameterType registerType(TIntermTyped *operand);
283 bool hasFlatQualifier(TIntermTyped *operand);
284 unsigned int registerIndex(TIntermTyped *operand);
285 int writeMask(TIntermTyped *destination, int index = 0);
286 int readSwizzle(TIntermTyped *argument, int size);
287 bool trivial(TIntermTyped *expression, int budget); // Fast to compute and no side effects
288 int cost(TIntermNode *expression, int budget);
289 const Function *findFunction(const TString &name);
291 int temporaryRegister(TIntermTyped *temporary);
292 int varyingRegister(TIntermTyped *varying);
293 void setPixelShaderInputs(const TType& type, int var, bool flat);
294 void declareVarying(TIntermTyped *varying, int reg);
295 void declareVarying(const TType &type, const TString &name, int registerIndex);
296 int uniformRegister(TIntermTyped *uniform);
297 int attributeRegister(TIntermTyped *attribute);
298 int fragmentOutputRegister(TIntermTyped *fragmentOutput);
299 int samplerRegister(TIntermTyped *sampler);
300 int samplerRegister(TIntermSymbol *sampler);
301 bool isSamplerRegister(TIntermTyped *operand);
303 typedef std::vector<TIntermTyped*> VariableArray;
305 int lookup(VariableArray &list, TIntermTyped *variable);
306 int lookup(VariableArray &list, TInterfaceBlock *block);
307 int blockMemberLookup(const TType &type, const TString &name, int registerIndex);
308 int allocate(VariableArray &list, TIntermTyped *variable);
309 void free(VariableArray &list, TIntermTyped *variable);
311 void declareUniform(const TType &type, const TString &name, int registerIndex, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
312 GLenum glVariableType(const TType &type);
313 GLenum glVariablePrecision(const TType &type);
315 static int dim(TIntermNode *v);
316 static int dim2(TIntermNode *m);
317 static unsigned int loopCount(TIntermLoop *node);
319 Shader *const shaderObject;
321 sw::PixelShader *pixelShader;
322 sw::VertexShader *vertexShader;
324 VariableArray temporaries;
325 VariableArray uniforms;
326 VariableArray varyings;
327 VariableArray attributes;
328 VariableArray samplers;
329 VariableArray fragmentOutputs;
331 struct TypedMemberInfo : public BlockMemberInfo
334 TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {}
339 ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) :
340 typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {}
341 TypedMemberInfo typedMemberInfo;
345 int getBlockId(TIntermTyped *argument);
346 ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index);
348 typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap;
349 std::vector<BlockDefinitionIndexMap> blockDefinitions;
355 std::vector<Function> functionArray;
357 TQualifier outputQualifier;
359 TParseContext &mContext;
362 class LoopUnrollable : public TIntermTraverser
365 bool traverse(TIntermNode *node);
368 bool visitBranch(Visit visit, TIntermBranch *node);
369 bool visitLoop(Visit visit, TIntermLoop *loop);
370 bool visitAggregate(Visit visit, TIntermAggregate *node);
377 #endif // COMPILER_OUTPUTASM_H_