| 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 "include/gpu/GrContextOptions.h" |
| 13 | #include "src/gpu/GrCaps.h" |
| 14 | #include "src/gpu/GrCoordTransform.h" |
| 15 | #include "src/gpu/GrFragmentProcessor.h" |
| 16 | #include "src/sksl/SkSLCompiler.h" |
| 17 | #include "src/sksl/SkSLPipelineStageCodeGenerator.h" |
| 18 | #include <atomic> |
| 19 | |
| 20 | #if GR_TEST_UTILS |
| 21 | #define GR_FP_SRC_STRING const char* |
| 22 | #else |
| 23 | #define GR_FP_SRC_STRING static const char* |
| 24 | #endif |
| 25 | |
| 26 | class GrContext_Base; |
| 27 | class GrShaderCaps; |
| 28 | class SkData; |
| 29 | class SkRuntimeEffect; |
| 30 | |
| 31 | class GrSkSLFP : public GrFragmentProcessor { |
| 32 | public: |
| 33 | /** |
| 34 | * Creates a new fragment processor from an SkRuntimeEffect and a struct of inputs to the |
| 35 | * program. The input struct's type is derived from the 'in' and 'uniform' variables in the SkSL |
| 36 | * source, so e.g. the shader: |
| 37 | * |
| 38 | * in bool dither; |
| 39 | * uniform float x; |
| 40 | * uniform float y; |
| 41 | * .... |
| 42 | * |
| 43 | * would expect a pointer to a struct set up like: |
| 44 | * |
| 45 | * struct { |
| 46 | * bool dither; |
| 47 | * float x; |
| 48 | * float y; |
| 49 | * }; |
| 50 | * |
| 51 | * While both 'in' and 'uniform' variables go into this struct, the difference between them is |
| 52 | * that 'in' variables are statically "baked in" to the generated code, becoming literals, |
| 53 | * whereas uniform variables may be changed from invocation to invocation without having to |
| 54 | * recompile the shader. |
| 55 | * |
| 56 | * As the decision of whether to create a new shader or just upload new uniforms all happens |
| 57 | * behind the scenes, the difference between the two from an end-user perspective is primarily |
| 58 | * in performance: on the one hand, changing the value of an 'in' variable is very expensive |
| 59 | * (requiring the compiler to regenerate the code, upload a new shader to the GPU, and so |
| 60 | * forth), but on the other hand the compiler can optimize around its value because it is known |
| 61 | * at compile time. 'in' variables are therefore suitable for things like flags, where there are |
| 62 | * only a few possible values and a known-in-advance value can cause entire chunks of code to |
| 63 | * become dead (think static @ifs), while 'uniform's are used for continuous values like colors |
| 64 | * and coordinates, where it would be silly to create a separate shader for each possible set of |
| 65 | * values. Other than the (significant) performance implications, the only difference between |
| 66 | * the two is that 'in' variables can be used in static @if / @switch tests. When in doubt, use |
| 67 | * 'uniform'. |
| 68 | */ |
| 69 | static std::unique_ptr<GrSkSLFP> Make(GrContext_Base* context, |
| 70 | sk_sp<SkRuntimeEffect> effect, |
| 71 | const char* name, |
| 72 | sk_sp<SkData> inputs, |
| 73 | const SkMatrix* matrix = nullptr); |
| 74 | |
| 75 | const char* name() const override; |
| 76 | |
| 77 | void addChild(std::unique_ptr<GrFragmentProcessor> child); |
| 78 | |
| 79 | std::unique_ptr<GrFragmentProcessor> clone() const override; |
| 80 | |
| 81 | private: |
| 82 | using ShaderErrorHandler = GrContextOptions::ShaderErrorHandler; |
| 83 | |
| 84 | GrSkSLFP(sk_sp<const GrShaderCaps> shaderCaps, ShaderErrorHandler* shaderErrorHandler, |
| 85 | sk_sp<SkRuntimeEffect> effect, const char* name, sk_sp<SkData> inputs, |
| 86 | const SkMatrix* matrix); |
| 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 | sk_sp<const GrShaderCaps> fShaderCaps; |
| 97 | ShaderErrorHandler* fShaderErrorHandler; |
| 98 | |
| 99 | sk_sp<SkRuntimeEffect> fEffect; |
| 100 | const char* fName; |
| 101 | sk_sp<SkData> fInputs; |
| 102 | |
| 103 | GrCoordTransform fCoordTransform; |
| 104 | |
| 105 | GR_DECLARE_FRAGMENT_PROCESSOR_TEST |
| 106 | |
| 107 | typedef GrFragmentProcessor INHERITED; |
| 108 | |
| 109 | friend class GrGLSLSkSLFP; |
| 110 | |
| 111 | friend class GrSkSLFPFactory; |
| 112 | }; |
| 113 | |
| 114 | #endif |
| 115 | |