blob: eba33c6112752518847d8d7a72d701e4fd4eead2 [file] [log] [blame]
Ethan Nicholas00543112018-07-31 09:44:36 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkRefCnt.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrCaps.h"
13#include "src/gpu/GrCoordTransform.h"
14#include "src/gpu/GrFragmentProcessor.h"
15#include "src/gpu/GrShaderCaps.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040016#include "src/gpu/GrSkSLFPFactoryCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/sksl/SkSLCompiler.h"
18#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
Mike Klein0ec1c572018-12-04 11:52:51 -050019#include <atomic>
Ethan Nicholas00543112018-07-31 09:44:36 -040020
Ethan Nicholas78aceb22018-08-31 16:13:58 -040021#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
Robert Phillips1efecea2019-02-15 16:58:40 -050027class GrContext_Base;
Ethan Nicholas00543112018-07-31 09:44:36 -040028class GrSkSLFPFactory;
29
30class GrSkSLFP : public GrFragmentProcessor {
31public:
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 */
36 static int NewIndex() {
Mike Klein0ec1c572018-12-04 11:52:51 -050037 static std::atomic<int> nextIndex{0};
38 return nextIndex++;
Ethan Nicholas00543112018-07-31 09:44:36 -040039 }
40
41 /**
42 * Creates a new fragment processor from an SkSL source string and a struct of inputs to the
Ethan Nicholasac18a5c2019-09-26 09:34:20 -040043 * program. The input struct's type is derived from the 'in' and 'uniform' variables in the SkSL
44 * source, so e.g. the shader:
Ethan Nicholas00543112018-07-31 09:44:36 -040045 *
46 * in bool dither;
Ethan Nicholasac18a5c2019-09-26 09:34:20 -040047 * uniform float x;
48 * uniform float y;
Ethan Nicholas00543112018-07-31 09:44:36 -040049 * ....
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 *
Ethan Nicholasac18a5c2019-09-26 09:34:20 -040059 * While both 'in' and 'uniform' variables go into this struct, the difference between them is
60 * that 'in' variables are statically "baked in" to the generated code, becoming literals,
61 * whereas uniform variables may be changed from invocation to invocation without having to
62 * recompile the shader.
63 *
64 * As the decision of whether to create a new shader or just upload new uniforms all happens
65 * behind the scenes, the difference between the two from an end-user perspective is primarily
66 * in performance: on the one hand, changing the value of an 'in' variable is very expensive
67 * (requiring the compiler to regenerate the code, upload a new shader to the GPU, and so
68 * forth), but on the other hand the compiler can optimize around its value because it is known
69 * at compile time. 'in' variables are therefore suitable for things like flags, where there are
70 * only a few possible values and a known-in-advance value can cause entire chunks of code to
71 * become dead (think static @ifs), while 'uniform's are used for continuous values like colors
72 * and coordinates, where it would be silly to create a separate shader for each possible set of
73 * values. Other than the (significant) performance implications, the only difference between
74 * the two is that 'in' variables can be used in static @if / @switch tests. When in doubt, use
75 * 'uniform'.
76 *
Ethan Nicholas00543112018-07-31 09:44:36 -040077 * As turning SkSL into GLSL / SPIR-V / etc. is fairly expensive, and the output may differ
78 * based on the inputs, internally the process is divided into two steps: we first parse and
79 * semantically analyze the SkSL into an internal representation, and then "specialize" this
80 * internal representation based on the inputs. The unspecialized internal representation of
81 * the program is cached, so further specializations of the same code are much faster than the
82 * first call.
83 *
84 * This caching is based on the 'index' parameter, which should be derived by statically calling
85 * 'NewIndex()'. Each given SkSL string should have a single, statically defined index
86 * associated with it.
87 */
Ethan Nicholaseace9352018-10-15 20:09:54 +000088 static std::unique_ptr<GrSkSLFP> Make(
Robert Phillips1efecea2019-02-15 16:58:40 -050089 GrContext_Base* context,
Ethan Nicholaseace9352018-10-15 20:09:54 +000090 int index,
91 const char* name,
92 const char* sksl,
93 const void* inputs,
Ethan Nicholas0d997662019-04-08 09:46:01 -040094 size_t inputSize,
Brian Osman3b1e4c22019-08-12 15:12:14 -040095 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind,
96 const SkMatrix* matrix = nullptr);
Ethan Nicholas00543112018-07-31 09:44:36 -040097
Ethan Nicholasa70693b2019-03-04 13:07:36 -050098 static std::unique_ptr<GrSkSLFP> Make(
99 GrContext_Base* context,
100 int index,
101 const char* name,
102 SkString sksl,
103 const void* inputs,
Ethan Nicholas0d997662019-04-08 09:46:01 -0400104 size_t inputSize,
Brian Osman3b1e4c22019-08-12 15:12:14 -0400105 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind,
106 const SkMatrix* matrix = nullptr);
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500107
Ethan Nicholas00543112018-07-31 09:44:36 -0400108 const char* name() const override;
109
Ethan Nicholasce008112018-08-30 09:19:50 -0400110 void addChild(std::unique_ptr<GrFragmentProcessor> child);
111
Ethan Nicholas00543112018-07-31 09:44:36 -0400112 std::unique_ptr<GrFragmentProcessor> clone() const override;
113
114private:
Ethan Nicholas0d997662019-04-08 09:46:01 -0400115 GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
116 SkSL::Program::Kind kind, int fIndex, const char* name, const char* sksl,
Brian Osman3b1e4c22019-08-12 15:12:14 -0400117 SkString skslString, const void* inputs, size_t inputSize, const SkMatrix* matrix);
Ethan Nicholas00543112018-07-31 09:44:36 -0400118
119 GrSkSLFP(const GrSkSLFP& other);
120
121 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
122
123 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
124
125 bool onIsEqual(const GrFragmentProcessor&) const override;
126
127 void createFactory() const;
128
129 sk_sp<GrSkSLFPFactoryCache> fFactoryCache;
130
131 const sk_sp<GrShaderCaps> fShaderCaps;
132
133 mutable sk_sp<GrSkSLFPFactory> fFactory;
134
Ethan Nicholas0d997662019-04-08 09:46:01 -0400135 SkSL::Program::Kind fKind;
136
Ethan Nicholas00543112018-07-31 09:44:36 -0400137 int fIndex;
138
139 const char* fName;
140
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500141 // For object lifetime purposes, we have fields for the SkSL as both a const char* and a
142 // SkString. The const char* is the one we actually use, but it may point to the SkString's
143 // bytes. Since GrSkSLFPs are frequently created from constant strings, this allows us to
144 // generally avoid the overhead of copying the bytes into an SkString (in which case fSkSLString
145 // is the empty string), while still allowing the GrSkSLFP to manage the string's lifetime when
146 // needed.
147 SkString fSkSLString;
148
Ethan Nicholas00543112018-07-31 09:44:36 -0400149 const char* fSkSL;
150
Ethan Nicholaseace9352018-10-15 20:09:54 +0000151 const std::unique_ptr<int8_t[]> fInputs;
Ethan Nicholas00543112018-07-31 09:44:36 -0400152
153 size_t fInputSize;
154
Brian Osman3b1e4c22019-08-12 15:12:14 -0400155 GrCoordTransform fCoordTransform;
156
Ethan Nicholas00543112018-07-31 09:44:36 -0400157 mutable SkSL::String fKey;
158
159 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
160
161 typedef GrFragmentProcessor INHERITED;
162
Ethan Nicholasce008112018-08-30 09:19:50 -0400163 friend class GrGLSLSkSLFP;
164
Ethan Nicholas00543112018-07-31 09:44:36 -0400165 friend class GrSkSLFPFactory;
166};
167
168/**
169 * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends
170 * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL
171 * string, then use that to create the actual GrFragmentProcessor.
172 */
Mike Klein408ef212018-10-30 15:23:00 +0000173class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> {
Ethan Nicholas00543112018-07-31 09:44:36 -0400174public:
175 /**
176 * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will
177 * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause
178 * the produced shaders to differ), so it is important to reuse the same factory instance for
179 * the same shader in order to avoid repeatedly re-parsing the SkSL.
180 */
Ethan Nicholas0d997662019-04-08 09:46:01 -0400181 GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
182 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
Ethan Nicholas00543112018-07-31 09:44:36 -0400183
184 const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs,
185 size_t inputSize);
186
Ethan Nicholas0d997662019-04-08 09:46:01 -0400187 SkSL::Program::Kind fKind;
188
Ethan Nicholas00543112018-07-31 09:44:36 -0400189 const char* fName;
190
191 SkSL::Compiler fCompiler;
192
193 std::shared_ptr<SkSL::Program> fBaseProgram;
194
Ethan Nicholasac18a5c2019-09-26 09:34:20 -0400195 std::vector<const SkSL::Variable*> fInAndUniformVars;
Ethan Nicholas00543112018-07-31 09:44:36 -0400196
Ethan Nicholas00543112018-07-31 09:44:36 -0400197 std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations;
198
199 friend class GrSkSLFP;
200};
201
202#endif