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