/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SKIASL_TYPE #define SKIASL_TYPE #include "SkSLModifiers.h" #include "SkSLSymbol.h" #include "../SkSLPosition.h" #include "../SkSLUtil.h" #include "../spirv.h" #include #include namespace SkSL { class Context; /** * Represents a type, such as int or vec4. */ class Type : public Symbol { public: struct Field { Field(Modifiers modifiers, String name, const Type* type) : fModifiers(modifiers) , fName(std::move(name)) , fType(std::move(type)) {} const String description() const { return fType->description() + " " + fName + ";"; } Modifiers fModifiers; String fName; const Type* fType; }; enum Kind { kScalar_Kind, kVector_Kind, kMatrix_Kind, kArray_Kind, kStruct_Kind, kGeneric_Kind, kSampler_Kind, kOther_Kind }; // Create an "other" (special) type with the given name. These types cannot be directly // referenced from user code. Type(String name) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kOther_Kind) {} // Create a generic type which maps to the listed types. Type(String name, std::vector types) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kGeneric_Kind) , fCoercibleTypes(std::move(types)) {} // Create a struct type with the given fields. Type(Position position, String name, std::vector fields) : INHERITED(position, kType_Kind, std::move(name)) , fTypeKind(kStruct_Kind) , fFields(std::move(fields)) {} // Create a scalar type. Type(String name, bool isNumber) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kScalar_Kind) , fIsNumber(isNumber) , fColumns(1) , fRows(1) {} // Create a scalar type which can be coerced to the listed types. Type(String name, bool isNumber, std::vector coercibleTypes) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kScalar_Kind) , fIsNumber(isNumber) , fCoercibleTypes(std::move(coercibleTypes)) , fColumns(1) , fRows(1) {} // Create a vector type. Type(String name, const Type& componentType, int columns) : Type(name, kVector_Kind, componentType, columns) {} // Create a vector or array type. Type(String name, Kind kind, const Type& componentType, int columns) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kind) , fComponentType(&componentType) , fColumns(columns) , fRows(1) , fDimensions(SpvDim1D) {} // Create a matrix type. Type(String name, const Type& componentType, int columns, int rows) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kMatrix_Kind) , fComponentType(&componentType) , fColumns(columns) , fRows(rows) , fDimensions(SpvDim1D) {} // Create a sampler type. Type(String name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, bool isSampled) : INHERITED(Position(), kType_Kind, std::move(name)) , fTypeKind(kSampler_Kind) , fDimensions(dimensions) , fIsDepth(isDepth) , fIsArrayed(isArrayed) , fIsMultisampled(isMultisampled) , fIsSampled(isSampled) {} String name() const { return fName; } String description() const override { return fName; } bool operator==(const Type& other) const { return fName == other.fName; } bool operator!=(const Type& other) const { return fName != other.fName; } /** * Returns the category (scalar, vector, matrix, etc.) of this type. */ Kind kind() const { return fTypeKind; } /** * Returns true if this is a numeric scalar type. */ bool isNumber() const { return fIsNumber; } /** * Returns true if an instance of this type can be freely coerced (implicitly converted) to * another type. */ bool canCoerceTo(const Type& other) const { int cost; return determineCoercionCost(other, &cost); } /** * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost * is a number with no particular meaning other than that lower costs are preferable to higher * costs. Returns true if a conversion is possible, false otherwise. The value of the out * parameter is undefined if false is returned. */ bool determineCoercionCost(const Type& other, int* outCost) const; /** * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component * type of kFloat_Type). For all other types, causes an assertion failure. */ const Type& componentType() const { ASSERT(fComponentType); return *fComponentType; } /** * For matrices and vectors, returns the number of columns (e.g. both mat3 and vec3 return 3). * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1. * For all other types, causes an assertion failure. */ int columns() const { ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind || fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind); return fColumns; } /** * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars, * returns 1. For all other types, causes an assertion failure. */ int rows() const { ASSERT(fRows > 0); return fRows; } const std::vector& fields() const { ASSERT(fTypeKind == kStruct_Kind); return fFields; } /** * 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. */ const std::vector& coercibleTypes() const { ASSERT(fCoercibleTypes.size() > 0); return fCoercibleTypes; } SpvDim_ dimensions() const { ASSERT(kSampler_Kind == fTypeKind); return fDimensions; } bool isDepth() const { ASSERT(kSampler_Kind == fTypeKind); return fIsDepth; } bool isArrayed() const { ASSERT(kSampler_Kind == fTypeKind); return fIsArrayed; } bool isMultisampled() const { ASSERT(kSampler_Kind == fTypeKind); return fIsMultisampled; } bool isSampled() const { ASSERT(kSampler_Kind == fTypeKind); return fIsSampled; } /** * Returns the corresponding vector or matrix type with the specified number of columns and * rows. */ const Type& toCompound(const Context& context, int columns, int rows) const; private: typedef Symbol INHERITED; const Kind fTypeKind; const bool fIsNumber = false; const Type* fComponentType = nullptr; const std::vector fCoercibleTypes; const int fColumns = -1; const int fRows = -1; const std::vector fFields; const SpvDim_ fDimensions = SpvDim1D; const bool fIsDepth = false; const bool fIsArrayed = false; const bool fIsMultisampled = false; const bool fIsSampled = false; }; } // namespace #endif