Flutter Engine
The Flutter Engine
SkSLModuleLoader.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
8
24
25#include <algorithm>
26#include <memory>
27#include <string>
28#include <utility>
29#include <vector>
30
31#define MODULE_DATA(name) #name, GetModuleData(ModuleName::name, #name ".sksl")
32
33namespace SkSL {
34
35#define TYPE(t) &BuiltinTypes::f ## t
36
37static constexpr BuiltinTypePtr kRootTypes[] = {
38 TYPE(Void),
39
40 TYPE( Float), TYPE( Float2), TYPE( Float3), TYPE( Float4),
41 TYPE( Half), TYPE( Half2), TYPE( Half3), TYPE( Half4),
42 TYPE( Int), TYPE( Int2), TYPE( Int3), TYPE( Int4),
43 TYPE( UInt), TYPE( UInt2), TYPE( UInt3), TYPE( UInt4),
44 TYPE( Short), TYPE( Short2), TYPE( Short3), TYPE( Short4),
45 TYPE(UShort), TYPE(UShort2), TYPE(UShort3), TYPE(UShort4),
46 TYPE( Bool), TYPE( Bool2), TYPE( Bool3), TYPE( Bool4),
47
48 TYPE(Float2x2), TYPE(Float2x3), TYPE(Float2x4),
49 TYPE(Float3x2), TYPE(Float3x3), TYPE(Float3x4),
50 TYPE(Float4x2), TYPE(Float4x3), TYPE(Float4x4),
51
52 TYPE(Half2x2), TYPE(Half2x3), TYPE(Half2x4),
53 TYPE(Half3x2), TYPE(Half3x3), TYPE(Half3x4),
54 TYPE(Half4x2), TYPE(Half4x3), TYPE(Half4x4),
55
56 TYPE(SquareMat), TYPE(SquareHMat),
57 TYPE(Mat), TYPE(HMat),
58
59 // TODO(skia:12349): generic short/ushort
60 TYPE(GenType), TYPE(GenIType), TYPE(GenUType),
61 TYPE(GenHType), /* (GenSType) (GenUSType) */
62 TYPE(GenBType),
63 TYPE(IntLiteral),
64 TYPE(FloatLiteral),
65
66 TYPE(Vec), TYPE(IVec), TYPE(UVec),
67 TYPE(HVec), TYPE(SVec), TYPE(USVec),
68 TYPE(BVec),
69
71 TYPE(Shader),
72 TYPE(Blender),
73};
74
75static constexpr BuiltinTypePtr kPrivateTypes[] = {
76 TYPE(Sampler2D), TYPE(SamplerExternalOES), TYPE(Sampler2DRect),
77
78 TYPE(SubpassInput), TYPE(SubpassInputMS),
79
81 TYPE(Texture2D_sample),
82 TYPE(Texture2D), TYPE(ReadOnlyTexture2D), TYPE(WriteOnlyTexture2D),
83 TYPE(GenTexture2D), TYPE(ReadableTexture2D), TYPE(WritableTexture2D),
84
85 TYPE(AtomicUInt),
86};
87
88#undef TYPE
89
91 Impl();
92
94
95 // This mutex is taken when ModuleLoader::Get is called, and released when the returned
96 // ModuleLoader object falls out of scope.
97 SkMutex fMutex;
99
100 std::unique_ptr<const Module> fRootModule;
101
102 std::unique_ptr<const Module> fSharedModule; // [Root] + Public intrinsics
103 std::unique_ptr<const Module> fGPUModule; // [Shared] + Non-public intrinsics/
104 // helper functions
105 std::unique_ptr<const Module> fVertexModule; // [GPU] + Vertex stage decls
106 std::unique_ptr<const Module> fFragmentModule; // [GPU] + Fragment stage decls
107 std::unique_ptr<const Module> fComputeModule; // [GPU] + Compute stage decls
108 std::unique_ptr<const Module> fGraphiteVertexModule; // [Vert] + Graphite vertex helpers
109 std::unique_ptr<const Module> fGraphiteFragmentModule; // [Frag] + Graphite fragment helpers
110 std::unique_ptr<const Module> fGraphiteVertexES2Module; // [Vert] + Graphite vertex ES2 helpers
111 std::unique_ptr<const Module> fGraphiteFragmentES2Module;//[Frag] + Graphite fragment ES2 " "
112
113 std::unique_ptr<const Module> fPublicModule; // [Shared] minus Private types +
114 // Runtime effect intrinsics
115 std::unique_ptr<const Module> fRuntimeShaderModule; // [Public] + Runtime shader decls
116};
117
119 static SkNoDestructor<ModuleLoader::Impl> sModuleLoaderImpl;
120 return ModuleLoader(*sModuleLoaderImpl);
121}
122
124 fModuleLoader.fMutex.acquire();
125}
126
128 fModuleLoader.fMutex.release();
129}
130
132 fModuleLoader.fSharedModule = nullptr;
133 fModuleLoader.fGPUModule = nullptr;
134 fModuleLoader.fVertexModule = nullptr;
135 fModuleLoader.fFragmentModule = nullptr;
136 fModuleLoader.fComputeModule = nullptr;
137 fModuleLoader.fGraphiteVertexModule = nullptr;
138 fModuleLoader.fGraphiteFragmentModule = nullptr;
139 fModuleLoader.fPublicModule = nullptr;
140 fModuleLoader.fRuntimeShaderModule = nullptr;
141}
142
144 this->makeRootSymbolTable();
145}
146
147static std::unique_ptr<Module> compile_and_shrink(SkSL::Compiler* compiler,
148 ProgramKind kind,
149 const char* moduleName,
150 std::string moduleSource,
151 const Module* parent) {
152 std::unique_ptr<Module> m = compiler->compileModule(kind,
154 std::move(moduleSource),
155 parent,
156 /*shouldInline=*/true);
157 if (!m) {
158 SK_ABORT("Unable to load module %s", moduleName);
159 }
160
161 // We can eliminate FunctionPrototypes without changing the meaning of the module; the function
162 // declaration is still safely in the symbol table. This only impacts our ability to recreate
163 // the input verbatim, which we don't care about at runtime.
164 m->fElements.erase(std::remove_if(m->fElements.begin(), m->fElements.end(),
165 [](const std::unique_ptr<ProgramElement>& element) {
166 switch (element->kind()) {
167 case ProgramElement::Kind::kFunction:
168 case ProgramElement::Kind::kGlobalVar:
169 case ProgramElement::Kind::kInterfaceBlock:
170 case ProgramElement::Kind::kStructDefinition:
171 // We need to preserve these.
172 return false;
173
174 case ProgramElement::Kind::kFunctionPrototype:
175 // These are already in the symbol table; the
176 // ProgramElement isn't needed anymore.
177 return true;
178
179 default:
180 SkDEBUGFAILF("Unsupported element: %s\n",
181 element->description().c_str());
182 return false;
183 }
184 }),
185 m->fElements.end());
186
187 m->fElements.shrink_to_fit();
188 return m;
189}
190
192 return fModuleLoader.fBuiltinTypes;
193}
194
196 return fModuleLoader.fRootModule.get();
197}
198
200 const SkSL::BuiltinTypes& types = this->builtinTypes();
201 SymbolTable* symbols = module->fSymbols.get();
202
203 // Add some aliases to the runtime effect modules so that it's friendlier, and more like GLSL.
204 symbols->addWithoutOwnershipOrDie(types.fVec2.get());
205 symbols->addWithoutOwnershipOrDie(types.fVec3.get());
206 symbols->addWithoutOwnershipOrDie(types.fVec4.get());
207
208 symbols->addWithoutOwnershipOrDie(types.fIVec2.get());
209 symbols->addWithoutOwnershipOrDie(types.fIVec3.get());
210 symbols->addWithoutOwnershipOrDie(types.fIVec4.get());
211
212 symbols->addWithoutOwnershipOrDie(types.fUVec2.get());
213 symbols->addWithoutOwnershipOrDie(types.fUVec3.get());
214 symbols->addWithoutOwnershipOrDie(types.fUVec4.get());
215
216 symbols->addWithoutOwnershipOrDie(types.fBVec2.get());
217 symbols->addWithoutOwnershipOrDie(types.fBVec3.get());
218 symbols->addWithoutOwnershipOrDie(types.fBVec4.get());
219
220 symbols->addWithoutOwnershipOrDie(types.fMat2.get());
221 symbols->addWithoutOwnershipOrDie(types.fMat3.get());
222 symbols->addWithoutOwnershipOrDie(types.fMat4.get());
223
224 symbols->addWithoutOwnershipOrDie(types.fMat2x2.get());
225 symbols->addWithoutOwnershipOrDie(types.fMat2x3.get());
226 symbols->addWithoutOwnershipOrDie(types.fMat2x4.get());
227 symbols->addWithoutOwnershipOrDie(types.fMat3x2.get());
228 symbols->addWithoutOwnershipOrDie(types.fMat3x3.get());
229 symbols->addWithoutOwnershipOrDie(types.fMat3x4.get());
230 symbols->addWithoutOwnershipOrDie(types.fMat4x2.get());
231 symbols->addWithoutOwnershipOrDie(types.fMat4x3.get());
232 symbols->addWithoutOwnershipOrDie(types.fMat4x4.get());
233
234 // Hide all the private symbols by aliasing them all to "invalid". This will prevent code from
235 // using built-in names like `sampler2D` as variable names.
236 for (BuiltinTypePtr privateType : kPrivateTypes) {
237 symbols->inject(Type::MakeAliasType((types.*privateType)->name(), *types.fInvalid));
238 }
239}
240
242 if (!fModuleLoader.fPublicModule) {
243 const Module* sharedModule = this->loadSharedModule(compiler);
247 sharedModule);
248 this->addPublicTypeAliases(fModuleLoader.fPublicModule.get());
249 }
250 return fModuleLoader.fPublicModule.get();
251}
252
254 if (!fModuleLoader.fRuntimeShaderModule) {
255 const Module* publicModule = this->loadPublicModule(compiler);
259 publicModule);
260 }
261 return fModuleLoader.fRuntimeShaderModule.get();
262}
263
265 if (!fModuleLoader.fSharedModule) {
266 const Module* rootModule = this->rootModule();
270 rootModule);
271 }
272 return fModuleLoader.fSharedModule.get();
273}
274
276 if (!fModuleLoader.fGPUModule) {
277 const Module* sharedModule = this->loadSharedModule(compiler);
278 fModuleLoader.fGPUModule = compile_and_shrink(compiler,
281 sharedModule);
282 }
283 return fModuleLoader.fGPUModule.get();
284}
285
287 if (!fModuleLoader.fFragmentModule) {
288 const Module* gpuModule = this->loadGPUModule(compiler);
292 gpuModule);
293 }
294 return fModuleLoader.fFragmentModule.get();
295}
296
298 if (!fModuleLoader.fVertexModule) {
299 const Module* gpuModule = this->loadGPUModule(compiler);
303 gpuModule);
304 }
305 return fModuleLoader.fVertexModule.get();
306}
307
309 if (!fModuleLoader.fComputeModule) {
310 const Module* gpuModule = this->loadGPUModule(compiler);
314 gpuModule);
315 }
316 return fModuleLoader.fComputeModule.get();
317}
318
320#if defined(SK_GRAPHITE)
321 if (!fModuleLoader.fGraphiteFragmentModule) {
322 const Module* fragmentModule = this->loadFragmentModule(compiler);
326 fragmentModule);
327 }
328 return fModuleLoader.fGraphiteFragmentModule.get();
329#else
330 return this->loadFragmentModule(compiler);
331#endif
332}
333
335#if defined(SK_GRAPHITE)
336 if (!fModuleLoader.fGraphiteFragmentES2Module) {
337 const Module* fragmentModule = this->loadFragmentModule(compiler);
338 fModuleLoader.fGraphiteFragmentES2Module =
342 fragmentModule);
343 }
344 return fModuleLoader.fGraphiteFragmentES2Module.get();
345#else
346 return this->loadFragmentModule(compiler);
347#endif
348}
349
351#if defined(SK_GRAPHITE)
352 if (!fModuleLoader.fGraphiteVertexModule) {
353 const Module* vertexModule = this->loadVertexModule(compiler);
357 vertexModule);
358 }
359 return fModuleLoader.fGraphiteVertexModule.get();
360#else
361 return this->loadVertexModule(compiler);
362#endif
363}
364
366#if defined(SK_GRAPHITE)
367 if (!fModuleLoader.fGraphiteVertexES2Module) {
368 const Module* vertexModule = this->loadVertexModule(compiler);
369 fModuleLoader.fGraphiteVertexES2Module =
373 vertexModule);
374 }
375 return fModuleLoader.fGraphiteVertexES2Module.get();
376#else
377 return this->loadVertexModule(compiler);
378#endif
379}
380
382 auto rootModule = std::make_unique<Module>();
383 rootModule->fSymbols = std::make_unique<SymbolTable>(/*builtin=*/true);
384
385 for (BuiltinTypePtr rootType : kRootTypes) {
386 rootModule->fSymbols->addWithoutOwnershipOrDie((fBuiltinTypes.*rootType).get());
387 }
388
389 for (BuiltinTypePtr privateType : kPrivateTypes) {
390 rootModule->fSymbols->addWithoutOwnershipOrDie((fBuiltinTypes.*privateType).get());
391 }
392
393 // sk_Caps is "builtin", but all references to it are resolved to Settings, so we don't need to
394 // treat it as builtin (ie, no need to clone it into the Program).
395 rootModule->fSymbols->addOrDie(Variable::Make(/*pos=*/Position(),
396 /*modifiersPosition=*/Position(),
397 Layout{},
400 "sk_Caps",
401 /*mangledName=*/"",
402 /*builtin=*/false,
404 fRootModule = std::move(rootModule);
405}
406
407} // namespace SkSL
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
#define MODULE_DATA(name)
#define TYPE(t)
const std::unique_ptr< Type > fUVec3
const std::unique_ptr< Type > fMat4x4
const std::unique_ptr< Type > fMat4x2
const std::unique_ptr< Type > fSkCaps
const std::unique_ptr< Type > fUVec2
const std::unique_ptr< Type > fMat2x4
const std::unique_ptr< Type > fMat2
const std::unique_ptr< Type > fBVec2
const std::unique_ptr< Type > fMat4
const std::unique_ptr< Type > fMat4x3
const std::unique_ptr< Type > fMat2x2
const std::unique_ptr< Type > fInvalid
const std::unique_ptr< Type > fBVec3
const std::unique_ptr< Type > fBVec4
const std::unique_ptr< Type > fVec4
const std::unique_ptr< Type > fVec3
const std::unique_ptr< Type > fIVec3
const std::unique_ptr< Type > fIVec4
const std::unique_ptr< Type > fUVec4
const std::unique_ptr< Type > fIVec2
const std::unique_ptr< Type > fMat3
const std::unique_ptr< Type > fMat3x4
const std::unique_ptr< Type > fMat3x3
const std::unique_ptr< Type > fMat2x3
const std::unique_ptr< Type > fMat3x2
const std::unique_ptr< Type > fVec2
const Module * loadComputeModule(SkSL::Compiler *compiler)
const Module * loadPublicModule(SkSL::Compiler *compiler)
const Module * loadGPUModule(SkSL::Compiler *compiler)
const Module * loadSharedModule(SkSL::Compiler *compiler)
const Module * rootModule()
const Module * loadPrivateRTShaderModule(SkSL::Compiler *compiler)
const BuiltinTypes & builtinTypes()
const Module * loadGraphiteFragmentES2Module(SkSL::Compiler *compiler)
void addPublicTypeAliases(const SkSL::Module *module)
const Module * loadGraphiteFragmentModule(SkSL::Compiler *compiler)
const Module * loadGraphiteVertexModule(SkSL::Compiler *compiler)
static ModuleLoader Get()
const Module * loadFragmentModule(SkSL::Compiler *compiler)
const Module * loadGraphiteVertexES2Module(SkSL::Compiler *compiler)
ModuleLoader(ModuleLoader::Impl &)
const Module * loadVertexModule(SkSL::Compiler *compiler)
static std::unique_ptr< Type > MakeAliasType(std::string_view name, const Type &targetType)
static std::unique_ptr< Variable > Make(Position pos, Position modifiersPosition, const Layout &layout, ModifierFlags flags, const Type *type, std::string_view name, std::string mangledName, bool builtin, Storage storage)
const std::unique_ptr< Type > BuiltinTypes::* BuiltinTypePtr
static constexpr BuiltinTypePtr kPrivateTypes[]
static std::unique_ptr< Module > compile_and_shrink(SkSL::Compiler *compiler, ProgramKind kind, const char *moduleName, std::string moduleSource, const Module *parent)
static constexpr BuiltinTypePtr kRootTypes[]
std::function< ProfileSample(void)> Sampler
Sampler is run during SamplingProfiler::SampleRepeatedly. Each platform should implement its version ...
SK_API sk_sp< PrecompileShader > ColorFilter(SkSpan< const sk_sp< PrecompileShader > > shaders, SkSpan< const sk_sp< PrecompileColorFilter > > colorFilters)
std::unique_ptr< const Module > fGraphiteVertexModule
std::unique_ptr< const Module > fGraphiteFragmentModule
std::unique_ptr< const Module > fGPUModule
std::unique_ptr< const Module > fGraphiteVertexES2Module
std::unique_ptr< const Module > fGraphiteFragmentES2Module
std::unique_ptr< const Module > fComputeModule
std::unique_ptr< const Module > fFragmentModule
std::unique_ptr< const Module > fVertexModule
std::unique_ptr< const Module > fPublicModule
std::unique_ptr< const Module > fSharedModule
const BuiltinTypes fBuiltinTypes
std::unique_ptr< const Module > fRootModule
std::unique_ptr< const Module > fRuntimeShaderModule
std::unique_ptr< SymbolTable > fSymbols
Definition: SkSLCompiler.h:58