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 | |