diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 4c5b1a756a..c9d2913a1c 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -79,93 +79,51 @@ public: std::shared_ptr fPrevious; }; -// Helper classes for converting caps fields to Expressions and Types in the CapsLookupTable. -class CapsLookupMethod { -public: - virtual ~CapsLookupMethod() {} - virtual const Type* type(const Context& context) const = 0; - virtual std::unique_ptr value(const Context& context) const = 0; -}; - -class BoolCapsLookup : public CapsLookupMethod { -public: - using CapsFn = bool (ShaderCapsClass::*)() const; - - BoolCapsLookup(const CapsFn& fn) : fGetCap(fn) {} - - const Type* type(const Context& context) const override { - return context.fTypes.fBool.get(); - } - std::unique_ptr value(const Context& context) const override { - return std::make_unique(context, /*offset=*/-1, (context.fCaps.*fGetCap)()); - } - -private: - CapsFn fGetCap; -}; - -class IntCapsLookup : public CapsLookupMethod { -public: - using CapsFn = int (ShaderCapsClass::*)() const; - - IntCapsLookup(const CapsFn& fn) : fGetCap(fn) {} - - const Type* type(const Context& context) const override { - return context.fTypes.fInt.get(); - } - std::unique_ptr value(const Context& context) const override { - return std::make_unique(context, /*offset=*/-1, (context.fCaps.*fGetCap)()); - } - -private: - CapsFn fGetCap; -}; - -class CapsLookupTable { -public: - using Pair = std::pair; - - CapsLookupTable(std::initializer_list capsLookups) { - for (auto& entry : capsLookups) { - fMap[entry.first] = std::unique_ptr(entry.second); - } - } - - const CapsLookupMethod* lookup(const String& name) const { - auto iter = fMap.find(name); - return (iter != fMap.end()) ? iter->second.get() : nullptr; - } - -private: - std::unordered_map> fMap; -}; - -// Create a lookup table at startup that converts strings into the equivalent ShaderCapsClass -// methods. -static CapsLookupTable sCapsLookupTable{{ -#define CAP(T, name) CapsLookupTable::Pair{#name, new T##CapsLookup{&ShaderCapsClass::name}} - CAP(Bool, fbFetchSupport), - CAP(Bool, fbFetchNeedsCustomOutput), - CAP(Bool, flatInterpolationSupport), - CAP(Bool, noperspectiveInterpolationSupport), - CAP(Bool, externalTextureSupport), - CAP(Bool, mustEnableAdvBlendEqs), - CAP(Bool, mustDeclareFragmentShaderOutput), - CAP(Bool, mustDoOpBetweenFloorAndAbs), - CAP(Bool, mustGuardDivisionEvenAfterExplicitZeroCheck), - CAP(Bool, inBlendModesFailRandomlyForAllZeroVec), - CAP(Bool, atan2ImplementedAsAtanYOverX), - CAP(Bool, canUseAnyFunctionInShader), - CAP(Bool, floatIs32Bits), - CAP(Bool, integerSupport), - CAP(Bool, builtinFMASupport), - CAP(Bool, builtinDeterminantSupport), +void IRGenerator::FillCapsMap(const SkSL::ShaderCapsClass& caps, + std::unordered_map* capsMap) { +#define CAP(name) capsMap->insert({String(#name), CapsValue(caps.name())}) + CAP(fbFetchSupport); + CAP(fbFetchNeedsCustomOutput); + CAP(flatInterpolationSupport); + CAP(noperspectiveInterpolationSupport); + CAP(externalTextureSupport); + CAP(mustEnableAdvBlendEqs); + CAP(mustDeclareFragmentShaderOutput); + CAP(mustDoOpBetweenFloorAndAbs); + CAP(mustGuardDivisionEvenAfterExplicitZeroCheck); + CAP(inBlendModesFailRandomlyForAllZeroVec); + CAP(atan2ImplementedAsAtanYOverX); + CAP(canUseAnyFunctionInShader); + CAP(floatIs32Bits); + CAP(integerSupport); + CAP(builtinFMASupport); + CAP(builtinDeterminantSupport); #undef CAP -}}; +} + +std::unique_ptr IRGenerator::CapsValue::literal(const Context& context, + int offset) const { + switch (fKind) { + case kBool_Kind: + return std::make_unique(context, offset, fValue); + + case kInt_Kind: + return std::make_unique(context, offset, fValue); + + case kFloat_Kind: + return std::make_unique(context, offset, fValueF); + + default: + SkDEBUGFAILF("unrecognized caps kind: %d", fKind); + return nullptr; + } +} IRGenerator::IRGenerator(const Context* context) : fContext(*context) - , fModifiers(new ModifiersPool()) {} + , fModifiers(new ModifiersPool()) { + FillCapsMap(context->fCaps, &fCapsMap); +} void IRGenerator::pushSymbolTable() { auto childSymTable = std::make_shared(std::move(fSymbolTable), fIsBuiltinCode); @@ -2431,21 +2389,27 @@ std::unique_ptr IRGenerator::convertSwizzle(std::unique_ptrtype(fContext); + auto found = fCapsMap.find(name); + if (found == fCapsMap.end()) { + this->errorReporter().error(offset, "unknown capability flag '" + name + "'"); + return nullptr; } - - this->errorReporter().error(offset, "unknown capability flag '" + name + "'"); + switch (found->second.fKind) { + case CapsValue::kBool_Kind: return fContext.fTypes.fBool.get(); + case CapsValue::kFloat_Kind: return fContext.fTypes.fFloat.get(); + case CapsValue::kInt_Kind: return fContext.fTypes.fInt.get(); + } + SkUNREACHABLE; return nullptr; } std::unique_ptr IRGenerator::valueForSetting(int offset, String name) const { - if (const CapsLookupMethod* caps = sCapsLookupTable.lookup(name)) { - return caps->value(fContext); + auto found = fCapsMap.find(name); + if (found == fCapsMap.end()) { + this->errorReporter().error(offset, "unknown capability flag '" + name + "'"); + return nullptr; } - - this->errorReporter().error(offset, "unknown capability flag '" + name + "'"); - return nullptr; + return found->second.literal(fContext, offset); } std::unique_ptr IRGenerator::convertTypeField(int offset, const Type& type, diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 06a90580e9..68102535f5 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -278,6 +278,30 @@ private: std::unique_ptr fFile; + struct CapsValue { + CapsValue(bool b) : fKind(kBool_Kind), fValue(b) {} + CapsValue(int i) : fKind(kInt_Kind), fValue(i) {} + CapsValue(unsigned int i) : fKind(kInt_Kind), fValue(i) {} + CapsValue(float f) : fKind(kFloat_Kind), fValueF(f) {} + + std::unique_ptr literal(const Context& context, int offset) const; + + enum { + kBool_Kind, + kInt_Kind, + kFloat_Kind, + } fKind; + + union { + int fValue; // for kBool_Kind and kInt_Kind + float fValueF; // for kFloat_Kind + }; + }; + + static void FillCapsMap(const SkSL::ShaderCapsClass& caps, + std::unordered_map* capsMap); + + std::unordered_map fCapsMap; std::shared_ptr fSymbolTable = nullptr; // additional statements that need to be inserted before the one that convertStatement is // currently working on