blob: 1764e9dfda09e5128e11e7f5ab28343b1e9371ce [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
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 */
Ethan Nicholaseace9352018-10-15 20:09:54 +000070 static std::unique_ptr<GrSkSLFP> Make(
Robert Phillips1efecea2019-02-15 16:58:40 -050071 GrContext_Base* context,
Ethan Nicholaseace9352018-10-15 20:09:54 +000072 int index,
73 const char* name,
74 const char* sksl,
75 const void* inputs,
Ethan Nicholas0d997662019-04-08 09:46:01 -040076 size_t inputSize,
77 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
Ethan Nicholas00543112018-07-31 09:44:36 -040078
Ethan Nicholasa70693b2019-03-04 13:07:36 -050079 static std::unique_ptr<GrSkSLFP> Make(
80 GrContext_Base* context,
81 int index,
82 const char* name,
83 SkString sksl,
84 const void* inputs,
Ethan Nicholas0d997662019-04-08 09:46:01 -040085 size_t inputSize,
86 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
Ethan Nicholasa70693b2019-03-04 13:07:36 -050087
Ethan Nicholas00543112018-07-31 09:44:36 -040088 const char* name() const override;
89
Ethan Nicholasce008112018-08-30 09:19:50 -040090 void addChild(std::unique_ptr<GrFragmentProcessor> child);
91
Ethan Nicholas00543112018-07-31 09:44:36 -040092 std::unique_ptr<GrFragmentProcessor> clone() const override;
93
94private:
Ethan Nicholas0d997662019-04-08 09:46:01 -040095 GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
96 SkSL::Program::Kind kind, int fIndex, const char* name, const char* sksl,
97 SkString skslString, const void* inputs, size_t inputSize);
Ethan Nicholas00543112018-07-31 09:44:36 -040098
99 GrSkSLFP(const GrSkSLFP& other);
100
101 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
102
103 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
104
105 bool onIsEqual(const GrFragmentProcessor&) const override;
106
107 void createFactory() const;
108
109 sk_sp<GrSkSLFPFactoryCache> fFactoryCache;
110
111 const sk_sp<GrShaderCaps> fShaderCaps;
112
113 mutable sk_sp<GrSkSLFPFactory> fFactory;
114
Ethan Nicholas0d997662019-04-08 09:46:01 -0400115 SkSL::Program::Kind fKind;
116
Ethan Nicholas00543112018-07-31 09:44:36 -0400117 int fIndex;
118
119 const char* fName;
120
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500121 // For object lifetime purposes, we have fields for the SkSL as both a const char* and a
122 // SkString. The const char* is the one we actually use, but it may point to the SkString's
123 // bytes. Since GrSkSLFPs are frequently created from constant strings, this allows us to
124 // generally avoid the overhead of copying the bytes into an SkString (in which case fSkSLString
125 // is the empty string), while still allowing the GrSkSLFP to manage the string's lifetime when
126 // needed.
127 SkString fSkSLString;
128
Ethan Nicholas00543112018-07-31 09:44:36 -0400129 const char* fSkSL;
130
Ethan Nicholaseace9352018-10-15 20:09:54 +0000131 const std::unique_ptr<int8_t[]> fInputs;
Ethan Nicholas00543112018-07-31 09:44:36 -0400132
133 size_t fInputSize;
134
135 mutable SkSL::String fKey;
136
137 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
138
139 typedef GrFragmentProcessor INHERITED;
140
Ethan Nicholasce008112018-08-30 09:19:50 -0400141 friend class GrGLSLSkSLFP;
142
Ethan Nicholas00543112018-07-31 09:44:36 -0400143 friend class GrSkSLFPFactory;
144};
145
146/**
147 * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends
148 * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL
149 * string, then use that to create the actual GrFragmentProcessor.
150 */
Mike Klein408ef212018-10-30 15:23:00 +0000151class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> {
Ethan Nicholas00543112018-07-31 09:44:36 -0400152public:
153 /**
154 * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will
155 * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause
156 * the produced shaders to differ), so it is important to reuse the same factory instance for
157 * the same shader in order to avoid repeatedly re-parsing the SkSL.
158 */
Ethan Nicholas0d997662019-04-08 09:46:01 -0400159 GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
160 SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
Ethan Nicholas00543112018-07-31 09:44:36 -0400161
162 const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs,
163 size_t inputSize);
164
Ethan Nicholas0d997662019-04-08 09:46:01 -0400165 SkSL::Program::Kind fKind;
166
Ethan Nicholas00543112018-07-31 09:44:36 -0400167 const char* fName;
168
169 SkSL::Compiler fCompiler;
170
171 std::shared_ptr<SkSL::Program> fBaseProgram;
172
173 std::vector<const SkSL::Variable*> fInputVars;
174
Ethan Nicholas00543112018-07-31 09:44:36 -0400175 std::vector<const SkSL::Variable*> fKeyVars;
176
177 std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations;
178
179 friend class GrSkSLFP;
180};
181
182#endif