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