1b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/* 2b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Copyright 2016 Google Inc. 3b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * 4b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Use of this source code is governed by a BSD-style license that can be 5b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * found in the LICENSE file. 6b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */ 7b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLSPIRVCodeGenerator.h" 9b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 10b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "string.h" 11b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "GLSL.std.450.h" 13b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 14b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLExpressionStatement.h" 15b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLExtension.h" 16b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLIndexExpression.h" 17b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "ir/SkSLVariableReference.h" 185961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#include "SkSLCompiler.h" 19b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 20b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasnamespace SkSL { 21b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 22b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#define SPIRV_DEBUG 0 23b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 24b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstatic const int32_t SKSL_MAGIC = 0x0; // FIXME: we should probably register a magic number 25b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 26b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid SPIRVCodeGenerator::setupIntrinsics() { 27b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#define ALL_GLSL(x) std::make_tuple(kGLSL_STD_450_IntrinsicKind, GLSLstd450 ## x, GLSLstd450 ## x, \ 28b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas GLSLstd450 ## x, GLSLstd450 ## x) 29b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#define BY_TYPE_GLSL(ifFloat, ifInt, ifUInt) std::make_tuple(kGLSL_STD_450_IntrinsicKind, \ 30b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas GLSLstd450 ## ifFloat, \ 31b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas GLSLstd450 ## ifInt, \ 32b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas GLSLstd450 ## ifUInt, \ 33b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpUndef) 34b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#define SPECIAL(x) std::make_tuple(kSpecial_IntrinsicKind, k ## x ## _SpecialIntrinsic, \ 35b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas k ## x ## _SpecialIntrinsic, k ## x ## _SpecialIntrinsic, \ 36b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas k ## x ## _SpecialIntrinsic) 379e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("round")] = ALL_GLSL(Round); 389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("roundEven")] = ALL_GLSL(RoundEven); 399e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("trunc")] = ALL_GLSL(Trunc); 409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("abs")] = BY_TYPE_GLSL(FAbs, SAbs, SAbs); 419e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("sign")] = BY_TYPE_GLSL(FSign, SSign, SSign); 429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("floor")] = ALL_GLSL(Floor); 439e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("ceil")] = ALL_GLSL(Ceil); 449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("fract")] = ALL_GLSL(Fract); 459e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("radians")] = ALL_GLSL(Radians); 469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("degrees")] = ALL_GLSL(Degrees); 479e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("sin")] = ALL_GLSL(Sin); 489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("cos")] = ALL_GLSL(Cos); 499e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("tan")] = ALL_GLSL(Tan); 509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("asin")] = ALL_GLSL(Asin); 519e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("acos")] = ALL_GLSL(Acos); 529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("atan")] = SPECIAL(Atan); 539e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("sinh")] = ALL_GLSL(Sinh); 549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("cosh")] = ALL_GLSL(Cosh); 559e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("tanh")] = ALL_GLSL(Tanh); 569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("asinh")] = ALL_GLSL(Asinh); 579e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("acosh")] = ALL_GLSL(Acosh); 589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("atanh")] = ALL_GLSL(Atanh); 599e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("pow")] = ALL_GLSL(Pow); 609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("exp")] = ALL_GLSL(Exp); 619e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("log")] = ALL_GLSL(Log); 629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("exp2")] = ALL_GLSL(Exp2); 639e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("log2")] = ALL_GLSL(Log2); 649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("sqrt")] = ALL_GLSL(Sqrt); 659e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("inversesqrt")] = ALL_GLSL(InverseSqrt); 669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("determinant")] = ALL_GLSL(Determinant); 679e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("matrixInverse")] = ALL_GLSL(MatrixInverse); 689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("mod")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpFMod, 699e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpSMod, SpvOpUMod, SpvOpUndef); 709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("min")] = BY_TYPE_GLSL(FMin, SMin, UMin); 719e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("max")] = BY_TYPE_GLSL(FMax, SMax, UMax); 729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("clamp")] = BY_TYPE_GLSL(FClamp, SClamp, UClamp); 739e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("dot")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDot, 749e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef, SpvOpUndef, SpvOpUndef); 759e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("mix")] = ALL_GLSL(FMix); 769e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("step")] = ALL_GLSL(Step); 779e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("smoothstep")] = ALL_GLSL(SmoothStep); 789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("fma")] = ALL_GLSL(Fma); 799e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("frexp")] = ALL_GLSL(Frexp); 809e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("ldexp")] = ALL_GLSL(Ldexp); 819e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas 829e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas#define PACK(type) fIntrinsicMap[SkString("pack" #type)] = ALL_GLSL(Pack ## type); \ 839e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("unpack" #type)] = ALL_GLSL(Unpack ## type) 84b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas PACK(Snorm4x8); 85b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas PACK(Unorm4x8); 86b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas PACK(Snorm2x16); 87b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas PACK(Unorm2x16); 88b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas PACK(Half2x16); 89b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas PACK(Double2x32); 909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("length")] = ALL_GLSL(Length); 919e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("distance")] = ALL_GLSL(Distance); 929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("cross")] = ALL_GLSL(Cross); 939e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("normalize")] = ALL_GLSL(Normalize); 949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("faceForward")] = ALL_GLSL(FaceForward); 959e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("reflect")] = ALL_GLSL(Reflect); 969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("refract")] = ALL_GLSL(Refract); 979e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("findLSB")] = ALL_GLSL(FindILsb); 989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("findMSB")] = BY_TYPE_GLSL(FindSMsb, FindSMsb, FindUMsb); 999e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("dFdx")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDPdx, 1009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef, SpvOpUndef, SpvOpUndef); 1019e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("dFdy")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDPdy, 1029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef, SpvOpUndef, SpvOpUndef); 1039e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("dFdy")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDPdy, 1049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef, SpvOpUndef, SpvOpUndef); 1059e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("texture")] = SPECIAL(Texture); 1069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas 10764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel fIntrinsicMap[SkString("subpassLoad")] = SPECIAL(SubpassLoad); 10864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 10964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel fIntrinsicMap[SkString("any")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef, 1109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef, SpvOpUndef, SpvOpAny); 11164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel fIntrinsicMap[SkString("all")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef, 1129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef, SpvOpUndef, SpvOpAll); 1139e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("equal")] = std::make_tuple(kSPIRV_IntrinsicKind, 1149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpFOrdEqual, SpvOpIEqual, 1159e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpIEqual, SpvOpLogicalEqual); 1169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("notEqual")] = std::make_tuple(kSPIRV_IntrinsicKind, 1179e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpFOrdNotEqual, SpvOpINotEqual, 1189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpINotEqual, 1199e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpLogicalNotEqual); 1209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("lessThan")] = std::make_tuple(kSPIRV_IntrinsicKind, 1219e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpSLessThan, SpvOpULessThan, 1229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpFOrdLessThan, SpvOpUndef); 1239e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("lessThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind, 12464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpSLessThanEqual, 1259e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpULessThanEqual, 1269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpFOrdLessThanEqual, 1279e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef); 1289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fIntrinsicMap[SkString("greaterThan")] = std::make_tuple(kSPIRV_IntrinsicKind, 12964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpSGreaterThan, 1309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUGreaterThan, 13164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpFOrdGreaterThan, 1329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef); 13364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel fIntrinsicMap[SkString("greaterThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind, 13464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpSGreaterThanEqual, 13564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpUGreaterThanEqual, 1369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpFOrdGreaterThanEqual, 1379e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOpUndef); 138b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas// interpolateAt* not yet supported... 140b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 141b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeWord(int32_t word, SkWStream& out) { 143b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if SPIRV_DEBUG 144b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out << "(" << word << ") "; 145b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#else 146b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out.write((const char*) &word, sizeof(word)); 147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif 148b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 149b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 150d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic bool is_float(const Context& context, const Type& type) { 151b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (type.kind() == Type::kVector_Kind) { 152d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return is_float(context, type.componentType()); 153b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 154d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return type == *context.fFloat_Type || type == *context.fDouble_Type; 155b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 156b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 157d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic bool is_signed(const Context& context, const Type& type) { 158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (type.kind() == Type::kVector_Kind) { 159d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return is_signed(context, type.componentType()); 160b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 161d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return type == *context.fInt_Type; 162b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 164d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic bool is_unsigned(const Context& context, const Type& type) { 165b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (type.kind() == Type::kVector_Kind) { 166d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return is_unsigned(context, type.componentType()); 167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 168d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return type == *context.fUInt_Type; 169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 171d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic bool is_bool(const Context& context, const Type& type) { 172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (type.kind() == Type::kVector_Kind) { 173d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return is_bool(context, type.componentType()); 174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 175d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return type == *context.fBool_Type; 176b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 177b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 178d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstatic bool is_out(const Variable& var) { 179d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return (var.fModifiers.fFlags & Modifiers::kOut_Flag) != 0; 180b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 181b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 182b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if SPIRV_DEBUG 1839e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasstatic SkString opcode_text(SpvOp_ opCode) { 184b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (opCode) { 185b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpNop: 1869e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Nop"); 187b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUndef: 1889e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Undef"); 189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSourceContinued: 1909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SourceContinued"); 191b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSource: 1929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Source"); 193b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSourceExtension: 1949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SourceExtension"); 195b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpName: 1969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Name"); 197b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemberName: 1989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MemberName"); 199b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpString: 2009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("String"); 201b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLine: 2029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Line"); 203b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpExtension: 2049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Extension"); 205b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpExtInstImport: 2069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ExtInstImport"); 207b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpExtInst: 2089e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ExtInst"); 209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemoryModel: 2109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MemoryModel"); 211b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEntryPoint: 2129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EntryPoint"); 213b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpExecutionMode: 2149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ExecutionMode"); 215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCapability: 2169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Capability"); 217b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeVoid: 2189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeVoid"); 219b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeBool: 2209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeBool"); 221b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeInt: 2229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeInt"); 223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeFloat: 2249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeFloat"); 225b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeVector: 2269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeVector"); 227b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeMatrix: 2289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeMatrix"); 229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeImage: 2309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeImage"); 231b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeSampler: 2329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeSampler"); 233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeSampledImage: 2349e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeSampledImage"); 235b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeArray: 2369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeArray"); 237b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeRuntimeArray: 2389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeRuntimeArray"); 239b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeStruct: 2409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeStruct"); 241b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeOpaque: 2429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeOpaque"); 243b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypePointer: 2449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypePointer"); 245b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeFunction: 2469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeFunction"); 247b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeEvent: 2489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeEvent"); 249b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeDeviceEvent: 2509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeDeviceEvent"); 251b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeReserveId: 2529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeReserveId"); 253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeQueue: 2549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeQueue"); 255b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypePipe: 2569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypePipe"); 257b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeForwardPointer: 2589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("TypeForwardPointer"); 259b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantTrue: 2609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConstantTrue"); 261b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantFalse: 2629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConstantFalse"); 263b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstant: 2649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Constant"); 265b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantComposite: 2669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConstantComposite"); 267b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantSampler: 2689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConstantSampler"); 269b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantNull: 2709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConstantNull"); 271b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSpecConstantTrue: 2729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SpecConstantTrue"); 273b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSpecConstantFalse: 2749e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SpecConstantFalse"); 275b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSpecConstant: 2769e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SpecConstant"); 277b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSpecConstantComposite: 2789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SpecConstantComposite"); 279b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSpecConstantOp: 2809e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SpecConstantOp"); 281b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunction: 2829e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Function"); 283b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunctionParameter: 2849e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FunctionParameter"); 285b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunctionEnd: 2869e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FunctionEnd"); 287b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunctionCall: 2889e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FunctionCall"); 289b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVariable: 2909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Variable"); 291b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageTexelPointer: 2929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageTexelPointer"); 293b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLoad: 2949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Load"); 295b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpStore: 2969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Store"); 297b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCopyMemory: 2989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CopyMemory"); 299b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCopyMemorySized: 3009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CopyMemorySized"); 301b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAccessChain: 3029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AccessChain"); 303b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpInBoundsAccessChain: 3049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("InBoundsAccessChain"); 305b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpPtrAccessChain: 3069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("PtrAccessChain"); 307b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpArrayLength: 3089e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ArrayLength"); 309b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGenericPtrMemSemantics: 3109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GenericPtrMemSemantics"); 311b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpInBoundsPtrAccessChain: 3129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("InBoundsPtrAccessChain"); 313b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDecorate: 3149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Decorate"); 315b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemberDecorate: 3169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MemberDecorate"); 317b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDecorationGroup: 3189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DecorationGroup"); 319b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupDecorate: 3209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupDecorate"); 321b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupMemberDecorate: 3229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupMemberDecorate"); 323b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVectorExtractDynamic: 3249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("VectorExtractDynamic"); 325b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVectorInsertDynamic: 3269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("VectorInsertDynamic"); 327b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVectorShuffle: 3289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("VectorShuffle"); 329b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCompositeConstruct: 3309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CompositeConstruct"); 331b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCompositeExtract: 3329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CompositeExtract"); 333b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCompositeInsert: 3349e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CompositeInsert"); 335b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCopyObject: 3369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CopyObject"); 337b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTranspose: 3389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Transpose"); 339b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSampledImage: 3409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SampledImage"); 341b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleImplicitLod: 3429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleImplicitLod"); 343b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleExplicitLod: 3449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleExplicitLod"); 345b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleDrefImplicitLod: 3469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleDrefImplicitLod"); 347b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleDrefExplicitLod: 3489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleDrefExplicitLod"); 349b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleProjImplicitLod: 3509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleProjImplicitLod"); 351b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleProjExplicitLod: 3529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleProjExplicitLod"); 353b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleProjDrefImplicitLod: 3549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleProjDrefImplicitLod"); 355b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSampleProjDrefExplicitLod: 3569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSampleProjDrefExplicitLod"); 357b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageFetch: 3589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageFetch"); 359b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageGather: 3609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageGather"); 361b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageDrefGather: 3629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageDrefGather"); 363b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageRead: 3649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageRead"); 365b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageWrite: 3669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageWrite"); 367b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImage: 3689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Image"); 369b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQueryFormat: 3709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQueryFormat"); 371b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQueryOrder: 3729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQueryOrder"); 373b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQuerySizeLod: 3749e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQuerySizeLod"); 375b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQuerySize: 3769e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQuerySize"); 377b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQueryLod: 3789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQueryLod"); 379b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQueryLevels: 3809e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQueryLevels"); 381b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageQuerySamples: 3829e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageQuerySamples"); 383b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConvertFToU: 3849e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConvertFToU"); 385b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConvertFToS: 3869e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConvertFToS"); 387b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConvertSToF: 3889e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConvertSToF"); 389b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConvertUToF: 3909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConvertUToF"); 391b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUConvert: 3929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("UConvert"); 393b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSConvert: 3949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SConvert"); 395b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFConvert: 3969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FConvert"); 397b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpQuantizeToF16: 3989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("QuantizeToF16"); 399b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConvertPtrToU: 4009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConvertPtrToU"); 401b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSatConvertSToU: 4029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SatConvertSToU"); 403b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSatConvertUToS: 4049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SatConvertUToS"); 405b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConvertUToPtr: 4069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ConvertUToPtr"); 407b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpPtrCastToGeneric: 4089e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("PtrCastToGeneric"); 409b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGenericCastToPtr: 4109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GenericCastToPtr"); 411b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGenericCastToPtrExplicit: 4129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GenericCastToPtrExplicit"); 413b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitcast: 4149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Bitcast"); 415b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSNegate: 4169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SNegate"); 417b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFNegate: 4189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FNegate"); 419b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIAdd: 4209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IAdd"); 421b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFAdd: 4229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FAdd"); 423b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpISub: 4249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ISub"); 425b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFSub: 4269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FSub"); 427b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIMul: 4289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IMul"); 429b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFMul: 4309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FMul"); 431b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUDiv: 4329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("UDiv"); 433b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSDiv: 4349e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SDiv"); 435b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFDiv: 4369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FDiv"); 437b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUMod: 4389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("UMod"); 439b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSRem: 4409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SRem"); 441b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSMod: 4429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SMod"); 443b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFRem: 4449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FRem"); 445b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFMod: 4469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FMod"); 447b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVectorTimesScalar: 4489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("VectorTimesScalar"); 449b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMatrixTimesScalar: 4509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MatrixTimesScalar"); 451b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVectorTimesMatrix: 4529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("VectorTimesMatrix"); 453b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMatrixTimesVector: 4549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MatrixTimesVector"); 455b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMatrixTimesMatrix: 4569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MatrixTimesMatrix"); 457b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpOuterProduct: 4589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("OuterProduct"); 459b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDot: 4609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Dot"); 461b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIAddCarry: 4629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IAddCarry"); 463b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpISubBorrow: 4649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ISubBorrow"); 465b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUMulExtended: 4669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("UMulExtended"); 467b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSMulExtended: 4689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SMulExtended"); 469b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAny: 4709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Any"); 471b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAll: 4729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("All"); 473b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIsNan: 4749e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IsNan"); 475b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIsInf: 4769e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IsInf"); 477b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIsFinite: 4789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IsFinite"); 479b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIsNormal: 4809e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IsNormal"); 481b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSignBitSet: 4829e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SignBitSet"); 483b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLessOrGreater: 4849e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LessOrGreater"); 485b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpOrdered: 4869e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Ordered"); 487b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUnordered: 4889e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Unordered"); 489b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLogicalEqual: 4909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LogicalEqual"); 491b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLogicalNotEqual: 4929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LogicalNotEqual"); 493b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLogicalOr: 4949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LogicalOr"); 495b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLogicalAnd: 4969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LogicalAnd"); 497b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLogicalNot: 4989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LogicalNot"); 499b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSelect: 5009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Select"); 501b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIEqual: 5029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IEqual"); 503b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpINotEqual: 5049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("INotEqual"); 505b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUGreaterThan: 5069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("UGreaterThan"); 507b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSGreaterThan: 5089e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SGreaterThan"); 509b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUGreaterThanEqual: 5109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("UGreaterThanEqual"); 511b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSGreaterThanEqual: 5129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SGreaterThanEqual"); 513b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpULessThan: 5149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ULessThan"); 515b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSLessThan: 5169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SLessThan"); 517b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpULessThanEqual: 5189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ULessThanEqual"); 519b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSLessThanEqual: 5209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SLessThanEqual"); 521b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFOrdEqual: 5229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FOrdEqual"); 523b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFUnordEqual: 5249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FUnordEqual"); 525b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFOrdNotEqual: 5269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FOrdNotEqual"); 527b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFUnordNotEqual: 5289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FUnordNotEqual"); 529b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFOrdLessThan: 5309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FOrdLessThan"); 531b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFUnordLessThan: 5329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FUnordLessThan"); 533b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFOrdGreaterThan: 5349e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FOrdGreaterThan"); 535b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFUnordGreaterThan: 5369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FUnordGreaterThan"); 537b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFOrdLessThanEqual: 5389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FOrdLessThanEqual"); 539b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFUnordLessThanEqual: 5409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FUnordLessThanEqual"); 541b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFOrdGreaterThanEqual: 5429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FOrdGreaterThanEqual"); 543b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFUnordGreaterThanEqual: 5449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FUnordGreaterThanEqual"); 545b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpShiftRightLogical: 5469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ShiftRightLogical"); 547b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpShiftRightArithmetic: 5489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ShiftRightArithmetic"); 549b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpShiftLeftLogical: 5509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ShiftLeftLogical"); 551b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitwiseOr: 5529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitwiseOr"); 553b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitwiseXor: 5549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitwiseXor"); 555b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitwiseAnd: 5569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitwiseAnd"); 557b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpNot: 5589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Not"); 559b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitFieldInsert: 5609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitFieldInsert"); 561b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitFieldSExtract: 5629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitFieldSExtract"); 563b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitFieldUExtract: 5649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitFieldUExtract"); 565b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitReverse: 5669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitReverse"); 567b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBitCount: 5689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BitCount"); 569b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDPdx: 5709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DPdx"); 571b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDPdy: 5729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DPdy"); 573b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFwidth: 5749e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Fwidth"); 575b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDPdxFine: 5769e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DPdxFine"); 577b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDPdyFine: 5789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DPdyFine"); 579b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFwidthFine: 5809e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FwidthFine"); 581b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDPdxCoarse: 5829e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DPdxCoarse"); 583b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDPdyCoarse: 5849e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("DPdyCoarse"); 585b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFwidthCoarse: 5869e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("FwidthCoarse"); 587b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEmitVertex: 5889e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EmitVertex"); 589b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEndPrimitive: 5909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EndPrimitive"); 591b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEmitStreamVertex: 5929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EmitStreamVertex"); 593b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEndStreamPrimitive: 5949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EndStreamPrimitive"); 595b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpControlBarrier: 5969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ControlBarrier"); 597b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemoryBarrier: 5989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("MemoryBarrier"); 599b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicLoad: 6009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicLoad"); 601b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicStore: 6029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicStore"); 603b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicExchange: 6049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicExchange"); 605b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicCompareExchange: 6069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicCompareExchange"); 607b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicCompareExchangeWeak: 6089e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicCompareExchangeWeak"); 609b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicIIncrement: 6109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicIIncrement"); 611b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicIDecrement: 6129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicIDecrement"); 613b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicIAdd: 6149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicIAdd"); 615b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicISub: 6169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicISub"); 617b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicSMin: 6189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicSMin"); 619b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicUMin: 6209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicUMin"); 621b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicSMax: 6229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicSMax"); 623b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicUMax: 6249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicUMax"); 625b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicAnd: 6269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicAnd"); 627b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicOr: 6289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicOr"); 629b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicXor: 6309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicXor"); 631b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpPhi: 6329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Phi"); 633b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLoopMerge: 6349e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LoopMerge"); 635b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSelectionMerge: 6369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SelectionMerge"); 637b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLabel: 6389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Label"); 639b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBranch: 6409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Branch"); 641b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBranchConditional: 6429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BranchConditional"); 643b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSwitch: 6449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Switch"); 645b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpKill: 6469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Kill"); 647b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReturn: 6489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Return"); 649b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReturnValue: 6509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReturnValue"); 651b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpUnreachable: 6529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("Unreachable"); 653b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLifetimeStart: 6549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LifetimeStart"); 655b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpLifetimeStop: 6569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("LifetimeStop"); 657b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupAsyncCopy: 6589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupAsyncCopy"); 659b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupWaitEvents: 6609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupWaitEvents"); 661b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupAll: 6629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupAll"); 663b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupAny: 6649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupAny"); 665b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupBroadcast: 6669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupBroadcast"); 667b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupIAdd: 6689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupIAdd"); 669b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupFAdd: 6709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupFAdd"); 671b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupFMin: 6729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupFMin"); 673b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupUMin: 6749e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupUMin"); 675b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupSMin: 6769e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupSMin"); 677b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupFMax: 6789e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupFMax"); 679b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupUMax: 6809e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupUMax"); 681b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupSMax: 6829e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupSMax"); 683b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReadPipe: 6849e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReadPipe"); 685b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpWritePipe: 6869e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("WritePipe"); 687b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReservedReadPipe: 6889e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReservedReadPipe"); 689b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReservedWritePipe: 6909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReservedWritePipe"); 691b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReserveReadPipePackets: 6929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReserveReadPipePackets"); 693b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReserveWritePipePackets: 6949e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReserveWritePipePackets"); 695b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCommitReadPipe: 6969e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CommitReadPipe"); 697b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCommitWritePipe: 6989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CommitWritePipe"); 699b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIsValidReserveId: 7009e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IsValidReserveId"); 701b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetNumPipePackets: 7029e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetNumPipePackets"); 703b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetMaxPipePackets: 7049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetMaxPipePackets"); 705b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupReserveReadPipePackets: 7069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupReserveReadPipePackets"); 707b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupReserveWritePipePackets: 7089e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupReserveWritePipePackets"); 709b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupCommitReadPipe: 7109e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupCommitReadPipe"); 711b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGroupCommitWritePipe: 7129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GroupCommitWritePipe"); 713b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEnqueueMarker: 7149e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EnqueueMarker"); 715b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEnqueueKernel: 7169e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("EnqueueKernel"); 717b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetKernelNDrangeSubGroupCount: 7189e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetKernelNDrangeSubGroupCount"); 719b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetKernelNDrangeMaxSubGroupSize: 7209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetKernelNDrangeMaxSubGroupSize"); 721b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetKernelWorkGroupSize: 7229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetKernelWorkGroupSize"); 723b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetKernelPreferredWorkGroupSizeMultiple: 7249e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetKernelPreferredWorkGroupSizeMultiple"); 725b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpRetainEvent: 7269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("RetainEvent"); 727b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReleaseEvent: 7289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ReleaseEvent"); 729b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCreateUserEvent: 7309e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CreateUserEvent"); 731b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpIsValidEvent: 7329e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("IsValidEvent"); 733b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSetUserEventStatus: 7349e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("SetUserEventStatus"); 735b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCaptureEventProfilingInfo: 7369e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("CaptureEventProfilingInfo"); 737b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpGetDefaultQueue: 7389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("GetDefaultQueue"); 739b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBuildNDRange: 7409e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("BuildNDRange"); 741b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleImplicitLod: 7429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleImplicitLod"); 743b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleExplicitLod: 7449e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleExplicitLod"); 745b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleDrefImplicitLod: 7469e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleDrefImplicitLod"); 747b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleDrefExplicitLod: 7489e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleDrefExplicitLod"); 749b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleProjImplicitLod: 7509e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleProjImplicitLod"); 751b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleProjExplicitLod: 7529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleProjExplicitLod"); 753b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleProjDrefImplicitLod: 7549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleProjDrefImplicitLod"); 755b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseSampleProjDrefExplicitLod: 7569e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseSampleProjDrefExplicitLod"); 757b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseFetch: 7589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseFetch"); 759b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseGather: 7609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseGather"); 761b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseDrefGather: 7629e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseDrefGather"); 763b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseTexelsResident: 7649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseTexelsResident"); 765b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpNoLine: 7669e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("NoLine"); 767b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicFlagTestAndSet: 7689e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicFlagTestAndSet"); 769b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpAtomicFlagClear: 7709e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("AtomicFlagClear"); 771b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpImageSparseRead: 7729e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas return SkString("ImageSparseRead"); 773b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 774b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported SPIR-V op"); 775b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 776b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 777b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif 778b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 7799e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, SkWStream& out) { 780b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(opCode != SpvOpUndef); 781b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (opCode) { 782b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReturn: // fall through 783b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpReturnValue: // fall through 784552882f768b02a2aa20552a765913187851e382bethannicholas case SpvOpKill: // fall through 785b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBranch: // fall through 786b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpBranchConditional: 787b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(fCurrentBlock); 788b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fCurrentBlock = 0; 789b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 790b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstant: // fall through 791b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantTrue: // fall through 792b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantFalse: // fall through 793b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpConstantComposite: // fall through 794b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeVoid: // fall through 795b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeInt: // fall through 796b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeFloat: // fall through 797b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeBool: // fall through 798b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeVector: // fall through 799b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeMatrix: // fall through 800b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeArray: // fall through 801b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypePointer: // fall through 802b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeFunction: // fall through 803b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeRuntimeArray: // fall through 804b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeStruct: // fall through 805b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeImage: // fall through 806b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpTypeSampledImage: // fall through 807b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpVariable: // fall through 808b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunction: // fall through 809b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunctionParameter: // fall through 810b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpFunctionEnd: // fall through 811b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpExecutionMode: // fall through 812b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemoryModel: // fall through 813b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpCapability: // fall through 814b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpExtInstImport: // fall through 815b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpEntryPoint: // fall through 816b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSource: // fall through 817b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpSourceExtension: // fall through 818b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpName: // fall through 819b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemberName: // fall through 820b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpDecorate: // fall through 821b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case SpvOpMemberDecorate: 822b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 823b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 824b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(fCurrentBlock); 825b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 826b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if SPIRV_DEBUG 827b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out << std::endl << opcode_text(opCode) << " "; 828b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#else 829b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord((length << 16) | opCode, out); 830b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif 831b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 832b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8339e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeLabel(SpvId label, SkWStream& out) { 834b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fCurrentBlock = label; 835b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpLabel, label, out); 836b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 837b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, SkWStream& out) { 839b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 1, out); 840b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 841b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8429e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, SkWStream& out) { 843b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 2, out); 844b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 845b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 846b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8479e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeString(const char* string, SkWStream& out) { 848b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas size_t length = strlen(string); 8499e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas out.writeText(string); 850b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (length % 4) { 851b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 1: 8529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas out.write8(0); 853b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // fall through 854b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 2: 8559e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas out.write8(0); 856b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // fall through 857b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case 3: 8589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas out.write8(0); 859b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 860b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 861b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(0, out); 862b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 863b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 864b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 8659e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, const char* string, SkWStream& out) { 866b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t length = (int32_t) strlen(string); 867b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 1 + (length + 4) / 4, out); 868b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeString(string, out); 869b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 870b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 871b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 87264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, 8739e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 874b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t length = (int32_t) strlen(string); 875b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 2 + (length + 4) / 4, out); 876b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 877b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeString(string, out); 878b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 879b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 88064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 8819e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas const char* string, SkWStream& out) { 882b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t length = (int32_t) strlen(string); 883b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 3 + (length + 4) / 4, out); 884b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 885b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 886b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeString(string, out); 887b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 888b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 88964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 8909e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 891b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 3, out); 892b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 893b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 894b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 895b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 89664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 8979e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas int32_t word3, SkWStream& out) { 898b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 4, out); 899b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 900b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 901b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word3, out); 902b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 903b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 90464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 9059e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas int32_t word3, int32_t word4, SkWStream& out) { 906b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 5, out); 907b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 908b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 909b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word3, out); 910b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word4, out); 911b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 912b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 91364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 91464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel int32_t word3, int32_t word4, int32_t word5, 9159e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 916b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 6, out); 917b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 918b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 919b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word3, out); 920b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word4, out); 921b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word5, out); 922b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 923b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 92464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 925b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t word3, int32_t word4, int32_t word5, 9269e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas int32_t word6, SkWStream& out) { 927b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 7, out); 928b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 929b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 930b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word3, out); 931b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word4, out); 932b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word5, out); 933b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word6, out); 934b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 935b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 93664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 937b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t word3, int32_t word4, int32_t word5, 9389e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas int32_t word6, int32_t word7, SkWStream& out) { 939b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 8, out); 940b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 941b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 942b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word3, out); 943b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word4, out); 944b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word5, out); 945b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word6, out); 946b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word7, out); 947b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 948b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 94964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 950b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t word3, int32_t word4, int32_t word5, 951b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t word6, int32_t word7, int32_t word8, 9529e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 953b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(opCode, 9, out); 954b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word1, out); 955b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word2, out); 956b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word3, out); 957b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word4, out); 958b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word5, out); 959b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word6, out); 960b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word7, out); 961b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(word8, out); 962b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 963b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 9649e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeCapabilities(SkWStream& out) { 965b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (uint64_t i = 0, bit = 1; i <= kLast_Capability; i++, bit <<= 1) { 966b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fCapabilities & bit) { 967b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpCapability, (SpvId) i, out); 968b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 969b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 970b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 971b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 972b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasSpvId SPIRVCodeGenerator::nextId() { 973b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return fIdCount++; 974b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 975b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 97619671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholasvoid SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memoryLayout, 97719671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas SpvId resultId) { 978b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpName, resultId, type.name().c_str(), fNameBuffer); 979b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // go ahead and write all of the field types, so we don't inadvertently write them while we're 980b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // in the middle of writing the struct instruction 981b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> types; 982b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (const auto& f : type.fields()) { 98319671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas types.push_back(this->getType(*f.fType, memoryLayout)); 984b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 985b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuffer); 986b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(resultId, fConstantBuffer); 987b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : types) { 988b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, fConstantBuffer); 989b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 990b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas size_t offset = 0; 991b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) { 99219671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas size_t size = memoryLayout.size(*type.fields()[i].fType); 99319671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas size_t alignment = memoryLayout.alignment(*type.fields()[i].fType); 99419671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout; 99519671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas if (fieldLayout.fOffset >= 0) { 996dbd44c78ec98adc07569d430f3b27e0834186a7eGreg Daniel if (fieldLayout.fOffset < (int) offset) { 997941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrors.error(type.fPosition, 998941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas "offset of field '" + type.fields()[i].fName + "' must be at " 999941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas "least " + to_string((int) offset)); 100019671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas } 100119671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas if (fieldLayout.fOffset % alignment) { 1002941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fErrors.error(type.fPosition, 1003941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas "offset of field '" + type.fields()[i].fName + "' must be a multiple" 1004941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas " of " + to_string((int) alignment)); 100519671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas } 100619671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas offset = fieldLayout.fOffset; 100719671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas } else { 100819671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas size_t mod = offset % alignment; 100919671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas if (mod) { 101019671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas offset += alignment - mod; 101119671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas } 1012b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1013b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName.c_str(), 1014b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fNameBuffer); 101519671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas this->writeLayout(fieldLayout, resultId, i); 1016b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) { 101764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset, 1018b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas (SpvId) offset, fDecorationBuffer); 1019b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 10200730be7c303ac415484b15ef44ff1dce077a93b8ethannicholas if (type.fields()[i].fType->kind() == Type::kMatrix_Kind) { 102164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor, 1022b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 102364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride, 102419671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas (SpvId) memoryLayout.stride(*type.fields()[i].fType), 10258ac838d978578c44b75a801489c985e5284dd66fethannicholas fDecorationBuffer); 1026b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1027b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas offset += size; 10280730be7c303ac415484b15ef44ff1dce077a93b8ethannicholas Type::Kind kind = type.fields()[i].fType->kind(); 1029b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if ((kind == Type::kArray_Kind || kind == Type::kStruct_Kind) && offset % alignment != 0) { 1030b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas offset += alignment - offset % alignment; 1031b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1032b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1033b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1034b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1035b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasSpvId SPIRVCodeGenerator::getType(const Type& type) { 10368ac838d978578c44b75a801489c985e5284dd66fethannicholas return this->getType(type, fDefaultLayout); 10378ac838d978578c44b75a801489c985e5284dd66fethannicholas} 10388ac838d978578c44b75a801489c985e5284dd66fethannicholas 10398ac838d978578c44b75a801489c985e5284dd66fethannicholasSpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) { 10408ac838d978578c44b75a801489c985e5284dd66fethannicholas SkString key = type.name() + to_string((int) layout.fStd); 10418ac838d978578c44b75a801489c985e5284dd66fethannicholas auto entry = fTypeMap.find(key); 1042b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fTypeMap.end()) { 1043b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1044b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (type.kind()) { 1045b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kScalar_Kind: 1046d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type == *fContext.fBool_Type) { 1047b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpTypeBool, result, fConstantBuffer); 1048d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (type == *fContext.fInt_Type) { 1049b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpTypeInt, result, 32, 1, fConstantBuffer); 1050d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (type == *fContext.fUInt_Type) { 1051b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpTypeInt, result, 32, 0, fConstantBuffer); 1052d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (type == *fContext.fFloat_Type) { 1053b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpTypeFloat, result, 32, fConstantBuffer); 1054d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (type == *fContext.fDouble_Type) { 1055b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpTypeFloat, result, 64, fConstantBuffer); 1056b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1057b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(false); 1058b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1059b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1060b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kVector_Kind: 106164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpTypeVector, result, 10628ac838d978578c44b75a801489c985e5284dd66fethannicholas this->getType(type.componentType(), layout), 1063b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas type.columns(), fConstantBuffer); 1064b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1065b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kMatrix_Kind: 106664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpTypeMatrix, result, 10678ac838d978578c44b75a801489c985e5284dd66fethannicholas this->getType(index_type(fContext, type), layout), 1068b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas type.columns(), fConstantBuffer); 1069b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1070b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kStruct_Kind: 10718ac838d978578c44b75a801489c985e5284dd66fethannicholas this->writeStruct(type, layout, result); 1072b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1073b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kArray_Kind: { 1074b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (type.columns() > 0) { 1075d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas IntLiteral count(fContext, Position(), type.columns()); 107664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpTypeArray, result, 10778ac838d978578c44b75a801489c985e5284dd66fethannicholas this->getType(type.componentType(), layout), 1078b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeIntLiteral(count), fConstantBuffer); 107964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride, 10808ac838d978578c44b75a801489c985e5284dd66fethannicholas (int32_t) layout.stride(type), 10818ac838d978578c44b75a801489c985e5284dd66fethannicholas fDecorationBuffer); 1082b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1083b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("runtime-sized arrays are not yet supported"); 108464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpTypeRuntimeArray, result, 10858ac838d978578c44b75a801489c985e5284dd66fethannicholas this->getType(type.componentType(), layout), 10868ac838d978578c44b75a801489c985e5284dd66fethannicholas fConstantBuffer); 1087b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1088b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1089b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1090b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kSampler_Kind: { 109164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId image = result; 109264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (SpvDimSubpassData != type.dimensions()) { 109364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel image = this->nextId(); 109464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } 10958ac838d978578c44b75a801489c985e5284dd66fethannicholas this->writeInstruction(SpvOpTypeImage, image, 10968ac838d978578c44b75a801489c985e5284dd66fethannicholas this->getType(*fContext.fFloat_Type, layout), 1097b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas type.dimensions(), type.isDepth(), type.isArrayed(), 109864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel type.isMultisampled(), type.isSampled() ? 1 : 2, 1099b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvImageFormatUnknown, fConstantBuffer); 110064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (SpvDimSubpassData != type.dimensions()) { 110164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpTypeSampledImage, result, image, fConstantBuffer); 110264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } 1103b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1104b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1105b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1106d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type == *fContext.fVoid_Type) { 1107b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffer); 1108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1109b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("invalid type: %s", type.description().c_str()); 1110b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1111b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 11128ac838d978578c44b75a801489c985e5284dd66fethannicholas fTypeMap[key] = result; 1113b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1114b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 1116b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1117b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1118d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasSpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { 11199e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkString key = function.fReturnType.description() + "("; 11209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkString separator; 1121d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas for (size_t i = 0; i < function.fParameters.size(); i++) { 1122b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas key += separator; 1123b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas separator = ", "; 1124d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas key += function.fParameters[i]->fType.description(); 1125b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1126b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas key += ")"; 1127b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto entry = fTypeMap.find(key); 1128b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fTypeMap.end()) { 1129b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1130d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int32_t length = 3 + (int32_t) function.fParameters.size(); 1131d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId returnType = this->getType(function.fReturnType); 1132b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> parameterTypes; 1133d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas for (size_t i = 0; i < function.fParameters.size(); i++) { 113464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // glslang seems to treat all function arguments as pointers whether they need to be or 113564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // not. I was initially puzzled by this until I ran bizarre failures with certain 113664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // patterns of function calls and control constructs, as exemplified by this minimal 1137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // failure case: 1138b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // 1139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // void sphere(float x) { 1140b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // } 114164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // 1142b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // void map() { 1143b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // sphere(1.0); 1144b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // } 114564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // 1146b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // void main() { 1147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // for (int i = 0; i < 1; i++) { 1148b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // map(); 1149b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // } 1150b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // } 1151b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // 115264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // As of this writing, compiling this in the "obvious" way (with sphere taking a float) 115364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // crashes. Making it take a float* and storing the argument in a temporary variable, 1154b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // as glslang does, fixes it. It's entirely possible I simply missed whichever part of 1155b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // the spec makes this make sense. 1156b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas// if (is_out(function->fParameters[i])) { 1157d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas parameterTypes.push_back(this->getPointerType(function.fParameters[i]->fType, 1158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvStorageClassFunction)); 1159b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas// } else { 1160d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas// parameterTypes.push_back(this->getType(function.fParameters[i]->fType)); 1161b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas// } 1162b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpTypeFunction, length, fConstantBuffer); 1164b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, fConstantBuffer); 1165b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(returnType, fConstantBuffer); 1166b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : parameterTypes) { 1167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, fConstantBuffer); 1168b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1169b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fTypeMap[key] = result; 1170b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 1173b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 11758ac838d978578c44b75a801489c985e5284dd66fethannicholasSpvId SPIRVCodeGenerator::getPointerType(const Type& type, SpvStorageClass_ storageClass) { 11768ac838d978578c44b75a801489c985e5284dd66fethannicholas return this->getPointerType(type, fDefaultLayout, storageClass); 11778ac838d978578c44b75a801489c985e5284dd66fethannicholas} 11788ac838d978578c44b75a801489c985e5284dd66fethannicholas 11798ac838d978578c44b75a801489c985e5284dd66fethannicholasSpvId SPIRVCodeGenerator::getPointerType(const Type& type, const MemoryLayout& layout, 1180b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvStorageClass_ storageClass) { 11818ac838d978578c44b75a801489c985e5284dd66fethannicholas SkString key = type.description() + "*" + to_string(layout.fStd) + to_string(storageClass); 1182b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto entry = fTypeMap.find(key); 1183b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fTypeMap.end()) { 1184b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 118564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpTypePointer, result, storageClass, 1186d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->getType(type), fConstantBuffer); 1187b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fTypeMap[key] = result; 1188b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1190b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 1191b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1192b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 11939e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, SkWStream& out) { 1194b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 1195b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kBinary_Kind: 1196b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeBinaryExpression((BinaryExpression&) expr, out); 1197b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kBoolLiteral_Kind: 1198b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeBoolLiteral((BoolLiteral&) expr); 1199b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kConstructor_Kind: 1200b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeConstructor((Constructor&) expr, out); 1201b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kIntLiteral_Kind: 1202b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeIntLiteral((IntLiteral&) expr); 1203b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFieldAccess_Kind: 1204b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeFieldAccess(((FieldAccess&) expr), out); 1205b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFloatLiteral_Kind: 1206b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeFloatLiteral(((FloatLiteral&) expr)); 1207b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFunctionCall_Kind: 1208b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeFunctionCall((FunctionCall&) expr, out); 1209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kPrefix_Kind: 1210b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writePrefixExpression((PrefixExpression&) expr, out); 1211b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kPostfix_Kind: 1212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writePostfixExpression((PostfixExpression&) expr, out); 1213b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kSwizzle_Kind: 1214b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeSwizzle((Swizzle&) expr, out); 1215b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kVariableReference_Kind: 1216b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeVariableReference((VariableReference&) expr, out); 1217b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kTernary_Kind: 1218b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeTernaryExpression((TernaryExpression&) expr, out); 1219b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kIndex_Kind: 1220b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeIndexExpression((IndexExpression&) expr, out); 1221b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1222b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported expression: %s", expr.description().c_str()); 1223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1224b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return -1; 1225b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1226b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 12279e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, SkWStream& out) { 1228d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas auto intrinsic = fIntrinsicMap.find(c.fFunction.fName); 1229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(intrinsic != fIntrinsicMap.end()); 1230d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& type = c.fArguments[0]->fType; 1231b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int32_t intrinsicId; 1232d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (std::get<0>(intrinsic->second) == kSpecial_IntrinsicKind || is_float(fContext, type)) { 1233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas intrinsicId = std::get<1>(intrinsic->second); 1234d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (is_signed(fContext, type)) { 1235b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas intrinsicId = std::get<2>(intrinsic->second); 1236d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (is_unsigned(fContext, type)) { 1237b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas intrinsicId = std::get<3>(intrinsic->second); 1238d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (is_bool(fContext, type)) { 1239b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas intrinsicId = std::get<4>(intrinsic->second); 1240b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1241b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("invalid call %s, cannot operate on '%s'", c.description().c_str(), 1242d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas type.description().c_str()); 1243b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1244b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (std::get<0>(intrinsic->second)) { 1245b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case kGLSL_STD_450_IntrinsicKind: { 1246b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1247b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1248b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 1249b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1250b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1251b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpExtInst, 5 + (int32_t) arguments.size(), out); 1252d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1254b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(fGLSLExtendedInstructions, out); 1255b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(intrinsicId, out); 1256b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : arguments) { 1257b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1258b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1259b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1260b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1261b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case kSPIRV_IntrinsicKind: { 1262b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1263b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1264b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 1265b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1266b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1267b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode((SpvOp_) intrinsicId, 3 + (int32_t) arguments.size(), out); 1268d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1269b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1270b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : arguments) { 1271b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1272b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1273b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1274b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1275b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case kSpecial_IntrinsicKind: 1276b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeSpecialIntrinsic(c, (SpecialIntrinsic) intrinsicId, out); 1277b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1278b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported intrinsic kind"); 1279b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1280b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1281b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 128264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg DanielSpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, 12839e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 1284b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1285b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (kind) { 1286b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case kAtan_SpecialIntrinsic: { 1287b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1288b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 1289b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1290b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1291b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpExtInst, 5 + (int32_t) arguments.size(), out); 1292d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1293b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1294b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(fGLSLExtendedInstructions, out); 1295b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(arguments.size() == 2 ? GLSLstd450Atan2 : GLSLstd450Atan, out); 1296b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : arguments) { 1297b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1298b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 129964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return result; 1300b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1301b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case kTexture_SpecialIntrinsic: { 13022b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas SpvOp_ op = SpvOpImageSampleImplicitLod; 13032b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas switch (c.fArguments[0]->fType.dimensions()) { 13042b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim1D: 13052b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec2_Type) { 13062b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas op = SpvOpImageSampleProjImplicitLod; 13072b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 13082b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fFloat_Type); 13092b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 13102b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 13112b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim2D: 13122b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec3_Type) { 13132b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas op = SpvOpImageSampleProjImplicitLod; 13142b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 13152b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type); 13162b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 13172b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 13182b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim3D: 13192b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec4_Type) { 13202b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas op = SpvOpImageSampleProjImplicitLod; 13212b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 13222b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type); 13232b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 13242b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 13252b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimCube: // fall through 13262b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimRect: // fall through 13272b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimBuffer: // fall through 13282b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimSubpassData: 13292b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 1330b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1331d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId type = this->getType(c.fType); 1332b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId sampler = this->writeExpression(*c.fArguments[0], out); 1333b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId uv = this->writeExpression(*c.fArguments[1], out); 1334b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (c.fArguments.size() == 3) { 13352b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->writeInstruction(op, type, result, sampler, uv, 1336b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvImageOperandsBiasMask, 1337b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeExpression(*c.fArguments[2], out), 1338b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1339b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1340b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(c.fArguments.size() == 2); 13412b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->writeInstruction(op, type, result, sampler, uv, 1342b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1343b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1344b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1345b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 134664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel case kSubpassLoad_SpecialIntrinsic: { 134764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId img = this->writeExpression(*c.fArguments[0], out); 134864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel std::vector<std::unique_ptr<Expression>> args; 134964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel args.emplace_back(new FloatLiteral(fContext, Position(), 0.0)); 135064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel args.emplace_back(new FloatLiteral(fContext, Position(), 0.0)); 135164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel Constructor ctor(Position(), *fContext.fVec2_Type, std::move(args)); 135264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId coords = this->writeConstantVector(ctor); 135364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (1 == c.fArguments.size()) { 135464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpImageRead, 135564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->getType(c.fType), 135664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel result, 135764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel img, 135864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel coords, 135964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel out); 136064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } else { 136164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SkASSERT(2 == c.fArguments.size()); 136264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId sample = this->writeExpression(*c.fArguments[1], out); 136364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpImageRead, 136464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->getType(c.fType), 136564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel result, 136664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel img, 136764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel coords, 136864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvImageOperandsSampleMask, 136964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel sample, 137064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel out); 137164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } 137264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel break; 137364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } 1374b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1375b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1376b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1377b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 13789e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, SkWStream& out) { 1379d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const auto& entry = fFunctionMap.find(&c.fFunction); 1380b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fFunctionMap.end()) { 1381b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeIntrinsicCall(c, out); 1382b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1383b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // stores (variable, type, lvalue) pairs to extract and save after the function call is complete 1384b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<std::tuple<SpvId, SpvId, std::unique_ptr<LValue>>> lvalues; 1385b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1386b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 138764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // id of temporary variable that we will use to hold this argument, or 0 if it is being 1388b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // passed directly 1389b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId tmpVar; 1390b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // if we need a temporary var to store this argument, this is the value to store in the var 1391b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId tmpValueId; 1392d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (is_out(*c.fFunction.fParameters[i])) { 1393b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<LValue> lv = this->getLValue(*c.fArguments[i], out); 1394b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId ptr = lv->getPointer(); 1395b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (ptr) { 1396b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(ptr); 1397b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas continue; 1398b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1399b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // lvalue cannot simply be read and written via a pointer (e.g. a swizzle). Need to 1400b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // copy it into a temp, call the function, read the value out of the temp, and then 1401b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // update the lvalue. 1402b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas tmpValueId = lv->load(out); 1403b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas tmpVar = this->nextId(); 1404d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas lvalues.push_back(std::make_tuple(tmpVar, this->getType(c.fArguments[i]->fType), 1405b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::move(lv))); 1406b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1407b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1408b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // see getFunctionType for an explanation of why we're always using pointer parameters 1409b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas tmpValueId = this->writeExpression(*c.fArguments[i], out); 1410b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas tmpVar = this->nextId(); 1411b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 141264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpVariable, 141364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->getPointerType(c.fArguments[i]->fType, 1414b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvStorageClassFunction), 141564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel tmpVar, 1416b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvStorageClassFunction, 1417d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fVariableBuffer); 1418b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpStore, tmpVar, tmpValueId, out); 1419b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(tmpVar); 1420b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1421b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1422b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpFunctionCall, 4 + (int32_t) c.fArguments.size(), out); 1423d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1424b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1425b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(entry->second, out); 1426b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : arguments) { 1427b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1428b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1429b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // now that the call is complete, we may need to update some lvalues with the new values of out 1430b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // arguments 1431b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (const auto& tuple : lvalues) { 1432b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId load = this->nextId(); 1433b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpLoad, std::get<1>(tuple), load, std::get<0>(tuple), out); 1434b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::get<2>(tuple)->store(load, out); 1435b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1436b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1437b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1438b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1439f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasSpvId SPIRVCodeGenerator::writeConstantVector(const Constructor& c) { 1440d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fType.kind() == Type::kVector_Kind && c.isConstant()); 1441b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1442b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1443b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 1444b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(this->writeExpression(*c.fArguments[i], fConstantBuffer)); 1445b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1446d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId type = this->getType(c.fType); 1447b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (c.fArguments.size() == 1) { 1448b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // with a single argument, a vector will have all of its entries equal to the argument 1449d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeOpCode(SpvOpConstantComposite, 3 + c.fType.columns(), fConstantBuffer); 1450b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(type, fConstantBuffer); 1451b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, fConstantBuffer); 1452d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas for (int i = 0; i < c.fType.columns(); i++) { 1453b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(arguments[0], fConstantBuffer); 1454b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1455b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 145664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeOpCode(SpvOpConstantComposite, 3 + (int32_t) c.fArguments.size(), 1457b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fConstantBuffer); 1458b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(type, fConstantBuffer); 1459b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, fConstantBuffer); 1460b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : arguments) { 1461b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, fConstantBuffer); 1462b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1463b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1464b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1465b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1466b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 14679e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeFloatConstructor(const Constructor& c, SkWStream& out) { 1468d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fType == *fContext.fFloat_Type); 1469b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(c.fArguments.size() == 1); 1470d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fArguments[0]->fType.isNumber()); 1471b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1472b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId parameter = this->writeExpression(*c.fArguments[0], out); 1473d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (c.fArguments[0]->fType == *fContext.fInt_Type) { 147464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConvertSToF, this->getType(c.fType), result, parameter, 1475b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1476d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) { 147764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConvertUToF, this->getType(c.fType), result, parameter, 1478b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1479d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (c.fArguments[0]->fType == *fContext.fFloat_Type) { 1480b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return parameter; 1481b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1482b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1483b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1484b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 14859e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeIntConstructor(const Constructor& c, SkWStream& out) { 1486d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fType == *fContext.fInt_Type); 1487b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(c.fArguments.size() == 1); 1488d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fArguments[0]->fType.isNumber()); 1489b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1490b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId parameter = this->writeExpression(*c.fArguments[0], out); 1491d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (c.fArguments[0]->fType == *fContext.fFloat_Type) { 149264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConvertFToS, this->getType(c.fType), result, parameter, 1493b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1494d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) { 149564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpSatConvertUToS, this->getType(c.fType), result, parameter, 1496b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1497d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (c.fArguments[0]->fType == *fContext.fInt_Type) { 1498b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return parameter; 1499b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1500b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1501b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1502b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 150384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholasvoid SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, 150484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas SkWStream& out) { 150584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas FloatLiteral zero(fContext, Position(), 0); 150684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas SpvId zeroId = this->writeFloatLiteral(zero); 150784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas std::vector<SpvId> columnIds; 150884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas for (int column = 0; column < type.columns(); column++) { 150984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + type.rows(), 151084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas out); 151184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeWord(this->getType(type.componentType().toCompound(fContext, type.rows(), 1)), 151284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas out); 151384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas SpvId columnId = this->nextId(); 151484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeWord(columnId, out); 151584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas columnIds.push_back(columnId); 151684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas for (int row = 0; row < type.columns(); row++) { 151784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeWord(row == column ? diagonal : zeroId, out); 151884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas } 151984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas } 152084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + type.columns(), 152184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas out); 152284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeWord(this->getType(type), out); 152384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeWord(id, out); 152484645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas for (SpvId id : columnIds) { 152584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeWord(id, out); 152684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas } 152784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas} 152884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas 152984645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholasvoid SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcType, 153084645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas const Type& dstType, SkWStream& out) { 153184645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas ABORT("unimplemented"); 153284645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas} 153384645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas 15349e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, SkWStream& out) { 1535d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fType.kind() == Type::kMatrix_Kind); 1536b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // go ahead and write the arguments so we don't try to write new instructions in the middle of 1537b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // an instruction 1538b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1539b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 1540b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1541b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1542b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1543d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int rows = c.fType.rows(); 1544d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas int columns = c.fType.columns(); 154584645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) { 154684645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeUniformScaleMatrix(result, arguments[0], c.fType, out); 154784645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas } else if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kMatrix_Kind) { 154884645e3c679581d191406b2d7ab93c3f6c5e3a63Ethan Nicholas this->writeMatrixCopy(result, arguments[0], c.fArguments[0]->fType, c.fType, out); 1549b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1550b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> columnIds; 1551b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int currentCount = 0; 1552b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < arguments.size(); i++) { 1553d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (c.fArguments[i]->fType.kind() == Type::kVector_Kind) { 1554b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(currentCount == 0); 1555b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas columnIds.push_back(arguments[i]); 1556b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas currentCount = 0; 1557b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1558d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fArguments[i]->fType.kind() == Type::kScalar_Kind); 1559b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (currentCount == 0) { 1560d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.rows(), out); 156164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows, 156264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 1)), 1563b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1564b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId id = this->nextId(); 1565b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1566b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas columnIds.push_back(id); 1567b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1568b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(arguments[i], out); 1569b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas currentCount = (currentCount + 1) % rows; 1570b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1571b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1572b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(columnIds.size() == (size_t) columns); 1573b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + columns, out); 1574d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1575b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1576b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : columnIds) { 1577b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1578b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1579b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1580b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1581b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1582b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 15839e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, SkWStream& out) { 1584d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(c.fType.kind() == Type::kVector_Kind); 1585b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (c.isConstant()) { 1586b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeConstantVector(c); 1587b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1588b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // go ahead and write the arguments so we don't try to write new instructions in the middle of 1589b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // an instruction 1590b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> arguments; 1591b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < c.fArguments.size(); i++) { 1592b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1593b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1594b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1595d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) { 1596d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.columns(), out); 1597d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1598b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1599d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas for (int i = 0; i < c.fType.columns(); i++) { 1600b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(arguments[0], out); 1601b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1602b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1603b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + (int32_t) c.fArguments.size(), out); 1604d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(c.fType), out); 1605b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1606b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId id : arguments) { 1607b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(id, out); 1608b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1609b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1610b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1611b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1612b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 16139e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, SkWStream& out) { 1614d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (c.fType == *fContext.fFloat_Type) { 1615b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeFloatConstructor(c, out); 1616d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (c.fType == *fContext.fInt_Type) { 1617b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeIntConstructor(c, out); 1618b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1619d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas switch (c.fType.kind()) { 1620b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kVector_Kind: 1621b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeVectorConstructor(c, out); 1622b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Type::kMatrix_Kind: 1623b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeMatrixConstructor(c, out); 1624b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1625b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported constructor: %s", c.description().c_str()); 1626b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1627b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1628b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1629b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasSpvStorageClass_ get_storage_class(const Modifiers& modifiers) { 1630b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (modifiers.fFlags & Modifiers::kIn_Flag) { 16318ac838d978578c44b75a801489c985e5284dd66fethannicholas ASSERT(!modifiers.fLayout.fPushConstant); 1632b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return SpvStorageClassInput; 1633b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 16348ac838d978578c44b75a801489c985e5284dd66fethannicholas ASSERT(!modifiers.fLayout.fPushConstant); 1635b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return SpvStorageClassOutput; 1636b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else if (modifiers.fFlags & Modifiers::kUniform_Flag) { 16378ac838d978578c44b75a801489c985e5284dd66fethannicholas if (modifiers.fLayout.fPushConstant) { 16388ac838d978578c44b75a801489c985e5284dd66fethannicholas return SpvStorageClassPushConstant; 16398ac838d978578c44b75a801489c985e5284dd66fethannicholas } 1640b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return SpvStorageClassUniform; 1641b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1642b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return SpvStorageClassFunction; 1643b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1644b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1645b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1646f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasSpvStorageClass_ get_storage_class(const Expression& expr) { 1647b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 1648b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kVariableReference_Kind: 1649d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return get_storage_class(((VariableReference&) expr).fVariable.fModifiers); 1650b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFieldAccess_Kind: 1651b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return get_storage_class(*((FieldAccess&) expr).fBase); 1652b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kIndex_Kind: 1653b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return get_storage_class(*((IndexExpression&) expr).fBase); 1654b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1655b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return SpvStorageClassFunction; 1656b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1657b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1658b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 16599e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasstd::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, SkWStream& out) { 1660b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> chain; 1661b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 1662b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kIndex_Kind: { 1663b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas IndexExpression& indexExpr = (IndexExpression&) expr; 1664b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas chain = this->getAccessChain(*indexExpr.fBase, out); 1665b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas chain.push_back(this->writeExpression(*indexExpr.fIndex, out)); 1666b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1667b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1668b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFieldAccess_Kind: { 1669b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas FieldAccess& fieldExpr = (FieldAccess&) expr; 1670b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas chain = this->getAccessChain(*fieldExpr.fBase, out); 1671d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas IntLiteral index(fContext, Position(), fieldExpr.fFieldIndex); 1672b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas chain.push_back(this->writeIntLiteral(index)); 1673b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1674b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1675b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1676b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas chain.push_back(this->getLValue(expr, out)->getPointer()); 1677b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1678b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return chain; 1679b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1680b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1681b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasclass PointerLValue : public SPIRVCodeGenerator::LValue { 1682b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholaspublic: 168364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel PointerLValue(SPIRVCodeGenerator& gen, SpvId pointer, SpvId type) 1684b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas : fGen(gen) 1685b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fPointer(pointer) 1686b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fType(type) {} 1687b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1688b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas virtual SpvId getPointer() override { 1689b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return fPointer; 1690b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1691b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 16929e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas virtual SpvId load(SkWStream& out) override { 1693b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = fGen.nextId(); 1694b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeInstruction(SpvOpLoad, fType, result, fPointer, out); 1695b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1696b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1697b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 16989e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas virtual void store(SpvId value, SkWStream& out) override { 1699b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeInstruction(SpvOpStore, fPointer, value, out); 1700b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1701b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1702b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasprivate: 1703b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SPIRVCodeGenerator& fGen; 1704b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const SpvId fPointer; 1705b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const SpvId fType; 1706b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}; 1707b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1708b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasclass SwizzleLValue : public SPIRVCodeGenerator::LValue { 1709b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholaspublic: 171064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SwizzleLValue(SPIRVCodeGenerator& gen, SpvId vecPointer, const std::vector<int>& components, 1711b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const Type& baseType, const Type& swizzleType) 1712b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas : fGen(gen) 1713b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fVecPointer(vecPointer) 1714b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fComponents(components) 1715b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fBaseType(baseType) 1716b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas , fSwizzleType(swizzleType) {} 1717b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1718b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas virtual SpvId getPointer() override { 1719b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return 0; 1720b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1721b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 17229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas virtual SpvId load(SkWStream& out) override { 1723b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId base = fGen.nextId(); 1724b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeInstruction(SpvOpLoad, fGen.getType(fBaseType), base, fVecPointer, out); 1725b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = fGen.nextId(); 1726b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) fComponents.size(), out); 1727b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(fGen.getType(fSwizzleType), out); 1728b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(result, out); 1729b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(base, out); 1730b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(base, out); 1731b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int component : fComponents) { 1732b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(component, out); 1733b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1734b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1735b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1736b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 17379e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas virtual void store(SpvId value, SkWStream& out) override { 1738b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // use OpVectorShuffle to mix and match the vector components. We effectively create 1739b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // a virtual vector out of the concatenation of the left and right vectors, and then 174064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // select components from this virtual vector to make the result vector. For 1741b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // instance, given: 1742b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // vec3 L = ...; 1743b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // vec3 R = ...; 1744b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // L.xz = R.xy; 174564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // we end up with the virtual vector (L.x, L.y, L.z, R.x, R.y, R.z). Then we want 1746b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // our result vector to look like (R.x, L.y, R.y), so we need to select indices 1747b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // (3, 1, 4). 1748b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId base = fGen.nextId(); 1749b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeInstruction(SpvOpLoad, fGen.getType(fBaseType), base, fVecPointer, out); 1750b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId shuffle = fGen.nextId(); 1751b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeOpCode(SpvOpVectorShuffle, 5 + fBaseType.columns(), out); 1752b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(fGen.getType(fBaseType), out); 1753b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(shuffle, out); 1754b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(base, out); 1755b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(value, out); 1756b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int i = 0; i < fBaseType.columns(); i++) { 1757b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // current offset into the virtual vector, defaults to pulling the unmodified 1758b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // value from the left side 1759b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas int offset = i; 1760b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // check to see if we are writing this component 1761b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t j = 0; j < fComponents.size(); j++) { 1762b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fComponents[j] == i) { 176364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // we're writing to this component, so adjust the offset to pull from 1764b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // the correct component of the right side instead of preserving the 1765b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // value from the left 1766b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas offset = (int) (j + fBaseType.columns()); 1767b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 1768b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1769b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1770b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeWord(offset, out); 1771b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1772b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGen.writeInstruction(SpvOpStore, fVecPointer, shuffle, out); 1773b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1774b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1775b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasprivate: 1776b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SPIRVCodeGenerator& fGen; 1777b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const SpvId fVecPointer; 1778b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const std::vector<int>& fComponents; 1779b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const Type& fBaseType; 1780b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const Type& fSwizzleType; 1781b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas}; 1782b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 178364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielstd::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr, 17849e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 1785b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (expr.fKind) { 1786b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kVariableReference_Kind: { 1787d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Variable& var = ((VariableReference&) expr).fVariable; 1788d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas auto entry = fVariableMap.find(&var); 1789b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(entry != fVariableMap.end()); 1790b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1791b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *this, 179264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel entry->second, 1793d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->getType(expr.fType))); 1794b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1795b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kIndex_Kind: // fall through 1796b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kFieldAccess_Kind: { 1797b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::vector<SpvId> chain = this->getAccessChain(expr, out); 1798b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId member = this->nextId(); 1799b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out); 180064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeWord(this->getPointerType(expr.fType, get_storage_class(expr)), out); 1801b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(member, out); 1802b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (SpvId idx : chain) { 1803b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(idx, out); 1804b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1805b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1806b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *this, 180764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel member, 1808d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->getType(expr.fType))); 1809b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1810b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1811b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Expression::kSwizzle_Kind: { 1812b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas Swizzle& swizzle = (Swizzle&) expr; 1813b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas size_t count = swizzle.fComponents.size(); 1814b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer(); 1815b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(base); 1816b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (count == 1) { 1817d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas IntLiteral index(fContext, Position(), swizzle.fComponents[0]); 1818b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId member = this->nextId(); 1819b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpAccessChain, 182064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->getPointerType(swizzle.fType, 182164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel get_storage_class(*swizzle.fBase)), 182264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel member, 182364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel base, 182464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeIntLiteral(index), 1825b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 1826b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1827b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *this, 182864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel member, 1829d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->getType(expr.fType))); 1830b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1831b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<SPIRVCodeGenerator::LValue>(new SwizzleLValue( 183264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel *this, 183364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel base, 183464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel swizzle.fComponents, 1835d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas swizzle.fBase->fType, 1836d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas expr.fType)); 1837b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1838b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1839b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1840b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1841b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // expr isn't actually an lvalue, create a dummy variable for it. This case happens due 184264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // to the need to store values in temporary variables during function calls (see 1843b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // comments in getFunctionType); erroneous uses of rvalues as lvalues should have been 1844b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // caught by IRGenerator 1845b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1846b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId type = this->getPointerType(expr.fType, SpvStorageClassFunction); 1847d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeInstruction(SpvOpVariable, type, result, SpvStorageClassFunction, 1848d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fVariableBuffer); 1849b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpStore, result, this->writeExpression(expr, out), out); 1850b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1851b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *this, 185264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel result, 1853d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->getType(expr.fType))); 1854b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1855b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1856b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 18579e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, SkWStream& out) { 1858941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId result = this->nextId(); 1859d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas auto entry = fVariableMap.find(&ref.fVariable); 1860b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(entry != fVariableMap.end()); 1861b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId var = entry->second; 1862d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable.fType), result, var, out); 1863941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN && 1864941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fFlipY) { 1865941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // need to remap to a top-left coordinate system 1866941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fRTHeightStructId == (SpvId) -1) { 1867941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // height variable hasn't been written yet 1868941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas std::shared_ptr<SymbolTable> st(new SymbolTable(fErrors)); 1869941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(fRTHeightFieldIndex == (SpvId) -1); 1870941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas std::vector<Type::Field> fields; 1871941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), 1872941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fContext.fFloat_Type.get()); 1873941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SkString name("sksl_synthetic_uniforms"); 1874941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas Type intfStruct(Position(), name, fields); 1875941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified, 187652cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas false, Layout::kUnspecified_Primitive, -1, -1); 1877941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas Variable intfVar(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name, 1878941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas intfStruct, Variable::kGlobal_Storage); 187950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas InterfaceBlock intf(Position(), intfVar, name, SkString(""), 188050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas std::vector<std::unique_ptr<Expression>>(), st); 1881941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fRTHeightStructId = this->writeInterfaceBlock(intf); 1882941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fRTHeightFieldIndex = 0; 1883941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 1884941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(fRTHeightFieldIndex != (SpvId) -1); 1885941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // write vec4(gl_FragCoord.x, u_skRTHeight - gl_FragCoord.y, 0.0, 1.0) 1886941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId xId = this->nextId(); 1887941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId, 1888941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas result, 0, out); 1889941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex); 1890941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); 1891613a697ed124296620b2280533fad2eef776ba54Ethan Nicholas SpvId heightPtr = this->nextId(); 1892941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeOpCode(SpvOpAccessChain, 5, out); 1893941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(this->getPointerType(*fContext.fFloat_Type, SpvStorageClassUniform), out); 1894613a697ed124296620b2280533fad2eef776ba54Ethan Nicholas this->writeWord(heightPtr, out); 1895941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(fRTHeightStructId, out); 1896941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(fieldIndexId, out); 1897613a697ed124296620b2280533fad2eef776ba54Ethan Nicholas SpvId heightRead = this->nextId(); 1898613a697ed124296620b2280533fad2eef776ba54Ethan Nicholas this->writeInstruction(SpvOpLoad, this->getType(*fContext.fFloat_Type), heightRead, 1899613a697ed124296620b2280533fad2eef776ba54Ethan Nicholas heightPtr, out); 1900941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId rawYId = this->nextId(); 1901941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), rawYId, 1902941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas result, 1, out); 1903941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId flippedYId = this->nextId(); 1904941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId, 1905941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas heightRead, rawYId, out); 1906941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas FloatLiteral zero(fContext, Position(), 0.0); 1907941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId zeroId = writeFloatLiteral(zero); 1908941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas FloatLiteral one(fContext, Position(), 1.0); 1909941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId oneId = writeFloatLiteral(one); 1910941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId flipped = this->nextId(); 1911941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeOpCode(SpvOpCompositeConstruct, 7, out); 1912941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(this->getType(*fContext.fVec4_Type), out); 1913941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(flipped, out); 1914941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(xId, out); 1915941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(flippedYId, out); 1916941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(zeroId, out); 1917941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(oneId, out); 1918941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return flipped; 1919941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 1920b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1921b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1922b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 19239e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, SkWStream& out) { 1924b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return getLValue(expr, out)->load(out); 1925b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1926b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 19279e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeFieldAccess(const FieldAccess& f, SkWStream& out) { 1928b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return getLValue(f, out)->load(out); 1929b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1930b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 19319e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeSwizzle(const Swizzle& swizzle, SkWStream& out) { 1932b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId base = this->writeExpression(*swizzle.fBase, out); 1933b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1934b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas size_t count = swizzle.fComponents.size(); 1935b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (count == 1) { 193664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpCompositeExtract, this->getType(swizzle.fType), result, base, 193764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel swizzle.fComponents[0], out); 1938b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1939b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) count, out); 1940d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeWord(this->getType(swizzle.fType), out); 1941b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(result, out); 1942b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(base, out); 1943b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(base, out); 1944b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int component : swizzle.fComponents) { 1945b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(component, out); 1946b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1947b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1948b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1949b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1950b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 195164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg DanielSpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType, 195264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel const Type& operandType, SpvId lhs, 195364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, 19549e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SpvOp_ ifUInt, SpvOp_ ifBool, SkWStream& out) { 1955b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 1956d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (is_float(fContext, operandType)) { 1957b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(ifFloat, this->getType(resultType), result, lhs, rhs, out); 1958d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (is_signed(fContext, operandType)) { 1959b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(ifInt, this->getType(resultType), result, lhs, rhs, out); 1960d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (is_unsigned(fContext, operandType)) { 1961b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(ifUInt, this->getType(resultType), result, lhs, rhs, out); 1962d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (operandType == *fContext.fBool_Type) { 1963b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(ifBool, this->getType(resultType), result, lhs, rhs, out); 1964b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 1965b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("invalid operandType: %s", operandType.description().c_str()); 1966b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1967b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 1968b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1969b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1970b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasbool is_assignment(Token::Kind op) { 1971b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (op) { 1972b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::EQ: // fall through 1973b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUSEQ: // fall through 1974b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUSEQ: // fall through 1975b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::STAREQ: // fall through 1976b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SLASHEQ: // fall through 1977b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PERCENTEQ: // fall through 1978b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SHLEQ: // fall through 1979b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SHREQ: // fall through 1980b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::BITWISEOREQ: // fall through 1981b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::BITWISEXOREQ: // fall through 1982b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::BITWISEANDEQ: // fall through 1983b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALOREQ: // fall through 1984b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALXOREQ: // fall through 1985b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALANDEQ: 1986b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return true; 1987b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 1988b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return false; 1989b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 1990b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 1991b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 1992ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan NicholasSpvId SPIRVCodeGenerator::foldToBool(SpvId id, const Type& operandType, SkWStream& out) { 1993ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas if (operandType.kind() == Type::kVector_Kind) { 1994ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas SpvId result = this->nextId(); 1995ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas this->writeInstruction(SpvOpAll, this->getType(*fContext.fBool_Type), result, id, out); 1996ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas return result; 1997ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas } 1998ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas return id; 1999ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas} 2000ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas 20019e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, SkWStream& out) { 2002b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // handle cases where we don't necessarily evaluate both LHS and RHS 2003b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (b.fOperator) { 2004b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::EQ: { 2005b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhs = this->writeExpression(*b.fRight, out); 2006b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->getLValue(*b.fLeft, out)->store(rhs, out); 2007b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return rhs; 2008b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2009b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALAND: 2010b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeLogicalAnd(b, out); 2011b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LOGICALOR: 2012b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeLogicalOr(b, out); 2013b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 2014b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2015b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2016b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2017b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // "normal" operators 2018d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Type& resultType = b.fType; 2019b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<LValue> lvalue; 2020b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId lhs; 2021b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (is_assignment(b.fOperator)) { 2022b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue = this->getLValue(*b.fLeft, out); 2023b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs = lvalue->load(out); 2024b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2025b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue = nullptr; 2026b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs = this->writeExpression(*b.fLeft, out); 2027b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2028b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhs = this->writeExpression(*b.fRight, out); 2029b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // component type we are operating on: float, int, uint 2030b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas const Type* operandType; 2031b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // IR allows mismatched types in expressions (e.g. vec2 * float), but they need special handling 2032b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // in SPIR-V 2033b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (b.fLeft->fType != b.fRight->fType) { 203464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (b.fLeft->fType.kind() == Type::kVector_Kind && 2035d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas b.fRight->fType.isNumber()) { 2036b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // promote number to vector 2037b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId vec = this->nextId(); 2038d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + b.fType.columns(), out); 2039b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(this->getType(resultType), out); 2040b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(vec, out); 2041b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int i = 0; i < resultType.columns(); i++) { 2042b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(rhs, out); 2043b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2044b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas rhs = vec; 2045d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas operandType = &b.fRight->fType; 204664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } else if (b.fRight->fType.kind() == Type::kVector_Kind && 2047d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas b.fLeft->fType.isNumber()) { 2048b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // promote number to vector 2049b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId vec = this->nextId(); 2050d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeOpCode(SpvOpCompositeConstruct, 3 + b.fType.columns(), out); 2051b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(this->getType(resultType), out); 2052b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(vec, out); 2053b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int i = 0; i < resultType.columns(); i++) { 2054b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(lhs, out); 2055b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2056b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs = vec; 2057b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(!lvalue); 2058d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas operandType = &b.fLeft->fType; 2059d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (b.fLeft->fType.kind() == Type::kMatrix_Kind) { 2060b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOp_ op; 2061d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (b.fRight->fType.kind() == Type::kMatrix_Kind) { 2062b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas op = SpvOpMatrixTimesMatrix; 2063d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (b.fRight->fType.kind() == Type::kVector_Kind) { 2064b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas op = SpvOpMatrixTimesVector; 2065b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2066d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(b.fRight->fType.kind() == Type::kScalar_Kind); 2067b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas op = SpvOpMatrixTimesScalar; 2068b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2069b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2070d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeInstruction(op, this->getType(b.fType), result, lhs, rhs, out); 2071b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (b.fOperator == Token::STAREQ) { 2072b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2073b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2074b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(b.fOperator == Token::STAR); 2075b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2076b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2077d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (b.fRight->fType.kind() == Type::kMatrix_Kind) { 2078b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2079d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (b.fLeft->fType.kind() == Type::kVector_Kind) { 208064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(b.fType), result, 2081b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs, rhs, out); 2082b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2083d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(b.fLeft->fType.kind() == Type::kScalar_Kind); 208464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(b.fType), result, rhs, 2085b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs, out); 2086b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2087b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (b.fOperator == Token::STAREQ) { 2088b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2089b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2090b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(b.fOperator == Token::STAR); 2091b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2092b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2093b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2094b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported binary expression: %s", b.description().c_str()); 2095b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2096b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2097d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas operandType = &b.fLeft->fType; 2098d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(*operandType == b.fRight->fType); 2099b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2100b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (b.fOperator) { 2101ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas case Token::EQEQ: { 2102d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(resultType == *fContext.fBool_Type); 2103ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas return this->foldToBool(this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 2104ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas SpvOpFOrdEqual, SpvOpIEqual, 2105ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas SpvOpIEqual, SpvOpLogicalEqual, out), 2106ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas *operandType, out); 2107ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas } 2108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::NEQ: 2109d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(resultType == *fContext.fBool_Type); 2110ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas return this->foldToBool(this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 2111ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas SpvOpFOrdNotEqual, SpvOpINotEqual, 2112ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas SpvOpINotEqual, SpvOpLogicalNotEqual, 2113ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas out), 2114ef653b86b2a9cf9e0793a647e5990806bdbd6934Ethan Nicholas *operandType, out); 2115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::GT: 2116d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(resultType == *fContext.fBool_Type); 211764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 211864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpFOrdGreaterThan, SpvOpSGreaterThan, 2119b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpUGreaterThan, SpvOpUndef, out); 2120b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LT: 2121d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(resultType == *fContext.fBool_Type); 212264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdLessThan, 2123b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpSLessThan, SpvOpULessThan, SpvOpUndef, out); 2124b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::GTEQ: 2125d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(resultType == *fContext.fBool_Type); 212664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 212764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpFOrdGreaterThanEqual, SpvOpSGreaterThanEqual, 2128b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpUGreaterThanEqual, SpvOpUndef, out); 2129b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::LTEQ: 2130d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(resultType == *fContext.fBool_Type); 213164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 213264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpFOrdLessThanEqual, SpvOpSLessThanEqual, 2133b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpULessThanEqual, SpvOpUndef, out); 2134b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUS: 213564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd, 2136b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); 2137b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUS: 213864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub, 2139b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpISub, SpvOpISub, SpvOpUndef, out); 2140b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::STAR: 214164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (b.fLeft->fType.kind() == Type::kMatrix_Kind && 2142d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas b.fRight->fType.kind() == Type::kMatrix_Kind) { 2143b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // matrix multiply 2144b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2145b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(resultType), result, 2146b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs, rhs, out); 2147b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2148b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 214964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul, 2150b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpIMul, SpvOpIMul, SpvOpUndef, out); 2151b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SLASH: 215264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv, 2153b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out); 2154b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUSEQ: { 215564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd, 2156b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); 2157b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(lvalue); 2158b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2159b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2160b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2161b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUSEQ: { 216264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub, 2163b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpISub, SpvOpISub, SpvOpUndef, out); 2164b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(lvalue); 2165b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2166b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2167b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2168b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::STAREQ: { 216964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (b.fLeft->fType.kind() == Type::kMatrix_Kind && 2170d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas b.fRight->fType.kind() == Type::kMatrix_Kind) { 2171b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // matrix multiply 2172b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2173b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(resultType), result, 2174b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lhs, rhs, out); 2175b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(lvalue); 2176b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2177b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2178b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 217964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul, 2180b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpIMul, SpvOpIMul, SpvOpUndef, out); 2181b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(lvalue); 2182b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2183b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2184b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2185b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::SLASHEQ: { 218664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv, 2187b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out); 2188b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(lvalue); 2189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lvalue->store(result, out); 2190b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2191b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2192b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 2193b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // FIXME: missing support for some operators (bitwise, &&=, ||=, shift...) 2194b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported binary expression: %s", b.description().c_str()); 2195b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2196b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2197b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 21989e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, SkWStream& out) { 2199b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(a.fOperator == Token::LOGICALAND); 2200d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas BoolLiteral falseLiteral(fContext, Position(), false); 2201b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId falseConstant = this->writeBoolLiteral(falseLiteral); 2202b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId lhs = this->writeExpression(*a.fLeft, out); 2203b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhsLabel = this->nextId(); 2204b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId end = this->nextId(); 2205b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId lhsBlock = fCurrentBlock; 2206b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2207b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranchConditional, lhs, rhsLabel, end, out); 2208b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(rhsLabel, out); 2209b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhs = this->writeExpression(*a.fRight, out); 2210b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhsBlock = fCurrentBlock; 2211b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, end, out); 2212b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(end, out); 2213b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 221464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, falseConstant, 2215d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas lhsBlock, rhs, rhsBlock, out); 2216b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2217b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2218b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 22199e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, SkWStream& out) { 2220b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(o.fOperator == Token::LOGICALOR); 2221d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas BoolLiteral trueLiteral(fContext, Position(), true); 2222b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId trueConstant = this->writeBoolLiteral(trueLiteral); 2223b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId lhs = this->writeExpression(*o.fLeft, out); 2224b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhsLabel = this->nextId(); 2225b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId end = this->nextId(); 2226b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId lhsBlock = fCurrentBlock; 2227b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2228b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranchConditional, lhs, end, rhsLabel, out); 2229b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(rhsLabel, out); 2230b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhs = this->writeExpression(*o.fRight, out); 2231b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId rhsBlock = fCurrentBlock; 2232b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, end, out); 2233b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(end, out); 2234b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 223564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, trueConstant, 2236d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas lhsBlock, rhs, rhsBlock, out); 2237b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2238b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2239b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 22409e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, SkWStream& out) { 2241b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId test = this->writeExpression(*t.fTest, out); 2242b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (t.fIfTrue->isConstant() && t.fIfFalse->isConstant()) { 2243b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // both true and false are constants, can just use OpSelect 2244b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2245b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId trueId = this->writeExpression(*t.fIfTrue, out); 2246b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId falseId = this->writeExpression(*t.fIfFalse, out); 224764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpSelect, this->getType(t.fType), result, test, trueId, falseId, 2248b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 2249b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2250b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 225164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel // was originally using OpPhi to choose the result, but for some reason that is crashing on 2252b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // Adreno. Switched to storing the result in a temp variable as glslang does. 2253b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId var = this->nextId(); 225464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpVariable, this->getPointerType(t.fType, SpvStorageClassFunction), 2255d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas var, SpvStorageClassFunction, fVariableBuffer); 2256b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId trueLabel = this->nextId(); 2257b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId falseLabel = this->nextId(); 2258b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId end = this->nextId(); 2259b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2260b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranchConditional, test, trueLabel, falseLabel, out); 2261b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(trueLabel, out); 2262b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpStore, var, this->writeExpression(*t.fIfTrue, out), out); 2263b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, end, out); 2264b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(falseLabel, out); 2265b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpStore, var, this->writeExpression(*t.fIfFalse, out), out); 2266b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, end, out); 2267b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(end, out); 2268b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2269d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeInstruction(SpvOpLoad, this->getType(t.fType), result, var, out); 2270b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2271b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2272b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2273d598f7981f34811e6f2a949207dc13638852f3f7ethannicholasstd::unique_ptr<Expression> create_literal_1(const Context& context, const Type& type) { 2274d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (type == *context.fInt_Type) { 2275d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new IntLiteral(context, Position(), 1)); 2276b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2277d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas else if (type == *context.fFloat_Type) { 2278d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas return std::unique_ptr<Expression>(new FloatLiteral(context, Position(), 1.0)); 2279b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2280b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("math is unsupported on type '%s'") 2281b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2282b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2283b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 22849e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, SkWStream& out) { 2285b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (p.fOperator == Token::MINUS) { 2286b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2287d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId typeId = this->getType(p.fType); 2288b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId expr = this->writeExpression(*p.fOperand, out); 2289d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (is_float(fContext, p.fType)) { 2290b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpFNegate, typeId, result, expr, out); 2291d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas } else if (is_signed(fContext, p.fType)) { 2292b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpSNegate, typeId, result, expr, out); 2293b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2294b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported prefix expression %s", p.description().c_str()); 2295b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas }; 2296b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2297b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2298b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (p.fOperator) { 2299b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUS: 2300b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return this->writeExpression(*p.fOperand, out); 2301b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUSPLUS: { 2302b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out); 2303d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); 230464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one, 230564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpFAdd, SpvOpIAdd, SpvOpIAdd, SpvOpUndef, 2306b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 2307b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lv->store(result, out); 2308b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2309b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2310b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUSMINUS: { 2311b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out); 2312d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); 231364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one, 231464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvOpFSub, SpvOpISub, SpvOpISub, SpvOpUndef, 2315b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 2316b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lv->store(result, out); 2317b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2318b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 23195961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Token::LOGICALNOT: { 2320d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(p.fOperand->fType == *fContext.fBool_Type); 2321b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2322d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeInstruction(SpvOpLogicalNot, this->getType(p.fOperand->fType), result, 2323b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeExpression(*p.fOperand, out), out); 2324b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2325b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 23265961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Token::BITWISENOT: { 23275961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas SpvId result = this->nextId(); 23285961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeInstruction(SpvOpNot, this->getType(p.fOperand->fType), result, 23295961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(*p.fOperand, out), out); 23305961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return result; 23315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 2332b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 2333b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported prefix expression: %s", p.description().c_str()); 2334b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2335b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2336b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 23379e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, SkWStream& out) { 2338b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out); 2339b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = lv->load(out); 2340d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); 2341b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (p.fOperator) { 2342b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::PLUSPLUS: { 234364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFAdd, 2344b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); 2345b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lv->store(temp, out); 2346b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2347b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2348b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Token::MINUSMINUS: { 234964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFSub, 2350b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvOpISub, SpvOpISub, SpvOpUndef, out); 2351b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas lv->store(temp, out); 2352b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2353b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2354b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 2355b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported postfix expression %s", p.description().c_str()); 2356b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2357b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2358b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2359f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasSpvId SPIRVCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 2360b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (b.fValue) { 2361b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fBoolTrue == 0) { 2362b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fBoolTrue = this->nextId(); 236364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConstantTrue, this->getType(b.fType), fBoolTrue, 2364b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fConstantBuffer); 2365b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2366b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return fBoolTrue; 2367b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2368b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fBoolFalse == 0) { 2369b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fBoolFalse = this->nextId(); 237064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConstantFalse, this->getType(b.fType), fBoolFalse, 2371b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fConstantBuffer); 2372b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2373b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return fBoolFalse; 2374b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2375b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2376b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2377f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasSpvId SPIRVCodeGenerator::writeIntLiteral(const IntLiteral& i) { 2378d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (i.fType == *fContext.fInt_Type) { 2379b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto entry = fIntConstants.find(i.fValue); 2380b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fIntConstants.end()) { 2381b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 238264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue, 2383b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fConstantBuffer); 2384b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fIntConstants[i.fValue] = result; 2385b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2386b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2387b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 2388b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2389d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(i.fType == *fContext.fUInt_Type); 2390b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto entry = fUIntConstants.find(i.fValue); 2391b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fUIntConstants.end()) { 2392b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 239364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue, 2394b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fConstantBuffer); 2395b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fUIntConstants[i.fValue] = result; 2396b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2397b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2398b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 2399b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2400b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2401b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2402f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasSpvId SPIRVCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 2403d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (f.fType == *fContext.fFloat_Type) { 2404b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas float value = (float) f.fValue; 2405b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto entry = fFloatConstants.find(value); 2406b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fFloatConstants.end()) { 2407b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2408b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas uint32_t bits; 2409b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(sizeof(bits) == sizeof(value)); 2410b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas memcpy(&bits, &value, sizeof(bits)); 241164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, bits, 2412b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fConstantBuffer); 2413b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fFloatConstants[value] = result; 2414b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2415b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2416b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 2417b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2418d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas ASSERT(f.fType == *fContext.fDouble_Type); 2419b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas auto entry = fDoubleConstants.find(f.fValue); 2420b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (entry == fDoubleConstants.end()) { 2421b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2422b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas uint64_t bits; 2423b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(sizeof(bits) == sizeof(f.fValue)); 2424b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas memcpy(&bits, &f.fValue, sizeof(bits)); 242564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, 2426b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas bits & 0xffffffff, bits >> 32, fConstantBuffer); 2427b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDoubleConstants[f.fValue] = result; 2428b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2429b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2430b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return entry->second; 2431b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2432b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2433b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 24349e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, SkWStream& out) { 2435d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvId result = fFunctionMap[&f]; 243664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result, 2437b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvFunctionControlMaskNone, this->getFunctionType(f), out); 2438d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeInstruction(SpvOpName, result, f.fName.c_str(), fNameBuffer); 2439d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas for (size_t i = 0; i < f.fParameters.size(); i++) { 2440b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId id = this->nextId(); 2441d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fVariableMap[f.fParameters[i]] = id; 2442b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId type; 2443d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas type = this->getPointerType(f.fParameters[i]->fType, SpvStorageClassFunction); 2444b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpFunctionParameter, type, id, out); 2445b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2446b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2447b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2448b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 24499e1138d56665d13641f8805cd72ae81adc255f79Ethan NicholasSpvId SPIRVCodeGenerator::writeFunction(const FunctionDefinition& f, SkWStream& out) { 2450b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->writeFunctionStart(f.fDeclaration, out); 2451b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(this->nextId(), out); 2452d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if (f.fDeclaration.fName == "main") { 24539e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*fGlobalInitializersBuffer.detachAsData(), out); 2454b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 24559e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkDynamicMemoryWStream bodyBuffer; 2456e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas this->writeBlock(*f.fBody, bodyBuffer); 24579e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*fVariableBuffer.detachAsData(), out); 24589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*bodyBuffer.detachAsData(), out); 2459b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fCurrentBlock) { 2460b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpReturn, out); 2461b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2462b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpFunctionEnd, out); 2463b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2464b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2465b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2466b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target) { 2467b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fLocation >= 0) { 246864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, SpvDecorationLocation, layout.fLocation, 2469b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 2470b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2471b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fBinding >= 0) { 247264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, SpvDecorationBinding, layout.fBinding, 2473b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 2474b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2475b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fIndex >= 0) { 247664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, SpvDecorationIndex, layout.fIndex, 2477b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 2478b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2479b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fSet >= 0) { 248064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet, 2481b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 2482b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 248364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (layout.fInputAttachmentIndex >= 0) { 248464773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, SpvDecorationInputAttachmentIndex, 248564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel layout.fInputAttachmentIndex, fDecorationBuffer); 248664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } 24875961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (layout.fBuiltin >= 0 && layout.fBuiltin != SK_FRAGCOLOR_BUILTIN) { 248864773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin, 2489b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 2490b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2491b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2492b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2493b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasvoid SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, int member) { 2494b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fLocation >= 0) { 249564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationLocation, 2496b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas layout.fLocation, fDecorationBuffer); 2497b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2498b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fBinding >= 0) { 249964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBinding, 2500b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas layout.fBinding, fDecorationBuffer); 2501b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2502b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fIndex >= 0) { 250364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationIndex, 2504b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas layout.fIndex, fDecorationBuffer); 2505b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2506b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fSet >= 0) { 250764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationDescriptorSet, 2508b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas layout.fSet, fDecorationBuffer); 2509b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 251064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (layout.fInputAttachmentIndex >= 0) { 251164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpDecorate, target, member, SpvDecorationInputAttachmentIndex, 251264773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel layout.fInputAttachmentIndex, fDecorationBuffer); 251364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel } 2514b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (layout.fBuiltin >= 0) { 251564773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBuiltIn, 2516b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas layout.fBuiltin, fDecorationBuffer); 2517b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2518b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2519b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2520f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasSpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 25218ac838d978578c44b75a801489c985e5284dd66fethannicholas MemoryLayout layout = intf.fVariable.fModifiers.fLayout.fPushConstant ? 25228ac838d978578c44b75a801489c985e5284dd66fethannicholas MemoryLayout(MemoryLayout::k430_Standard) : 25238ac838d978578c44b75a801489c985e5284dd66fethannicholas fDefaultLayout; 2524b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId result = this->nextId(); 2525941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const Type* type = &intf.fVariable.fType; 2526941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fInputs.fRTHeight) { 2527941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(fRTHeightStructId == (SpvId) -1); 2528941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(fRTHeightFieldIndex == (SpvId) -1); 2529941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas std::vector<Type::Field> fields = type->fields(); 2530941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fRTHeightStructId = result; 2531941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fRTHeightFieldIndex = fields.size(); 2532941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); 2533941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas type = new Type(type->fPosition, type->name(), fields); 2534941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 2535941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas SpvId typeId = this->getType(*type, layout); 2536941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer); 2537d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers); 2538b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId ptrType = this->nextId(); 2539941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, typeId, fConstantBuffer); 2540b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConstantBuffer); 2541d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas this->writeLayout(intf.fVariable.fModifiers.fLayout, result); 2542d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fVariableMap[&intf.fVariable] = result; 254339b101b13da171a0ba08ae7196d1a88bc8375ef7Ethan Nicholas if (fProgram.fInputs.fRTHeight) { 254439b101b13da171a0ba08ae7196d1a88bc8375ef7Ethan Nicholas delete type; 254539b101b13da171a0ba08ae7196d1a88bc8375ef7Ethan Nicholas } 2546b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas return result; 2547b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2548b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 25495961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#define BUILTIN_IGNORE 9999 255064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl, 25519e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkWStream& out) { 2552b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < decl.fVars.size(); i++) { 2553e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas const VarDeclaration& varDecl = decl.fVars[i]; 255414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas const Variable* var = varDecl.fVar; 2555f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon // These haven't been implemented in our SPIR-V generator yet and we only currently use them 2556f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon // in the OpenGL backend. 2557f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon ASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag | 2558f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kWriteOnly_Flag | 2559f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kCoherent_Flag | 2560f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kVolatile_Flag | 2561f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kRestrict_Flag))); 25625961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) { 25635961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas continue; 25645961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 25655961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN && 25665961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas kind != Program::kFragment_Kind) { 25675961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas continue; 25685961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 256986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas if (!var->fReadCount && !var->fWriteCount && 257014fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas !(var->fModifiers.fFlags & (Modifiers::kIn_Flag | 257114fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Modifiers::kOut_Flag | 257214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas Modifiers::kUniform_Flag))) { 2573d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas // variable is dead and not an input / output var (the Vulkan debug layers complain if 2574d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas // we elide an interface var, even if it's dead) 2575b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas continue; 2576b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2577b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvStorageClass_ storageClass; 257814fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (var->fModifiers.fFlags & Modifiers::kIn_Flag) { 2579b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas storageClass = SpvStorageClassInput; 258014fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas } else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) { 2581b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas storageClass = SpvStorageClassOutput; 258214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas } else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) { 258314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (var->fType.kind() == Type::kSampler_Kind) { 2584b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas storageClass = SpvStorageClassUniformConstant; 2585b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2586b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas storageClass = SpvStorageClassUniform; 2587b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2588b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2589b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas storageClass = SpvStorageClassPrivate; 2590b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2591b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId id = this->nextId(); 259214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas fVariableMap[var] = id; 259314fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas SpvId type = this->getPointerType(var->fType, storageClass); 2594b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantBuffer); 259514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); 259614fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (var->fType.kind() == Type::kMatrix_Kind) { 259764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationColMajor, 2598b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fDecorationBuffer); 259964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationMatrixStride, 26008ac838d978578c44b75a801489c985e5284dd66fethannicholas (SpvId) fDefaultLayout.stride(var->fType), fDecorationBuffer); 2601b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 260214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas if (varDecl.fValue) { 2603f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ASSERT(!fCurrentBlock); 2604f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fCurrentBlock = -1; 260514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas SpvId value = this->writeExpression(*varDecl.fValue, fGlobalInitializersBuffer); 2606b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer); 2607f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fCurrentBlock = 0; 2608b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 260914fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas this->writeLayout(var->fModifiers.fLayout, id); 2610b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2611b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2612b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 26139e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, SkWStream& out) { 261414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas for (const auto& varDecl : decl.fVars) { 2615e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas const Variable* var = varDecl.fVar; 2616f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon // These haven't been implemented in our SPIR-V generator yet and we only currently use them 2617f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon // in the OpenGL backend. 2618f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon ASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag | 2619f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kWriteOnly_Flag | 2620f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kCoherent_Flag | 2621f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kVolatile_Flag | 2622f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon Modifiers::kRestrict_Flag))); 2623b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId id = this->nextId(); 262414fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas fVariableMap[var] = id; 262514fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas SpvId type = this->getPointerType(var->fType, SpvStorageClassFunction); 2626b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer); 262714fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); 2628e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas if (varDecl.fValue) { 2629e1d9cb82bf9004eb05831f34bb3e9e708ae0617fEthan Nicholas SpvId value = this->writeExpression(*varDecl.fValue, out); 2630b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpStore, id, value, out); 2631b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2632b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2633b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2634b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 26359e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeStatement(const Statement& s, SkWStream& out) { 2636b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (s.fKind) { 2637b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kBlock_Kind: 2638b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeBlock((Block&) s, out); 2639b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2640b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kExpression_Kind: 2641b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeExpression(*((ExpressionStatement&) s).fExpression, out); 2642b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 264364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel case Statement::kReturn_Kind: 2644b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeReturnStatement((ReturnStatement&) s, out); 2645b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 264614fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas case Statement::kVarDeclarations_Kind: 264714fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, out); 2648b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2649b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kIf_Kind: 2650b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeIfStatement((IfStatement&) s, out); 2651b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2652b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kFor_Kind: 2653b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeForStatement((ForStatement&) s, out); 2654b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2655fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas case Statement::kWhile_Kind: 2656fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeWhileStatement((WhileStatement&) s, out); 2657fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas break; 2658fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas case Statement::kDo_Kind: 2659fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeDoStatement((DoStatement&) s, out); 2660fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas break; 2661b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kBreak_Kind: 2662b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, fBreakTarget.top(), out); 2663b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2664b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kContinue_Kind: 2665b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, fContinueTarget.top(), out); 2666b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2667b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Statement::kDiscard_Kind: 2668b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpKill, out); 2669b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2670b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas default: 2671b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ABORT("unsupported statement: %s", s.description().c_str()); 2672b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2673b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2674b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 26759e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeBlock(const Block& b, SkWStream& out) { 2676b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < b.fStatements.size(); i++) { 2677b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeStatement(*b.fStatements[i], out); 2678b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2679b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2680b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 26819e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeIfStatement(const IfStatement& stmt, SkWStream& out) { 2682b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId test = this->writeExpression(*stmt.fTest, out); 2683b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId ifTrue = this->nextId(); 2684b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId ifFalse = this->nextId(); 2685b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (stmt.fIfFalse) { 2686b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId end = this->nextId(); 2687b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2688b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranchConditional, test, ifTrue, ifFalse, out); 2689b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(ifTrue, out); 2690b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeStatement(*stmt.fIfTrue, out); 2691b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fCurrentBlock) { 2692b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, end, out); 2693b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2694b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(ifFalse, out); 2695b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeStatement(*stmt.fIfFalse, out); 2696b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fCurrentBlock) { 2697b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, end, out); 2698b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2699b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(end, out); 2700b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2701b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpSelectionMerge, ifFalse, SpvSelectionControlMaskNone, out); 2702b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranchConditional, test, ifTrue, ifFalse, out); 2703b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(ifTrue, out); 2704b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeStatement(*stmt.fIfTrue, out); 2705b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fCurrentBlock) { 2706b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, ifFalse, out); 2707b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2708b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(ifFalse, out); 2709b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2710b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2711b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 27129e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeForStatement(const ForStatement& f, SkWStream& out) { 2713b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (f.fInitializer) { 2714b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeStatement(*f.fInitializer, out); 2715b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2716b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId header = this->nextId(); 2717b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId start = this->nextId(); 2718b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId body = this->nextId(); 2719b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId next = this->nextId(); 2720b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fContinueTarget.push(next); 2721b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId end = this->nextId(); 2722b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fBreakTarget.push(end); 2723b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, header, out); 2724b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(header, out); 2725b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpLoopMerge, end, next, SpvLoopControlMaskNone, out); 2726f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeInstruction(SpvOpBranch, start, out); 2727b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(start, out); 272822f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas if (f.fTest) { 272922f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas SpvId test = this->writeExpression(*f.fTest, out); 273022f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas this->writeInstruction(SpvOpBranchConditional, test, body, end, out); 273122f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas } 2732b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(body, out); 2733b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeStatement(*f.fStatement, out); 2734b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (fCurrentBlock) { 2735b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, next, out); 2736b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2737b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(next, out); 2738b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (f.fNext) { 2739b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeExpression(*f.fNext, out); 2740b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2741b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpBranch, header, out); 2742b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeLabel(end, out); 2743b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fBreakTarget.pop(); 2744b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fContinueTarget.pop(); 2745b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2746b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2747fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholasvoid SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, SkWStream& out) { 2748fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // We believe the while loop code below will work, but Skia doesn't actually use them and 2749fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // adequately testing this code in the absence of Skia exercising it isn't straightforward. For 2750fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // the time being, we just fail with an error due to the lack of testing. If you encounter this 2751fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // message, simply remove the error call below to see whether our while loop support actually 2752fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // works. 2753fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fErrors.error(w.fPosition, "internal error: while loop support has been disabled in SPIR-V, " 2754fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas "see SkSLSPIRVCodeGenerator.cpp for details"); 2755fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas 2756fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId header = this->nextId(); 2757fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId start = this->nextId(); 2758fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId body = this->nextId(); 2759fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fContinueTarget.push(start); 2760fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId end = this->nextId(); 2761fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fBreakTarget.push(end); 2762fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranch, header, out); 2763fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(header, out); 2764fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out); 2765fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranch, start, out); 2766fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(start, out); 2767fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId test = this->writeExpression(*w.fTest, out); 2768fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranchConditional, test, body, end, out); 2769fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(body, out); 2770fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeStatement(*w.fStatement, out); 2771fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas if (fCurrentBlock) { 2772fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranch, start, out); 2773fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas } 2774fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(end, out); 2775fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fBreakTarget.pop(); 2776fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fContinueTarget.pop(); 2777fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas} 2778fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas 2779fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholasvoid SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, SkWStream& out) { 2780fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // We believe the do loop code below will work, but Skia doesn't actually use them and 2781fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // adequately testing this code in the absence of Skia exercising it isn't straightforward. For 2782fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // the time being, we just fail with an error due to the lack of testing. If you encounter this 2783fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // message, simply remove the error call below to see whether our do loop support actually 2784fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas // works. 2785fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fErrors.error(d.fPosition, "internal error: do loop support has been disabled in SPIR-V, see " 2786fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas "SkSLSPIRVCodeGenerator.cpp for details"); 2787fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas 2788fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId header = this->nextId(); 2789fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId start = this->nextId(); 2790fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId next = this->nextId(); 2791fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fContinueTarget.push(next); 2792fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId end = this->nextId(); 2793fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fBreakTarget.push(end); 2794fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranch, header, out); 2795fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(header, out); 2796fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out); 2797fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranch, start, out); 2798fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(start, out); 2799fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeStatement(*d.fStatement, out); 2800fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas if (fCurrentBlock) { 2801fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranch, next, out); 2802fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas } 2803fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(next, out); 2804fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas SpvId test = this->writeExpression(*d.fTest, out); 2805fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeInstruction(SpvOpBranchConditional, test, start, end, out); 2806fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas this->writeLabel(end, out); 2807fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fBreakTarget.pop(); 2808fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas fContinueTarget.pop(); 2809fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas} 2810fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0Ethan Nicholas 28119e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, SkWStream& out) { 2812b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (r.fExpression) { 281364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpression, out), 2814b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 2815b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } else { 2816b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpReturn, out); 2817b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2818b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2819b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 28209e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholasvoid SPIRVCodeGenerator::writeInstructions(const Program& program, SkWStream& out) { 2821b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas fGLSLExtendedInstructions = this->nextId(); 28229e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkDynamicMemoryWStream body; 28238e48c1e1d38bf0f0086971be2b077d1a2cb12131Ethan Nicholas std::set<SpvId> interfaceVars; 2824b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas // assign IDs to functions 2825b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < program.fElements.size(); i++) { 2826b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (program.fElements[i]->fKind == ProgramElement::kFunction_Kind) { 2827b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas FunctionDefinition& f = (FunctionDefinition&) *program.fElements[i]; 2828d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas fFunctionMap[&f.fDeclaration] = this->nextId(); 2829b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2830b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2831b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < program.fElements.size(); i++) { 2832b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (program.fElements[i]->fKind == ProgramElement::kInterfaceBlock_Kind) { 2833b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas InterfaceBlock& intf = (InterfaceBlock&) *program.fElements[i]; 2834b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvId id = this->writeInterfaceBlock(intf); 2835d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas if ((intf.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) || 2836d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas (intf.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) { 28378e48c1e1d38bf0f0086971be2b077d1a2cb12131Ethan Nicholas interfaceVars.insert(id); 2838b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2839b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2840b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2841b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < program.fElements.size(); i++) { 2842b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) { 284364773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]), 28445961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas body); 2845b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2846b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2847b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < program.fElements.size(); i++) { 2848b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (program.fElements[i]->fKind == ProgramElement::kFunction_Kind) { 2849b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeFunction(((FunctionDefinition&) *program.fElements[i]), body); 2850b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2851b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2852d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const FunctionDeclaration* main = nullptr; 2853b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (auto entry : fFunctionMap) { 2854f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (entry.first->fName == "main") { 2855b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas main = entry.first; 2856b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2857b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2858b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ASSERT(main); 2859b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (auto entry : fVariableMap) { 2860d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas const Variable* var = entry.first; 286164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if (var->fStorage == Variable::kGlobal_Storage && 2862b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas ((var->fModifiers.fFlags & Modifiers::kIn_Flag) || 2863b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas (var->fModifiers.fFlags & Modifiers::kOut_Flag))) { 28648e48c1e1d38bf0f0086971be2b077d1a2cb12131Ethan Nicholas interfaceVars.insert(entry.second); 2865b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2866b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2867b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeCapabilities(out); 2868b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out); 2869b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out); 287064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) + 2871b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas (int32_t) interfaceVars.size(), out); 2872b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas switch (program.fKind) { 2873b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Program::kVertex_Kind: 2874b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(SpvExecutionModelVertex, out); 2875b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 2876b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas case Program::kFragment_Kind: 2877b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(SpvExecutionModelFragment, out); 2878b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas break; 287952cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case Program::kGeometry_Kind: 288052cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas this->writeWord(SpvExecutionModelGeometry, out); 288152cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 2882b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2883b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(fFunctionMap[main], out); 2884b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeString(main->fName.c_str(), out); 2885b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (int var : interfaceVars) { 2886b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas this->writeWord(var, out); 2887b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2888b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (program.fKind == Program::kFragment_Kind) { 288964773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpExecutionMode, 289064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel fFunctionMap[main], 2891b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas SpvExecutionModeOriginUpperLeft, 2892b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 2893b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2894b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas for (size_t i = 0; i < program.fElements.size(); i++) { 2895b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas if (program.fElements[i]->fKind == ProgramElement::kExtension_Kind) { 289664773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel this->writeInstruction(SpvOpSourceExtension, 289764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel ((Extension&) *program.fElements[i]).fName.c_str(), 2898b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas out); 2899b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 2900b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas } 290164773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 2902941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas write_data(*fExtraGlobalsBuffer.detachAsData(), out); 29039e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*fNameBuffer.detachAsData(), out); 29049e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*fDecorationBuffer.detachAsData(), out); 29059e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*fConstantBuffer.detachAsData(), out); 29069e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*fExternalFunctionsBuffer.detachAsData(), out); 29079e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas write_data(*body.detachAsData(), out); 2908b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2909b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2910941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasbool SPIRVCodeGenerator::generateCode() { 2911941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(!fErrors.errorCount()); 2912941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(SpvMagicNumber, *fOut); 2913941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(SpvVersion, *fOut); 2914941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(SKSL_MAGIC, *fOut); 29159e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas SkDynamicMemoryWStream buffer; 2916941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeInstructions(fProgram, buffer); 2917941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(fIdCount, *fOut); 2918941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeWord(0, *fOut); // reserved, always zero 2919941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas write_data(*buffer.detachAsData(), *fOut); 2920941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return 0 == fErrors.errorCount(); 2921b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2922b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas 2923b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} 2924