Improve handling of SkSL literal types.

Previously, the only way to detect a literal Type was to explicitly
check against the values fFloatLiteral/fIntLiteral or compare the name
against $floatLiteral or $intLiteral.

Now, you can call type.isLiteral() to see if the type corresponds to a
literal, or call type.scalarTypeForLiteral() to promote to the
equivalent non-literal type (fFloat/fInt). Calling
type.scalarTypeForLiteral() on a non-literal type is safe and will just
return the input type unscathed.

Change-Id: Ib939dda9bcd43b3ef4159211c5349d71fc857b95
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/353037
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2021-01-12 11:41:14 -05:00 committed by Skia Commit-Bot
parent 5251c8275e
commit 1497527c6f
5 changed files with 45 additions and 37 deletions

View File

@ -27,13 +27,7 @@ namespace SkSL {
}
BuiltinTypes::BuiltinTypes()
: fInvalid(Type::MakeOtherType("<INVALID>"))
, fVoid(Type::MakeOtherType("void"))
, fFloatLiteral(
Type::MakeScalarType("$floatLiteral", Type::NumberKind::kFloat, /*priority=*/8))
, fIntLiteral(
Type::MakeScalarType("$intLiteral", Type::NumberKind::kSigned, /*priority=*/5))
, fFloat(Type::MakeScalarType(
: fFloat(Type::MakeScalarType(
"float", Type::NumberKind::kFloat, /*priority=*/10, /*highPrecision=*/true))
, fFloat2(Type::MakeVectorType("float2", *fFloat, /*columns=*/2))
, fFloat3(Type::MakeVectorType("float3", *fFloat, /*columns=*/3))
@ -72,6 +66,10 @@ BuiltinTypes::BuiltinTypes()
, fBool2(Type::MakeVectorType("bool2", *fBool, /*columns=*/2))
, fBool3(Type::MakeVectorType("bool3", *fBool, /*columns=*/3))
, fBool4(Type::MakeVectorType("bool4", *fBool, /*columns=*/4))
, fInvalid(Type::MakeOtherType("<INVALID>"))
, fVoid(Type::MakeOtherType("void"))
, fFloatLiteral(Type::MakeLiteralType("$floatLiteral", *fFloat, /*priority=*/8))
, fIntLiteral(Type::MakeLiteralType("$intLiteral", *fInt, /*priority=*/5))
, fFloat2x2(Type::MakeMatrixType("float2x2", *fFloat, /*columns=*/2, /*rows=*/2))
, fFloat2x3(Type::MakeMatrixType("float2x3", *fFloat, /*columns=*/2, /*rows=*/3))
, fFloat2x4(Type::MakeMatrixType("float2x4", *fFloat, /*columns=*/2, /*rows=*/4))

View File

@ -22,11 +22,6 @@ namespace SkSL {
struct BuiltinTypes {
BuiltinTypes();
const std::unique_ptr<Type> fInvalid;
const std::unique_ptr<Type> fVoid;
const std::unique_ptr<Type> fFloatLiteral;
const std::unique_ptr<Type> fIntLiteral;
const std::unique_ptr<Type> fFloat;
const std::unique_ptr<Type> fFloat2;
const std::unique_ptr<Type> fFloat3;
@ -72,6 +67,11 @@ struct BuiltinTypes {
const std::unique_ptr<Type> fBool3;
const std::unique_ptr<Type> fBool4;
const std::unique_ptr<Type> fInvalid;
const std::unique_ptr<Type> fVoid;
const std::unique_ptr<Type> fFloatLiteral;
const std::unique_ptr<Type> fIntLiteral;
const std::unique_ptr<Type> fFloat2x2;
const std::unique_ptr<Type> fFloat2x3;
const std::unique_ptr<Type> fFloat2x4;

View File

@ -1555,13 +1555,7 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
return std::make_unique<Constructor>(offset, &type, std::move(args));
}
std::unique_ptr<Expression> ctor;
if (type == *fContext.fTypes.fFloatLiteral) {
ctor = this->convertIdentifier(offset, "float");
} else if (type == *fContext.fTypes.fIntLiteral) {
ctor = this->convertIdentifier(offset, "int");
} else {
ctor = this->convertIdentifier(offset, type.name());
}
ctor = this->convertIdentifier(offset, type.scalarTypeForLiteral().name());
if (!ctor) {
this->errorReporter().error(offset, "null identifier: " + type.name());
return nullptr;

View File

@ -595,12 +595,9 @@ Inliner::InlineVariable Inliner::makeInlineVariable(const String& baseName,
// $floatLiteral or $intLiteral aren't real types that we can use for scratch variables, so
// replace them if they ever appear here. If this happens, we likely forgot to coerce a type
// somewhere during compilation.
if (type == fContext->fTypes.fFloatLiteral.get()) {
SkDEBUGFAIL("found a $floatLiteral type while inlining");
type = fContext->fTypes.fFloat.get();
} else if (type == fContext->fTypes.fIntLiteral.get()) {
SkDEBUGFAIL("found an $intLiteral type while inlining");
type = fContext->fTypes.fInt.get();
if (type->isLiteral()) {
SkDEBUGFAIL("found a $literal type while inlining");
type = &type->scalarTypeForLiteral();
}
// Provide our new variable with a unique name, and add it to our symbol table.

View File

@ -119,7 +119,8 @@ public:
}
// Create a struct type with the given fields.
static std::unique_ptr<Type> MakeStructType(int offset, String name, std::vector<Field> fields) {
static std::unique_ptr<Type> MakeStructType(int offset, String name,
std::vector<Field> fields) {
return std::unique_ptr<Type>(new Type(offset, std::move(name), std::move(fields)));
}
@ -129,6 +130,12 @@ public:
return std::unique_ptr<Type>(new Type(name, numberKind, priority, highPrecision));
}
// Create a type for literal scalars.
static std::unique_ptr<Type> MakeLiteralType(const char* name, const Type& scalarType,
int priority) {
return std::unique_ptr<Type>(new Type(name, scalarType, priority));
}
// Create a vector type.
static std::unique_ptr<Type> MakeVectorType(const char* name, const Type& componentType,
int columns) {
@ -163,14 +170,7 @@ public:
}
String displayName() const {
StringFragment name = this->name();
if (name == "$floatLiteral") {
return "float";
}
if (name == "$intLiteral") {
return "int";
}
return name;
return this->scalarTypeForLiteral().name();
}
String description() const override {
@ -326,8 +326,7 @@ public:
}
/**
* For generic types, returns the types that this generic type can substitute for. For other
* types, returns a list of other types that this type can be coerced into.
* For generic types, returns the types that this generic type can substitute for.
*/
const std::vector<const Type*>& coercibleTypes() const {
SkASSERT(fCoercibleTypes.size() > 0);
@ -353,6 +352,14 @@ public:
return fTypeKind == TypeKind::kScalar;
}
bool isLiteral() const {
return fScalarTypeForLiteral != nullptr;
}
const Type& scalarTypeForLiteral() const {
return fScalarTypeForLiteral ? *fScalarTypeForLiteral : *this;
}
bool isVector() const {
return fTypeKind == TypeKind::kVector;
}
@ -425,7 +432,7 @@ private:
, fCoercibleTypes(std::move(types)) {}
// Constructor for MakeScalarType.
Type(const char* name, NumberKind numberKind, int priority, bool highPrecision = false)
Type(const char* name, NumberKind numberKind, int priority, bool highPrecision)
: INHERITED(-1, kSymbolKind, name)
, fTypeKind(TypeKind::kScalar)
, fNumberKind(numberKind)
@ -434,6 +441,17 @@ private:
, fRows(1)
, fHighPrecision(highPrecision) {}
// Constructor for MakeLiteralType.
Type(const char* name, const Type& scalarType, int priority)
: INHERITED(-1, kSymbolKind, name)
, fTypeKind(TypeKind::kScalar)
, fNumberKind(scalarType.numberKind())
, fPriority(priority)
, fColumns(1)
, fRows(1)
, fHighPrecision(scalarType.highPrecision())
, fScalarTypeForLiteral(&scalarType) {}
// Constructor shared by MakeVectorType and MakeArrayType.
Type(String name, TypeKind kind, const Type& componentType, int columns)
: INHERITED(-1, kSymbolKind, "")
@ -516,6 +534,7 @@ private:
bool fIsSampled = false;
bool fHighPrecision = false;
const Type* fTextureType = nullptr;
const Type* fScalarTypeForLiteral = nullptr;
};
} // namespace SkSL