Coverage Report

Created: 2021-08-22 09:07

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