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 ¶meter, TIntermNode *argument, int index = 0); 279 void destination(sw::Shader::DestinationParameter ¶meter, 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