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