Index: src/sksl/SkSLSPIRVCodeGenerator.h |
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..885c6b8b706bc1ea6043b2d41af122d2113f9bcf |
--- /dev/null |
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h |
@@ -0,0 +1,264 @@ |
+/* |
+ * 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() |
+ : fCapabilities(1 << SpvCapabilityShader) |
+ , fIdCount(1) |
+ , fBoolTrue(0) |
+ , fBoolFalse(0) |
+ , fCurrentBlock(0) { |
+ this->setupIntrinsics(); |
+ } |
+ |
+ void generateCode(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(std::shared_ptr<FunctionDeclaration> function); |
+ |
+ SpvId getPointerType(std::shared_ptr<Type> type, SpvStorageClass_ storageClass); |
+ |
+ std::vector<SpvId> getAccessChain(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(ProgramElement& pe, std::ostream& out); |
+ |
+ SpvId writeInterfaceBlock(InterfaceBlock& intf); |
+ |
+ SpvId writeFunctionStart(std::shared_ptr<FunctionDeclaration> f, std::ostream& out); |
+ |
+ SpvId writeFunctionDeclaration(std::shared_ptr<FunctionDeclaration> f, std::ostream& out); |
+ |
+ SpvId writeFunction(FunctionDefinition& f, std::ostream& out); |
+ |
+ void writeGlobalVars(VarDeclaration& v, std::ostream& out); |
+ |
+ void writeVarDeclaration(VarDeclaration& decl, std::ostream& out); |
+ |
+ SpvId writeVariableReference(VariableReference& ref, std::ostream& out); |
+ |
+ std::unique_ptr<LValue> getLValue(Expression& value, std::ostream& out); |
+ |
+ SpvId writeExpression(Expression& expr, std::ostream& out); |
+ |
+ SpvId writeIntrinsicCall(FunctionCall& c, std::ostream& out); |
+ |
+ SpvId writeFunctionCall(FunctionCall& c, std::ostream& out); |
+ |
+ SpvId writeSpecialIntrinsic(FunctionCall& c, SpecialIntrinsic kind, std::ostream& out); |
+ |
+ SpvId writeConstantVector(Constructor& c); |
+ |
+ SpvId writeFloatConstructor(Constructor& c, std::ostream& out); |
+ |
+ SpvId writeIntConstructor(Constructor& c, std::ostream& out); |
+ |
+ SpvId writeMatrixConstructor(Constructor& c, std::ostream& out); |
+ |
+ SpvId writeVectorConstructor(Constructor& c, std::ostream& out); |
+ |
+ SpvId writeConstructor(Constructor& c, std::ostream& out); |
+ |
+ SpvId writeFieldAccess(FieldAccess& f, std::ostream& out); |
+ |
+ SpvId writeSwizzle(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(BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, |
+ std::ostream& out); |
+ |
+ SpvId writeBinaryExpression(BinaryExpression& b, std::ostream& out); |
+ |
+ SpvId writeTernaryExpression(TernaryExpression& t, std::ostream& out); |
+ |
+ SpvId writeIndexExpression(IndexExpression& expr, std::ostream& out); |
+ |
+ SpvId writeLogicalAnd(BinaryExpression& b, std::ostream& out); |
+ |
+ SpvId writeLogicalOr(BinaryExpression& o, std::ostream& out); |
+ |
+ SpvId writePrefixExpression(PrefixExpression& p, std::ostream& out); |
+ |
+ SpvId writePostfixExpression(PostfixExpression& p, std::ostream& out); |
+ |
+ SpvId writeBoolLiteral(BoolLiteral& b); |
+ |
+ SpvId writeIntLiteral(IntLiteral& i); |
+ |
+ SpvId writeFloatLiteral(FloatLiteral& f); |
+ |
+ void writeStatement(Statement& s, std::ostream& out); |
+ |
+ void writeBlock(Block& b, std::ostream& out); |
+ |
+ void writeIfStatement(IfStatement& stmt, std::ostream& out); |
+ |
+ void writeForStatement(ForStatement& f, std::ostream& out); |
+ |
+ void writeReturnStatement(ReturnStatement& r, std::ostream& out); |
+ |
+ void writeCapabilities(std::ostream& out); |
+ |
+ void writeInstructions(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); |
+ |
+ 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<std::shared_ptr<FunctionDeclaration>, SpvId> fFunctionMap; |
+ std::unordered_map<std::shared_ptr<Variable>, SpvId> fVariableMap; |
+ std::unordered_map<std::shared_ptr<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 |