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 "SkStream.h"
     16 #include "SkSLCodeGenerator.h"
     17 #include "SkSLMemoryLayout.h"
     18 #include "ir/SkSLBinaryExpression.h"
     19 #include "ir/SkSLBoolLiteral.h"
     20 #include "ir/SkSLConstructor.h"
     21 #include "ir/SkSLDoStatement.h"
     22 #include "ir/SkSLFloatLiteral.h"
     23 #include "ir/SkSLIfStatement.h"
     24 #include "ir/SkSLIndexExpression.h"
     25 #include "ir/SkSLInterfaceBlock.h"
     26 #include "ir/SkSLIntLiteral.h"
     27 #include "ir/SkSLFieldAccess.h"
     28 #include "ir/SkSLForStatement.h"
     29 #include "ir/SkSLFunctionCall.h"
     30 #include "ir/SkSLFunctionDeclaration.h"
     31 #include "ir/SkSLFunctionDefinition.h"
     32 #include "ir/SkSLPrefixExpression.h"
     33 #include "ir/SkSLPostfixExpression.h"
     34 #include "ir/SkSLProgramElement.h"
     35 #include "ir/SkSLReturnStatement.h"
     36 #include "ir/SkSLStatement.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(SkWStream& out) = 0;
     63 
     64         virtual void store(SpvId value, SkWStream& out) = 0;
     65     };
     66 
     67     SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
     68                        SkWStream* 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         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         kTexture_SpecialIntrinsic,
     93         kSubpassLoad_SpecialIntrinsic,
     94     };
     95 
     96     void setupIntrinsics();
     97 
     98     SpvId nextId();
     99 
    100     SpvId getType(const Type& type);
    101 
    102     SpvId getType(const Type& type, const MemoryLayout& layout);
    103 
    104     SpvId getFunctionType(const FunctionDeclaration& function);
    105 
    106     SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass);
    107 
    108     SpvId getPointerType(const Type& type, const MemoryLayout& layout,
    109                          SpvStorageClass_ storageClass);
    110 
    111     std::vector<SpvId> getAccessChain(const Expression& expr, SkWStream& out);
    112 
    113     void writeLayout(const Layout& layout, SpvId target);
    114 
    115     void writeLayout(const Layout& layout, SpvId target, int member);
    116 
    117     void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId);
    118 
    119     void writeProgramElement(const ProgramElement& pe, SkWStream& out);
    120 
    121     SpvId writeInterfaceBlock(const InterfaceBlock& intf);
    122 
    123     SpvId writeFunctionStart(const FunctionDeclaration& f, SkWStream& out);
    124 
    125     SpvId writeFunctionDeclaration(const FunctionDeclaration& f, SkWStream& out);
    126 
    127     SpvId writeFunction(const FunctionDefinition& f, SkWStream& out);
    128 
    129     void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, SkWStream& out);
    130 
    131     void writeVarDeclarations(const VarDeclarations& decl, SkWStream& out);
    132 
    133     SpvId writeVariableReference(const VariableReference& ref, SkWStream& out);
    134 
    135     std::unique_ptr<LValue> getLValue(const Expression& value, SkWStream& out);
    136 
    137     SpvId writeExpression(const Expression& expr, SkWStream& out);
    138 
    139     SpvId writeIntrinsicCall(const FunctionCall& c, SkWStream& out);
    140 
    141     SpvId writeFunctionCall(const FunctionCall& c, SkWStream& out);
    142 
    143     SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, SkWStream& out);
    144 
    145     SpvId writeConstantVector(const Constructor& c);
    146 
    147     SpvId writeFloatConstructor(const Constructor& c, SkWStream& out);
    148 
    149     SpvId writeIntConstructor(const Constructor& c, SkWStream& out);
    150 
    151     /**
    152      * Writes a matrix with the diagonal entries all equal to the provided expression, and all other
    153      * entries equal to zero.
    154      */
    155     void writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, SkWStream& out);
    156 
    157     /**
    158      * Writes a potentially-different-sized copy of a matrix. Entries which do not exist in the
    159      * source matrix are filled with zero; entries which do not exist in the destination matrix are
    160      * ignored.
    161      */
    162     void writeMatrixCopy(SpvId id, SpvId src, const Type& srcType, const Type& dstType,
    163                          SkWStream& out);
    164 
    165     SpvId writeMatrixConstructor(const Constructor& c, SkWStream& out);
    166 
    167     SpvId writeVectorConstructor(const Constructor& c, SkWStream& out);
    168 
    169     SpvId writeConstructor(const Constructor& c, SkWStream& out);
    170 
    171     SpvId writeFieldAccess(const FieldAccess& f, SkWStream& out);
    172 
    173     SpvId writeSwizzle(const Swizzle& swizzle, SkWStream& out);
    174 
    175     /**
    176      * Folds the potentially-vector result of a logical operation down to a single bool. If
    177      * operandType is a vector type, assumes that the intermediate result in id is a bvec of the
    178      * same dimensions, and applys all() to it to fold it down to a single bool value. Otherwise,
    179      * returns the original id value.
    180      */
    181     SpvId foldToBool(SpvId id, const Type& operandType, SkWStream& out);
    182 
    183     SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
    184                                SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
    185                                SpvOp_ ifBool, SkWStream& out);
    186 
    187     SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
    188                                SpvOp_ ifUInt, SkWStream& out);
    189 
    190     SpvId writeBinaryExpression(const BinaryExpression& b, SkWStream& out);
    191 
    192     SpvId writeTernaryExpression(const TernaryExpression& t, SkWStream& out);
    193 
    194     SpvId writeIndexExpression(const IndexExpression& expr, SkWStream& out);
    195 
    196     SpvId writeLogicalAnd(const BinaryExpression& b, SkWStream& out);
    197 
    198     SpvId writeLogicalOr(const BinaryExpression& o, SkWStream& out);
    199 
    200     SpvId writePrefixExpression(const PrefixExpression& p, SkWStream& out);
    201 
    202     SpvId writePostfixExpression(const PostfixExpression& p, SkWStream& out);
    203 
    204     SpvId writeBoolLiteral(const BoolLiteral& b);
    205 
    206     SpvId writeIntLiteral(const IntLiteral& i);
    207 
    208     SpvId writeFloatLiteral(const FloatLiteral& f);
    209 
    210     void writeStatement(const Statement& s, SkWStream& out);
    211 
    212     void writeBlock(const Block& b, SkWStream& out);
    213 
    214     void writeIfStatement(const IfStatement& stmt, SkWStream& out);
    215 
    216     void writeForStatement(const ForStatement& f, SkWStream& out);
    217 
    218     void writeWhileStatement(const WhileStatement& w, SkWStream& out);
    219 
    220     void writeDoStatement(const DoStatement& d, SkWStream& out);
    221 
    222     void writeReturnStatement(const ReturnStatement& r, SkWStream& out);
    223 
    224     void writeCapabilities(SkWStream& out);
    225 
    226     void writeInstructions(const Program& program, SkWStream& out);
    227 
    228     void writeOpCode(SpvOp_ opCode, int length, SkWStream& out);
    229 
    230     void writeWord(int32_t word, SkWStream& out);
    231 
    232     void writeString(const char* string, SkWStream& out);
    233 
    234     void writeLabel(SpvId id, SkWStream& out);
    235 
    236     void writeInstruction(SpvOp_ opCode, SkWStream& out);
    237 
    238     void writeInstruction(SpvOp_ opCode, const char* string, SkWStream& out);
    239 
    240     void writeInstruction(SpvOp_ opCode, int32_t word1, SkWStream& out);
    241 
    242     void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, SkWStream& out);
    243 
    244     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
    245                           SkWStream& out);
    246 
    247     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, SkWStream& out);
    248 
    249     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
    250                           SkWStream& out);
    251 
    252     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    253                           SkWStream& out);
    254 
    255     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    256                           int32_t word5, SkWStream& out);
    257 
    258     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    259                           int32_t word5, int32_t word6, SkWStream& out);
    260 
    261     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    262                           int32_t word5, int32_t word6, int32_t word7, SkWStream& out);
    263 
    264     void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
    265                           int32_t word5, int32_t word6, int32_t word7, int32_t word8,
    266                           SkWStream& out);
    267 
    268     const Context& fContext;
    269     const MemoryLayout fDefaultLayout;
    270 
    271     uint64_t fCapabilities;
    272     SpvId fIdCount;
    273     SpvId fGLSLExtendedInstructions;
    274     typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic;
    275     std::unordered_map<SkString, Intrinsic> fIntrinsicMap;
    276     std::unordered_map<const FunctionDeclaration*, SpvId> fFunctionMap;
    277     std::unordered_map<const Variable*, SpvId> fVariableMap;
    278     std::unordered_map<const Variable*, int32_t> fInterfaceBlockMap;
    279     std::unordered_map<SkString, SpvId> fTypeMap;
    280     SkDynamicMemoryWStream fCapabilitiesBuffer;
    281     SkDynamicMemoryWStream fGlobalInitializersBuffer;
    282     SkDynamicMemoryWStream fConstantBuffer;
    283     SkDynamicMemoryWStream fExtraGlobalsBuffer;
    284     SkDynamicMemoryWStream fExternalFunctionsBuffer;
    285     SkDynamicMemoryWStream fVariableBuffer;
    286     SkDynamicMemoryWStream fNameBuffer;
    287     SkDynamicMemoryWStream fDecorationBuffer;
    288 
    289     SpvId fBoolTrue;
    290     SpvId fBoolFalse;
    291     std::unordered_map<int64_t, SpvId> fIntConstants;
    292     std::unordered_map<uint64_t, SpvId> fUIntConstants;
    293     std::unordered_map<float, SpvId> fFloatConstants;
    294     std::unordered_map<double, SpvId> fDoubleConstants;
    295     bool fSetupFragPosition;
    296     // label of the current block, or 0 if we are not in a block
    297     SpvId fCurrentBlock;
    298     std::stack<SpvId> fBreakTarget;
    299     std::stack<SpvId> fContinueTarget;
    300     SpvId fRTHeightStructId = (SpvId) -1;
    301     SpvId fRTHeightFieldIndex = (SpvId) -1;
    302 
    303     friend class PointerLValue;
    304     friend class SwizzleLValue;
    305 
    306     typedef CodeGenerator INHERITED;
    307 };
    308 
    309 }
    310 
    311 #endif
    312