Remove CapsMap from IR Generator.
Previously, the IRGenerator's fCapsMap was a lookup table from caps-name to caps-value. This has been replaced with a lookup table from caps-name to caps-lookup-method. This is more general-purpose; you can initialize it once and it always works, instead of needing to initialize it based on a static set of caps. The next step after this CL is to migrate this logic into Settings and remove caps handling from the IR Generator entirely. Change-Id: I09fc8220f8d5bf297033adbaf4c955f2ce0589cf Bug: skia:11365, skia:11319 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/375074 Commit-Queue: John Stiles <johnstiles@google.com> Commit-Queue: Brian Osman <brianosman@google.com> Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
d42932a1b5
commit
6394bb43cb
@ -79,51 +79,93 @@ public:
|
|||||||
std::shared_ptr<SymbolTable> fPrevious;
|
std::shared_ptr<SymbolTable> fPrevious;
|
||||||
};
|
};
|
||||||
|
|
||||||
void IRGenerator::FillCapsMap(const SkSL::ShaderCapsClass& caps,
|
// Helper classes for converting caps fields to Expressions and Types in the CapsLookupTable.
|
||||||
std::unordered_map<String, CapsValue>* capsMap) {
|
class CapsLookupMethod {
|
||||||
#define CAP(name) capsMap->insert({String(#name), CapsValue(caps.name())})
|
public:
|
||||||
CAP(fbFetchSupport);
|
virtual ~CapsLookupMethod() {}
|
||||||
CAP(fbFetchNeedsCustomOutput);
|
virtual const Type* type(const Context& context) const = 0;
|
||||||
CAP(flatInterpolationSupport);
|
virtual std::unique_ptr<Expression> value(const Context& context) const = 0;
|
||||||
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<Expression> IRGenerator::CapsValue::literal(const Context& context,
|
class BoolCapsLookup : public CapsLookupMethod {
|
||||||
int offset) const {
|
public:
|
||||||
switch (fKind) {
|
using CapsFn = bool (ShaderCapsClass::*)() const;
|
||||||
case kBool_Kind:
|
|
||||||
return std::make_unique<BoolLiteral>(context, offset, fValue);
|
|
||||||
|
|
||||||
case kInt_Kind:
|
BoolCapsLookup(const CapsFn& fn) : fGetCap(fn) {}
|
||||||
return std::make_unique<IntLiteral>(context, offset, fValue);
|
|
||||||
|
|
||||||
case kFloat_Kind:
|
const Type* type(const Context& context) const override {
|
||||||
return std::make_unique<FloatLiteral>(context, offset, fValueF);
|
return context.fTypes.fBool.get();
|
||||||
|
|
||||||
default:
|
|
||||||
SkDEBUGFAILF("unrecognized caps kind: %d", fKind);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
std::unique_ptr<Expression> value(const Context& context) const override {
|
||||||
|
return std::make_unique<BoolLiteral>(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<Expression> value(const Context& context) const override {
|
||||||
|
return std::make_unique<IntLiteral>(context, /*offset=*/-1, (context.fCaps.*fGetCap)());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CapsFn fGetCap;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CapsLookupTable {
|
||||||
|
public:
|
||||||
|
using Pair = std::pair<const char*, CapsLookupMethod*>;
|
||||||
|
|
||||||
|
CapsLookupTable(std::initializer_list<Pair> capsLookups) {
|
||||||
|
for (auto& entry : capsLookups) {
|
||||||
|
fMap[entry.first] = std::unique_ptr<CapsLookupMethod>(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<String, std::unique_ptr<CapsLookupMethod>> 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),
|
||||||
|
#undef CAP
|
||||||
|
}};
|
||||||
|
|
||||||
IRGenerator::IRGenerator(const Context* context)
|
IRGenerator::IRGenerator(const Context* context)
|
||||||
: fContext(*context)
|
: fContext(*context)
|
||||||
, fModifiers(new ModifiersPool()) {
|
, fModifiers(new ModifiersPool()) {}
|
||||||
FillCapsMap(context->fCaps, &fCapsMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRGenerator::pushSymbolTable() {
|
void IRGenerator::pushSymbolTable() {
|
||||||
auto childSymTable = std::make_shared<SymbolTable>(std::move(fSymbolTable), fIsBuiltinCode);
|
auto childSymTable = std::make_shared<SymbolTable>(std::move(fSymbolTable), fIsBuiltinCode);
|
||||||
@ -2389,27 +2431,21 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Type* IRGenerator::typeForSetting(int offset, String name) const {
|
const Type* IRGenerator::typeForSetting(int offset, String name) const {
|
||||||
auto found = fCapsMap.find(name);
|
if (const CapsLookupMethod* caps = sCapsLookupTable.lookup(name)) {
|
||||||
if (found == fCapsMap.end()) {
|
return caps->type(fContext);
|
||||||
this->errorReporter().error(offset, "unknown capability flag '" + name + "'");
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
switch (found->second.fKind) {
|
|
||||||
case CapsValue::kBool_Kind: return fContext.fTypes.fBool.get();
|
this->errorReporter().error(offset, "unknown capability flag '" + name + "'");
|
||||||
case CapsValue::kFloat_Kind: return fContext.fTypes.fFloat.get();
|
|
||||||
case CapsValue::kInt_Kind: return fContext.fTypes.fInt.get();
|
|
||||||
}
|
|
||||||
SkUNREACHABLE;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Expression> IRGenerator::valueForSetting(int offset, String name) const {
|
std::unique_ptr<Expression> IRGenerator::valueForSetting(int offset, String name) const {
|
||||||
auto found = fCapsMap.find(name);
|
if (const CapsLookupMethod* caps = sCapsLookupTable.lookup(name)) {
|
||||||
if (found == fCapsMap.end()) {
|
return caps->value(fContext);
|
||||||
this->errorReporter().error(offset, "unknown capability flag '" + name + "'");
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
return found->second.literal(fContext, offset);
|
|
||||||
|
this->errorReporter().error(offset, "unknown capability flag '" + name + "'");
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
|
std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
|
||||||
|
@ -278,30 +278,6 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<ASTFile> fFile;
|
std::unique_ptr<ASTFile> 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<Expression> 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<String, CapsValue>* capsMap);
|
|
||||||
|
|
||||||
std::unordered_map<String, CapsValue> fCapsMap;
|
|
||||||
std::shared_ptr<SymbolTable> fSymbolTable = nullptr;
|
std::shared_ptr<SymbolTable> fSymbolTable = nullptr;
|
||||||
// additional statements that need to be inserted before the one that convertStatement is
|
// additional statements that need to be inserted before the one that convertStatement is
|
||||||
// currently working on
|
// currently working on
|
||||||
|
Loading…
Reference in New Issue
Block a user