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 ¶meter, 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