• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 #include "src/sksl/ir/SkSLSetting.h"
9 
10 #include "include/sksl/SkSLErrorReporter.h"
11 #include "src/sksl/SkSLProgramSettings.h"
12 #include "src/sksl/ir/SkSLLiteral.h"
13 #include "src/sksl/ir/SkSLVariableReference.h"
14 
15 namespace SkSL {
16 
17 // Helper classes for converting caps fields to Expressions and Types in the CapsLookupTable.
18 namespace {
19 
20 class CapsLookupMethod {
21 public:
~CapsLookupMethod()22     virtual ~CapsLookupMethod() {}
23     virtual const Type* type(const Context& context) const = 0;
24     virtual std::unique_ptr<Expression> value(const Context& context) const = 0;
25 };
26 
27 class BoolCapsLookup : public CapsLookupMethod {
28 public:
29     using CapsFn = bool (ShaderCapsClass::*)() const;
30 
BoolCapsLookup(const CapsFn & fn)31     BoolCapsLookup(const CapsFn& fn) : fGetCap(fn) {}
32 
type(const Context & context) const33     const Type* type(const Context& context) const override {
34         return context.fTypes.fBool.get();
35     }
value(const Context & context) const36     std::unique_ptr<Expression> value(const Context& context) const override {
37         return Literal::MakeBool(context, /*line=*/-1, (context.fCaps.*fGetCap)());
38     }
39 
40 private:
41     CapsFn fGetCap;
42 };
43 
44 class IntCapsLookup : public CapsLookupMethod {
45 public:
46     using CapsFn = int (ShaderCapsClass::*)() const;
47 
IntCapsLookup(const CapsFn & fn)48     IntCapsLookup(const CapsFn& fn) : fGetCap(fn) {}
49 
type(const Context & context) const50     const Type* type(const Context& context) const override {
51         return context.fTypes.fInt.get();
52     }
value(const Context & context) const53     std::unique_ptr<Expression> value(const Context& context) const override {
54         return Literal::MakeInt(context, /*line=*/-1, (context.fCaps.*fGetCap)());
55     }
56 
57 private:
58     CapsFn fGetCap;
59 };
60 
61 class CapsLookupTable {
62 public:
63     using Pair = std::pair<const char*, CapsLookupMethod*>;
64 
CapsLookupTable(std::initializer_list<Pair> capsLookups)65     CapsLookupTable(std::initializer_list<Pair> capsLookups) {
66         for (auto& entry : capsLookups) {
67             fMap[entry.first] = std::unique_ptr<CapsLookupMethod>(entry.second);
68         }
69     }
70 
lookup(skstd::string_view name) const71     const CapsLookupMethod* lookup(skstd::string_view name) const {
72         auto iter = fMap.find(name);
73         return (iter != fMap.end()) ? iter->second.get() : nullptr;
74     }
75 
76 private:
77     std::unordered_map<skstd::string_view, std::unique_ptr<CapsLookupMethod>> fMap;
78 };
79 
caps_lookup_table()80 static const CapsLookupTable& caps_lookup_table() {
81     // Create a lookup table that converts strings into the equivalent ShaderCapsClass methods.
82     static CapsLookupTable* sCapsLookupTable = new CapsLookupTable({
83     #define CAP(T, name) CapsLookupTable::Pair{#name, new T##CapsLookup{&ShaderCapsClass::name}}
84         CAP(Bool, fbFetchSupport),
85         CAP(Bool, fbFetchNeedsCustomOutput),
86         CAP(Bool, flatInterpolationSupport),
87         CAP(Bool, noperspectiveInterpolationSupport),
88         CAP(Bool, externalTextureSupport),
89         CAP(Bool, mustEnableAdvBlendEqs),
90         CAP(Bool, mustDeclareFragmentShaderOutput),
91         CAP(Bool, mustDoOpBetweenFloorAndAbs),
92         CAP(Bool, mustGuardDivisionEvenAfterExplicitZeroCheck),
93         CAP(Bool, atan2ImplementedAsAtanYOverX),
94         CAP(Bool, canUseAnyFunctionInShader),
95         CAP(Bool, floatIs32Bits),
96         CAP(Bool, integerSupport),
97         CAP(Bool, builtinFMASupport),
98         CAP(Bool, builtinDeterminantSupport),
99         CAP(Bool, rewriteMatrixVectorMultiply),
100     #undef CAP
101     });
102     return *sCapsLookupTable;
103 }
104 
105 }  // namespace
106 
get_type(const Context & context,int line,skstd::string_view name)107 static const Type* get_type(const Context& context, int line, skstd::string_view name) {
108     if (const CapsLookupMethod* caps = caps_lookup_table().lookup(name)) {
109         return caps->type(context);
110     }
111 
112     context.fErrors->error(line, "unknown capability flag '" + name + "'");
113     return nullptr;
114 }
115 
get_value(const Context & context,int line,const skstd::string_view & name)116 static std::unique_ptr<Expression> get_value(const Context& context, int line,
117                                              const skstd::string_view& name) {
118     if (const CapsLookupMethod* caps = caps_lookup_table().lookup(name)) {
119         return caps->value(context);
120     }
121 
122     context.fErrors->error(line, "unknown capability flag '" + name + "'");
123     return nullptr;
124 }
125 
Convert(const Context & context,int line,const skstd::string_view & name)126 std::unique_ptr<Expression> Setting::Convert(const Context& context, int line,
127                                              const skstd::string_view& name) {
128     SkASSERT(context.fConfig);
129 
130     if (context.fConfig->fSettings.fReplaceSettings) {
131         // Insert the settings value directly into the IR.
132         return get_value(context, line, name);
133     }
134 
135     // Generate a Setting IRNode.
136     const Type* type = get_type(context, line, name);
137     return type ? std::make_unique<Setting>(line, name, type) : nullptr;
138 }
139 
140 }  // namespace SkSL
141