Home | History | Annotate | Download | only in sksl
      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 SKSL_SPIRVCODEGENERATOR
      9 #define SKSL_SPIRVCODEGENERATOR
     10 
     11 #include <stack>
     12 #include <tuple>
     13 #include <unordered_map>
     14 
     15 #include "SkSLCodeGenerator.h"
     16 #include "SkSLMemoryLayout.h"
     17 #include "ir/SkSLBinaryExpression.h"
     18 #include "ir/SkSLBoolLiteral.h"
     19 #include "ir/SkSLConstructor.h"
     20 #include "ir/SkSLDoStatement.h"
     21 #include "ir/SkSLFloatLiteral.h"
     22 #include "ir/SkSLIfStatement.h"
     23 #include "ir/SkSLIndexExpression.h"
     24 #include "ir/SkSLInterfaceBlock.h"
     25 #include "ir/SkSLIntLiteral.h"
     26 #include "ir/SkSLFieldAccess.h"
     27 #include "ir/SkSLForStatement.h"
     28 #include "ir/SkSLFunctionCall.h"
     29 #include "ir/SkSLFunctionDeclaration.h"
     30 #include "ir/SkSLFunctionDefinition.h"
     31 #include "ir/SkSLPrefixExpression.h"
     32 #include "ir/SkSLPostfixExpression.h"
     33 #include "ir/SkSLProgramElement.h"
     34 #include "ir/SkSLReturnStatement.h"
     35 #include "ir/SkSLStatement.h"
     36 #include "ir/SkSLSwizzle.h"
     37 #include "ir/SkSLTernaryExpression.h"
     38 #include "ir/SkSLVarDeclarations.h"
     39 #include "ir/SkSLVarDeclarationsStatement.h"
     40 #include "ir/SkSLVariableReference.h"
     41 #include "ir/SkSLWhileStatement.h"
     42 #include "spirv.h"
     43 
     44 namespace SkSL {
     45 
     46 #define kLast_Capability SpvCapabilityMultiViewport
     47 
     48 /**
     49  * Converts a Program into a SPIR-V binary.
     50  */
     51 class SPIRVCodeGenerator : public CodeGenerator {
     52 public:
     53     class LValue {
     54     public:
     55         virtual ~LValue() {}
     56 
     57         // returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced
     58         // by a pointer (e.g. vector swizzles), returns 0.
     59         virtual SpvId getPointer() = 0;
     60 
     61         virtual SpvId load(OutputStream& out) = 0;
     62 
     63         virtual void store(SpvId value, OutputStream& out) = 0;
     64     };
     65 
     66     SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
     67                        OutputStream* out)
     68     : INHERITED(program, errors, out)
     69     , fContext(*context)
     70     , fDefaultLayout(MemoryLayout::k140_Standard)
     71     , fCapabilities(1 << SpvCapabilityShader)
     72     , fIdCount(1)
     73     , fBoolTrue(0)
     74     , fBoolFalse(0)
     75     , fSetupFragPosition(false)
     76     , fCurrentBlock(0)
     77     , fSynthetics(nullptr, errors) {
     78         this->setupIntrinsics();
     79     }
     80 
     81     bool generateCode() override;
     82 
     83 private:
     84     enum IntrinsicKind {
     85         kGLSL_STD_450_IntrinsicKind,
     86         kSPIRV_IntrinsicKind,
     87         kSpecial_IntrinsicKind
     88     };
     89 
     90     enum SpecialIntrinsic {
     91         kAtan_SpecialIntrinsic,
     92         kSubpassLoad_SpecialIntrinsic,
     93         kTexelFetch_SpecialIntrinsic,
     94         kTexture_SpecialIntrinsic,
     95     };
     96 
     97     void setupIntrinsics();
     98 
     99     SpvId nextId();
    100 
    101     SpvId getType(const Type& type);
    102 
    103     SpvId getType(const Type& type, const MemoryLayout& layout);
    104 
    105     SpvId getImageType(const Type& type);
    106 
    107     SpvId getFunctionType(const FunctionDeclaration& function);
    108 
    109     SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass);
    110 
    111     SpvId getPointerType(const Type& type, const MemoryLayout& layout,
    112                          SpvStorageClass_ storageClass);
    113 
    114     void writePrecisionModifier(const Modifiers& modifiers, SpvId id);
    115 
    116     std::vector<SpvId> getAccessChain(const Expression& expr, OutputStream& out);
    117 
    118     void writeLayout(const Layout& layout, SpvId target);
    119 
    120     void writeLayout(const Layout& layout, SpvId target, int member);
    121 
    122     void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId);
    123 
    124     void writeProgramElement(const ProgramElement& pe, OutputStream& out);
    125 
    126     SpvId writeInterfaceBlock(const InterfaceBlock& intf);
    127 
    128     SpvId writeFunctionStart(const FunctionDeclaration& f, OutputStream& out);
    129 
    130     SpvId writeFunctionDeclaration(const FunctionDeclaration& f, OutputStream& out);
    131 
    132     SpvId writeFunction(const FunctionDefinition& f, OutputStream& out);
    133 
    134     void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, OutputStream& out);
    135 
    136     void writeVarDeclarations(const VarDeclarations& decl, OutputStream& out);
    137 
    138     SpvId writeVariableReference(const VariableReference& ref, OutputStream& out);
    139 
    140     std::unique_ptr<LValue> getLValue(const Expression& value, OutputStream& out);
    141 
    142     SpvId writeExpression(const Expression& expr, OutputStream& out);
    143 
    144     SpvId writeIntrinsicCall(const FunctionCall& c, OutputStream& out);
    145 
    146     SpvId writeFunctionCall(const FunctionCall& c, OutputStream& out);
    147 
    148     SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, OutputStream& out);
    149 
    150     SpvId writeConstantVector(const Constructor& c);
    151 
    152     SpvId writeFloatConstructor(const Constructor& c, OutputStream& out);
    153 
    154     SpvId writeIntConstructor(const Constructor& c, OutputStream& out);
    155 
    156     SpvId writeUIntConstructor(const Constructor& c, OutputStream& out);
    157 
    158     /**
    159      * Writes a matrix with the diagonal entries all equal to the provided expression, and all other
    160      * entries equal to zero.
    161      */
    162     void writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, OutputStream& out);
    163 
    164     /**
    165      * Writes a potentially-different-sized copy of a matrix. Entries which do not exist in the
    166      * source matrix are filled with zero; entries which do not exist in the destination matrix are
    167      * ignored.
    168      */
    169     void writeMatrixCopy(SpvId id, SpvId src, const Type& srcType, const Type& dstType,
    170                          OutputStream& out);
    171 
    172     SpvId writeMatrixConstructor(const Constructor& c, OutputStream& out);
    173 
    174     SpvId writeVectorConstructor(const Constructor& c, OutputStream& out);
    175 
    176     SpvId writeConstructor(const Constructor& c, OutputStream& out);
    177 
    178     SpvId writeFieldAccess(const FieldAccess& f, OutputStream& out);
    179 
    180     SpvId writeSwizzle(const Swizzle& swizzle, OutputStream& out);
    181 
    182     /**
    183      * Folds the potentially-vector result of a logical operation down to a single bool. If
    184      * operandType is a vector type, assumes that the intermediate result in id is a bvec of the
    185      * same dimensions, and applys all() to it to fold it down to a single bool value. Otherwise,
    186      * returns the original id value.
    187      */
    188     SpvId foldToBool(SpvId id, const Type& operandType, OutputStream& out);
    189 
    190     SpvId writeMatrixComparison(const Type& operandType, SpvId lhs, SpvId rhs, SpvOp_ floatOperator,
    191                                 SpvOp_ intOperator, OutputStream& out);
    192 
    193     SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
    194                                SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
    195                                SpvOp_ ifBool, OutputStream& out);
    196 
    197     SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
    198                                SpvOp_ ifUInt, OutputStream& out);
    199 
    200     SpvId writeBinaryExpression(const BinaryExpression& b, OutputStream& out);
    201 
    202     SpvId writeTernaryExpression(const TernaryExpression& t, OutputStream& out);
    203 
    204     SpvId writeIndexExpression(const IndexExpression& expr, OutputStream& out);
    205 
    206     SpvId writeLogicalAnd(const BinaryExpression& b, OutputStream& out);
    207 
    208     SpvId writeLogicalOr(const BinaryExpression& o, OutputStream& out);
    209 
    210     SpvId writePrefixExpression(const PrefixExpression& p, OutputStream& out);
    211 
    212     SpvId writePostfixExpression(const PostfixExpression& p, OutputStream& out);
    213 
    214     SpvId writeBoolLiteral(const BoolLiteral& b);
    215 
    216     SpvId writeIntLiteral(const IntLiteral& i);
    217 
    218     SpvId writeFloatLiteral(const FloatLiteral& f);
    219 
    220     void writeStatement(const Statement& s, OutputStream& out);
    221 
    222     void writeBlock(const Block& b, OutputStream& out);
    223 
    224     void writeIfStatement(const IfStatement& stmt, OutputStream& out);
    225 
    226     void writeForStatement(const ForStatement& f, OutputStream& out);
    227 
    228     void writeWhileStatement(const WhileStatement& w, OutputStream& out);
    229 
    230     void writeDoStatement(const DoStatement& d, OutputStream& out);
    231 
    232     void writeReturnStatement(const ReturnStatement& r, OutputStream& out);
    233 
    234     void writeCapabilities(OutputStream& out);
    235 
    236     void writeInstructions(const Program& program, OutputStream& out);
    237 
    238     void writeOpCode(SpvOp_ opCode, int length, OutputStream& out);
    239 
    240     void writeWord(int32_t word, OutputStream& out);
    241 
    242     void writeString(const char* string, OutputStream& out);
    243 
    244     void writeLabel(SpvId id, OutputStream& out);
    245 
    246     void writeInstruction(SpvOp_ opCode, OutputStream& out);
    247 
    248     void writeInstruction(SpvOp_ opCode, const char* string, OutputStream& out);
    249 
    250     void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out);
    251 
    252     void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, OutputStream& out);
    253 
    254     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
    255                           OutputStream& out);
    256 
    257     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, OutputStream& out);
    258 
    259     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
    260                           OutputStream& out);
    261 
    262     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    263                           OutputStream& out);
    264 
    265     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    266                           int32_t word5, OutputStream& out);
    267 
    268     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    269                           int32_t word5, int32_t word6, OutputStream& out);
    270 
    271     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    272                           int32_t word5, int32_t word6, int32_t word7, OutputStream& out);
    273 
    274     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    275                           int32_t word5, int32_t word6, int32_t word7, int32_t word8,
    276                           OutputStream& out);
    277 
    278     const Context& fContext;
    279     const MemoryLayout fDefaultLayout;
    280 
    281     uint64_t fCapabilities;
    282     SpvId fIdCount;
    283     SpvId fGLSLExtendedInstructions;
    284     typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic;
    285     std::unordered_map<String, Intrinsic> fIntrinsicMap;
    286     std::unordered_map<const FunctionDeclaration*, SpvId> fFunctionMap;
    287     std::unordered_map<const Variable*, SpvId> fVariableMap;
    288     std::unordered_map<const Variable*, int32_t> fInterfaceBlockMap;
    289     std::unordered_map<String, SpvId> fImageTypeMap;
    290     std::unordered_map<String, SpvId> fTypeMap;
    291     StringStream fCapabilitiesBuffer;
    292     StringStream fGlobalInitializersBuffer;
    293     StringStream fConstantBuffer;
    294     StringStream fExtraGlobalsBuffer;
    295     StringStream fExternalFunctionsBuffer;
    296     StringStream fVariableBuffer;
    297     StringStream fNameBuffer;
    298     StringStream fDecorationBuffer;
    299 
    300     SpvId fBoolTrue;
    301     SpvId fBoolFalse;
    302     std::unordered_map<int64_t, SpvId> fIntConstants;
    303     std::unordered_map<uint64_t, SpvId> fUIntConstants;
    304     std::unordered_map<float, SpvId> fFloatConstants;
    305     std::unordered_map<double, SpvId> fDoubleConstants;
    306     bool fSetupFragPosition;
    307     // label of the current block, or 0 if we are not in a block
    308     SpvId fCurrentBlock;
    309     std::stack<SpvId> fBreakTarget;
    310     std::stack<SpvId> fContinueTarget;
    311     SpvId fRTHeightStructId = (SpvId) -1;
    312     SpvId fRTHeightFieldIndex = (SpvId) -1;
    313     // holds variables synthesized during output, for lifetime purposes
    314     SymbolTable fSynthetics;
    315 
    316     friend class PointerLValue;
    317     friend class SwizzleLValue;
    318 
    319     typedef CodeGenerator INHERITED;
    320 };
    321 
    322 }
    323 
    324 #endif
    325