Home | History | Annotate | Download | only in ir
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SKIASL_TYPE
      9 #define SKIASL_TYPE
     10 
     11 #include "SkSLModifiers.h"
     12 #include "SkSLSymbol.h"
     13 #include "../SkSLPosition.h"
     14 #include "../SkSLUtil.h"
     15 #include "../spirv.h"
     16 #include <climits>
     17 #include <vector>
     18 #include <memory>
     19 
     20 namespace SkSL {
     21 
     22 class Context;
     23 
     24 /**
     25  * Represents a type, such as int or float4.
     26  */
     27 class Type : public Symbol {
     28 public:
     29     struct Field {
     30         Field(Modifiers modifiers, StringFragment name, const Type* type)
     31         : fModifiers(modifiers)
     32         , fName(name)
     33         , fType(std::move(type)) {}
     34 
     35         const String description() const {
     36             return fType->description() + " " + fName + ";";
     37         }
     38 
     39         Modifiers fModifiers;
     40         StringFragment fName;
     41         const Type* fType;
     42     };
     43 
     44     enum Kind {
     45         kArray_Kind,
     46         kEnum_Kind,
     47         kGeneric_Kind,
     48         kNullable_Kind,
     49         kMatrix_Kind,
     50         kOther_Kind,
     51         kSampler_Kind,
     52         kScalar_Kind,
     53         kStruct_Kind,
     54         kVector_Kind
     55     };
     56 
     57     enum NumberKind {
     58         kFloat_NumberKind,
     59         kSigned_NumberKind,
     60         kUnsigned_NumberKind,
     61         kNonnumeric_NumberKind
     62     };
     63 
     64     // Create an "other" (special) type with the given name. These types cannot be directly
     65     // referenced from user code.
     66     Type(const char* name)
     67     : INHERITED(-1, kType_Kind, StringFragment())
     68     , fNameString(name)
     69     , fTypeKind(kOther_Kind)
     70     , fNumberKind(kNonnumeric_NumberKind) {
     71         fName.fChars = fNameString.c_str();
     72         fName.fLength = fNameString.size();
     73     }
     74 
     75     // Create an "other" (special) type that supports field access.
     76     Type(const char* name, std::vector<Field> fields)
     77     : INHERITED(-1, kType_Kind, StringFragment())
     78     , fNameString(name)
     79     , fTypeKind(kOther_Kind)
     80     , fNumberKind(kNonnumeric_NumberKind)
     81     , fFields(std::move(fields)) {
     82         fName.fChars = fNameString.c_str();
     83         fName.fLength = fNameString.size();
     84     }
     85 
     86     // Create a simple type.
     87     Type(String name, Kind kind)
     88     : INHERITED(-1, kType_Kind, StringFragment())
     89     , fNameString(std::move(name))
     90     , fTypeKind(kind)
     91     , fNumberKind(kNonnumeric_NumberKind) {
     92         fName.fChars = fNameString.c_str();
     93         fName.fLength = fNameString.size();
     94     }
     95 
     96     // Create a generic type which maps to the listed types.
     97     Type(const char* name, std::vector<const Type*> types)
     98     : INHERITED(-1, kType_Kind, StringFragment())
     99     , fNameString(name)
    100     , fTypeKind(kGeneric_Kind)
    101     , fNumberKind(kNonnumeric_NumberKind)
    102     , fCoercibleTypes(std::move(types)) {
    103         fName.fChars = fNameString.c_str();
    104         fName.fLength = fNameString.size();
    105     }
    106 
    107     // Create a struct type with the given fields.
    108     Type(int offset, String name, std::vector<Field> fields)
    109     : INHERITED(offset, kType_Kind, StringFragment())
    110     , fNameString(std::move(name))
    111     , fTypeKind(kStruct_Kind)
    112     , fNumberKind(kNonnumeric_NumberKind)
    113     , fFields(std::move(fields)) {
    114         fName.fChars = fNameString.c_str();
    115         fName.fLength = fNameString.size();
    116     }
    117 
    118     // Create a scalar type.
    119     Type(const char* name, NumberKind numberKind, int priority, bool highPrecision = false)
    120     : INHERITED(-1, kType_Kind, StringFragment())
    121     , fNameString(name)
    122     , fTypeKind(kScalar_Kind)
    123     , fNumberKind(numberKind)
    124     , fPriority(priority)
    125     , fColumns(1)
    126     , fRows(1)
    127     , fHighPrecision(highPrecision) {
    128         fName.fChars = fNameString.c_str();
    129         fName.fLength = fNameString.size();
    130     }
    131 
    132     // Create a scalar type which can be coerced to the listed types.
    133     Type(const char* name,
    134          NumberKind numberKind,
    135          int priority,
    136          std::vector<const Type*> coercibleTypes)
    137     : INHERITED(-1, kType_Kind, StringFragment())
    138     , fNameString(name)
    139     , fTypeKind(kScalar_Kind)
    140     , fNumberKind(numberKind)
    141     , fPriority(priority)
    142     , fCoercibleTypes(std::move(coercibleTypes))
    143     , fColumns(1)
    144     , fRows(1) {
    145         fName.fChars = fNameString.c_str();
    146         fName.fLength = fNameString.size();
    147     }
    148 
    149     // Create a nullable type.
    150     Type(String name, Kind kind, const Type& componentType)
    151     : INHERITED(-1, kType_Kind, StringFragment())
    152     , fNameString(std::move(name))
    153     , fTypeKind(kind)
    154     , fNumberKind(kNonnumeric_NumberKind)
    155     , fComponentType(&componentType)
    156     , fColumns(1)
    157     , fRows(1)
    158     , fDimensions(SpvDim1D) {
    159         fName.fChars = fNameString.c_str();
    160         fName.fLength = fNameString.size();
    161     }
    162 
    163     // Create a vector type.
    164     Type(const char* name, const Type& componentType, int columns)
    165     : Type(name, kVector_Kind, componentType, columns) {}
    166 
    167     // Create a vector or array type.
    168     Type(String name, Kind kind, const Type& componentType, int columns)
    169     : INHERITED(-1, kType_Kind, StringFragment())
    170     , fNameString(std::move(name))
    171     , fTypeKind(kind)
    172     , fNumberKind(kNonnumeric_NumberKind)
    173     , fComponentType(&componentType)
    174     , fColumns(columns)
    175     , fRows(1)
    176     , fDimensions(SpvDim1D) {
    177         fName.fChars = fNameString.c_str();
    178         fName.fLength = fNameString.size();
    179     }
    180 
    181     // Create a matrix type.
    182     Type(const char* name, const Type& componentType, int columns, int rows)
    183     : INHERITED(-1, kType_Kind, StringFragment())
    184     , fNameString(name)
    185     , fTypeKind(kMatrix_Kind)
    186     , fNumberKind(kNonnumeric_NumberKind)
    187     , fComponentType(&componentType)
    188     , fColumns(columns)
    189     , fRows(rows)
    190     , fDimensions(SpvDim1D) {
    191         fName.fChars = fNameString.c_str();
    192         fName.fLength = fNameString.size();
    193     }
    194 
    195     // Create a sampler type.
    196     Type(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
    197          bool isSampled)
    198     : INHERITED(-1, kType_Kind, StringFragment())
    199     , fNameString(name)
    200     , fTypeKind(kSampler_Kind)
    201     , fNumberKind(kNonnumeric_NumberKind)
    202     , fDimensions(dimensions)
    203     , fIsDepth(isDepth)
    204     , fIsArrayed(isArrayed)
    205     , fIsMultisampled(isMultisampled)
    206     , fIsSampled(isSampled) {
    207         fName.fChars = fNameString.c_str();
    208         fName.fLength = fNameString.size();
    209     }
    210 
    211     const String& name() const {
    212         return fNameString;
    213     }
    214 
    215     String description() const override {
    216         if (fNameString == "$floatLiteral") {
    217             return "float";
    218         }
    219         if (fNameString == "$intLiteral") {
    220             return "int";
    221         }
    222         return fNameString;
    223     }
    224 
    225     bool operator==(const Type& other) const {
    226         return fName == other.fName;
    227     }
    228 
    229     bool operator!=(const Type& other) const {
    230         return fName != other.fName;
    231     }
    232 
    233     /**
    234      * Returns the category (scalar, vector, matrix, etc.) of this type.
    235      */
    236     Kind kind() const {
    237         return fTypeKind;
    238     }
    239 
    240     /**
    241      * Returns true if this is a numeric scalar type.
    242      */
    243     bool isNumber() const {
    244         return fNumberKind != kNonnumeric_NumberKind;
    245     }
    246 
    247     /**
    248      * Returns true if this is a floating-point scalar type (float, half, or double).
    249      */
    250     bool isFloat() const {
    251         return fNumberKind == kFloat_NumberKind;
    252     }
    253 
    254     /**
    255      * Returns true if this is a signed scalar type (int or short).
    256      */
    257     bool isSigned() const {
    258         return fNumberKind == kSigned_NumberKind;
    259     }
    260 
    261     /**
    262      * Returns true if this is an unsigned scalar type (uint or ushort).
    263      */
    264     bool isUnsigned() const {
    265         return fNumberKind == kUnsigned_NumberKind;
    266     }
    267 
    268     /**
    269      * Returns true if this is a signed or unsigned integer.
    270      */
    271     bool isInteger() const {
    272         return isSigned() || isUnsigned();
    273     }
    274 
    275     /**
    276      * Returns the "priority" of a number type, in order of double > float > half > int > short.
    277      * When operating on two number types, the result is the higher-priority type.
    278      */
    279     int priority() const {
    280         return fPriority;
    281     }
    282 
    283     /**
    284      * Returns true if an instance of this type can be freely coerced (implicitly converted) to
    285      * another type.
    286      */
    287     bool canCoerceTo(const Type& other) const {
    288         return coercionCost(other) != INT_MAX;
    289     }
    290 
    291     /**
    292      * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
    293      * is a number with no particular meaning other than that lower costs are preferable to higher
    294      * costs. Returns INT_MAX if the coercion is not possible.
    295      */
    296     int coercionCost(const Type& other) const;
    297 
    298     /**
    299      * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
    300      * type of kFloat_Type). For all other types, causes an SkASSERTion failure.
    301      */
    302     const Type& componentType() const {
    303         SkASSERT(fComponentType);
    304         return *fComponentType;
    305     }
    306 
    307     /**
    308      * For nullable types, returns the base type, otherwise returns the type itself.
    309      */
    310     const Type& nonnullable() const {
    311         if (fTypeKind == kNullable_Kind) {
    312             return this->componentType();
    313         }
    314         return *this;
    315     }
    316 
    317     /**
    318      * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3return 3).
    319      * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
    320      * For all other types, causes an SkASSERTion failure.
    321      */
    322     int columns() const {
    323         SkASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind ||
    324                fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind);
    325         return fColumns;
    326     }
    327 
    328     /**
    329      * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars,
    330      * returns 1. For all other types, causes an SkASSERTion failure.
    331      */
    332     int rows() const {
    333         SkASSERT(fRows > 0);
    334         return fRows;
    335     }
    336 
    337     const std::vector<Field>& fields() const {
    338         SkASSERT(fTypeKind == kStruct_Kind || fTypeKind == kOther_Kind);
    339         return fFields;
    340     }
    341 
    342     /**
    343      * For generic types, returns the types that this generic type can substitute for. For other
    344      * types, returns a list of other types that this type can be coerced into.
    345      */
    346     const std::vector<const Type*>& coercibleTypes() const {
    347         SkASSERT(fCoercibleTypes.size() > 0);
    348         return fCoercibleTypes;
    349     }
    350 
    351     SpvDim_ dimensions() const {
    352         SkASSERT(kSampler_Kind == fTypeKind);
    353         return fDimensions;
    354     }
    355 
    356     bool isDepth() const {
    357         SkASSERT(kSampler_Kind == fTypeKind);
    358         return fIsDepth;
    359     }
    360 
    361     bool isArrayed() const {
    362         SkASSERT(kSampler_Kind == fTypeKind);
    363         return fIsArrayed;
    364     }
    365 
    366     bool isMultisampled() const {
    367         SkASSERT(kSampler_Kind == fTypeKind);
    368         return fIsMultisampled;
    369     }
    370 
    371     bool isSampled() const {
    372         SkASSERT(kSampler_Kind == fTypeKind);
    373         return fIsSampled;
    374     }
    375 
    376     bool highPrecision() const {
    377         if (fComponentType) {
    378             return fComponentType->highPrecision();
    379         }
    380         return fHighPrecision;
    381     }
    382 
    383     /**
    384      * Returns the corresponding vector or matrix type with the specified number of columns and
    385      * rows.
    386      */
    387     const Type& toCompound(const Context& context, int columns, int rows) const;
    388 
    389 private:
    390     typedef Symbol INHERITED;
    391 
    392     String fNameString;
    393     Kind fTypeKind;
    394     // always kNonnumeric_NumberKind for non-scalar values
    395     NumberKind fNumberKind;
    396     int fPriority = -1;
    397     const Type* fComponentType = nullptr;
    398     std::vector<const Type*> fCoercibleTypes;
    399     int fColumns = -1;
    400     int fRows = -1;
    401     std::vector<Field> fFields;
    402     SpvDim_ fDimensions = SpvDim1D;
    403     bool fIsDepth = false;
    404     bool fIsArrayed = false;
    405     bool fIsMultisampled = false;
    406     bool fIsSampled = false;
    407     bool fHighPrecision = false;
    408 };
    409 
    410 } // namespace
    411 
    412 #endif
    413