2016-07-01 15:22:01 +00:00
|
|
|
/*
|
|
|
|
* 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 <stack>
|
|
|
|
#include <tuple>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
#include "SkStream.h"
|
2016-07-01 15:22:01 +00:00
|
|
|
#include "SkSLCodeGenerator.h"
|
2016-11-22 16:39:36 +00:00
|
|
|
#include "SkSLMemoryLayout.h"
|
2016-07-01 15:22:01 +00:00
|
|
|
#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"
|
2016-10-13 20:25:34 +00:00
|
|
|
#include "ir/SkSLVarDeclarations.h"
|
|
|
|
#include "ir/SkSLVarDeclarationsStatement.h"
|
2016-07-01 15:22:01 +00:00
|
|
|
#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() {}
|
2016-11-22 14:44:03 +00:00
|
|
|
|
2016-07-01 15:22:01 +00:00
|
|
|
// 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;
|
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
virtual SpvId load(SkWStream& out) = 0;
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
virtual void store(SpvId value, SkWStream& out) = 0;
|
2016-07-01 15:22:01 +00:00
|
|
|
};
|
|
|
|
|
2016-12-12 17:20:42 +00:00
|
|
|
SPIRVCodeGenerator(const Context* context)
|
|
|
|
: fContext(*context)
|
2016-11-22 16:39:36 +00:00
|
|
|
, fDefaultLayout(MemoryLayout::k140_Standard)
|
2016-07-25 17:08:54 +00:00
|
|
|
, fCapabilities(1 << SpvCapabilityShader)
|
2016-07-01 15:22:01 +00:00
|
|
|
, fIdCount(1)
|
|
|
|
, fBoolTrue(0)
|
|
|
|
, fBoolFalse(0)
|
|
|
|
, fCurrentBlock(0) {
|
|
|
|
this->setupIntrinsics();
|
|
|
|
}
|
|
|
|
|
2016-12-12 17:20:42 +00:00
|
|
|
void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) override;
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
enum IntrinsicKind {
|
|
|
|
kGLSL_STD_450_IntrinsicKind,
|
|
|
|
kSPIRV_IntrinsicKind,
|
|
|
|
kSpecial_IntrinsicKind
|
|
|
|
};
|
|
|
|
|
|
|
|
enum SpecialIntrinsic {
|
|
|
|
kAtan_SpecialIntrinsic,
|
|
|
|
kTexture_SpecialIntrinsic,
|
2016-11-22 14:44:03 +00:00
|
|
|
kSubpassLoad_SpecialIntrinsic,
|
2016-07-01 15:22:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void setupIntrinsics();
|
|
|
|
|
|
|
|
SpvId nextId();
|
|
|
|
|
|
|
|
SpvId getType(const Type& type);
|
|
|
|
|
2016-11-22 16:39:36 +00:00
|
|
|
SpvId getType(const Type& type, const MemoryLayout& layout);
|
|
|
|
|
2016-07-25 17:08:54 +00:00
|
|
|
SpvId getFunctionType(const FunctionDeclaration& function);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-07-25 17:08:54 +00:00
|
|
|
SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-12-12 17:20:42 +00:00
|
|
|
SpvId getPointerType(const Type& type, const MemoryLayout& layout,
|
2016-11-22 16:39:36 +00:00
|
|
|
SpvStorageClass_ storageClass);
|
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
std::vector<SpvId> getAccessChain(const Expression& expr, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeLayout(const Layout& layout, SpvId target);
|
|
|
|
|
|
|
|
void writeLayout(const Layout& layout, SpvId target, int member);
|
|
|
|
|
2016-11-22 16:39:36 +00:00
|
|
|
void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeProgramElement(const ProgramElement& pe, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-08-03 19:43:36 +00:00
|
|
|
SpvId writeInterfaceBlock(const InterfaceBlock& intf);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeFunctionStart(const FunctionDeclaration& f, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeFunctionDeclaration(const FunctionDeclaration& f, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeFunction(const FunctionDefinition& f, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeVarDeclarations(const VarDeclarations& decl, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeVariableReference(const VariableReference& ref, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
std::unique_ptr<LValue> getLValue(const Expression& value, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeExpression(const Expression& expr, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeIntrinsicCall(const FunctionCall& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeFunctionCall(const FunctionCall& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-08-03 19:43:36 +00:00
|
|
|
SpvId writeConstantVector(const Constructor& c);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeFloatConstructor(const Constructor& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeIntConstructor(const Constructor& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeMatrixConstructor(const Constructor& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeVectorConstructor(const Constructor& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeConstructor(const Constructor& c, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeFieldAccess(const FieldAccess& f, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeSwizzle(const Swizzle& swizzle, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-12-12 17:20:42 +00:00
|
|
|
SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
|
|
|
|
SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvOp_ ifBool, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-12-12 17:20:42 +00:00
|
|
|
SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvOp_ ifUInt, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeBinaryExpression(const BinaryExpression& b, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeTernaryExpression(const TernaryExpression& t, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeIndexExpression(const IndexExpression& expr, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeLogicalAnd(const BinaryExpression& b, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writeLogicalOr(const BinaryExpression& o, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writePrefixExpression(const PrefixExpression& p, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
SpvId writePostfixExpression(const PostfixExpression& p, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-08-03 19:43:36 +00:00
|
|
|
SpvId writeBoolLiteral(const BoolLiteral& b);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-08-03 19:43:36 +00:00
|
|
|
SpvId writeIntLiteral(const IntLiteral& i);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-08-03 19:43:36 +00:00
|
|
|
SpvId writeFloatLiteral(const FloatLiteral& f);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeStatement(const Statement& s, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeBlock(const Block& b, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeIfStatement(const IfStatement& stmt, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeForStatement(const ForStatement& f, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeReturnStatement(const ReturnStatement& r, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeCapabilities(SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeInstructions(const Program& program, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeOpCode(SpvOp_ opCode, int length, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeWord(int32_t word, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeString(const char* string, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeLabel(SpvId id, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeInstruction(SpvOp_ opCode, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeInstruction(SpvOp_ opCode, const char* string, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
|
2016-11-21 15:39:35 +00:00
|
|
|
SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-11-21 15:39:35 +00:00
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-12-12 17:20:42 +00:00
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
|
2016-11-21 15:39:35 +00:00
|
|
|
SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
|
2016-11-21 15:39:35 +00:00
|
|
|
SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
|
2016-11-21 15:39:35 +00:00
|
|
|
int32_t word5, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
|
2016-11-21 15:39:35 +00:00
|
|
|
int32_t word5, int32_t word6, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
|
2016-11-21 15:39:35 +00:00
|
|
|
int32_t word5, int32_t word6, int32_t word7, SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
|
2016-12-12 17:20:42 +00:00
|
|
|
int32_t word5, int32_t word6, int32_t word7, int32_t word8,
|
2016-11-21 15:39:35 +00:00
|
|
|
SkWStream& out);
|
2016-07-01 15:22:01 +00:00
|
|
|
|
2016-07-25 17:08:54 +00:00
|
|
|
const Context& fContext;
|
2016-11-22 16:39:36 +00:00
|
|
|
const MemoryLayout fDefaultLayout;
|
2016-12-12 17:20:42 +00:00
|
|
|
ErrorReporter* fErrors;
|
2016-07-25 17:08:54 +00:00
|
|
|
|
2016-07-01 15:22:01 +00:00
|
|
|
uint64_t fCapabilities;
|
|
|
|
SpvId fIdCount;
|
|
|
|
SpvId fGLSLExtendedInstructions;
|
|
|
|
typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic;
|
2016-11-21 15:39:35 +00:00
|
|
|
std::unordered_map<SkString, Intrinsic> fIntrinsicMap;
|
2016-07-25 17:08:54 +00:00
|
|
|
std::unordered_map<const FunctionDeclaration*, SpvId> fFunctionMap;
|
|
|
|
std::unordered_map<const Variable*, SpvId> fVariableMap;
|
|
|
|
std::unordered_map<const Variable*, int32_t> fInterfaceBlockMap;
|
2016-11-21 15:39:35 +00:00
|
|
|
std::unordered_map<SkString, SpvId> fTypeMap;
|
|
|
|
SkDynamicMemoryWStream fCapabilitiesBuffer;
|
|
|
|
SkDynamicMemoryWStream fGlobalInitializersBuffer;
|
|
|
|
SkDynamicMemoryWStream fConstantBuffer;
|
|
|
|
SkDynamicMemoryWStream fExternalFunctionsBuffer;
|
|
|
|
SkDynamicMemoryWStream fVariableBuffer;
|
|
|
|
SkDynamicMemoryWStream fNameBuffer;
|
|
|
|
SkDynamicMemoryWStream fDecorationBuffer;
|
2016-07-01 15:22:01 +00:00
|
|
|
|
|
|
|
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
|