• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
7 #include "src/sksl/SkSLModuleLoader.h"
8 
9 #include "include/core/SkTypes.h"
10 #include "include/private/base/SkMutex.h"
11 #include "src/base/SkNoDestructor.h"
12 #include "src/sksl/SkSLBuiltinTypes.h"
13 #include "src/sksl/SkSLCompiler.h"
14 #include "src/sksl/SkSLModuleData.h"
15 #include "src/sksl/SkSLPosition.h"
16 #include "src/sksl/SkSLProgramKind.h"
17 #include "src/sksl/ir/SkSLIRNode.h"
18 #include "src/sksl/ir/SkSLLayout.h"
19 #include "src/sksl/ir/SkSLModifierFlags.h"
20 #include "src/sksl/ir/SkSLProgramElement.h"
21 #include "src/sksl/ir/SkSLSymbolTable.h"
22 #include "src/sksl/ir/SkSLType.h"
23 #include "src/sksl/ir/SkSLVariable.h"
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 
33 namespace SkSL {
34 
35 #define TYPE(t) &BuiltinTypes::f ## t
36 
37 static 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 
70     TYPE(ColorFilter),
71     TYPE(Shader),
72     TYPE(Blender),
73 };
74 
75 static constexpr BuiltinTypePtr kPrivateTypes[] = {
76     TYPE(Sampler2D), TYPE(SamplerExternalOES), TYPE(Sampler2DRect),
77 
78     TYPE(SubpassInput), TYPE(SubpassInputMS),
79 
80     TYPE(Sampler),
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 
90 struct ModuleLoader::Impl {
91     Impl();
92 
93     void makeRootSymbolTable();
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;
98     const BuiltinTypes fBuiltinTypes;
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 
Get()118 ModuleLoader ModuleLoader::Get() {
119     static SkNoDestructor<ModuleLoader::Impl> sModuleLoaderImpl;
120     return ModuleLoader(*sModuleLoaderImpl);
121 }
122 
ModuleLoader(ModuleLoader::Impl & m)123 ModuleLoader::ModuleLoader(ModuleLoader::Impl& m) : fModuleLoader(m) {
124     fModuleLoader.fMutex.acquire();
125 }
126 
~ModuleLoader()127 ModuleLoader::~ModuleLoader() {
128     fModuleLoader.fMutex.release();
129 }
130 
unloadModules()131 void ModuleLoader::unloadModules() {
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 
Impl()143 ModuleLoader::Impl::Impl() {
144     this->makeRootSymbolTable();
145 }
146 
compile_and_shrink(SkSL::Compiler * compiler,ProgramKind kind,const char * moduleName,std::string moduleSource,const Module * parent)147 static 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,
153                                                         moduleName,
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 
builtinTypes()191 const BuiltinTypes& ModuleLoader::builtinTypes() {
192     return fModuleLoader.fBuiltinTypes;
193 }
194 
rootModule()195 const Module* ModuleLoader::rootModule() {
196     return fModuleLoader.fRootModule.get();
197 }
198 
addPublicTypeAliases(const SkSL::Module * module)199 void ModuleLoader::addPublicTypeAliases(const SkSL::Module* module) {
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 
loadPublicModule(SkSL::Compiler * compiler)241 const Module* ModuleLoader::loadPublicModule(SkSL::Compiler* compiler) {
242     if (!fModuleLoader.fPublicModule) {
243         const Module* sharedModule = this->loadSharedModule(compiler);
244         fModuleLoader.fPublicModule = compile_and_shrink(compiler,
245                                                          ProgramKind::kFragment,
246                                                          MODULE_DATA(sksl_public),
247                                                          sharedModule);
248         this->addPublicTypeAliases(fModuleLoader.fPublicModule.get());
249     }
250     return fModuleLoader.fPublicModule.get();
251 }
252 
loadPrivateRTShaderModule(SkSL::Compiler * compiler)253 const Module* ModuleLoader::loadPrivateRTShaderModule(SkSL::Compiler* compiler) {
254     if (!fModuleLoader.fRuntimeShaderModule) {
255         const Module* publicModule = this->loadPublicModule(compiler);
256         fModuleLoader.fRuntimeShaderModule = compile_and_shrink(compiler,
257                                                                 ProgramKind::kFragment,
258                                                                 MODULE_DATA(sksl_rt_shader),
259                                                                 publicModule);
260     }
261     return fModuleLoader.fRuntimeShaderModule.get();
262 }
263 
loadSharedModule(SkSL::Compiler * compiler)264 const Module* ModuleLoader::loadSharedModule(SkSL::Compiler* compiler) {
265     if (!fModuleLoader.fSharedModule) {
266         const Module* rootModule = this->rootModule();
267         fModuleLoader.fSharedModule = compile_and_shrink(compiler,
268                                                          ProgramKind::kFragment,
269                                                          MODULE_DATA(sksl_shared),
270                                                          rootModule);
271     }
272     return fModuleLoader.fSharedModule.get();
273 }
274 
loadGPUModule(SkSL::Compiler * compiler)275 const Module* ModuleLoader::loadGPUModule(SkSL::Compiler* compiler) {
276     if (!fModuleLoader.fGPUModule) {
277         const Module* sharedModule = this->loadSharedModule(compiler);
278         fModuleLoader.fGPUModule = compile_and_shrink(compiler,
279                                                       ProgramKind::kFragment,
280                                                       MODULE_DATA(sksl_gpu),
281                                                       sharedModule);
282     }
283     return fModuleLoader.fGPUModule.get();
284 }
285 
loadFragmentModule(SkSL::Compiler * compiler)286 const Module* ModuleLoader::loadFragmentModule(SkSL::Compiler* compiler) {
287     if (!fModuleLoader.fFragmentModule) {
288         const Module* gpuModule = this->loadGPUModule(compiler);
289         fModuleLoader.fFragmentModule = compile_and_shrink(compiler,
290                                                            ProgramKind::kFragment,
291                                                            MODULE_DATA(sksl_frag),
292                                                            gpuModule);
293     }
294     return fModuleLoader.fFragmentModule.get();
295 }
296 
loadVertexModule(SkSL::Compiler * compiler)297 const Module* ModuleLoader::loadVertexModule(SkSL::Compiler* compiler) {
298     if (!fModuleLoader.fVertexModule) {
299         const Module* gpuModule = this->loadGPUModule(compiler);
300         fModuleLoader.fVertexModule = compile_and_shrink(compiler,
301                                                          ProgramKind::kVertex,
302                                                          MODULE_DATA(sksl_vert),
303                                                          gpuModule);
304     }
305     return fModuleLoader.fVertexModule.get();
306 }
307 
loadComputeModule(SkSL::Compiler * compiler)308 const Module* ModuleLoader::loadComputeModule(SkSL::Compiler* compiler) {
309     if (!fModuleLoader.fComputeModule) {
310         const Module* gpuModule = this->loadGPUModule(compiler);
311         fModuleLoader.fComputeModule = compile_and_shrink(compiler,
312                                                           ProgramKind::kCompute,
313                                                           MODULE_DATA(sksl_compute),
314                                                           gpuModule);
315     }
316     return fModuleLoader.fComputeModule.get();
317 }
318 
loadGraphiteFragmentModule(SkSL::Compiler * compiler)319 const Module* ModuleLoader::loadGraphiteFragmentModule(SkSL::Compiler* compiler) {
320 #if defined(SK_GRAPHITE)
321     if (!fModuleLoader.fGraphiteFragmentModule) {
322         const Module* fragmentModule = this->loadFragmentModule(compiler);
323         fModuleLoader.fGraphiteFragmentModule = compile_and_shrink(compiler,
324                                                                    ProgramKind::kGraphiteFragment,
325                                                                    MODULE_DATA(sksl_graphite_frag),
326                                                                    fragmentModule);
327     }
328     return fModuleLoader.fGraphiteFragmentModule.get();
329 #else
330     return this->loadFragmentModule(compiler);
331 #endif
332 }
333 
loadGraphiteFragmentES2Module(SkSL::Compiler * compiler)334 const Module* ModuleLoader::loadGraphiteFragmentES2Module(SkSL::Compiler* compiler) {
335 #if defined(SK_GRAPHITE)
336     if (!fModuleLoader.fGraphiteFragmentES2Module) {
337         const Module* fragmentModule = this->loadFragmentModule(compiler);
338         fModuleLoader.fGraphiteFragmentES2Module =
339                 compile_and_shrink(compiler,
340                                    ProgramKind::kGraphiteFragmentES2,
341                                    MODULE_DATA(sksl_graphite_frag_es2),
342                                    fragmentModule);
343     }
344     return fModuleLoader.fGraphiteFragmentES2Module.get();
345 #else
346     return this->loadFragmentModule(compiler);
347 #endif
348 }
349 
loadGraphiteVertexModule(SkSL::Compiler * compiler)350 const Module* ModuleLoader::loadGraphiteVertexModule(SkSL::Compiler* compiler) {
351 #if defined(SK_GRAPHITE)
352     if (!fModuleLoader.fGraphiteVertexModule) {
353         const Module* vertexModule = this->loadVertexModule(compiler);
354         fModuleLoader.fGraphiteVertexModule = compile_and_shrink(compiler,
355                                                                  ProgramKind::kGraphiteVertex,
356                                                                  MODULE_DATA(sksl_graphite_vert),
357                                                                  vertexModule);
358     }
359     return fModuleLoader.fGraphiteVertexModule.get();
360 #else
361     return this->loadVertexModule(compiler);
362 #endif
363 }
364 
loadGraphiteVertexES2Module(SkSL::Compiler * compiler)365 const Module* ModuleLoader::loadGraphiteVertexES2Module(SkSL::Compiler* compiler) {
366 #if defined(SK_GRAPHITE)
367     if (!fModuleLoader.fGraphiteVertexES2Module) {
368         const Module* vertexModule = this->loadVertexModule(compiler);
369         fModuleLoader.fGraphiteVertexES2Module =
370                 compile_and_shrink(compiler,
371                                    ProgramKind::kGraphiteVertexES2,
372                                    MODULE_DATA(sksl_graphite_vert_es2),
373                                    vertexModule);
374     }
375     return fModuleLoader.fGraphiteVertexES2Module.get();
376 #else
377     return this->loadVertexModule(compiler);
378 #endif
379 }
380 
makeRootSymbolTable()381 void ModuleLoader::Impl::makeRootSymbolTable() {
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{},
398                                                   ModifierFlag::kNone,
399                                                   fBuiltinTypes.fSkCaps.get(),
400                                                   "sk_Caps",
401                                                   /*mangledName=*/"",
402                                                   /*builtin=*/false,
403                                                   Variable::Storage::kGlobal));
404     fRootModule = std::move(rootModule);
405 }
406 
407 }  // namespace SkSL
408