Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
23
24#include <algorithm>
25#include <string>
26#include <utility>
27#include <vector>
28
29#if SKSL_STANDALONE
30
32#include "src/utils/SkOSPath.h"
34
35 // In standalone mode, we load the original SkSL source files. GN is responsible for copying
36 // these files from src/sksl/ to the directory where the executable is located.
37 #include <fstream>
38
39 static std::string load_module_file(const char* moduleFilename) {
40 std::string exePath = SkGetExecutablePath();
41 SkString exeDir = SkOSPath::Dirname(exePath.c_str());
42 SkString modulePath = SkOSPath::Join(exeDir.c_str(), moduleFilename);
43 std::ifstream in(std::string{modulePath.c_str()});
44 std::string moduleSource{std::istreambuf_iterator<char>(in),
45 std::istreambuf_iterator<char>()};
46 if (in.rdstate()) {
47 SK_ABORT("Error reading %s\n", modulePath.c_str());
48 }
49 return moduleSource;
50 }
51
52 #define MODULE_DATA(name) #name, load_module_file(#name ".sksl")
53
54#else
55
56 // We include minified SkSL module code and pass it directly to the compiler.
57 #if defined(SK_ENABLE_OPTIMIZE_SIZE) || !defined(SK_DEBUG)
58 #include "src/sksl/generated/sksl_shared.minified.sksl"
59 #include "src/sksl/generated/sksl_compute.minified.sksl"
60 #include "src/sksl/generated/sksl_frag.minified.sksl"
61 #include "src/sksl/generated/sksl_gpu.minified.sksl"
62 #include "src/sksl/generated/sksl_public.minified.sksl"
63 #include "src/sksl/generated/sksl_rt_shader.minified.sksl"
64 #include "src/sksl/generated/sksl_vert.minified.sksl"
65 #if defined(SK_GRAPHITE)
66 #include "src/sksl/generated/sksl_graphite_frag.minified.sksl"
67 #include "src/sksl/generated/sksl_graphite_vert.minified.sksl"
68 #include "src/sksl/generated/sksl_graphite_frag_es2.minified.sksl"
69 #include "src/sksl/generated/sksl_graphite_vert_es2.minified.sksl"
70 #endif
71 #else
72 #include "src/sksl/generated/sksl_shared.unoptimized.sksl"
73 #include "src/sksl/generated/sksl_compute.unoptimized.sksl"
74 #include "src/sksl/generated/sksl_frag.unoptimized.sksl"
75 #include "src/sksl/generated/sksl_gpu.unoptimized.sksl"
76 #include "src/sksl/generated/sksl_public.unoptimized.sksl"
77 #include "src/sksl/generated/sksl_rt_shader.unoptimized.sksl"
78 #include "src/sksl/generated/sksl_vert.unoptimized.sksl"
79 #if defined(SK_GRAPHITE)
80 #include "src/sksl/generated/sksl_graphite_frag.unoptimized.sksl"
81 #include "src/sksl/generated/sksl_graphite_vert.unoptimized.sksl"
82 #include "src/sksl/generated/sksl_graphite_frag_es2.unoptimized.sksl"
83 #include "src/sksl/generated/sksl_graphite_vert_es2.unoptimized.sksl"
84 #endif
85 #endif
86
87 #define MODULE_DATA(name) #name, std::string(SKSL_MINIFIED_##name)
88
89#endif
90
91namespace SkSL {
92
93#define TYPE(t) &BuiltinTypes::f ## t
94
95static constexpr BuiltinTypePtr kRootTypes[] = {
96 TYPE(Void),
97
98 TYPE( Float), TYPE( Float2), TYPE( Float3), TYPE( Float4),
99 TYPE( Half), TYPE( Half2), TYPE( Half3), TYPE( Half4),
100 TYPE( Int), TYPE( Int2), TYPE( Int3), TYPE( Int4),
101 TYPE( UInt), TYPE( UInt2), TYPE( UInt3), TYPE( UInt4),
102 TYPE( Short), TYPE( Short2), TYPE( Short3), TYPE( Short4),
103 TYPE(UShort), TYPE(UShort2), TYPE(UShort3), TYPE(UShort4),
104 TYPE( Bool), TYPE( Bool2), TYPE( Bool3), TYPE( Bool4),
105
106 TYPE(Float2x2), TYPE(Float2x3), TYPE(Float2x4),
107 TYPE(Float3x2), TYPE(Float3x3), TYPE(Float3x4),
108 TYPE(Float4x2), TYPE(Float4x3), TYPE(Float4x4),
109
110 TYPE(Half2x2), TYPE(Half2x3), TYPE(Half2x4),
111 TYPE(Half3x2), TYPE(Half3x3), TYPE(Half3x4),
112 TYPE(Half4x2), TYPE(Half4x3), TYPE(Half4x4),
113
114 TYPE(SquareMat), TYPE(SquareHMat),
115 TYPE(Mat), TYPE(HMat),
116
117 // TODO(skia:12349): generic short/ushort
118 TYPE(GenType), TYPE(GenIType), TYPE(GenUType),
119 TYPE(GenHType), /* (GenSType) (GenUSType) */
120 TYPE(GenBType),
121 TYPE(IntLiteral),
122 TYPE(FloatLiteral),
123
124 TYPE(Vec), TYPE(IVec), TYPE(UVec),
125 TYPE(HVec), TYPE(SVec), TYPE(USVec),
126 TYPE(BVec),
127
128 TYPE(ColorFilter),
129 TYPE(Shader),
130 TYPE(Blender),
131};
132
133static constexpr BuiltinTypePtr kPrivateTypes[] = {
134 TYPE(Sampler2D), TYPE(SamplerExternalOES), TYPE(Sampler2DRect),
135
136 TYPE(SubpassInput), TYPE(SubpassInputMS),
137
138 TYPE(Sampler),
139 TYPE(Texture2D_sample),
140 TYPE(Texture2D), TYPE(ReadOnlyTexture2D), TYPE(WriteOnlyTexture2D),
141 TYPE(GenTexture2D), TYPE(ReadableTexture2D), TYPE(WritableTexture2D),
142
143 TYPE(AtomicUInt),
144};
145
146#undef TYPE
147
149 Impl();
150
151 void makeRootSymbolTable();
152
153 // This mutex is taken when ModuleLoader::Get is called, and released when the returned
154 // ModuleLoader object falls out of scope.
155 SkMutex fMutex;
157
158 std::unique_ptr<const Module> fRootModule;
159
160 std::unique_ptr<const Module> fSharedModule; // [Root] + Public intrinsics
161 std::unique_ptr<const Module> fGPUModule; // [Shared] + Non-public intrinsics/
162 // helper functions
163 std::unique_ptr<const Module> fVertexModule; // [GPU] + Vertex stage decls
164 std::unique_ptr<const Module> fFragmentModule; // [GPU] + Fragment stage decls
165 std::unique_ptr<const Module> fComputeModule; // [GPU] + Compute stage decls
166 std::unique_ptr<const Module> fGraphiteVertexModule; // [Vert] + Graphite vertex helpers
167 std::unique_ptr<const Module> fGraphiteFragmentModule; // [Frag] + Graphite fragment helpers
168 std::unique_ptr<const Module> fGraphiteVertexES2Module; // [Vert] + Graphite vertex ES2 helpers
169 std::unique_ptr<const Module> fGraphiteFragmentES2Module;//[Frag] + Graphite fragment ES2 " "
170
171 std::unique_ptr<const Module> fPublicModule; // [Shared] minus Private types +
172 // Runtime effect intrinsics
173 std::unique_ptr<const Module> fRuntimeShaderModule; // [Public] + Runtime shader decls
174};
175
177 static SkNoDestructor<ModuleLoader::Impl> sModuleLoaderImpl;
178 return ModuleLoader(*sModuleLoaderImpl);
179}
180
182 fModuleLoader.fMutex.acquire();
183}
184
186 fModuleLoader.fMutex.release();
187}
188
190 fModuleLoader.fSharedModule = nullptr;
191 fModuleLoader.fGPUModule = nullptr;
192 fModuleLoader.fVertexModule = nullptr;
193 fModuleLoader.fFragmentModule = nullptr;
194 fModuleLoader.fComputeModule = nullptr;
195 fModuleLoader.fGraphiteVertexModule = nullptr;
196 fModuleLoader.fGraphiteFragmentModule = nullptr;
197 fModuleLoader.fPublicModule = nullptr;
198 fModuleLoader.fRuntimeShaderModule = nullptr;
199}
200
204
205static std::unique_ptr<Module> compile_and_shrink(SkSL::Compiler* compiler,
206 ProgramKind kind,
207 const char* moduleName,
208 std::string moduleSource,
209 const Module* parent) {
210 std::unique_ptr<Module> m = compiler->compileModule(kind,
211 moduleName,
212 std::move(moduleSource),
213 parent,
214 /*shouldInline=*/true);
215 if (!m) {
216 SK_ABORT("Unable to load module %s", moduleName);
217 }
218
219 // We can eliminate FunctionPrototypes without changing the meaning of the module; the function
220 // declaration is still safely in the symbol table. This only impacts our ability to recreate
221 // the input verbatim, which we don't care about at runtime.
222 m->fElements.erase(std::remove_if(m->fElements.begin(), m->fElements.end(),
223 [](const std::unique_ptr<ProgramElement>& element) {
224 switch (element->kind()) {
225 case ProgramElement::Kind::kFunction:
226 case ProgramElement::Kind::kGlobalVar:
227 case ProgramElement::Kind::kInterfaceBlock:
228 case ProgramElement::Kind::kStructDefinition:
229 // We need to preserve these.
230 return false;
231
232 case ProgramElement::Kind::kFunctionPrototype:
233 // These are already in the symbol table; the
234 // ProgramElement isn't needed anymore.
235 return true;
236
237 default:
238 SkDEBUGFAILF("Unsupported element: %s\n",
239 element->description().c_str());
240 return false;
241 }
242 }),
243 m->fElements.end());
244
245 m->fElements.shrink_to_fit();
246 return m;
247}
248
250 return fModuleLoader.fBuiltinTypes;
251}
252
254 return fModuleLoader.fRootModule.get();
255}
256
258 const SkSL::BuiltinTypes& types = this->builtinTypes();
259 SymbolTable* symbols = module->fSymbols.get();
260
261 // Add some aliases to the runtime effect modules so that it's friendlier, and more like GLSL.
262 symbols->addWithoutOwnershipOrDie(types.fVec2.get());
263 symbols->addWithoutOwnershipOrDie(types.fVec3.get());
264 symbols->addWithoutOwnershipOrDie(types.fVec4.get());
265
266 symbols->addWithoutOwnershipOrDie(types.fIVec2.get());
267 symbols->addWithoutOwnershipOrDie(types.fIVec3.get());
268 symbols->addWithoutOwnershipOrDie(types.fIVec4.get());
269
270 symbols->addWithoutOwnershipOrDie(types.fBVec2.get());
271 symbols->addWithoutOwnershipOrDie(types.fBVec3.get());
272 symbols->addWithoutOwnershipOrDie(types.fBVec4.get());
273
274 symbols->addWithoutOwnershipOrDie(types.fMat2.get());
275 symbols->addWithoutOwnershipOrDie(types.fMat3.get());
276 symbols->addWithoutOwnershipOrDie(types.fMat4.get());
277
278 symbols->addWithoutOwnershipOrDie(types.fMat2x2.get());
279 symbols->addWithoutOwnershipOrDie(types.fMat2x3.get());
280 symbols->addWithoutOwnershipOrDie(types.fMat2x4.get());
281 symbols->addWithoutOwnershipOrDie(types.fMat3x2.get());
282 symbols->addWithoutOwnershipOrDie(types.fMat3x3.get());
283 symbols->addWithoutOwnershipOrDie(types.fMat3x4.get());
284 symbols->addWithoutOwnershipOrDie(types.fMat4x2.get());
285 symbols->addWithoutOwnershipOrDie(types.fMat4x3.get());
286 symbols->addWithoutOwnershipOrDie(types.fMat4x4.get());
287
288 // Hide all the private symbols by aliasing them all to "invalid". This will prevent code from
289 // using built-in names like `sampler2D` as variable names.
290 for (BuiltinTypePtr privateType : kPrivateTypes) {
291 symbols->inject(Type::MakeAliasType((types.*privateType)->name(), *types.fInvalid));
292 }
293}
294
296 if (!fModuleLoader.fPublicModule) {
297 const Module* sharedModule = this->loadSharedModule(compiler);
300 MODULE_DATA(sksl_public),
301 sharedModule);
302 this->addPublicTypeAliases(fModuleLoader.fPublicModule.get());
303 }
304 return fModuleLoader.fPublicModule.get();
305}
306
308 if (!fModuleLoader.fRuntimeShaderModule) {
309 const Module* publicModule = this->loadPublicModule(compiler);
312 MODULE_DATA(sksl_rt_shader),
313 publicModule);
314 }
315 return fModuleLoader.fRuntimeShaderModule.get();
316}
317
319 if (!fModuleLoader.fSharedModule) {
320 const Module* rootModule = this->rootModule();
323 MODULE_DATA(sksl_shared),
324 rootModule);
325 }
326 return fModuleLoader.fSharedModule.get();
327}
328
330 if (!fModuleLoader.fGPUModule) {
331 const Module* sharedModule = this->loadSharedModule(compiler);
332 fModuleLoader.fGPUModule = compile_and_shrink(compiler,
334 MODULE_DATA(sksl_gpu),
335 sharedModule);
336 }
337 return fModuleLoader.fGPUModule.get();
338}
339
341 if (!fModuleLoader.fFragmentModule) {
342 const Module* gpuModule = this->loadGPUModule(compiler);
345 MODULE_DATA(sksl_frag),
346 gpuModule);
347 }
348 return fModuleLoader.fFragmentModule.get();
349}
350
352 if (!fModuleLoader.fVertexModule) {
353 const Module* gpuModule = this->loadGPUModule(compiler);
356 MODULE_DATA(sksl_vert),
357 gpuModule);
358 }
359 return fModuleLoader.fVertexModule.get();
360}
361
363 if (!fModuleLoader.fComputeModule) {
364 const Module* gpuModule = this->loadGPUModule(compiler);
367 MODULE_DATA(sksl_compute),
368 gpuModule);
369 }
370 return fModuleLoader.fComputeModule.get();
371}
372
374#if defined(SK_GRAPHITE)
375 if (!fModuleLoader.fGraphiteFragmentModule) {
376 const Module* fragmentModule = this->loadFragmentModule(compiler);
379 MODULE_DATA(sksl_graphite_frag),
380 fragmentModule);
381 }
382 return fModuleLoader.fGraphiteFragmentModule.get();
383#else
384 return this->loadFragmentModule(compiler);
385#endif
386}
387
389#if defined(SK_GRAPHITE)
390 if (!fModuleLoader.fGraphiteFragmentES2Module) {
391 const Module* fragmentModule = this->loadFragmentModule(compiler);
392 fModuleLoader.fGraphiteFragmentES2Module =
395 MODULE_DATA(sksl_graphite_frag_es2),
396 fragmentModule);
397 }
398 return fModuleLoader.fGraphiteFragmentES2Module.get();
399#else
400 return this->loadFragmentModule(compiler);
401#endif
402}
403
405#if defined(SK_GRAPHITE)
406 if (!fModuleLoader.fGraphiteVertexModule) {
407 const Module* vertexModule = this->loadVertexModule(compiler);
410 MODULE_DATA(sksl_graphite_vert),
411 vertexModule);
412 }
413 return fModuleLoader.fGraphiteVertexModule.get();
414#else
415 return this->loadVertexModule(compiler);
416#endif
417}
418
420#if defined(SK_GRAPHITE)
421 if (!fModuleLoader.fGraphiteVertexES2Module) {
422 const Module* vertexModule = this->loadVertexModule(compiler);
423 fModuleLoader.fGraphiteVertexES2Module =
426 MODULE_DATA(sksl_graphite_vert_es2),
427 vertexModule);
428 }
429 return fModuleLoader.fGraphiteVertexES2Module.get();
430#else
431 return this->loadVertexModule(compiler);
432#endif
433}
434
436 auto rootModule = std::make_unique<Module>();
437 rootModule->fSymbols = std::make_unique<SymbolTable>(/*builtin=*/true);
438
439 for (BuiltinTypePtr rootType : kRootTypes) {
440 rootModule->fSymbols->addWithoutOwnershipOrDie((fBuiltinTypes.*rootType).get());
441 }
442
443 for (BuiltinTypePtr privateType : kPrivateTypes) {
444 rootModule->fSymbols->addWithoutOwnershipOrDie((fBuiltinTypes.*privateType).get());
445 }
446
447 // sk_Caps is "builtin", but all references to it are resolved to Settings, so we don't need to
448 // treat it as builtin (ie, no need to clone it into the Program).
449 rootModule->fSymbols->addOrDie(Variable::Make(/*pos=*/Position(),
450 /*modifiersPosition=*/Position(),
451 Layout{},
454 "sk_Caps",
455 /*mangledName=*/"",
456 /*builtin=*/false,
457 Variable::Storage::kGlobal));
458 fRootModule = std::move(rootModule);
459}
460
461} // namespace SkSL
#define SK_ABORT(message,...)
Definition SkAssert.h:70
std::string SkGetExecutablePath()
#define MODULE_DATA(name)
#define TYPE(t)
static SkString Join(const char *rootPath, const char *relativePath)
Definition SkOSPath.cpp:14
static SkString Dirname(const char *fullPath)
Definition SkOSPath.cpp:36
const std::unique_ptr< Type > fMat4x4
const std::unique_ptr< Type > fMat4x2
const std::unique_ptr< Type > fSkCaps
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 > 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)
Definition SkSLType.cpp:764
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 char * c_str() const
Definition SkString.h:133
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::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