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         kMatrix_Kind,
     49         kOther_Kind,
     50         kSampler_Kind,
     51         kScalar_Kind,
     52         kStruct_Kind,
     53         kVector_Kind
     54     };
     55 
     56     enum NumberKind {
     57         kFloat_NumberKind,
     58         kSigned_NumberKind,
     59         kUnsigned_NumberKind,
     60         kNonnumeric_NumberKind
     61     };
     62 
     63     // Create an "other" (special) type with the given name. These types cannot be directly
     64     // referenced from user code.
     65     Type(const char* name)
     66     : INHERITED(-1, kType_Kind, StringFragment())
     67     , fNameString(name)
     68     , fTypeKind(kOther_Kind)
     69     , fNumberKind(kNonnumeric_NumberKind) {
     70         fName.fChars = fNameString.c_str();
     71         fName.fLength = fNameString.size();
     72     }
     73 
     74     // Create an "other" (special) type that supports field access.
     75     Type(const char* name, std::vector<Field> fields)
     76     : INHERITED(-1, kType_Kind, StringFragment())
     77     , fNameString(name)
     78     , fTypeKind(kOther_Kind)
     79     , fNumberKind(kNonnumeric_NumberKind)
     80     , fFields(std::move(fields)) {
     81         fName.fChars = fNameString.c_str();
     82         fName.fLength = fNameString.size();
     83     }
     84 
     85     // Create a simple type.
     86     Type(String name, Kind kind)
     87     : INHERITED(-1, kType_Kind, StringFragment())
     88     , fNameString(std::move(name))
     89     , fTypeKind(kind)
     90     , fNumberKind(kNonnumeric_NumberKind) {
     91         fName.fChars = fNameString.c_str();
     92         fName.fLength = fNameString.size();
     93     }
     94 
     95     // Create a generic type which maps to the listed types.
     96     Type(const char* name, std::vector<const Type*> types)
     97     : INHERITED(-1, kType_Kind, StringFragment())
     98     , fNameString(name)
     99     , fTypeKind(kGeneric_Kind)
    100     , fNumberKind(kNonnumeric_NumberKind)
    101     , fCoercibleTypes(std::move(types)) {
    102         fName.fChars = fNameString.c_str();
    103         fName.fLength = fNameString.size();
    104     }
    105 
    106     // Create a struct type with the given fields.
    107     Type(int offset, String name, std::vector<Field> fields)
    108     : INHERITED(offset, kType_Kind, StringFragment())
    109     , fNameString(std::move(name))
    110     , fTypeKind(kStruct_Kind)
    111     , fNumberKind(kNonnumeric_NumberKind)
    112     , fFields(std::move(fields)) {
    113         fName.fChars = fNameString.c_str();
    114         fName.fLength = fNameString.size();
    115     }
    116 
    117     // Create a scalar type.
    118     Type(const char* name, NumberKind numberKind, int priority)
    119     : INHERITED(-1, kType_Kind, StringFragment())
    120     , fNameString(name)
    121     , fTypeKind(kScalar_Kind)
    122     , fNumberKind(numberKind)
    123     , fPriority(priority)
    124     , fColumns(1)
    125     , fRows(1) {
    126         fName.fChars = fNameString.c_str();
    127         fName.fLength = fNameString.size();
    128     }
    129 
    130     // Create a scalar type which can be coerced to the listed types.
    131     Type(const char* name,
    132          NumberKind numberKind,
    133          int priority,
    134          std::vector<const Type*> coercibleTypes)
    135     : INHERITED(-1, kType_Kind, StringFragment())
    136     , fNameString(name)
    137     , fTypeKind(kScalar_Kind)
    138     , fNumberKind(numberKind)
    139     , fPriority(priority)
    140     , fCoercibleTypes(std::move(coercibleTypes))
    141     , fColumns(1)
    142     , fRows(1) {
    143         fName.fChars = fNameString.c_str();
    144         fName.fLength = fNameString.size();
    145     }
    146 
    147     // Create a vector type.
    148     Type(const char* name, const Type& componentType, int columns)
    149     : Type(name, kVector_Kind, componentType, columns) {}
    150 
    151     // Create a vector or array type.
    152     Type(String name, Kind kind, const Type& componentType, int columns)
    153     : INHERITED(-1, kType_Kind, StringFragment())
    154     , fNameString(std::move(name))
    155     , fTypeKind(kind)
    156     , fNumberKind(kNonnumeric_NumberKind)
    157     , fComponentType(&componentType)
    158     , fColumns(columns)
    159     , fRows(1)
    160     , fDimensions(SpvDim1D) {
    161         fName.fChars = fNameString.c_str();
    162         fName.fLength = fNameString.size();
    163     }
    164 
    165     // Create a matrix type.
    166     Type(const char* name, const Type& componentType, int columns, int rows)
    167     : INHERITED(-1, kType_Kind, StringFragment())
    168     , fNameString(name)
    169     , fTypeKind(kMatrix_Kind)
    170     , fNumberKind(kNonnumeric_NumberKind)
    171     , fComponentType(&componentType)
    172     , fColumns(columns)
    173     , fRows(rows)
    174     , fDimensions(SpvDim1D) {
    175         fName.fChars = fNameString.c_str();
    176         fName.fLength = fNameString.size();
    177     }
    178 
    179     // Create a sampler type.
    180     Type(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
    181          bool isSampled)
    182     : INHERITED(-1, kType_Kind, StringFragment())
    183     , fNameString(name)
    184     , fTypeKind(kSampler_Kind)
    185     , fNumberKind(kNonnumeric_NumberKind)
    186     , fDimensions(dimensions)
    187     , fIsDepth(isDepth)
    188     , fIsArrayed(isArrayed)
    189     , fIsMultisampled(isMultisampled)
    190     , fIsSampled(isSampled) {
    191         fName.fChars = fNameString.c_str();
    192         fName.fLength = fNameString.size();
    193     }
    194 
    195     const String& name() const {
    196         return fNameString;
    197     }
    198 
    199     String description() const override {
    200         return fNameString;
    201     }
    202 
    203     bool operator==(const Type& other) const {
    204         return fName == other.fName;
    205     }
    206 
    207     bool operator!=(const Type& other) const {
    208         return fName != other.fName;
    209     }
    210 
    211     /**
    212      * Returns the category (scalar, vector, matrix, etc.) of this type.
    213      */
    214     Kind kind() const {
    215         return fTypeKind;
    216     }
    217 
    218     /**
    219      * Returns true if this is a numeric scalar type.
    220      */
    221     bool isNumber() const {
    222         return fNumberKind != kNonnumeric_NumberKind;
    223     }
    224 
    225     /**
    226      * Returns true if this is a floating-point scalar type (float, half, or double).
    227      */
    228     bool isFloat() const {
    229         return fNumberKind == kFloat_NumberKind;
    230     }
    231 
    232     /**
    233      * Returns true if this is a signed scalar type (int or short).
    234      */
    235     bool isSigned() const {
    236         return fNumberKind == kSigned_NumberKind;
    237     }
    238 
    239     /**
    240      * Returns true if this is an unsigned scalar type (uint or ushort).
    241      */
    242     bool isUnsigned() const {
    243         return fNumberKind == kUnsigned_NumberKind;
    244     }
    245 
    246     /**
    247      * Returns true if this is a signed or unsigned integer.
    248      */
    249     bool isInteger() const {
    250         return isSigned() || isUnsigned();
    251     }
    252 
    253     /**
    254      * Returns the "priority" of a number type, in order of double > float > half > int > short.
    255      * When operating on two number types, the result is the higher-priority type.
    256      */
    257     int priority() const {
    258         return fPriority;
    259     }
    260 
    261     /**
    262      * Returns true if an instance of this type can be freely coerced (implicitly converted) to
    263      * another type.
    264      */
    265     bool canCoerceTo(const Type& other) const {
    266         return coercionCost(other) != INT_MAX;
    267     }
    268 
    269     /**
    270      * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
    271      * is a number with no particular meaning other than that lower costs are preferable to higher
    272      * costs. Returns INT_MAX if the coercion is not possible.
    273      */
    274     int coercionCost(const Type& other) const;
    275 
    276     /**
    277      * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
    278      * type of kFloat_Type). For all other types, causes an SkASSERTion failure.
    279      */
    280     const Type& componentType() const {
    281         SkASSERT(fComponentType);
    282         return *fComponentType;
    283     }
    284 
    285     /**
    286      * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3return 3).
    287      * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
    288      * For all other types, causes an SkASSERTion failure.
    289      */
    290     int columns() const {
    291         SkASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind ||
    292                fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind);
    293         return fColumns;
    294     }
    295 
    296     /**
    297      * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars,
    298      * returns 1. For all other types, causes an SkASSERTion failure.
    299      */
    300     int rows() const {
    301         SkASSERT(fRows > 0);
    302         return fRows;
    303     }
    304 
    305     const std::vector<Field>& fields() const {
    306         SkASSERT(fTypeKind == kStruct_Kind || fTypeKind == kOther_Kind);
    307         return fFields;
    308     }
    309 
    310     /**
    311      * For generic types, returns the types that this generic type can substitute for. For other
    312      * types, returns a list of other types that this type can be coerced into.
    313      */
    314     const std::vector<const Type*>& coercibleTypes() const {
    315         SkASSERT(fCoercibleTypes.size() > 0);
    316         return fCoercibleTypes;
    317     }
    318 
    319     SpvDim_ dimensions() const {
    320         SkASSERT(kSampler_Kind == fTypeKind);
    321         return fDimensions;
    322     }
    323 
    324     bool isDepth() const {
    325         SkASSERT(kSampler_Kind == fTypeKind);
    326         return fIsDepth;
    327     }
    328 
    329     bool isArrayed() const {
    330         SkASSERT(kSampler_Kind == fTypeKind);
    331         return fIsArrayed;
    332     }
    333 
    334     bool isMultisampled() const {
    335         SkASSERT(kSampler_Kind == fTypeKind);
    336         return fIsMultisampled;
    337     }
    338 
    339     bool isSampled() const {
    340         SkASSERT(kSampler_Kind == fTypeKind);
    341         return fIsSampled;
    342     }
    343 
    344     /**
    345      * Returns the corresponding vector or matrix type with the specified number of columns and
    346      * rows.
    347      */
    348     const Type& toCompound(const Context& context, int columns, int rows) const;
    349 
    350 private:
    351     typedef Symbol INHERITED;
    352 
    353     String fNameString;
    354     Kind fTypeKind;
    355     // always kNonnumeric_NumberKind for non-scalar values
    356     NumberKind fNumberKind;
    357     int fPriority = -1;
    358     const Type* fComponentType = nullptr;
    359     std::vector<const Type*> fCoercibleTypes;
    360     int fColumns = -1;
    361     int fRows = -1;
    362     std::vector<Field> fFields;
    363     SpvDim_ fDimensions = SpvDim1D;
    364     bool fIsDepth = false;
    365     bool fIsArrayed = false;
    366     bool fIsMultisampled = false;
    367     bool fIsSampled = false;
    368 };
    369 
    370 } // namespace
    371 
    372 #endif
    373