1 /* 2 * Copyright 2018 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 GrSkSLFP_DEFINED 9 #define GrSkSLFP_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "src/gpu/GrCaps.h" 13 #include "src/gpu/GrCoordTransform.h" 14 #include "src/gpu/GrFragmentProcessor.h" 15 #include "src/gpu/GrShaderCaps.h" 16 #include "src/gpu/GrSkSLFPFactoryCache.h" 17 #include "src/sksl/SkSLCompiler.h" 18 #include "src/sksl/SkSLPipelineStageCodeGenerator.h" 19 #include <atomic> 20 21 #if GR_TEST_UTILS 22 #define GR_FP_SRC_STRING const char* 23 #else 24 #define GR_FP_SRC_STRING static const char* 25 #endif 26 27 class GrContext_Base; 28 class GrSkSLFPFactory; 29 30 class GrSkSLFP : public GrFragmentProcessor { 31 public: 32 /** 33 * Returns a new unique identifier. Each different SkSL fragment processor should call 34 * NewIndex once, statically, and use this index for all calls to Make. 35 */ NewIndex()36 static int NewIndex() { 37 static std::atomic<int> nextIndex{0}; 38 return nextIndex++; 39 } 40 41 /** 42 * Creates a new fragment processor from an SkSL source string and a struct of inputs to the 43 * program. The input struct's type is derived from the 'in' variables in the SkSL source, so 44 * e.g. the shader: 45 * 46 * in bool dither; 47 * in float x; 48 * in float y; 49 * .... 50 * 51 * would expect a pointer to a struct set up like: 52 * 53 * struct { 54 * bool dither; 55 * float x; 56 * float y; 57 * }; 58 * 59 * As turning SkSL into GLSL / SPIR-V / etc. is fairly expensive, and the output may differ 60 * based on the inputs, internally the process is divided into two steps: we first parse and 61 * semantically analyze the SkSL into an internal representation, and then "specialize" this 62 * internal representation based on the inputs. The unspecialized internal representation of 63 * the program is cached, so further specializations of the same code are much faster than the 64 * first call. 65 * 66 * This caching is based on the 'index' parameter, which should be derived by statically calling 67 * 'NewIndex()'. Each given SkSL string should have a single, statically defined index 68 * associated with it. 69 */ 70 static std::unique_ptr<GrSkSLFP> Make( 71 GrContext_Base* context, 72 int index, 73 const char* name, 74 const char* sksl, 75 const void* inputs, 76 size_t inputSize, 77 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind, 78 const SkMatrix* matrix = nullptr); 79 80 static std::unique_ptr<GrSkSLFP> Make( 81 GrContext_Base* context, 82 int index, 83 const char* name, 84 SkString sksl, 85 const void* inputs, 86 size_t inputSize, 87 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind, 88 const SkMatrix* matrix = nullptr); 89 90 const char* name() const override; 91 92 void addChild(std::unique_ptr<GrFragmentProcessor> child); 93 94 std::unique_ptr<GrFragmentProcessor> clone() const override; 95 96 private: 97 GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, 98 SkSL::Program::Kind kind, int fIndex, const char* name, const char* sksl, 99 SkString skslString, const void* inputs, size_t inputSize, const SkMatrix* matrix); 100 101 GrSkSLFP(const GrSkSLFP& other); 102 103 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 104 105 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 106 107 bool onIsEqual(const GrFragmentProcessor&) const override; 108 109 void createFactory() const; 110 111 sk_sp<GrSkSLFPFactoryCache> fFactoryCache; 112 113 const sk_sp<GrShaderCaps> fShaderCaps; 114 115 mutable sk_sp<GrSkSLFPFactory> fFactory; 116 117 SkSL::Program::Kind fKind; 118 119 int fIndex; 120 121 const char* fName; 122 123 // For object lifetime purposes, we have fields for the SkSL as both a const char* and a 124 // SkString. The const char* is the one we actually use, but it may point to the SkString's 125 // bytes. Since GrSkSLFPs are frequently created from constant strings, this allows us to 126 // generally avoid the overhead of copying the bytes into an SkString (in which case fSkSLString 127 // is the empty string), while still allowing the GrSkSLFP to manage the string's lifetime when 128 // needed. 129 SkString fSkSLString; 130 131 const char* fSkSL; 132 133 const std::unique_ptr<int8_t[]> fInputs; 134 135 size_t fInputSize; 136 137 GrCoordTransform fCoordTransform; 138 139 mutable SkSL::String fKey; 140 141 GR_DECLARE_FRAGMENT_PROCESSOR_TEST 142 143 typedef GrFragmentProcessor INHERITED; 144 145 friend class GrGLSLSkSLFP; 146 147 friend class GrSkSLFPFactory; 148 }; 149 150 /** 151 * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends 152 * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL 153 * string, then use that to create the actual GrFragmentProcessor. 154 */ 155 class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> { 156 public: 157 /** 158 * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will 159 * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause 160 * the produced shaders to differ), so it is important to reuse the same factory instance for 161 * the same shader in order to avoid repeatedly re-parsing the SkSL. 162 */ 163 GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl, 164 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind); 165 166 const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs, 167 size_t inputSize); 168 169 SkSL::Program::Kind fKind; 170 171 const char* fName; 172 173 SkSL::Compiler fCompiler; 174 175 std::shared_ptr<SkSL::Program> fBaseProgram; 176 177 std::vector<const SkSL::Variable*> fInputVars; 178 179 std::vector<const SkSL::Variable*> fKeyVars; 180 181 std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations; 182 183 friend class GrSkSLFP; 184 }; 185 186 #endif 187