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