1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SKSL_CODEGENERATOR 9 #define SKSL_CODEGENERATOR 10 11 #include "src/sksl/SkSLContext.h" 12 #include "src/sksl/SkSLOutputStream.h" 13 #include "src/sksl/ir/SkSLProgram.h" 14 15 namespace SkSL { 16 17 struct ShaderCaps; 18 19 /** 20 * Abstract superclass of all code generators, which take a Program as input and produce code as 21 * output. 22 */ 23 class CodeGenerator { 24 public: CodeGenerator(const Context * context,const ShaderCaps * caps,const Program * program,OutputStream * stream)25 CodeGenerator(const Context* context, 26 const ShaderCaps* caps, 27 const Program* program, 28 OutputStream* stream) 29 : fProgram(*program) 30 , fContext(fProgram.fContext->fTypes, *fProgram.fContext->fErrors) 31 , fCaps(*caps) 32 , fOut(stream) { 33 fContext.fConfig = fProgram.fConfig.get(); 34 fContext.fModule = fProgram.fContext->fModule; 35 fContext.fSymbolTable = fProgram.fSymbols.get(); 36 } 37 38 virtual ~CodeGenerator() = default; 39 40 virtual bool generateCode() = 0; 41 42 // Intended for use by AutoOutputStream. outputStream()43 OutputStream* outputStream() { return fOut; } setOutputStream(OutputStream * output)44 void setOutputStream(OutputStream* output) { fOut = output; } 45 46 protected: 47 #if defined(SK_USE_LEGACY_MIPMAP_LOD_BIAS) 48 static constexpr float kSharpenTexturesBias = -.5f; 49 #else 50 // For SkMipmapMode::kLinear we want a bias such that when the unbiased LOD value is 51 // midway between levels we select just the larger level, i.e. a bias of -.5. However, using 52 // this bias with kNearest mode with a draw that is a perfect power of two downscale puts us 53 // right on the rounding edge where it could go up or down depending on the particular GPU. 54 // Experimentally we found that at -.49 most iOS devices (iPhone 7, 8, and iPad Pro 55 // [PowerVRGT7800 version]) all round to the level twice as big as the device space footprint 56 // for some such draws in our unit tests on GLES. However, the iPhone 11 still fails and so 57 // we are using -.475. They do not at -.48. All other GPUs passed tests with -.499. Though, at 58 // this time the bias is not implemented in the MSL codegen and so iOS/Metal was not tested. 59 static constexpr float kSharpenTexturesBias = -.475f; 60 #endif 61 62 const Program& fProgram; 63 Context fContext; 64 const ShaderCaps& fCaps; 65 OutputStream* fOut; 66 }; 67 68 class AutoOutputStream { 69 public: 70 // Maintains the current indentation level while writing to the new output stream. AutoOutputStream(CodeGenerator * codeGen,OutputStream * newOutput)71 AutoOutputStream(CodeGenerator* codeGen, OutputStream* newOutput) 72 : fCodeGen(codeGen) 73 , fOldOutput(codeGen->outputStream()) { 74 fCodeGen->setOutputStream(newOutput); 75 } 76 // Resets the indentation when entering the scope, and restores it when leaving. AutoOutputStream(CodeGenerator * codeGen,OutputStream * newOutput,int * indentationPtr)77 AutoOutputStream(CodeGenerator* codeGen, OutputStream* newOutput, int *indentationPtr) 78 : fCodeGen(codeGen) 79 , fOldOutput(codeGen->outputStream()) 80 , fIndentationPtr(indentationPtr) 81 , fOldIndentation(indentationPtr ? *indentationPtr : 0) { 82 fCodeGen->setOutputStream(newOutput); 83 *fIndentationPtr = 0; 84 } ~AutoOutputStream()85 ~AutoOutputStream() { 86 fCodeGen->setOutputStream(fOldOutput); 87 if (fIndentationPtr) { 88 *fIndentationPtr = fOldIndentation; 89 } 90 } 91 92 private: 93 CodeGenerator* fCodeGen = nullptr; 94 OutputStream* fOldOutput = nullptr; 95 int *fIndentationPtr = nullptr; 96 int fOldIndentation = 0; 97 }; 98 99 } // namespace SkSL 100 101 #endif 102