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 // For SkMipmapMode::kLinear we want a bias such that when the unbiased LOD value is 48 // midway between levels we select just the larger level, i.e. a bias of -.5. However, using 49 // this bias with kNearest mode with a draw that is a perfect power of two downscale puts us 50 // right on the rounding edge where it could go up or down depending on the particular GPU. 51 // Experimentally we found that at -.49 most iOS devices (iPhone 7, 8, and iPad Pro 52 // [PowerVRGT7800 version]) all round to the level twice as big as the device space footprint 53 // for some such draws in our unit tests on GLES. However, the iPhone 11 still fails and so 54 // we are using -.475. They do not at -.48. All other GPUs passed tests with -.499. Though, at 55 // this time the bias is not implemented in the MSL codegen and so iOS/Metal was not tested. 56 static constexpr float kSharpenTexturesBias = -.475f; 57 58 const Program& fProgram; 59 Context fContext; 60 const ShaderCaps& fCaps; 61 OutputStream* fOut; 62 }; 63 64 class AutoOutputStream { 65 public: 66 // Maintains the current indentation level while writing to the new output stream. AutoOutputStream(CodeGenerator * codeGen,OutputStream * newOutput)67 AutoOutputStream(CodeGenerator* codeGen, OutputStream* newOutput) 68 : fCodeGen(codeGen) 69 , fOldOutput(codeGen->outputStream()) { 70 fCodeGen->setOutputStream(newOutput); 71 } 72 // Resets the indentation when entering the scope, and restores it when leaving. AutoOutputStream(CodeGenerator * codeGen,OutputStream * newOutput,int * indentationPtr)73 AutoOutputStream(CodeGenerator* codeGen, OutputStream* newOutput, int *indentationPtr) 74 : fCodeGen(codeGen) 75 , fOldOutput(codeGen->outputStream()) 76 , fIndentationPtr(indentationPtr) 77 , fOldIndentation(indentationPtr ? *indentationPtr : 0) { 78 fCodeGen->setOutputStream(newOutput); 79 *fIndentationPtr = 0; 80 } ~AutoOutputStream()81 ~AutoOutputStream() { 82 fCodeGen->setOutputStream(fOldOutput); 83 if (fIndentationPtr) { 84 *fIndentationPtr = fOldIndentation; 85 } 86 } 87 88 private: 89 CodeGenerator* fCodeGen = nullptr; 90 OutputStream* fOldOutput = nullptr; 91 int *fIndentationPtr = nullptr; 92 int fOldIndentation = 0; 93 }; 94 95 } // namespace SkSL 96 97 #endif 98