1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef SKSL_SPIRVCODEGENERATOR 9cb93a386Sopenharmony_ci#define SKSL_SPIRVCODEGENERATOR 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include <stack> 12cb93a386Sopenharmony_ci#include <tuple> 13cb93a386Sopenharmony_ci#include <unordered_map> 14cb93a386Sopenharmony_ci#include <unordered_set> 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#include "src/core/SkOpts.h" 17cb93a386Sopenharmony_ci#include "src/sksl/SkSLMemoryLayout.h" 18cb93a386Sopenharmony_ci#include "src/sksl/SkSLStringStream.h" 19cb93a386Sopenharmony_ci#include "src/sksl/codegen/SkSLCodeGenerator.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cinamespace SkSL { 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciclass BinaryExpression; 24cb93a386Sopenharmony_ciclass Block; 25cb93a386Sopenharmony_ciclass ConstructorCompound; 26cb93a386Sopenharmony_ciclass ConstructorCompoundCast; 27cb93a386Sopenharmony_ciclass ConstructorDiagonalMatrix; 28cb93a386Sopenharmony_ciclass ConstructorMatrixResize; 29cb93a386Sopenharmony_ciclass ConstructorScalarCast; 30cb93a386Sopenharmony_ciclass ConstructorSplat; 31cb93a386Sopenharmony_ciclass DoStatement; 32cb93a386Sopenharmony_ciclass FieldAccess; 33cb93a386Sopenharmony_ciclass ForStatement; 34cb93a386Sopenharmony_ciclass FunctionCall; 35cb93a386Sopenharmony_ciclass FunctionDeclaration; 36cb93a386Sopenharmony_ciclass FunctionDefinition; 37cb93a386Sopenharmony_ciclass FunctionPrototype; 38cb93a386Sopenharmony_ciclass IfStatement; 39cb93a386Sopenharmony_cistruct IndexExpression; 40cb93a386Sopenharmony_ciclass InterfaceBlock; 41cb93a386Sopenharmony_cienum IntrinsicKind : int8_t; 42cb93a386Sopenharmony_ciclass Literal; 43cb93a386Sopenharmony_ciclass Operator; 44cb93a386Sopenharmony_ciclass PostfixExpression; 45cb93a386Sopenharmony_ciclass PrefixExpression; 46cb93a386Sopenharmony_ciclass ReturnStatement; 47cb93a386Sopenharmony_ciclass Setting; 48cb93a386Sopenharmony_ciclass StructDefinition; 49cb93a386Sopenharmony_ciclass SwitchStatement; 50cb93a386Sopenharmony_cistruct Swizzle; 51cb93a386Sopenharmony_ciclass TernaryExpression; 52cb93a386Sopenharmony_ciclass VarDeclaration; 53cb93a386Sopenharmony_ciclass VariableReference; 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_cistruct SPIRVNumberConstant { 56cb93a386Sopenharmony_ci bool operator==(const SPIRVNumberConstant& that) const { 57cb93a386Sopenharmony_ci return fValueBits == that.fValueBits && 58cb93a386Sopenharmony_ci fKind == that.fKind; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci int32_t fValueBits; 61cb93a386Sopenharmony_ci SkSL::Type::NumberKind fKind; 62cb93a386Sopenharmony_ci}; 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_cistruct SPIRVVectorConstant { 65cb93a386Sopenharmony_ci bool operator==(const SPIRVVectorConstant& that) const { 66cb93a386Sopenharmony_ci return fTypeId == that.fTypeId && 67cb93a386Sopenharmony_ci fValueId[0] == that.fValueId[0] && 68cb93a386Sopenharmony_ci fValueId[1] == that.fValueId[1] && 69cb93a386Sopenharmony_ci fValueId[2] == that.fValueId[2] && 70cb93a386Sopenharmony_ci fValueId[3] == that.fValueId[3]; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci SpvId fTypeId; 73cb93a386Sopenharmony_ci SpvId fValueId[4]; 74cb93a386Sopenharmony_ci}; 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci} // namespace SkSL 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_cinamespace std { 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_citemplate <> 81cb93a386Sopenharmony_cistruct hash<SkSL::SPIRVNumberConstant> { 82cb93a386Sopenharmony_ci size_t operator()(const SkSL::SPIRVNumberConstant& key) const { 83cb93a386Sopenharmony_ci return key.fValueBits ^ (int)key.fKind; 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci}; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_citemplate <> 88cb93a386Sopenharmony_cistruct hash<SkSL::SPIRVVectorConstant> { 89cb93a386Sopenharmony_ci size_t operator()(const SkSL::SPIRVVectorConstant& key) const { 90cb93a386Sopenharmony_ci return SkOpts::hash(&key, sizeof(key)); 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci}; 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci} // namespace std 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_cinamespace SkSL { 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci/** 99cb93a386Sopenharmony_ci * Converts a Program into a SPIR-V binary. 100cb93a386Sopenharmony_ci */ 101cb93a386Sopenharmony_ciclass SPIRVCodeGenerator : public CodeGenerator { 102cb93a386Sopenharmony_cipublic: 103cb93a386Sopenharmony_ci class LValue { 104cb93a386Sopenharmony_ci public: 105cb93a386Sopenharmony_ci virtual ~LValue() {} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci // returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced 108cb93a386Sopenharmony_ci // by a pointer (e.g. vector swizzles), returns -1. 109cb93a386Sopenharmony_ci virtual SpvId getPointer() { return -1; } 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci // Returns true if a valid pointer returned by getPointer represents a memory object 112cb93a386Sopenharmony_ci // (see https://github.com/KhronosGroup/SPIRV-Tools/issues/2892). Has no meaning if 113cb93a386Sopenharmony_ci // getPointer() returns -1. 114cb93a386Sopenharmony_ci virtual bool isMemoryObjectPointer() const { return true; } 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci // Applies a swizzle to the components of the LValue, if possible. This is used to create 117cb93a386Sopenharmony_ci // LValues that are swizzes-of-swizzles. Non-swizzle LValues can just return false. 118cb93a386Sopenharmony_ci virtual bool applySwizzle(const ComponentArray& components, const Type& newType) { 119cb93a386Sopenharmony_ci return false; 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci virtual SpvId load(OutputStream& out) = 0; 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci virtual void store(SpvId value, OutputStream& out) = 0; 125cb93a386Sopenharmony_ci }; 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci SPIRVCodeGenerator(const Context* context, 128cb93a386Sopenharmony_ci const Program* program, 129cb93a386Sopenharmony_ci OutputStream* out) 130cb93a386Sopenharmony_ci : INHERITED(context, program, out) 131cb93a386Sopenharmony_ci , fDefaultLayout(MemoryLayout::k140_Standard) 132cb93a386Sopenharmony_ci , fCapabilities(0) 133cb93a386Sopenharmony_ci , fIdCount(1) 134cb93a386Sopenharmony_ci , fSetupFragPosition(false) 135cb93a386Sopenharmony_ci , fCurrentBlock(0) 136cb93a386Sopenharmony_ci , fSynthetics(fContext, /*builtin=*/true) { 137cb93a386Sopenharmony_ci this->setupIntrinsics(); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci bool generateCode() override; 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ciprivate: 143cb93a386Sopenharmony_ci enum IntrinsicOpcodeKind { 144cb93a386Sopenharmony_ci kGLSL_STD_450_IntrinsicOpcodeKind, 145cb93a386Sopenharmony_ci kSPIRV_IntrinsicOpcodeKind, 146cb93a386Sopenharmony_ci kSpecial_IntrinsicOpcodeKind 147cb93a386Sopenharmony_ci }; 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ci enum SpecialIntrinsic { 150cb93a386Sopenharmony_ci kAtan_SpecialIntrinsic, 151cb93a386Sopenharmony_ci kClamp_SpecialIntrinsic, 152cb93a386Sopenharmony_ci kMatrixCompMult_SpecialIntrinsic, 153cb93a386Sopenharmony_ci kMax_SpecialIntrinsic, 154cb93a386Sopenharmony_ci kMin_SpecialIntrinsic, 155cb93a386Sopenharmony_ci kMix_SpecialIntrinsic, 156cb93a386Sopenharmony_ci kMod_SpecialIntrinsic, 157cb93a386Sopenharmony_ci kDFdy_SpecialIntrinsic, 158cb93a386Sopenharmony_ci kSaturate_SpecialIntrinsic, 159cb93a386Sopenharmony_ci kSampledImage_SpecialIntrinsic, 160cb93a386Sopenharmony_ci kSmoothStep_SpecialIntrinsic, 161cb93a386Sopenharmony_ci kStep_SpecialIntrinsic, 162cb93a386Sopenharmony_ci kSubpassLoad_SpecialIntrinsic, 163cb93a386Sopenharmony_ci kTexture_SpecialIntrinsic, 164cb93a386Sopenharmony_ci }; 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci enum class Precision { 167cb93a386Sopenharmony_ci kDefault, 168cb93a386Sopenharmony_ci kRelaxed, 169cb93a386Sopenharmony_ci }; 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci struct TempVar { 172cb93a386Sopenharmony_ci SpvId spvId; 173cb93a386Sopenharmony_ci const Type* type; 174cb93a386Sopenharmony_ci std::unique_ptr<SPIRVCodeGenerator::LValue> lvalue; 175cb93a386Sopenharmony_ci }; 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci void setupIntrinsics(); 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci /** 180cb93a386Sopenharmony_ci * Pass in the type to automatically add a RelaxedPrecision decoration for the id when 181cb93a386Sopenharmony_ci * appropriate, or null to never add one. 182cb93a386Sopenharmony_ci */ 183cb93a386Sopenharmony_ci SpvId nextId(const Type* type); 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci SpvId nextId(Precision precision); 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci const Type& getActualType(const Type& type); 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci SpvId getType(const Type& type); 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci SpvId getType(const Type& type, const MemoryLayout& layout); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci SpvId getImageType(const Type& type); 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci SpvId getFunctionType(const FunctionDeclaration& function); 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass); 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci SpvId getPointerType(const Type& type, const MemoryLayout& layout, 200cb93a386Sopenharmony_ci SpvStorageClass_ storageClass); 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ci std::vector<SpvId> getAccessChain(const Expression& expr, OutputStream& out); 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci void writeLayout(const Layout& layout, SpvId target); 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci void writeLayout(const Layout& layout, SpvId target, int member); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId); 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci void writeProgramElement(const ProgramElement& pe, OutputStream& out); 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci SpvId writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTFlip = true); 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci SpvId writeFunctionStart(const FunctionDeclaration& f, OutputStream& out); 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci SpvId writeFunctionDeclaration(const FunctionDeclaration& f, OutputStream& out); 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci SpvId writeFunction(const FunctionDefinition& f, OutputStream& out); 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci void writeGlobalVar(ProgramKind kind, const VarDeclaration& v); 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ci void writeVarDeclaration(const VarDeclaration& var, OutputStream& out); 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci SpvId writeVariableReference(const VariableReference& ref, OutputStream& out); 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci int findUniformFieldIndex(const Variable& var) const; 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci std::unique_ptr<LValue> getLValue(const Expression& value, OutputStream& out); 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci SpvId writeExpression(const Expression& expr, OutputStream& out); 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci SpvId writeIntrinsicCall(const FunctionCall& c, OutputStream& out); 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci SpvId writeFunctionCallArgument(const Expression& arg, 235cb93a386Sopenharmony_ci const Modifiers& paramModifiers, 236cb93a386Sopenharmony_ci std::vector<TempVar>* tempVars, 237cb93a386Sopenharmony_ci OutputStream& out); 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci void copyBackTempVars(const std::vector<TempVar>& tempVars, OutputStream& out); 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci SpvId writeFunctionCall(const FunctionCall& c, OutputStream& out); 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_ci void writeGLSLExtendedInstruction(const Type& type, SpvId id, SpvId floatInst, 245cb93a386Sopenharmony_ci SpvId signedInst, SpvId unsignedInst, 246cb93a386Sopenharmony_ci const std::vector<SpvId>& args, OutputStream& out); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci /** 249cb93a386Sopenharmony_ci * Promotes an expression to a vector. If the expression is already a vector with vectorSize 250cb93a386Sopenharmony_ci * columns, returns it unmodified. If the expression is a scalar, either promotes it to a 251cb93a386Sopenharmony_ci * vector (if vectorSize > 1) or returns it unmodified (if vectorSize == 1). Asserts if the 252cb93a386Sopenharmony_ci * expression is already a vector and it does not have vectorSize columns. 253cb93a386Sopenharmony_ci */ 254cb93a386Sopenharmony_ci SpvId vectorize(const Expression& expr, int vectorSize, OutputStream& out); 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci /** 257cb93a386Sopenharmony_ci * Given a list of potentially mixed scalars and vectors, promotes the scalars to match the 258cb93a386Sopenharmony_ci * size of the vectors and returns the ids of the written expressions. e.g. given (float, vec2), 259cb93a386Sopenharmony_ci * returns (vec2(float), vec2). It is an error to use mismatched vector sizes, e.g. (float, 260cb93a386Sopenharmony_ci * vec2, vec3). 261cb93a386Sopenharmony_ci */ 262cb93a386Sopenharmony_ci std::vector<SpvId> vectorize(const ExpressionArray& args, OutputStream& out); 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, OutputStream& out); 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci SpvId writeConstantVector(const AnyConstructor& c); 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci SpvId writeScalarToMatrixSplat(const Type& matrixType, SpvId scalarId, OutputStream& out); 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci SpvId writeFloatConstructor(const AnyConstructor& c, OutputStream& out); 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci SpvId castScalarToFloat(SpvId inputId, const Type& inputType, const Type& outputType, 273cb93a386Sopenharmony_ci OutputStream& out); 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci SpvId writeIntConstructor(const AnyConstructor& c, OutputStream& out); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci SpvId castScalarToSignedInt(SpvId inputId, const Type& inputType, const Type& outputType, 278cb93a386Sopenharmony_ci OutputStream& out); 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci SpvId writeUIntConstructor(const AnyConstructor& c, OutputStream& out); 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ci SpvId castScalarToUnsignedInt(SpvId inputId, const Type& inputType, const Type& outputType, 283cb93a386Sopenharmony_ci OutputStream& out); 284cb93a386Sopenharmony_ci 285cb93a386Sopenharmony_ci SpvId writeBooleanConstructor(const AnyConstructor& c, OutputStream& out); 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci SpvId castScalarToBoolean(SpvId inputId, const Type& inputType, const Type& outputType, 288cb93a386Sopenharmony_ci OutputStream& out); 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci SpvId castScalarToType(SpvId inputExprId, const Type& inputType, const Type& outputType, 291cb93a386Sopenharmony_ci OutputStream& out); 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci /** 294cb93a386Sopenharmony_ci * Writes a matrix with the diagonal entries all equal to the provided expression, and all other 295cb93a386Sopenharmony_ci * entries equal to zero. 296cb93a386Sopenharmony_ci */ 297cb93a386Sopenharmony_ci void writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, OutputStream& out); 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ci /** 300cb93a386Sopenharmony_ci * Writes a potentially-different-sized copy of a matrix. Entries which do not exist in the 301cb93a386Sopenharmony_ci * source matrix are filled with zero; entries which do not exist in the destination matrix are 302cb93a386Sopenharmony_ci * ignored. 303cb93a386Sopenharmony_ci */ 304cb93a386Sopenharmony_ci SpvId writeMatrixCopy(SpvId src, const Type& srcType, const Type& dstType, OutputStream& out); 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci void addColumnEntry(const Type& columnType, std::vector<SpvId>* currentColumn, 307cb93a386Sopenharmony_ci std::vector<SpvId>* columnIds, int rows, SpvId entry, OutputStream& out); 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_ci SpvId writeConstructorCompound(const ConstructorCompound& c, OutputStream& out); 310cb93a386Sopenharmony_ci 311cb93a386Sopenharmony_ci SpvId writeMatrixConstructor(const ConstructorCompound& c, OutputStream& out); 312cb93a386Sopenharmony_ci 313cb93a386Sopenharmony_ci SpvId writeVectorConstructor(const ConstructorCompound& c, OutputStream& out); 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci SpvId writeCompositeConstructor(const AnyConstructor& c, OutputStream& out); 316cb93a386Sopenharmony_ci 317cb93a386Sopenharmony_ci SpvId writeConstructorDiagonalMatrix(const ConstructorDiagonalMatrix& c, OutputStream& out); 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ci SpvId writeConstructorMatrixResize(const ConstructorMatrixResize& c, OutputStream& out); 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci SpvId writeConstructorScalarCast(const ConstructorScalarCast& c, OutputStream& out); 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci SpvId writeConstructorSplat(const ConstructorSplat& c, OutputStream& out); 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci SpvId writeConstructorCompoundCast(const ConstructorCompoundCast& c, OutputStream& out); 326cb93a386Sopenharmony_ci 327cb93a386Sopenharmony_ci SpvId writeComposite(const std::vector<SpvId>& arguments, const Type& type, OutputStream& out); 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_ci SpvId writeFieldAccess(const FieldAccess& f, OutputStream& out); 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_ci SpvId writeSwizzle(const Swizzle& swizzle, OutputStream& out); 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_ci /** 334cb93a386Sopenharmony_ci * Folds the potentially-vector result of a logical operation down to a single bool. If 335cb93a386Sopenharmony_ci * operandType is a vector type, assumes that the intermediate result in id is a bvec of the 336cb93a386Sopenharmony_ci * same dimensions, and applys all() to it to fold it down to a single bool value. Otherwise, 337cb93a386Sopenharmony_ci * returns the original id value. 338cb93a386Sopenharmony_ci */ 339cb93a386Sopenharmony_ci SpvId foldToBool(SpvId id, const Type& operandType, SpvOp op, OutputStream& out); 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci SpvId writeMatrixComparison(const Type& operandType, SpvId lhs, SpvId rhs, SpvOp_ floatOperator, 342cb93a386Sopenharmony_ci SpvOp_ intOperator, SpvOp_ vectorMergeOperator, 343cb93a386Sopenharmony_ci SpvOp_ mergeOperator, OutputStream& out); 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci SpvId writeStructComparison(const Type& structType, SpvId lhs, Operator op, SpvId rhs, 346cb93a386Sopenharmony_ci OutputStream& out); 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_ci SpvId writeArrayComparison(const Type& structType, SpvId lhs, Operator op, SpvId rhs, 349cb93a386Sopenharmony_ci OutputStream& out); 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_ci // Used by writeStructComparison and writeArrayComparison to logically combine field-by-field 352cb93a386Sopenharmony_ci // comparisons into an overall comparison result. 353cb93a386Sopenharmony_ci // - `a.x == b.x` merged with `a.y == b.y` generates `(a.x == b.x) && (a.y == b.y)` 354cb93a386Sopenharmony_ci // - `a.x != b.x` merged with `a.y != b.y` generates `(a.x != b.x) || (a.y != b.y)` 355cb93a386Sopenharmony_ci SpvId mergeComparisons(SpvId comparison, SpvId allComparisons, Operator op, OutputStream& out); 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci SpvId writeComponentwiseMatrixBinary(const Type& operandType, SpvId lhs, SpvId rhs, 358cb93a386Sopenharmony_ci SpvOp_ op, OutputStream& out); 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ci SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs, 361cb93a386Sopenharmony_ci SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, 362cb93a386Sopenharmony_ci SpvOp_ ifBool, OutputStream& out); 363cb93a386Sopenharmony_ci 364cb93a386Sopenharmony_ci SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, 365cb93a386Sopenharmony_ci SpvOp_ ifUInt, OutputStream& out); 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_ci SpvId writeReciprocal(const Type& type, SpvId value, OutputStream& out); 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ci SpvId writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op, 370cb93a386Sopenharmony_ci const Type& rightType, SpvId rhs, const Type& resultType, 371cb93a386Sopenharmony_ci OutputStream& out); 372cb93a386Sopenharmony_ci 373cb93a386Sopenharmony_ci SpvId writeBinaryExpression(const BinaryExpression& b, OutputStream& out); 374cb93a386Sopenharmony_ci 375cb93a386Sopenharmony_ci SpvId writeTernaryExpression(const TernaryExpression& t, OutputStream& out); 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ci SpvId writeIndexExpression(const IndexExpression& expr, OutputStream& out); 378cb93a386Sopenharmony_ci 379cb93a386Sopenharmony_ci SpvId writeLogicalAnd(const Expression& left, const Expression& right, OutputStream& out); 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ci SpvId writeLogicalOr(const Expression& left, const Expression& right, OutputStream& out); 382cb93a386Sopenharmony_ci 383cb93a386Sopenharmony_ci SpvId writePrefixExpression(const PrefixExpression& p, OutputStream& out); 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci SpvId writePostfixExpression(const PostfixExpression& p, OutputStream& out); 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci SpvId writeLiteral(const Literal& f); 388cb93a386Sopenharmony_ci 389cb93a386Sopenharmony_ci SpvId writeLiteral(double value, const Type& type); 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_ci void writeStatement(const Statement& s, OutputStream& out); 392cb93a386Sopenharmony_ci 393cb93a386Sopenharmony_ci void writeBlock(const Block& b, OutputStream& out); 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci void writeIfStatement(const IfStatement& stmt, OutputStream& out); 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_ci void writeForStatement(const ForStatement& f, OutputStream& out); 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_ci void writeDoStatement(const DoStatement& d, OutputStream& out); 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci void writeSwitchStatement(const SwitchStatement& s, OutputStream& out); 402cb93a386Sopenharmony_ci 403cb93a386Sopenharmony_ci void writeReturnStatement(const ReturnStatement& r, OutputStream& out); 404cb93a386Sopenharmony_ci 405cb93a386Sopenharmony_ci void writeCapabilities(OutputStream& out); 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_ci void writeInstructions(const Program& program, OutputStream& out); 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_ci void writeOpCode(SpvOp_ opCode, int length, OutputStream& out); 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_ci void writeWord(int32_t word, OutputStream& out); 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ci void writeString(skstd::string_view s, OutputStream& out); 414cb93a386Sopenharmony_ci 415cb93a386Sopenharmony_ci void writeLabel(SpvId id, OutputStream& out); 416cb93a386Sopenharmony_ci 417cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, OutputStream& out); 418cb93a386Sopenharmony_ci 419cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, skstd::string_view string, OutputStream& out); 420cb93a386Sopenharmony_ci 421cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, OutputStream& out); 422cb93a386Sopenharmony_ci 423cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, skstd::string_view string, 424cb93a386Sopenharmony_ci OutputStream& out); 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, skstd::string_view string, 427cb93a386Sopenharmony_ci OutputStream& out); 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, OutputStream& out); 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, 432cb93a386Sopenharmony_ci OutputStream& out); 433cb93a386Sopenharmony_ci 434cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, 435cb93a386Sopenharmony_ci OutputStream& out); 436cb93a386Sopenharmony_ci 437cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, 438cb93a386Sopenharmony_ci int32_t word5, OutputStream& out); 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, 441cb93a386Sopenharmony_ci int32_t word5, int32_t word6, OutputStream& out); 442cb93a386Sopenharmony_ci 443cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, 444cb93a386Sopenharmony_ci int32_t word5, int32_t word6, int32_t word7, OutputStream& out); 445cb93a386Sopenharmony_ci 446cb93a386Sopenharmony_ci void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4, 447cb93a386Sopenharmony_ci int32_t word5, int32_t word6, int32_t word7, int32_t word8, 448cb93a386Sopenharmony_ci OutputStream& out); 449cb93a386Sopenharmony_ci 450cb93a386Sopenharmony_ci bool isDead(const Variable& var) const; 451cb93a386Sopenharmony_ci 452cb93a386Sopenharmony_ci MemoryLayout memoryLayoutForVariable(const Variable&) const; 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci struct EntrypointAdapter { 455cb93a386Sopenharmony_ci std::unique_ptr<FunctionDefinition> entrypointDef; 456cb93a386Sopenharmony_ci std::unique_ptr<FunctionDeclaration> entrypointDecl; 457cb93a386Sopenharmony_ci Layout fLayout; 458cb93a386Sopenharmony_ci Modifiers fModifiers; 459cb93a386Sopenharmony_ci }; 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_ci EntrypointAdapter writeEntrypointAdapter(const FunctionDeclaration& main); 462cb93a386Sopenharmony_ci 463cb93a386Sopenharmony_ci struct UniformBuffer { 464cb93a386Sopenharmony_ci std::unique_ptr<InterfaceBlock> fInterfaceBlock; 465cb93a386Sopenharmony_ci std::unique_ptr<Variable> fInnerVariable; 466cb93a386Sopenharmony_ci std::unique_ptr<Type> fStruct; 467cb93a386Sopenharmony_ci }; 468cb93a386Sopenharmony_ci 469cb93a386Sopenharmony_ci void writeUniformBuffer(std::shared_ptr<SymbolTable> topLevelSymbolTable); 470cb93a386Sopenharmony_ci 471cb93a386Sopenharmony_ci void addRTFlipUniform(int line); 472cb93a386Sopenharmony_ci 473cb93a386Sopenharmony_ci const MemoryLayout fDefaultLayout; 474cb93a386Sopenharmony_ci 475cb93a386Sopenharmony_ci uint64_t fCapabilities; 476cb93a386Sopenharmony_ci SpvId fIdCount; 477cb93a386Sopenharmony_ci SpvId fGLSLExtendedInstructions; 478cb93a386Sopenharmony_ci typedef std::tuple<IntrinsicOpcodeKind, int32_t, int32_t, int32_t, int32_t> Intrinsic; 479cb93a386Sopenharmony_ci std::unordered_map<IntrinsicKind, Intrinsic> fIntrinsicMap; 480cb93a386Sopenharmony_ci std::unordered_map<const FunctionDeclaration*, SpvId> fFunctionMap; 481cb93a386Sopenharmony_ci std::unordered_map<const Variable*, SpvId> fVariableMap; 482cb93a386Sopenharmony_ci std::unordered_map<const Variable*, int32_t> fInterfaceBlockMap; 483cb93a386Sopenharmony_ci std::unordered_map<String, SpvId> fImageTypeMap; 484cb93a386Sopenharmony_ci std::unordered_map<String, SpvId> fTypeMap; 485cb93a386Sopenharmony_ci StringStream fCapabilitiesBuffer; 486cb93a386Sopenharmony_ci StringStream fGlobalInitializersBuffer; 487cb93a386Sopenharmony_ci StringStream fConstantBuffer; 488cb93a386Sopenharmony_ci StringStream fExtraGlobalsBuffer; 489cb93a386Sopenharmony_ci StringStream fVariableBuffer; 490cb93a386Sopenharmony_ci StringStream fNameBuffer; 491cb93a386Sopenharmony_ci StringStream fDecorationBuffer; 492cb93a386Sopenharmony_ci 493cb93a386Sopenharmony_ci std::unordered_map<SPIRVNumberConstant, SpvId> fNumberConstants; 494cb93a386Sopenharmony_ci std::unordered_map<SPIRVVectorConstant, SpvId> fVectorConstants; 495cb93a386Sopenharmony_ci bool fSetupFragPosition; 496cb93a386Sopenharmony_ci // label of the current block, or 0 if we are not in a block 497cb93a386Sopenharmony_ci SpvId fCurrentBlock; 498cb93a386Sopenharmony_ci std::stack<SpvId> fBreakTarget; 499cb93a386Sopenharmony_ci std::stack<SpvId> fContinueTarget; 500cb93a386Sopenharmony_ci bool fWroteRTFlip = false; 501cb93a386Sopenharmony_ci // holds variables synthesized during output, for lifetime purposes 502cb93a386Sopenharmony_ci SymbolTable fSynthetics; 503cb93a386Sopenharmony_ci int fSkInCount = 1; 504cb93a386Sopenharmony_ci // Holds a list of uniforms that were declared as globals at the top-level instead of in an 505cb93a386Sopenharmony_ci // interface block. 506cb93a386Sopenharmony_ci UniformBuffer fUniformBuffer; 507cb93a386Sopenharmony_ci std::vector<const VarDeclaration*> fTopLevelUniforms; 508cb93a386Sopenharmony_ci std::unordered_map<const Variable*, int> fTopLevelUniformMap; //<var, UniformBuffer field index> 509cb93a386Sopenharmony_ci std::unordered_set<const Variable*> fSPIRVBonusVariables; 510cb93a386Sopenharmony_ci SpvId fUniformBufferId = -1; 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_ci friend class PointerLValue; 513cb93a386Sopenharmony_ci friend class SwizzleLValue; 514cb93a386Sopenharmony_ci 515cb93a386Sopenharmony_ci using INHERITED = CodeGenerator; 516cb93a386Sopenharmony_ci}; 517cb93a386Sopenharmony_ci 518cb93a386Sopenharmony_ci} // namespace SkSL 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_ci#endif 521