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; 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* context, 72 int index, 73 const char* name, 74 const char* sksl, 75 const void* inputs, 76 size_t inputSize); 77 78 const char* name() const override; 79 80 void addChild(std::unique_ptr<GrFragmentProcessor> child); 81 82 std::unique_ptr<GrFragmentProcessor> clone() const override; 83 84 private: 85 GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, int fIndex, 86 const char* name, const char* sksl, const void* inputs, size_t inputSize); 87 88 GrSkSLFP(const GrSkSLFP& other); 89 90 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 91 92 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 93 94 bool onIsEqual(const GrFragmentProcessor&) const override; 95 96 void createFactory() const; 97 98 sk_sp<GrSkSLFPFactoryCache> fFactoryCache; 99 100 const sk_sp<GrShaderCaps> fShaderCaps; 101 102 mutable sk_sp<GrSkSLFPFactory> fFactory; 103 104 int fIndex; 105 106 const char* fName; 107 108 const char* fSkSL; 109 110 const std::unique_ptr<int8_t[]> fInputs; 111 112 size_t fInputSize; 113 114 mutable SkSL::String fKey; 115 116 GR_DECLARE_FRAGMENT_PROCESSOR_TEST 117 118 typedef GrFragmentProcessor INHERITED; 119 120 friend class GrGLSLSkSLFP; 121 122 friend class GrSkSLFPFactory; 123 }; 124 125 /** 126 * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends 127 * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL 128 * string, then use that to create the actual GrFragmentProcessor. 129 */ 130 class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> { 131 public: 132 /** 133 * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will 134 * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause 135 * the produced shaders to differ), so it is important to reuse the same factory instance for 136 * the same shader in order to avoid repeatedly re-parsing the SkSL. 137 */ 138 GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl); 139 140 const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs, 141 size_t inputSize); 142 143 const char* fName; 144 145 SkSL::Compiler fCompiler; 146 147 std::shared_ptr<SkSL::Program> fBaseProgram; 148 149 std::vector<const SkSL::Variable*> fInputVars; 150 151 std::vector<const SkSL::Variable*> fKeyVars; 152 153 std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations; 154 155 friend class GrSkSLFP; 156 }; 157 158 #endif 159