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 "GrCaps.h" 12 #include "GrFragmentProcessor.h" 13 #include "GrCoordTransform.h" 14 #include "GrShaderCaps.h" 15 #include "SkSLCompiler.h" 16 #include "SkSLPipelineStageCodeGenerator.h" 17 #include "SkRefCnt.h" 18 #include "../private/GrSkSLFPFactoryCache.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 78 static std::unique_ptr<GrSkSLFP> Make( 79 GrContext_Base* context, 80 int index, 81 const char* name, 82 SkString sksl, 83 const void* inputs, 84 size_t inputSize); 85 86 const char* name() const override; 87 88 void addChild(std::unique_ptr<GrFragmentProcessor> child); 89 90 std::unique_ptr<GrFragmentProcessor> clone() const override; 91 92 private: 93 GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, int fIndex, 94 const char* name, const char* sksl, SkString skslString, const void* inputs, 95 size_t inputSize); 96 97 GrSkSLFP(const GrSkSLFP& other); 98 99 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 100 101 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 102 103 bool onIsEqual(const GrFragmentProcessor&) const override; 104 105 void createFactory() const; 106 107 sk_sp<GrSkSLFPFactoryCache> fFactoryCache; 108 109 const sk_sp<GrShaderCaps> fShaderCaps; 110 111 mutable sk_sp<GrSkSLFPFactory> fFactory; 112 113 int fIndex; 114 115 const char* fName; 116 117 // For object lifetime purposes, we have fields for the SkSL as both a const char* and a 118 // SkString. The const char* is the one we actually use, but it may point to the SkString's 119 // bytes. Since GrSkSLFPs are frequently created from constant strings, this allows us to 120 // generally avoid the overhead of copying the bytes into an SkString (in which case fSkSLString 121 // is the empty string), while still allowing the GrSkSLFP to manage the string's lifetime when 122 // needed. 123 SkString fSkSLString; 124 125 const char* fSkSL; 126 127 const std::unique_ptr<int8_t[]> fInputs; 128 129 size_t fInputSize; 130 131 mutable SkSL::String fKey; 132 133 GR_DECLARE_FRAGMENT_PROCESSOR_TEST 134 135 typedef GrFragmentProcessor INHERITED; 136 137 friend class GrGLSLSkSLFP; 138 139 friend class GrSkSLFPFactory; 140 }; 141 142 /** 143 * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends 144 * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL 145 * string, then use that to create the actual GrFragmentProcessor. 146 */ 147 class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> { 148 public: 149 /** 150 * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will 151 * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause 152 * the produced shaders to differ), so it is important to reuse the same factory instance for 153 * the same shader in order to avoid repeatedly re-parsing the SkSL. 154 */ 155 GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl); 156 157 const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs, 158 size_t inputSize); 159 160 const char* fName; 161 162 SkSL::Compiler fCompiler; 163 164 std::shared_ptr<SkSL::Program> fBaseProgram; 165 166 std::vector<const SkSL::Variable*> fInputVars; 167 168 std::vector<const SkSL::Variable*> fKeyVars; 169 170 std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations; 171 172 friend class GrSkSLFP; 173 }; 174 175 #endif 176