| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SKSL_SPIRVCODEGENERATOR |
| #define SKSL_SPIRVCODEGENERATOR |
| |
| #include <sstream> |
| #include <stack> |
| #include <tuple> |
| #include <unordered_map> |
| |
| #include "SkSLCodeGenerator.h" |
| #include "ir/SkSLBinaryExpression.h" |
| #include "ir/SkSLBoolLiteral.h" |
| #include "ir/SkSLConstructor.h" |
| #include "ir/SkSLFloatLiteral.h" |
| #include "ir/SkSLIfStatement.h" |
| #include "ir/SkSLIndexExpression.h" |
| #include "ir/SkSLInterfaceBlock.h" |
| #include "ir/SkSLIntLiteral.h" |
| #include "ir/SkSLFieldAccess.h" |
| #include "ir/SkSLForStatement.h" |
| #include "ir/SkSLFunctionCall.h" |
| #include "ir/SkSLFunctionDeclaration.h" |
| #include "ir/SkSLFunctionDefinition.h" |
| #include "ir/SkSLPrefixExpression.h" |
| #include "ir/SkSLPostfixExpression.h" |
| #include "ir/SkSLProgramElement.h" |
| #include "ir/SkSLReturnStatement.h" |
| #include "ir/SkSLStatement.h" |
| #include "ir/SkSLSwizzle.h" |
| #include "ir/SkSLTernaryExpression.h" |
| #include "ir/SkSLVarDeclaration.h" |
| #include "ir/SkSLVarDeclarationStatement.h" |
| #include "ir/SkSLVariableReference.h" |
| #include "spirv.h" |
| |
| namespace SkSL { |
| |
| #define kLast_Capability SpvCapabilityMultiViewport |
| |
| /** |
| * Converts a Program into a SPIR-V binary. |
| */ |
| class SPIRVCodeGenerator : public CodeGenerator { |
| public: |
| class LValue { |
| public: |
| virtual ~LValue() {} |
| |
| // returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced |
| // by a pointer (e.g. vector swizzles), returns 0. |
| virtual SpvId getPointer() = 0; |
| |
| virtual SpvId load(std::ostream& out) = 0; |
| |
| virtual void store(SpvId value, std::ostream& out) = 0; |
| }; |
| |
| SPIRVCodeGenerator(const Context* context) |
| : fContext(*context) |
| , fCapabilities(1 << SpvCapabilityShader) |
| , fIdCount(1) |
| , fBoolTrue(0) |
| , fBoolFalse(0) |
| , fCurrentBlock(0) { |
| this->setupIntrinsics(); |
| } |
| |
| void generateCode(const Program& program, std::ostream& out) override; |
| |
| private: |
| enum IntrinsicKind { |
| kGLSL_STD_450_IntrinsicKind, |
| kSPIRV_IntrinsicKind, |
| kSpecial_IntrinsicKind |
| }; |
| |
| enum SpecialIntrinsic { |
| kAtan_SpecialIntrinsic, |
| kTexture_SpecialIntrinsic, |
| kTexture2D_SpecialIntrinsic, |
| kTextureProj_SpecialIntrinsic |
| }; |
| |
| void setupIntrinsics(); |
| |
| SpvId nextId(); |
| |
| SpvId getType(const Type& type); |
| |
| SpvId getFunctionType(const FunctionDeclaration& function); |
| |
| SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass); |
| |
| std::vector<SpvId> getAccessChain(const Expression& expr, std::ostream& out); |
| |
| void writeLayout(const Layout& layout, SpvId target); |
| |
| void writeLayout(const Layout& layout, SpvId target, int member); |
| |
| void writeStruct(const Type& type, SpvId resultId); |
| |
| void writeProgramElement(const ProgramElement& pe, std::ostream& out); |
| |
| SpvId writeInterfaceBlock(const InterfaceBlock& intf); |
| |
| SpvId writeFunctionStart(const FunctionDeclaration& f, std::ostream& out); |
| |
| SpvId writeFunctionDeclaration(const FunctionDeclaration& f, std::ostream& out); |
| |
| SpvId writeFunction(const FunctionDefinition& f, std::ostream& out); |
| |
| void writeGlobalVars(const VarDeclarations& v, std::ostream& out); |
| |
| void writeVarDeclarations(const VarDeclarations& decl, std::ostream& out); |
| |
| SpvId writeVariableReference(const VariableReference& ref, std::ostream& out); |
| |
| std::unique_ptr<LValue> getLValue(const Expression& value, std::ostream& out); |
| |
| SpvId writeExpression(const Expression& expr, std::ostream& out); |
| |
| SpvId writeIntrinsicCall(const FunctionCall& c, std::ostream& out); |
| |
| SpvId writeFunctionCall(const FunctionCall& c, std::ostream& out); |
| |
| SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, std::ostream& out); |
| |
| SpvId writeConstantVector(const Constructor& c); |
| |
| SpvId writeFloatConstructor(const Constructor& c, std::ostream& out); |
| |
| SpvId writeIntConstructor(const Constructor& c, std::ostream& out); |
| |
| SpvId writeMatrixConstructor(const Constructor& c, std::ostream& out); |
| |
| SpvId writeVectorConstructor(const Constructor& c, std::ostream& out); |
| |
| SpvId writeConstructor(const Constructor& c, std::ostream& out); |
| |
| SpvId writeFieldAccess(const FieldAccess& f, std::ostream& out); |
| |
| SpvId writeSwizzle(const Swizzle& swizzle, std::ostream& out); |
| |
| SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs, |
| SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, |
| SpvOp_ ifBool, std::ostream& out); |
| |
| SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, |
| SpvOp_ ifUInt, std::ostream& out); |
| |
| SpvId writeBinaryExpression(const BinaryExpression& b, std::ostream& out); |
| |
| SpvId writeTernaryExpression(const TernaryExpression& t, std::ostream& out); |
| |
| SpvId writeIndexExpression(const IndexExpression& expr, std::ostream& out); |
| |
| SpvId writeLogicalAnd(const BinaryExpression& b, std::ostream& out); |
| |
| SpvId writeLogicalOr(const BinaryExpression& o, std::ostream& out); |
| |
| SpvId writePrefixExpression(const PrefixExpression& p, std::ostream& out); |
| |
| SpvId writePostfixExpression(const PostfixExpression& p, std::ostream& out); |
| |
| SpvId writeBoolLiteral(const BoolLiteral& b); |
| |
| SpvId writeIntLiteral(const IntLiteral& i); |
| |
| SpvId writeFloatLiteral(const FloatLiteral& f); |
| |
| void writeStatement(const Statement& s, std::ostream& out); |
| |
| void writeBlock(const Block& b, std::ostream& out); |
| |
| void writeIfStatement(const IfStatement& stmt, std::ostream& out); |
| |
| void writeForStatement(const ForStatement& f, std::ostream& out); |
| |
| void writeReturnStatement(const ReturnStatement& r, std::ostream& out); |
| |
| void writeCapabilities(std::ostream& out); |
| |
| void writeInstructions(const Program& program, std::ostream& out); |
| |
| void writeOpCode(SpvOp_ opCode, int length, std::ostream& out); |
| |
| void writeWord(int32_t word, std::ostream& out); |
| |
| void writeString(const char* string, std::ostream& out); |
| |
| void writeLabel(SpvId id, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, const char* string, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string, |
| std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, |
| std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, |
| std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, |
| int32_t word5, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, |
| int32_t word5, int32_t word6, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, |
| int32_t word5, int32_t word6, int32_t word7, std::ostream& out); |
| |
| void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, |
| int32_t word5, int32_t word6, int32_t word7, int32_t word8, |
| std::ostream& out); |
| |
| const Context& fContext; |
| |
| uint64_t fCapabilities; |
| SpvId fIdCount; |
| SpvId fGLSLExtendedInstructions; |
| typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic; |
| std::unordered_map<std::string, Intrinsic> fIntrinsicMap; |
| std::unordered_map<const FunctionDeclaration*, SpvId> fFunctionMap; |
| std::unordered_map<const Variable*, SpvId> fVariableMap; |
| std::unordered_map<const Variable*, int32_t> fInterfaceBlockMap; |
| std::unordered_map<std::string, SpvId> fTypeMap; |
| std::stringstream fCapabilitiesBuffer; |
| std::stringstream fGlobalInitializersBuffer; |
| std::stringstream fConstantBuffer; |
| std::stringstream fExternalFunctionsBuffer; |
| std::stringstream fVariableBuffer; |
| std::stringstream fNameBuffer; |
| std::stringstream fDecorationBuffer; |
| |
| SpvId fBoolTrue; |
| SpvId fBoolFalse; |
| std::unordered_map<int64_t, SpvId> fIntConstants; |
| std::unordered_map<uint64_t, SpvId> fUIntConstants; |
| std::unordered_map<float, SpvId> fFloatConstants; |
| std::unordered_map<double, SpvId> fDoubleConstants; |
| // label of the current block, or 0 if we are not in a block |
| SpvId fCurrentBlock; |
| std::stack<SpvId> fBreakTarget; |
| std::stack<SpvId> fContinueTarget; |
| |
| friend class PointerLValue; |
| friend class SwizzleLValue; |
| }; |
| |
| } |
| |
| #endif |