• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 
8 #include "src/sksl/transform/SkSLTransform.h"
9 
10 #include "include/private/SkSLProgramKind.h"
11 #include "src/sksl/SkSLBuiltinMap.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLContext.h"
14 #include "src/sksl/SkSLThreadContext.h"
15 #include "src/sksl/analysis/SkSLProgramVisitor.h"
16 #include "src/sksl/ir/SkSLFunctionDefinition.h"
17 #include "src/sksl/ir/SkSLInterfaceBlock.h"
18 #include "src/sksl/ir/SkSLVarDeclarations.h"
19 
20 namespace SkSL {
21 
22 namespace Transform {
23 
FindAndDeclareBuiltinVariables(const Context & context,ProgramKind programKind,std::vector<const ProgramElement * > & sharedElements)24 void FindAndDeclareBuiltinVariables(const Context& context,
25         ProgramKind programKind, std::vector<const ProgramElement*>& sharedElements) {
26     class BuiltinVariableScanner : public ProgramVisitor {
27     public:
28         BuiltinVariableScanner(const Context& context)
29             : fContext(context) {}
30 
31         void addDeclaringElement(const std::string& name) {
32             // If this is the *first* time we've seen this builtin, findAndInclude will return
33             // the corresponding ProgramElement.
34             BuiltinMap& builtins = *fContext.fBuiltins;
35             if (const ProgramElement* decl = builtins.findAndInclude(name)) {
36                 SkASSERT(decl->is<GlobalVarDeclaration>() || decl->is<InterfaceBlock>());
37                 fNewElements.push_back(decl);
38             }
39         }
40 
41         bool visitProgramElement(const ProgramElement& pe) override {
42             if (pe.is<FunctionDefinition>()) {
43                 const FunctionDefinition& funcDef = pe.as<FunctionDefinition>();
44                 // We synthesize writes to sk_FragColor if main() returns a color, even if it's
45                 // otherwise unreferenced. Check main's return type to see if it's half4.
46                 if (funcDef.declaration().isMain() &&
47                     funcDef.declaration().returnType().matches(*fContext.fTypes.fHalf4)) {
48                     fPreserveFragColor = true;
49                 }
50             }
51             return INHERITED::visitProgramElement(pe);
52         }
53 
54         bool visitExpression(const Expression& e) override {
55             if (e.is<VariableReference>() && e.as<VariableReference>().variable()->isBuiltin()) {
56                 this->addDeclaringElement(
57                         std::string(e.as<VariableReference>().variable()->name()));
58             }
59             return INHERITED::visitExpression(e);
60         }
61 
62         const Context& fContext;
63         std::vector<const ProgramElement*> fNewElements;
64         bool fPreserveFragColor = false;
65 
66         using INHERITED = ProgramVisitor;
67         using INHERITED::visitProgramElement;
68     };
69 
70     BuiltinVariableScanner scanner(context);
71     for (auto& e : ThreadContext::ProgramElements()) {
72         scanner.visitProgramElement(*e);
73     }
74 
75     if (scanner.fPreserveFragColor) {
76         // main() returns a half4, so make sure we don't dead-strip sk_FragColor.
77         scanner.addDeclaringElement(Compiler::FRAGCOLOR_NAME);
78     }
79 
80     switch (programKind) {
81         case ProgramKind::kFragment:
82             // Vulkan requires certain builtin variables be present, even if they're unused. At one
83             // time, validation errors would result if sk_Clockwise was missing. Now, it's just
84             // (Adreno) driver bugs that drop or corrupt draws if they're missing.
85             scanner.addDeclaringElement("sk_Clockwise");
86             break;
87         default:
88             break;
89     }
90 
91     sharedElements.insert(sharedElements.begin(), scanner.fNewElements.begin(),
92             scanner.fNewElements.end());
93 }
94 
95 } // namespace Transform
96 
97 } // namespace SkSL
98