SkSLSPIRVCodeGenerator.cpp revision fd146aa1dd8ea2d83396bb3a19c7556d9297a5e0
1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkSLSPIRVCodeGenerator.h" 9 10#include "string.h" 11 12#include "GLSL.std.450.h" 13 14#include "ir/SkSLExpressionStatement.h" 15#include "ir/SkSLExtension.h" 16#include "ir/SkSLIndexExpression.h" 17#include "ir/SkSLVariableReference.h" 18#include "SkSLCompiler.h" 19 20namespace SkSL { 21 22#define SPIRV_DEBUG 0 23 24static const int32_t SKSL_MAGIC = 0x0; // FIXME: we should probably register a magic number 25 26void SPIRVCodeGenerator::setupIntrinsics() { 27#define ALL_GLSL(x) std::make_tuple(kGLSL_STD_450_IntrinsicKind, GLSLstd450 ## x, GLSLstd450 ## x, \ 28 GLSLstd450 ## x, GLSLstd450 ## x) 29#define BY_TYPE_GLSL(ifFloat, ifInt, ifUInt) std::make_tuple(kGLSL_STD_450_IntrinsicKind, \ 30 GLSLstd450 ## ifFloat, \ 31 GLSLstd450 ## ifInt, \ 32 GLSLstd450 ## ifUInt, \ 33 SpvOpUndef) 34#define SPECIAL(x) std::make_tuple(kSpecial_IntrinsicKind, k ## x ## _SpecialIntrinsic, \ 35 k ## x ## _SpecialIntrinsic, k ## x ## _SpecialIntrinsic, \ 36 k ## x ## _SpecialIntrinsic) 37 fIntrinsicMap[SkString("round")] = ALL_GLSL(Round); 38 fIntrinsicMap[SkString("roundEven")] = ALL_GLSL(RoundEven); 39 fIntrinsicMap[SkString("trunc")] = ALL_GLSL(Trunc); 40 fIntrinsicMap[SkString("abs")] = BY_TYPE_GLSL(FAbs, SAbs, SAbs); 41 fIntrinsicMap[SkString("sign")] = BY_TYPE_GLSL(FSign, SSign, SSign); 42 fIntrinsicMap[SkString("floor")] = ALL_GLSL(Floor); 43 fIntrinsicMap[SkString("ceil")] = ALL_GLSL(Ceil); 44 fIntrinsicMap[SkString("fract")] = ALL_GLSL(Fract); 45 fIntrinsicMap[SkString("radians")] = ALL_GLSL(Radians); 46 fIntrinsicMap[SkString("degrees")] = ALL_GLSL(Degrees); 47 fIntrinsicMap[SkString("sin")] = ALL_GLSL(Sin); 48 fIntrinsicMap[SkString("cos")] = ALL_GLSL(Cos); 49 fIntrinsicMap[SkString("tan")] = ALL_GLSL(Tan); 50 fIntrinsicMap[SkString("asin")] = ALL_GLSL(Asin); 51 fIntrinsicMap[SkString("acos")] = ALL_GLSL(Acos); 52 fIntrinsicMap[SkString("atan")] = SPECIAL(Atan); 53 fIntrinsicMap[SkString("sinh")] = ALL_GLSL(Sinh); 54 fIntrinsicMap[SkString("cosh")] = ALL_GLSL(Cosh); 55 fIntrinsicMap[SkString("tanh")] = ALL_GLSL(Tanh); 56 fIntrinsicMap[SkString("asinh")] = ALL_GLSL(Asinh); 57 fIntrinsicMap[SkString("acosh")] = ALL_GLSL(Acosh); 58 fIntrinsicMap[SkString("atanh")] = ALL_GLSL(Atanh); 59 fIntrinsicMap[SkString("pow")] = ALL_GLSL(Pow); 60 fIntrinsicMap[SkString("exp")] = ALL_GLSL(Exp); 61 fIntrinsicMap[SkString("log")] = ALL_GLSL(Log); 62 fIntrinsicMap[SkString("exp2")] = ALL_GLSL(Exp2); 63 fIntrinsicMap[SkString("log2")] = ALL_GLSL(Log2); 64 fIntrinsicMap[SkString("sqrt")] = ALL_GLSL(Sqrt); 65 fIntrinsicMap[SkString("inversesqrt")] = ALL_GLSL(InverseSqrt); 66 fIntrinsicMap[SkString("determinant")] = ALL_GLSL(Determinant); 67 fIntrinsicMap[SkString("matrixInverse")] = ALL_GLSL(MatrixInverse); 68 fIntrinsicMap[SkString("mod")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpFMod, 69 SpvOpSMod, SpvOpUMod, SpvOpUndef); 70 fIntrinsicMap[SkString("min")] = BY_TYPE_GLSL(FMin, SMin, UMin); 71 fIntrinsicMap[SkString("max")] = BY_TYPE_GLSL(FMax, SMax, UMax); 72 fIntrinsicMap[SkString("clamp")] = BY_TYPE_GLSL(FClamp, SClamp, UClamp); 73 fIntrinsicMap[SkString("dot")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDot, 74 SpvOpUndef, SpvOpUndef, SpvOpUndef); 75 fIntrinsicMap[SkString("mix")] = ALL_GLSL(FMix); 76 fIntrinsicMap[SkString("step")] = ALL_GLSL(Step); 77 fIntrinsicMap[SkString("smoothstep")] = ALL_GLSL(SmoothStep); 78 fIntrinsicMap[SkString("fma")] = ALL_GLSL(Fma); 79 fIntrinsicMap[SkString("frexp")] = ALL_GLSL(Frexp); 80 fIntrinsicMap[SkString("ldexp")] = ALL_GLSL(Ldexp); 81 82#define PACK(type) fIntrinsicMap[SkString("pack" #type)] = ALL_GLSL(Pack ## type); \ 83 fIntrinsicMap[SkString("unpack" #type)] = ALL_GLSL(Unpack ## type) 84 PACK(Snorm4x8); 85 PACK(Unorm4x8); 86 PACK(Snorm2x16); 87 PACK(Unorm2x16); 88 PACK(Half2x16); 89 PACK(Double2x32); 90 fIntrinsicMap[SkString("length")] = ALL_GLSL(Length); 91 fIntrinsicMap[SkString("distance")] = ALL_GLSL(Distance); 92 fIntrinsicMap[SkString("cross")] = ALL_GLSL(Cross); 93 fIntrinsicMap[SkString("normalize")] = ALL_GLSL(Normalize); 94 fIntrinsicMap[SkString("faceForward")] = ALL_GLSL(FaceForward); 95 fIntrinsicMap[SkString("reflect")] = ALL_GLSL(Reflect); 96 fIntrinsicMap[SkString("refract")] = ALL_GLSL(Refract); 97 fIntrinsicMap[SkString("findLSB")] = ALL_GLSL(FindILsb); 98 fIntrinsicMap[SkString("findMSB")] = BY_TYPE_GLSL(FindSMsb, FindSMsb, FindUMsb); 99 fIntrinsicMap[SkString("dFdx")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDPdx, 100 SpvOpUndef, SpvOpUndef, SpvOpUndef); 101 fIntrinsicMap[SkString("dFdy")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDPdy, 102 SpvOpUndef, SpvOpUndef, SpvOpUndef); 103 fIntrinsicMap[SkString("dFdy")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpDPdy, 104 SpvOpUndef, SpvOpUndef, SpvOpUndef); 105 fIntrinsicMap[SkString("texture")] = SPECIAL(Texture); 106 107 fIntrinsicMap[SkString("subpassLoad")] = SPECIAL(SubpassLoad); 108 109 fIntrinsicMap[SkString("any")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef, 110 SpvOpUndef, SpvOpUndef, SpvOpAny); 111 fIntrinsicMap[SkString("all")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpUndef, 112 SpvOpUndef, SpvOpUndef, SpvOpAll); 113 fIntrinsicMap[SkString("equal")] = std::make_tuple(kSPIRV_IntrinsicKind, 114 SpvOpFOrdEqual, SpvOpIEqual, 115 SpvOpIEqual, SpvOpLogicalEqual); 116 fIntrinsicMap[SkString("notEqual")] = std::make_tuple(kSPIRV_IntrinsicKind, 117 SpvOpFOrdNotEqual, SpvOpINotEqual, 118 SpvOpINotEqual, 119 SpvOpLogicalNotEqual); 120 fIntrinsicMap[SkString("lessThan")] = std::make_tuple(kSPIRV_IntrinsicKind, 121 SpvOpSLessThan, SpvOpULessThan, 122 SpvOpFOrdLessThan, SpvOpUndef); 123 fIntrinsicMap[SkString("lessThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind, 124 SpvOpSLessThanEqual, 125 SpvOpULessThanEqual, 126 SpvOpFOrdLessThanEqual, 127 SpvOpUndef); 128 fIntrinsicMap[SkString("greaterThan")] = std::make_tuple(kSPIRV_IntrinsicKind, 129 SpvOpSGreaterThan, 130 SpvOpUGreaterThan, 131 SpvOpFOrdGreaterThan, 132 SpvOpUndef); 133 fIntrinsicMap[SkString("greaterThanEqual")] = std::make_tuple(kSPIRV_IntrinsicKind, 134 SpvOpSGreaterThanEqual, 135 SpvOpUGreaterThanEqual, 136 SpvOpFOrdGreaterThanEqual, 137 SpvOpUndef); 138 139// interpolateAt* not yet supported... 140} 141 142void SPIRVCodeGenerator::writeWord(int32_t word, SkWStream& out) { 143#if SPIRV_DEBUG 144 out << "(" << word << ") "; 145#else 146 out.write((const char*) &word, sizeof(word)); 147#endif 148} 149 150static bool is_float(const Context& context, const Type& type) { 151 if (type.kind() == Type::kVector_Kind) { 152 return is_float(context, type.componentType()); 153 } 154 return type == *context.fFloat_Type || type == *context.fDouble_Type; 155} 156 157static bool is_signed(const Context& context, const Type& type) { 158 if (type.kind() == Type::kVector_Kind) { 159 return is_signed(context, type.componentType()); 160 } 161 return type == *context.fInt_Type; 162} 163 164static bool is_unsigned(const Context& context, const Type& type) { 165 if (type.kind() == Type::kVector_Kind) { 166 return is_unsigned(context, type.componentType()); 167 } 168 return type == *context.fUInt_Type; 169} 170 171static bool is_bool(const Context& context, const Type& type) { 172 if (type.kind() == Type::kVector_Kind) { 173 return is_bool(context, type.componentType()); 174 } 175 return type == *context.fBool_Type; 176} 177 178static bool is_out(const Variable& var) { 179 return (var.fModifiers.fFlags & Modifiers::kOut_Flag) != 0; 180} 181 182#if SPIRV_DEBUG 183static SkString opcode_text(SpvOp_ opCode) { 184 switch (opCode) { 185 case SpvOpNop: 186 return SkString("Nop"); 187 case SpvOpUndef: 188 return SkString("Undef"); 189 case SpvOpSourceContinued: 190 return SkString("SourceContinued"); 191 case SpvOpSource: 192 return SkString("Source"); 193 case SpvOpSourceExtension: 194 return SkString("SourceExtension"); 195 case SpvOpName: 196 return SkString("Name"); 197 case SpvOpMemberName: 198 return SkString("MemberName"); 199 case SpvOpString: 200 return SkString("String"); 201 case SpvOpLine: 202 return SkString("Line"); 203 case SpvOpExtension: 204 return SkString("Extension"); 205 case SpvOpExtInstImport: 206 return SkString("ExtInstImport"); 207 case SpvOpExtInst: 208 return SkString("ExtInst"); 209 case SpvOpMemoryModel: 210 return SkString("MemoryModel"); 211 case SpvOpEntryPoint: 212 return SkString("EntryPoint"); 213 case SpvOpExecutionMode: 214 return SkString("ExecutionMode"); 215 case SpvOpCapability: 216 return SkString("Capability"); 217 case SpvOpTypeVoid: 218 return SkString("TypeVoid"); 219 case SpvOpTypeBool: 220 return SkString("TypeBool"); 221 case SpvOpTypeInt: 222 return SkString("TypeInt"); 223 case SpvOpTypeFloat: 224 return SkString("TypeFloat"); 225 case SpvOpTypeVector: 226 return SkString("TypeVector"); 227 case SpvOpTypeMatrix: 228 return SkString("TypeMatrix"); 229 case SpvOpTypeImage: 230 return SkString("TypeImage"); 231 case SpvOpTypeSampler: 232 return SkString("TypeSampler"); 233 case SpvOpTypeSampledImage: 234 return SkString("TypeSampledImage"); 235 case SpvOpTypeArray: 236 return SkString("TypeArray"); 237 case SpvOpTypeRuntimeArray: 238 return SkString("TypeRuntimeArray"); 239 case SpvOpTypeStruct: 240 return SkString("TypeStruct"); 241 case SpvOpTypeOpaque: 242 return SkString("TypeOpaque"); 243 case SpvOpTypePointer: 244 return SkString("TypePointer"); 245 case SpvOpTypeFunction: 246 return SkString("TypeFunction"); 247 case SpvOpTypeEvent: 248 return SkString("TypeEvent"); 249 case SpvOpTypeDeviceEvent: 250 return SkString("TypeDeviceEvent"); 251 case SpvOpTypeReserveId: 252 return SkString("TypeReserveId"); 253 case SpvOpTypeQueue: 254 return SkString("TypeQueue"); 255 case SpvOpTypePipe: 256 return SkString("TypePipe"); 257 case SpvOpTypeForwardPointer: 258 return SkString("TypeForwardPointer"); 259 case SpvOpConstantTrue: 260 return SkString("ConstantTrue"); 261 case SpvOpConstantFalse: 262 return SkString("ConstantFalse"); 263 case SpvOpConstant: 264 return SkString("Constant"); 265 case SpvOpConstantComposite: 266 return SkString("ConstantComposite"); 267 case SpvOpConstantSampler: 268 return SkString("ConstantSampler"); 269 case SpvOpConstantNull: 270 return SkString("ConstantNull"); 271 case SpvOpSpecConstantTrue: 272 return SkString("SpecConstantTrue"); 273 case SpvOpSpecConstantFalse: 274 return SkString("SpecConstantFalse"); 275 case SpvOpSpecConstant: 276 return SkString("SpecConstant"); 277 case SpvOpSpecConstantComposite: 278 return SkString("SpecConstantComposite"); 279 case SpvOpSpecConstantOp: 280 return SkString("SpecConstantOp"); 281 case SpvOpFunction: 282 return SkString("Function"); 283 case SpvOpFunctionParameter: 284 return SkString("FunctionParameter"); 285 case SpvOpFunctionEnd: 286 return SkString("FunctionEnd"); 287 case SpvOpFunctionCall: 288 return SkString("FunctionCall"); 289 case SpvOpVariable: 290 return SkString("Variable"); 291 case SpvOpImageTexelPointer: 292 return SkString("ImageTexelPointer"); 293 case SpvOpLoad: 294 return SkString("Load"); 295 case SpvOpStore: 296 return SkString("Store"); 297 case SpvOpCopyMemory: 298 return SkString("CopyMemory"); 299 case SpvOpCopyMemorySized: 300 return SkString("CopyMemorySized"); 301 case SpvOpAccessChain: 302 return SkString("AccessChain"); 303 case SpvOpInBoundsAccessChain: 304 return SkString("InBoundsAccessChain"); 305 case SpvOpPtrAccessChain: 306 return SkString("PtrAccessChain"); 307 case SpvOpArrayLength: 308 return SkString("ArrayLength"); 309 case SpvOpGenericPtrMemSemantics: 310 return SkString("GenericPtrMemSemantics"); 311 case SpvOpInBoundsPtrAccessChain: 312 return SkString("InBoundsPtrAccessChain"); 313 case SpvOpDecorate: 314 return SkString("Decorate"); 315 case SpvOpMemberDecorate: 316 return SkString("MemberDecorate"); 317 case SpvOpDecorationGroup: 318 return SkString("DecorationGroup"); 319 case SpvOpGroupDecorate: 320 return SkString("GroupDecorate"); 321 case SpvOpGroupMemberDecorate: 322 return SkString("GroupMemberDecorate"); 323 case SpvOpVectorExtractDynamic: 324 return SkString("VectorExtractDynamic"); 325 case SpvOpVectorInsertDynamic: 326 return SkString("VectorInsertDynamic"); 327 case SpvOpVectorShuffle: 328 return SkString("VectorShuffle"); 329 case SpvOpCompositeConstruct: 330 return SkString("CompositeConstruct"); 331 case SpvOpCompositeExtract: 332 return SkString("CompositeExtract"); 333 case SpvOpCompositeInsert: 334 return SkString("CompositeInsert"); 335 case SpvOpCopyObject: 336 return SkString("CopyObject"); 337 case SpvOpTranspose: 338 return SkString("Transpose"); 339 case SpvOpSampledImage: 340 return SkString("SampledImage"); 341 case SpvOpImageSampleImplicitLod: 342 return SkString("ImageSampleImplicitLod"); 343 case SpvOpImageSampleExplicitLod: 344 return SkString("ImageSampleExplicitLod"); 345 case SpvOpImageSampleDrefImplicitLod: 346 return SkString("ImageSampleDrefImplicitLod"); 347 case SpvOpImageSampleDrefExplicitLod: 348 return SkString("ImageSampleDrefExplicitLod"); 349 case SpvOpImageSampleProjImplicitLod: 350 return SkString("ImageSampleProjImplicitLod"); 351 case SpvOpImageSampleProjExplicitLod: 352 return SkString("ImageSampleProjExplicitLod"); 353 case SpvOpImageSampleProjDrefImplicitLod: 354 return SkString("ImageSampleProjDrefImplicitLod"); 355 case SpvOpImageSampleProjDrefExplicitLod: 356 return SkString("ImageSampleProjDrefExplicitLod"); 357 case SpvOpImageFetch: 358 return SkString("ImageFetch"); 359 case SpvOpImageGather: 360 return SkString("ImageGather"); 361 case SpvOpImageDrefGather: 362 return SkString("ImageDrefGather"); 363 case SpvOpImageRead: 364 return SkString("ImageRead"); 365 case SpvOpImageWrite: 366 return SkString("ImageWrite"); 367 case SpvOpImage: 368 return SkString("Image"); 369 case SpvOpImageQueryFormat: 370 return SkString("ImageQueryFormat"); 371 case SpvOpImageQueryOrder: 372 return SkString("ImageQueryOrder"); 373 case SpvOpImageQuerySizeLod: 374 return SkString("ImageQuerySizeLod"); 375 case SpvOpImageQuerySize: 376 return SkString("ImageQuerySize"); 377 case SpvOpImageQueryLod: 378 return SkString("ImageQueryLod"); 379 case SpvOpImageQueryLevels: 380 return SkString("ImageQueryLevels"); 381 case SpvOpImageQuerySamples: 382 return SkString("ImageQuerySamples"); 383 case SpvOpConvertFToU: 384 return SkString("ConvertFToU"); 385 case SpvOpConvertFToS: 386 return SkString("ConvertFToS"); 387 case SpvOpConvertSToF: 388 return SkString("ConvertSToF"); 389 case SpvOpConvertUToF: 390 return SkString("ConvertUToF"); 391 case SpvOpUConvert: 392 return SkString("UConvert"); 393 case SpvOpSConvert: 394 return SkString("SConvert"); 395 case SpvOpFConvert: 396 return SkString("FConvert"); 397 case SpvOpQuantizeToF16: 398 return SkString("QuantizeToF16"); 399 case SpvOpConvertPtrToU: 400 return SkString("ConvertPtrToU"); 401 case SpvOpSatConvertSToU: 402 return SkString("SatConvertSToU"); 403 case SpvOpSatConvertUToS: 404 return SkString("SatConvertUToS"); 405 case SpvOpConvertUToPtr: 406 return SkString("ConvertUToPtr"); 407 case SpvOpPtrCastToGeneric: 408 return SkString("PtrCastToGeneric"); 409 case SpvOpGenericCastToPtr: 410 return SkString("GenericCastToPtr"); 411 case SpvOpGenericCastToPtrExplicit: 412 return SkString("GenericCastToPtrExplicit"); 413 case SpvOpBitcast: 414 return SkString("Bitcast"); 415 case SpvOpSNegate: 416 return SkString("SNegate"); 417 case SpvOpFNegate: 418 return SkString("FNegate"); 419 case SpvOpIAdd: 420 return SkString("IAdd"); 421 case SpvOpFAdd: 422 return SkString("FAdd"); 423 case SpvOpISub: 424 return SkString("ISub"); 425 case SpvOpFSub: 426 return SkString("FSub"); 427 case SpvOpIMul: 428 return SkString("IMul"); 429 case SpvOpFMul: 430 return SkString("FMul"); 431 case SpvOpUDiv: 432 return SkString("UDiv"); 433 case SpvOpSDiv: 434 return SkString("SDiv"); 435 case SpvOpFDiv: 436 return SkString("FDiv"); 437 case SpvOpUMod: 438 return SkString("UMod"); 439 case SpvOpSRem: 440 return SkString("SRem"); 441 case SpvOpSMod: 442 return SkString("SMod"); 443 case SpvOpFRem: 444 return SkString("FRem"); 445 case SpvOpFMod: 446 return SkString("FMod"); 447 case SpvOpVectorTimesScalar: 448 return SkString("VectorTimesScalar"); 449 case SpvOpMatrixTimesScalar: 450 return SkString("MatrixTimesScalar"); 451 case SpvOpVectorTimesMatrix: 452 return SkString("VectorTimesMatrix"); 453 case SpvOpMatrixTimesVector: 454 return SkString("MatrixTimesVector"); 455 case SpvOpMatrixTimesMatrix: 456 return SkString("MatrixTimesMatrix"); 457 case SpvOpOuterProduct: 458 return SkString("OuterProduct"); 459 case SpvOpDot: 460 return SkString("Dot"); 461 case SpvOpIAddCarry: 462 return SkString("IAddCarry"); 463 case SpvOpISubBorrow: 464 return SkString("ISubBorrow"); 465 case SpvOpUMulExtended: 466 return SkString("UMulExtended"); 467 case SpvOpSMulExtended: 468 return SkString("SMulExtended"); 469 case SpvOpAny: 470 return SkString("Any"); 471 case SpvOpAll: 472 return SkString("All"); 473 case SpvOpIsNan: 474 return SkString("IsNan"); 475 case SpvOpIsInf: 476 return SkString("IsInf"); 477 case SpvOpIsFinite: 478 return SkString("IsFinite"); 479 case SpvOpIsNormal: 480 return SkString("IsNormal"); 481 case SpvOpSignBitSet: 482 return SkString("SignBitSet"); 483 case SpvOpLessOrGreater: 484 return SkString("LessOrGreater"); 485 case SpvOpOrdered: 486 return SkString("Ordered"); 487 case SpvOpUnordered: 488 return SkString("Unordered"); 489 case SpvOpLogicalEqual: 490 return SkString("LogicalEqual"); 491 case SpvOpLogicalNotEqual: 492 return SkString("LogicalNotEqual"); 493 case SpvOpLogicalOr: 494 return SkString("LogicalOr"); 495 case SpvOpLogicalAnd: 496 return SkString("LogicalAnd"); 497 case SpvOpLogicalNot: 498 return SkString("LogicalNot"); 499 case SpvOpSelect: 500 return SkString("Select"); 501 case SpvOpIEqual: 502 return SkString("IEqual"); 503 case SpvOpINotEqual: 504 return SkString("INotEqual"); 505 case SpvOpUGreaterThan: 506 return SkString("UGreaterThan"); 507 case SpvOpSGreaterThan: 508 return SkString("SGreaterThan"); 509 case SpvOpUGreaterThanEqual: 510 return SkString("UGreaterThanEqual"); 511 case SpvOpSGreaterThanEqual: 512 return SkString("SGreaterThanEqual"); 513 case SpvOpULessThan: 514 return SkString("ULessThan"); 515 case SpvOpSLessThan: 516 return SkString("SLessThan"); 517 case SpvOpULessThanEqual: 518 return SkString("ULessThanEqual"); 519 case SpvOpSLessThanEqual: 520 return SkString("SLessThanEqual"); 521 case SpvOpFOrdEqual: 522 return SkString("FOrdEqual"); 523 case SpvOpFUnordEqual: 524 return SkString("FUnordEqual"); 525 case SpvOpFOrdNotEqual: 526 return SkString("FOrdNotEqual"); 527 case SpvOpFUnordNotEqual: 528 return SkString("FUnordNotEqual"); 529 case SpvOpFOrdLessThan: 530 return SkString("FOrdLessThan"); 531 case SpvOpFUnordLessThan: 532 return SkString("FUnordLessThan"); 533 case SpvOpFOrdGreaterThan: 534 return SkString("FOrdGreaterThan"); 535 case SpvOpFUnordGreaterThan: 536 return SkString("FUnordGreaterThan"); 537 case SpvOpFOrdLessThanEqual: 538 return SkString("FOrdLessThanEqual"); 539 case SpvOpFUnordLessThanEqual: 540 return SkString("FUnordLessThanEqual"); 541 case SpvOpFOrdGreaterThanEqual: 542 return SkString("FOrdGreaterThanEqual"); 543 case SpvOpFUnordGreaterThanEqual: 544 return SkString("FUnordGreaterThanEqual"); 545 case SpvOpShiftRightLogical: 546 return SkString("ShiftRightLogical"); 547 case SpvOpShiftRightArithmetic: 548 return SkString("ShiftRightArithmetic"); 549 case SpvOpShiftLeftLogical: 550 return SkString("ShiftLeftLogical"); 551 case SpvOpBitwiseOr: 552 return SkString("BitwiseOr"); 553 case SpvOpBitwiseXor: 554 return SkString("BitwiseXor"); 555 case SpvOpBitwiseAnd: 556 return SkString("BitwiseAnd"); 557 case SpvOpNot: 558 return SkString("Not"); 559 case SpvOpBitFieldInsert: 560 return SkString("BitFieldInsert"); 561 case SpvOpBitFieldSExtract: 562 return SkString("BitFieldSExtract"); 563 case SpvOpBitFieldUExtract: 564 return SkString("BitFieldUExtract"); 565 case SpvOpBitReverse: 566 return SkString("BitReverse"); 567 case SpvOpBitCount: 568 return SkString("BitCount"); 569 case SpvOpDPdx: 570 return SkString("DPdx"); 571 case SpvOpDPdy: 572 return SkString("DPdy"); 573 case SpvOpFwidth: 574 return SkString("Fwidth"); 575 case SpvOpDPdxFine: 576 return SkString("DPdxFine"); 577 case SpvOpDPdyFine: 578 return SkString("DPdyFine"); 579 case SpvOpFwidthFine: 580 return SkString("FwidthFine"); 581 case SpvOpDPdxCoarse: 582 return SkString("DPdxCoarse"); 583 case SpvOpDPdyCoarse: 584 return SkString("DPdyCoarse"); 585 case SpvOpFwidthCoarse: 586 return SkString("FwidthCoarse"); 587 case SpvOpEmitVertex: 588 return SkString("EmitVertex"); 589 case SpvOpEndPrimitive: 590 return SkString("EndPrimitive"); 591 case SpvOpEmitStreamVertex: 592 return SkString("EmitStreamVertex"); 593 case SpvOpEndStreamPrimitive: 594 return SkString("EndStreamPrimitive"); 595 case SpvOpControlBarrier: 596 return SkString("ControlBarrier"); 597 case SpvOpMemoryBarrier: 598 return SkString("MemoryBarrier"); 599 case SpvOpAtomicLoad: 600 return SkString("AtomicLoad"); 601 case SpvOpAtomicStore: 602 return SkString("AtomicStore"); 603 case SpvOpAtomicExchange: 604 return SkString("AtomicExchange"); 605 case SpvOpAtomicCompareExchange: 606 return SkString("AtomicCompareExchange"); 607 case SpvOpAtomicCompareExchangeWeak: 608 return SkString("AtomicCompareExchangeWeak"); 609 case SpvOpAtomicIIncrement: 610 return SkString("AtomicIIncrement"); 611 case SpvOpAtomicIDecrement: 612 return SkString("AtomicIDecrement"); 613 case SpvOpAtomicIAdd: 614 return SkString("AtomicIAdd"); 615 case SpvOpAtomicISub: 616 return SkString("AtomicISub"); 617 case SpvOpAtomicSMin: 618 return SkString("AtomicSMin"); 619 case SpvOpAtomicUMin: 620 return SkString("AtomicUMin"); 621 case SpvOpAtomicSMax: 622 return SkString("AtomicSMax"); 623 case SpvOpAtomicUMax: 624 return SkString("AtomicUMax"); 625 case SpvOpAtomicAnd: 626 return SkString("AtomicAnd"); 627 case SpvOpAtomicOr: 628 return SkString("AtomicOr"); 629 case SpvOpAtomicXor: 630 return SkString("AtomicXor"); 631 case SpvOpPhi: 632 return SkString("Phi"); 633 case SpvOpLoopMerge: 634 return SkString("LoopMerge"); 635 case SpvOpSelectionMerge: 636 return SkString("SelectionMerge"); 637 case SpvOpLabel: 638 return SkString("Label"); 639 case SpvOpBranch: 640 return SkString("Branch"); 641 case SpvOpBranchConditional: 642 return SkString("BranchConditional"); 643 case SpvOpSwitch: 644 return SkString("Switch"); 645 case SpvOpKill: 646 return SkString("Kill"); 647 case SpvOpReturn: 648 return SkString("Return"); 649 case SpvOpReturnValue: 650 return SkString("ReturnValue"); 651 case SpvOpUnreachable: 652 return SkString("Unreachable"); 653 case SpvOpLifetimeStart: 654 return SkString("LifetimeStart"); 655 case SpvOpLifetimeStop: 656 return SkString("LifetimeStop"); 657 case SpvOpGroupAsyncCopy: 658 return SkString("GroupAsyncCopy"); 659 case SpvOpGroupWaitEvents: 660 return SkString("GroupWaitEvents"); 661 case SpvOpGroupAll: 662 return SkString("GroupAll"); 663 case SpvOpGroupAny: 664 return SkString("GroupAny"); 665 case SpvOpGroupBroadcast: 666 return SkString("GroupBroadcast"); 667 case SpvOpGroupIAdd: 668 return SkString("GroupIAdd"); 669 case SpvOpGroupFAdd: 670 return SkString("GroupFAdd"); 671 case SpvOpGroupFMin: 672 return SkString("GroupFMin"); 673 case SpvOpGroupUMin: 674 return SkString("GroupUMin"); 675 case SpvOpGroupSMin: 676 return SkString("GroupSMin"); 677 case SpvOpGroupFMax: 678 return SkString("GroupFMax"); 679 case SpvOpGroupUMax: 680 return SkString("GroupUMax"); 681 case SpvOpGroupSMax: 682 return SkString("GroupSMax"); 683 case SpvOpReadPipe: 684 return SkString("ReadPipe"); 685 case SpvOpWritePipe: 686 return SkString("WritePipe"); 687 case SpvOpReservedReadPipe: 688 return SkString("ReservedReadPipe"); 689 case SpvOpReservedWritePipe: 690 return SkString("ReservedWritePipe"); 691 case SpvOpReserveReadPipePackets: 692 return SkString("ReserveReadPipePackets"); 693 case SpvOpReserveWritePipePackets: 694 return SkString("ReserveWritePipePackets"); 695 case SpvOpCommitReadPipe: 696 return SkString("CommitReadPipe"); 697 case SpvOpCommitWritePipe: 698 return SkString("CommitWritePipe"); 699 case SpvOpIsValidReserveId: 700 return SkString("IsValidReserveId"); 701 case SpvOpGetNumPipePackets: 702 return SkString("GetNumPipePackets"); 703 case SpvOpGetMaxPipePackets: 704 return SkString("GetMaxPipePackets"); 705 case SpvOpGroupReserveReadPipePackets: 706 return SkString("GroupReserveReadPipePackets"); 707 case SpvOpGroupReserveWritePipePackets: 708 return SkString("GroupReserveWritePipePackets"); 709 case SpvOpGroupCommitReadPipe: 710 return SkString("GroupCommitReadPipe"); 711 case SpvOpGroupCommitWritePipe: 712 return SkString("GroupCommitWritePipe"); 713 case SpvOpEnqueueMarker: 714 return SkString("EnqueueMarker"); 715 case SpvOpEnqueueKernel: 716 return SkString("EnqueueKernel"); 717 case SpvOpGetKernelNDrangeSubGroupCount: 718 return SkString("GetKernelNDrangeSubGroupCount"); 719 case SpvOpGetKernelNDrangeMaxSubGroupSize: 720 return SkString("GetKernelNDrangeMaxSubGroupSize"); 721 case SpvOpGetKernelWorkGroupSize: 722 return SkString("GetKernelWorkGroupSize"); 723 case SpvOpGetKernelPreferredWorkGroupSizeMultiple: 724 return SkString("GetKernelPreferredWorkGroupSizeMultiple"); 725 case SpvOpRetainEvent: 726 return SkString("RetainEvent"); 727 case SpvOpReleaseEvent: 728 return SkString("ReleaseEvent"); 729 case SpvOpCreateUserEvent: 730 return SkString("CreateUserEvent"); 731 case SpvOpIsValidEvent: 732 return SkString("IsValidEvent"); 733 case SpvOpSetUserEventStatus: 734 return SkString("SetUserEventStatus"); 735 case SpvOpCaptureEventProfilingInfo: 736 return SkString("CaptureEventProfilingInfo"); 737 case SpvOpGetDefaultQueue: 738 return SkString("GetDefaultQueue"); 739 case SpvOpBuildNDRange: 740 return SkString("BuildNDRange"); 741 case SpvOpImageSparseSampleImplicitLod: 742 return SkString("ImageSparseSampleImplicitLod"); 743 case SpvOpImageSparseSampleExplicitLod: 744 return SkString("ImageSparseSampleExplicitLod"); 745 case SpvOpImageSparseSampleDrefImplicitLod: 746 return SkString("ImageSparseSampleDrefImplicitLod"); 747 case SpvOpImageSparseSampleDrefExplicitLod: 748 return SkString("ImageSparseSampleDrefExplicitLod"); 749 case SpvOpImageSparseSampleProjImplicitLod: 750 return SkString("ImageSparseSampleProjImplicitLod"); 751 case SpvOpImageSparseSampleProjExplicitLod: 752 return SkString("ImageSparseSampleProjExplicitLod"); 753 case SpvOpImageSparseSampleProjDrefImplicitLod: 754 return SkString("ImageSparseSampleProjDrefImplicitLod"); 755 case SpvOpImageSparseSampleProjDrefExplicitLod: 756 return SkString("ImageSparseSampleProjDrefExplicitLod"); 757 case SpvOpImageSparseFetch: 758 return SkString("ImageSparseFetch"); 759 case SpvOpImageSparseGather: 760 return SkString("ImageSparseGather"); 761 case SpvOpImageSparseDrefGather: 762 return SkString("ImageSparseDrefGather"); 763 case SpvOpImageSparseTexelsResident: 764 return SkString("ImageSparseTexelsResident"); 765 case SpvOpNoLine: 766 return SkString("NoLine"); 767 case SpvOpAtomicFlagTestAndSet: 768 return SkString("AtomicFlagTestAndSet"); 769 case SpvOpAtomicFlagClear: 770 return SkString("AtomicFlagClear"); 771 case SpvOpImageSparseRead: 772 return SkString("ImageSparseRead"); 773 default: 774 ABORT("unsupported SPIR-V op"); 775 } 776} 777#endif 778 779void SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, SkWStream& out) { 780 ASSERT(opCode != SpvOpUndef); 781 switch (opCode) { 782 case SpvOpReturn: // fall through 783 case SpvOpReturnValue: // fall through 784 case SpvOpKill: // fall through 785 case SpvOpBranch: // fall through 786 case SpvOpBranchConditional: 787 ASSERT(fCurrentBlock); 788 fCurrentBlock = 0; 789 break; 790 case SpvOpConstant: // fall through 791 case SpvOpConstantTrue: // fall through 792 case SpvOpConstantFalse: // fall through 793 case SpvOpConstantComposite: // fall through 794 case SpvOpTypeVoid: // fall through 795 case SpvOpTypeInt: // fall through 796 case SpvOpTypeFloat: // fall through 797 case SpvOpTypeBool: // fall through 798 case SpvOpTypeVector: // fall through 799 case SpvOpTypeMatrix: // fall through 800 case SpvOpTypeArray: // fall through 801 case SpvOpTypePointer: // fall through 802 case SpvOpTypeFunction: // fall through 803 case SpvOpTypeRuntimeArray: // fall through 804 case SpvOpTypeStruct: // fall through 805 case SpvOpTypeImage: // fall through 806 case SpvOpTypeSampledImage: // fall through 807 case SpvOpVariable: // fall through 808 case SpvOpFunction: // fall through 809 case SpvOpFunctionParameter: // fall through 810 case SpvOpFunctionEnd: // fall through 811 case SpvOpExecutionMode: // fall through 812 case SpvOpMemoryModel: // fall through 813 case SpvOpCapability: // fall through 814 case SpvOpExtInstImport: // fall through 815 case SpvOpEntryPoint: // fall through 816 case SpvOpSource: // fall through 817 case SpvOpSourceExtension: // fall through 818 case SpvOpName: // fall through 819 case SpvOpMemberName: // fall through 820 case SpvOpDecorate: // fall through 821 case SpvOpMemberDecorate: 822 break; 823 default: 824 ASSERT(fCurrentBlock); 825 } 826#if SPIRV_DEBUG 827 out << std::endl << opcode_text(opCode) << " "; 828#else 829 this->writeWord((length << 16) | opCode, out); 830#endif 831} 832 833void SPIRVCodeGenerator::writeLabel(SpvId label, SkWStream& out) { 834 fCurrentBlock = label; 835 this->writeInstruction(SpvOpLabel, label, out); 836} 837 838void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, SkWStream& out) { 839 this->writeOpCode(opCode, 1, out); 840} 841 842void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, SkWStream& out) { 843 this->writeOpCode(opCode, 2, out); 844 this->writeWord(word1, out); 845} 846 847void SPIRVCodeGenerator::writeString(const char* string, SkWStream& out) { 848 size_t length = strlen(string); 849 out.writeText(string); 850 switch (length % 4) { 851 case 1: 852 out.write8(0); 853 // fall through 854 case 2: 855 out.write8(0); 856 // fall through 857 case 3: 858 out.write8(0); 859 break; 860 default: 861 this->writeWord(0, out); 862 } 863} 864 865void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, const char* string, SkWStream& out) { 866 int32_t length = (int32_t) strlen(string); 867 this->writeOpCode(opCode, 1 + (length + 4) / 4, out); 868 this->writeString(string, out); 869} 870 871 872void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, 873 SkWStream& out) { 874 int32_t length = (int32_t) strlen(string); 875 this->writeOpCode(opCode, 2 + (length + 4) / 4, out); 876 this->writeWord(word1, out); 877 this->writeString(string, out); 878} 879 880void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 881 const char* string, SkWStream& out) { 882 int32_t length = (int32_t) strlen(string); 883 this->writeOpCode(opCode, 3 + (length + 4) / 4, out); 884 this->writeWord(word1, out); 885 this->writeWord(word2, out); 886 this->writeString(string, out); 887} 888 889void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 890 SkWStream& out) { 891 this->writeOpCode(opCode, 3, out); 892 this->writeWord(word1, out); 893 this->writeWord(word2, out); 894} 895 896void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 897 int32_t word3, SkWStream& out) { 898 this->writeOpCode(opCode, 4, out); 899 this->writeWord(word1, out); 900 this->writeWord(word2, out); 901 this->writeWord(word3, out); 902} 903 904void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 905 int32_t word3, int32_t word4, SkWStream& out) { 906 this->writeOpCode(opCode, 5, out); 907 this->writeWord(word1, out); 908 this->writeWord(word2, out); 909 this->writeWord(word3, out); 910 this->writeWord(word4, out); 911} 912 913void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 914 int32_t word3, int32_t word4, int32_t word5, 915 SkWStream& out) { 916 this->writeOpCode(opCode, 6, out); 917 this->writeWord(word1, out); 918 this->writeWord(word2, out); 919 this->writeWord(word3, out); 920 this->writeWord(word4, out); 921 this->writeWord(word5, out); 922} 923 924void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 925 int32_t word3, int32_t word4, int32_t word5, 926 int32_t word6, SkWStream& out) { 927 this->writeOpCode(opCode, 7, out); 928 this->writeWord(word1, out); 929 this->writeWord(word2, out); 930 this->writeWord(word3, out); 931 this->writeWord(word4, out); 932 this->writeWord(word5, out); 933 this->writeWord(word6, out); 934} 935 936void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 937 int32_t word3, int32_t word4, int32_t word5, 938 int32_t word6, int32_t word7, SkWStream& out) { 939 this->writeOpCode(opCode, 8, out); 940 this->writeWord(word1, out); 941 this->writeWord(word2, out); 942 this->writeWord(word3, out); 943 this->writeWord(word4, out); 944 this->writeWord(word5, out); 945 this->writeWord(word6, out); 946 this->writeWord(word7, out); 947} 948 949void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, 950 int32_t word3, int32_t word4, int32_t word5, 951 int32_t word6, int32_t word7, int32_t word8, 952 SkWStream& out) { 953 this->writeOpCode(opCode, 9, out); 954 this->writeWord(word1, out); 955 this->writeWord(word2, out); 956 this->writeWord(word3, out); 957 this->writeWord(word4, out); 958 this->writeWord(word5, out); 959 this->writeWord(word6, out); 960 this->writeWord(word7, out); 961 this->writeWord(word8, out); 962} 963 964void SPIRVCodeGenerator::writeCapabilities(SkWStream& out) { 965 for (uint64_t i = 0, bit = 1; i <= kLast_Capability; i++, bit <<= 1) { 966 if (fCapabilities & bit) { 967 this->writeInstruction(SpvOpCapability, (SpvId) i, out); 968 } 969 } 970} 971 972SpvId SPIRVCodeGenerator::nextId() { 973 return fIdCount++; 974} 975 976void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memoryLayout, 977 SpvId resultId) { 978 this->writeInstruction(SpvOpName, resultId, type.name().c_str(), fNameBuffer); 979 // go ahead and write all of the field types, so we don't inadvertently write them while we're 980 // in the middle of writing the struct instruction 981 std::vector<SpvId> types; 982 for (const auto& f : type.fields()) { 983 types.push_back(this->getType(*f.fType, memoryLayout)); 984 } 985 this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuffer); 986 this->writeWord(resultId, fConstantBuffer); 987 for (SpvId id : types) { 988 this->writeWord(id, fConstantBuffer); 989 } 990 size_t offset = 0; 991 for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) { 992 size_t size = memoryLayout.size(*type.fields()[i].fType); 993 size_t alignment = memoryLayout.alignment(*type.fields()[i].fType); 994 const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout; 995 if (fieldLayout.fOffset >= 0) { 996 if (fieldLayout.fOffset <= (int) offset) { 997 fErrors.error(type.fPosition, 998 "offset of field '" + type.fields()[i].fName + "' must be at " 999 "least " + to_string((int) offset)); 1000 } 1001 if (fieldLayout.fOffset % alignment) { 1002 fErrors.error(type.fPosition, 1003 "offset of field '" + type.fields()[i].fName + "' must be a multiple" 1004 " of " + to_string((int) alignment)); 1005 } 1006 offset = fieldLayout.fOffset; 1007 } else { 1008 size_t mod = offset % alignment; 1009 if (mod) { 1010 offset += alignment - mod; 1011 } 1012 } 1013 this->writeInstruction(SpvOpMemberName, resultId, i, type.fields()[i].fName.c_str(), 1014 fNameBuffer); 1015 this->writeLayout(fieldLayout, resultId, i); 1016 if (type.fields()[i].fModifiers.fLayout.fBuiltin < 0) { 1017 this->writeInstruction(SpvOpMemberDecorate, resultId, (SpvId) i, SpvDecorationOffset, 1018 (SpvId) offset, fDecorationBuffer); 1019 } 1020 if (type.fields()[i].fType->kind() == Type::kMatrix_Kind) { 1021 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationColMajor, 1022 fDecorationBuffer); 1023 this->writeInstruction(SpvOpMemberDecorate, resultId, i, SpvDecorationMatrixStride, 1024 (SpvId) memoryLayout.stride(*type.fields()[i].fType), 1025 fDecorationBuffer); 1026 } 1027 offset += size; 1028 Type::Kind kind = type.fields()[i].fType->kind(); 1029 if ((kind == Type::kArray_Kind || kind == Type::kStruct_Kind) && offset % alignment != 0) { 1030 offset += alignment - offset % alignment; 1031 } 1032 } 1033} 1034 1035SpvId SPIRVCodeGenerator::getType(const Type& type) { 1036 return this->getType(type, fDefaultLayout); 1037} 1038 1039SpvId SPIRVCodeGenerator::getType(const Type& type, const MemoryLayout& layout) { 1040 SkString key = type.name() + to_string((int) layout.fStd); 1041 auto entry = fTypeMap.find(key); 1042 if (entry == fTypeMap.end()) { 1043 SpvId result = this->nextId(); 1044 switch (type.kind()) { 1045 case Type::kScalar_Kind: 1046 if (type == *fContext.fBool_Type) { 1047 this->writeInstruction(SpvOpTypeBool, result, fConstantBuffer); 1048 } else if (type == *fContext.fInt_Type) { 1049 this->writeInstruction(SpvOpTypeInt, result, 32, 1, fConstantBuffer); 1050 } else if (type == *fContext.fUInt_Type) { 1051 this->writeInstruction(SpvOpTypeInt, result, 32, 0, fConstantBuffer); 1052 } else if (type == *fContext.fFloat_Type) { 1053 this->writeInstruction(SpvOpTypeFloat, result, 32, fConstantBuffer); 1054 } else if (type == *fContext.fDouble_Type) { 1055 this->writeInstruction(SpvOpTypeFloat, result, 64, fConstantBuffer); 1056 } else { 1057 ASSERT(false); 1058 } 1059 break; 1060 case Type::kVector_Kind: 1061 this->writeInstruction(SpvOpTypeVector, result, 1062 this->getType(type.componentType(), layout), 1063 type.columns(), fConstantBuffer); 1064 break; 1065 case Type::kMatrix_Kind: 1066 this->writeInstruction(SpvOpTypeMatrix, result, 1067 this->getType(index_type(fContext, type), layout), 1068 type.columns(), fConstantBuffer); 1069 break; 1070 case Type::kStruct_Kind: 1071 this->writeStruct(type, layout, result); 1072 break; 1073 case Type::kArray_Kind: { 1074 if (type.columns() > 0) { 1075 IntLiteral count(fContext, Position(), type.columns()); 1076 this->writeInstruction(SpvOpTypeArray, result, 1077 this->getType(type.componentType(), layout), 1078 this->writeIntLiteral(count), fConstantBuffer); 1079 this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride, 1080 (int32_t) layout.stride(type), 1081 fDecorationBuffer); 1082 } else { 1083 ABORT("runtime-sized arrays are not yet supported"); 1084 this->writeInstruction(SpvOpTypeRuntimeArray, result, 1085 this->getType(type.componentType(), layout), 1086 fConstantBuffer); 1087 } 1088 break; 1089 } 1090 case Type::kSampler_Kind: { 1091 SpvId image = result; 1092 if (SpvDimSubpassData != type.dimensions()) { 1093 image = this->nextId(); 1094 } 1095 this->writeInstruction(SpvOpTypeImage, image, 1096 this->getType(*fContext.fFloat_Type, layout), 1097 type.dimensions(), type.isDepth(), type.isArrayed(), 1098 type.isMultisampled(), type.isSampled() ? 1 : 2, 1099 SpvImageFormatUnknown, fConstantBuffer); 1100 if (SpvDimSubpassData != type.dimensions()) { 1101 this->writeInstruction(SpvOpTypeSampledImage, result, image, fConstantBuffer); 1102 } 1103 break; 1104 } 1105 default: 1106 if (type == *fContext.fVoid_Type) { 1107 this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffer); 1108 } else { 1109 ABORT("invalid type: %s", type.description().c_str()); 1110 } 1111 } 1112 fTypeMap[key] = result; 1113 return result; 1114 } 1115 return entry->second; 1116} 1117 1118SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { 1119 SkString key = function.fReturnType.description() + "("; 1120 SkString separator; 1121 for (size_t i = 0; i < function.fParameters.size(); i++) { 1122 key += separator; 1123 separator = ", "; 1124 key += function.fParameters[i]->fType.description(); 1125 } 1126 key += ")"; 1127 auto entry = fTypeMap.find(key); 1128 if (entry == fTypeMap.end()) { 1129 SpvId result = this->nextId(); 1130 int32_t length = 3 + (int32_t) function.fParameters.size(); 1131 SpvId returnType = this->getType(function.fReturnType); 1132 std::vector<SpvId> parameterTypes; 1133 for (size_t i = 0; i < function.fParameters.size(); i++) { 1134 // glslang seems to treat all function arguments as pointers whether they need to be or 1135 // not. I was initially puzzled by this until I ran bizarre failures with certain 1136 // patterns of function calls and control constructs, as exemplified by this minimal 1137 // failure case: 1138 // 1139 // void sphere(float x) { 1140 // } 1141 // 1142 // void map() { 1143 // sphere(1.0); 1144 // } 1145 // 1146 // void main() { 1147 // for (int i = 0; i < 1; i++) { 1148 // map(); 1149 // } 1150 // } 1151 // 1152 // As of this writing, compiling this in the "obvious" way (with sphere taking a float) 1153 // crashes. Making it take a float* and storing the argument in a temporary variable, 1154 // as glslang does, fixes it. It's entirely possible I simply missed whichever part of 1155 // the spec makes this make sense. 1156// if (is_out(function->fParameters[i])) { 1157 parameterTypes.push_back(this->getPointerType(function.fParameters[i]->fType, 1158 SpvStorageClassFunction)); 1159// } else { 1160// parameterTypes.push_back(this->getType(function.fParameters[i]->fType)); 1161// } 1162 } 1163 this->writeOpCode(SpvOpTypeFunction, length, fConstantBuffer); 1164 this->writeWord(result, fConstantBuffer); 1165 this->writeWord(returnType, fConstantBuffer); 1166 for (SpvId id : parameterTypes) { 1167 this->writeWord(id, fConstantBuffer); 1168 } 1169 fTypeMap[key] = result; 1170 return result; 1171 } 1172 return entry->second; 1173} 1174 1175SpvId SPIRVCodeGenerator::getPointerType(const Type& type, SpvStorageClass_ storageClass) { 1176 return this->getPointerType(type, fDefaultLayout, storageClass); 1177} 1178 1179SpvId SPIRVCodeGenerator::getPointerType(const Type& type, const MemoryLayout& layout, 1180 SpvStorageClass_ storageClass) { 1181 SkString key = type.description() + "*" + to_string(layout.fStd) + to_string(storageClass); 1182 auto entry = fTypeMap.find(key); 1183 if (entry == fTypeMap.end()) { 1184 SpvId result = this->nextId(); 1185 this->writeInstruction(SpvOpTypePointer, result, storageClass, 1186 this->getType(type), fConstantBuffer); 1187 fTypeMap[key] = result; 1188 return result; 1189 } 1190 return entry->second; 1191} 1192 1193SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, SkWStream& out) { 1194 switch (expr.fKind) { 1195 case Expression::kBinary_Kind: 1196 return this->writeBinaryExpression((BinaryExpression&) expr, out); 1197 case Expression::kBoolLiteral_Kind: 1198 return this->writeBoolLiteral((BoolLiteral&) expr); 1199 case Expression::kConstructor_Kind: 1200 return this->writeConstructor((Constructor&) expr, out); 1201 case Expression::kIntLiteral_Kind: 1202 return this->writeIntLiteral((IntLiteral&) expr); 1203 case Expression::kFieldAccess_Kind: 1204 return this->writeFieldAccess(((FieldAccess&) expr), out); 1205 case Expression::kFloatLiteral_Kind: 1206 return this->writeFloatLiteral(((FloatLiteral&) expr)); 1207 case Expression::kFunctionCall_Kind: 1208 return this->writeFunctionCall((FunctionCall&) expr, out); 1209 case Expression::kPrefix_Kind: 1210 return this->writePrefixExpression((PrefixExpression&) expr, out); 1211 case Expression::kPostfix_Kind: 1212 return this->writePostfixExpression((PostfixExpression&) expr, out); 1213 case Expression::kSwizzle_Kind: 1214 return this->writeSwizzle((Swizzle&) expr, out); 1215 case Expression::kVariableReference_Kind: 1216 return this->writeVariableReference((VariableReference&) expr, out); 1217 case Expression::kTernary_Kind: 1218 return this->writeTernaryExpression((TernaryExpression&) expr, out); 1219 case Expression::kIndex_Kind: 1220 return this->writeIndexExpression((IndexExpression&) expr, out); 1221 default: 1222 ABORT("unsupported expression: %s", expr.description().c_str()); 1223 } 1224 return -1; 1225} 1226 1227SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, SkWStream& out) { 1228 auto intrinsic = fIntrinsicMap.find(c.fFunction.fName); 1229 ASSERT(intrinsic != fIntrinsicMap.end()); 1230 const Type& type = c.fArguments[0]->fType; 1231 int32_t intrinsicId; 1232 if (std::get<0>(intrinsic->second) == kSpecial_IntrinsicKind || is_float(fContext, type)) { 1233 intrinsicId = std::get<1>(intrinsic->second); 1234 } else if (is_signed(fContext, type)) { 1235 intrinsicId = std::get<2>(intrinsic->second); 1236 } else if (is_unsigned(fContext, type)) { 1237 intrinsicId = std::get<3>(intrinsic->second); 1238 } else if (is_bool(fContext, type)) { 1239 intrinsicId = std::get<4>(intrinsic->second); 1240 } else { 1241 ABORT("invalid call %s, cannot operate on '%s'", c.description().c_str(), 1242 type.description().c_str()); 1243 } 1244 switch (std::get<0>(intrinsic->second)) { 1245 case kGLSL_STD_450_IntrinsicKind: { 1246 SpvId result = this->nextId(); 1247 std::vector<SpvId> arguments; 1248 for (size_t i = 0; i < c.fArguments.size(); i++) { 1249 arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1250 } 1251 this->writeOpCode(SpvOpExtInst, 5 + (int32_t) arguments.size(), out); 1252 this->writeWord(this->getType(c.fType), out); 1253 this->writeWord(result, out); 1254 this->writeWord(fGLSLExtendedInstructions, out); 1255 this->writeWord(intrinsicId, out); 1256 for (SpvId id : arguments) { 1257 this->writeWord(id, out); 1258 } 1259 return result; 1260 } 1261 case kSPIRV_IntrinsicKind: { 1262 SpvId result = this->nextId(); 1263 std::vector<SpvId> arguments; 1264 for (size_t i = 0; i < c.fArguments.size(); i++) { 1265 arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1266 } 1267 this->writeOpCode((SpvOp_) intrinsicId, 3 + (int32_t) arguments.size(), out); 1268 this->writeWord(this->getType(c.fType), out); 1269 this->writeWord(result, out); 1270 for (SpvId id : arguments) { 1271 this->writeWord(id, out); 1272 } 1273 return result; 1274 } 1275 case kSpecial_IntrinsicKind: 1276 return this->writeSpecialIntrinsic(c, (SpecialIntrinsic) intrinsicId, out); 1277 default: 1278 ABORT("unsupported intrinsic kind"); 1279 } 1280} 1281 1282SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, 1283 SkWStream& out) { 1284 SpvId result = this->nextId(); 1285 switch (kind) { 1286 case kAtan_SpecialIntrinsic: { 1287 std::vector<SpvId> arguments; 1288 for (size_t i = 0; i < c.fArguments.size(); i++) { 1289 arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1290 } 1291 this->writeOpCode(SpvOpExtInst, 5 + (int32_t) arguments.size(), out); 1292 this->writeWord(this->getType(c.fType), out); 1293 this->writeWord(result, out); 1294 this->writeWord(fGLSLExtendedInstructions, out); 1295 this->writeWord(arguments.size() == 2 ? GLSLstd450Atan2 : GLSLstd450Atan, out); 1296 for (SpvId id : arguments) { 1297 this->writeWord(id, out); 1298 } 1299 return result; 1300 } 1301 case kTexture_SpecialIntrinsic: { 1302 SpvOp_ op = SpvOpImageSampleImplicitLod; 1303 switch (c.fArguments[0]->fType.dimensions()) { 1304 case SpvDim1D: 1305 if (c.fArguments[1]->fType == *fContext.fVec2_Type) { 1306 op = SpvOpImageSampleProjImplicitLod; 1307 } else { 1308 ASSERT(c.fArguments[1]->fType == *fContext.fFloat_Type); 1309 } 1310 break; 1311 case SpvDim2D: 1312 if (c.fArguments[1]->fType == *fContext.fVec3_Type) { 1313 op = SpvOpImageSampleProjImplicitLod; 1314 } else { 1315 ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type); 1316 } 1317 break; 1318 case SpvDim3D: 1319 if (c.fArguments[1]->fType == *fContext.fVec4_Type) { 1320 op = SpvOpImageSampleProjImplicitLod; 1321 } else { 1322 ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type); 1323 } 1324 break; 1325 case SpvDimCube: // fall through 1326 case SpvDimRect: // fall through 1327 case SpvDimBuffer: // fall through 1328 case SpvDimSubpassData: 1329 break; 1330 } 1331 SpvId type = this->getType(c.fType); 1332 SpvId sampler = this->writeExpression(*c.fArguments[0], out); 1333 SpvId uv = this->writeExpression(*c.fArguments[1], out); 1334 if (c.fArguments.size() == 3) { 1335 this->writeInstruction(op, type, result, sampler, uv, 1336 SpvImageOperandsBiasMask, 1337 this->writeExpression(*c.fArguments[2], out), 1338 out); 1339 } else { 1340 ASSERT(c.fArguments.size() == 2); 1341 this->writeInstruction(op, type, result, sampler, uv, 1342 out); 1343 } 1344 break; 1345 } 1346 case kSubpassLoad_SpecialIntrinsic: { 1347 SpvId img = this->writeExpression(*c.fArguments[0], out); 1348 std::vector<std::unique_ptr<Expression>> args; 1349 args.emplace_back(new FloatLiteral(fContext, Position(), 0.0)); 1350 args.emplace_back(new FloatLiteral(fContext, Position(), 0.0)); 1351 Constructor ctor(Position(), *fContext.fVec2_Type, std::move(args)); 1352 SpvId coords = this->writeConstantVector(ctor); 1353 if (1 == c.fArguments.size()) { 1354 this->writeInstruction(SpvOpImageRead, 1355 this->getType(c.fType), 1356 result, 1357 img, 1358 coords, 1359 out); 1360 } else { 1361 SkASSERT(2 == c.fArguments.size()); 1362 SpvId sample = this->writeExpression(*c.fArguments[1], out); 1363 this->writeInstruction(SpvOpImageRead, 1364 this->getType(c.fType), 1365 result, 1366 img, 1367 coords, 1368 SpvImageOperandsSampleMask, 1369 sample, 1370 out); 1371 } 1372 break; 1373 } 1374 } 1375 return result; 1376} 1377 1378SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, SkWStream& out) { 1379 const auto& entry = fFunctionMap.find(&c.fFunction); 1380 if (entry == fFunctionMap.end()) { 1381 return this->writeIntrinsicCall(c, out); 1382 } 1383 // stores (variable, type, lvalue) pairs to extract and save after the function call is complete 1384 std::vector<std::tuple<SpvId, SpvId, std::unique_ptr<LValue>>> lvalues; 1385 std::vector<SpvId> arguments; 1386 for (size_t i = 0; i < c.fArguments.size(); i++) { 1387 // id of temporary variable that we will use to hold this argument, or 0 if it is being 1388 // passed directly 1389 SpvId tmpVar; 1390 // if we need a temporary var to store this argument, this is the value to store in the var 1391 SpvId tmpValueId; 1392 if (is_out(*c.fFunction.fParameters[i])) { 1393 std::unique_ptr<LValue> lv = this->getLValue(*c.fArguments[i], out); 1394 SpvId ptr = lv->getPointer(); 1395 if (ptr) { 1396 arguments.push_back(ptr); 1397 continue; 1398 } else { 1399 // lvalue cannot simply be read and written via a pointer (e.g. a swizzle). Need to 1400 // copy it into a temp, call the function, read the value out of the temp, and then 1401 // update the lvalue. 1402 tmpValueId = lv->load(out); 1403 tmpVar = this->nextId(); 1404 lvalues.push_back(std::make_tuple(tmpVar, this->getType(c.fArguments[i]->fType), 1405 std::move(lv))); 1406 } 1407 } else { 1408 // see getFunctionType for an explanation of why we're always using pointer parameters 1409 tmpValueId = this->writeExpression(*c.fArguments[i], out); 1410 tmpVar = this->nextId(); 1411 } 1412 this->writeInstruction(SpvOpVariable, 1413 this->getPointerType(c.fArguments[i]->fType, 1414 SpvStorageClassFunction), 1415 tmpVar, 1416 SpvStorageClassFunction, 1417 fVariableBuffer); 1418 this->writeInstruction(SpvOpStore, tmpVar, tmpValueId, out); 1419 arguments.push_back(tmpVar); 1420 } 1421 SpvId result = this->nextId(); 1422 this->writeOpCode(SpvOpFunctionCall, 4 + (int32_t) c.fArguments.size(), out); 1423 this->writeWord(this->getType(c.fType), out); 1424 this->writeWord(result, out); 1425 this->writeWord(entry->second, out); 1426 for (SpvId id : arguments) { 1427 this->writeWord(id, out); 1428 } 1429 // now that the call is complete, we may need to update some lvalues with the new values of out 1430 // arguments 1431 for (const auto& tuple : lvalues) { 1432 SpvId load = this->nextId(); 1433 this->writeInstruction(SpvOpLoad, std::get<1>(tuple), load, std::get<0>(tuple), out); 1434 std::get<2>(tuple)->store(load, out); 1435 } 1436 return result; 1437} 1438 1439SpvId SPIRVCodeGenerator::writeConstantVector(const Constructor& c) { 1440 ASSERT(c.fType.kind() == Type::kVector_Kind && c.isConstant()); 1441 SpvId result = this->nextId(); 1442 std::vector<SpvId> arguments; 1443 for (size_t i = 0; i < c.fArguments.size(); i++) { 1444 arguments.push_back(this->writeExpression(*c.fArguments[i], fConstantBuffer)); 1445 } 1446 SpvId type = this->getType(c.fType); 1447 if (c.fArguments.size() == 1) { 1448 // with a single argument, a vector will have all of its entries equal to the argument 1449 this->writeOpCode(SpvOpConstantComposite, 3 + c.fType.columns(), fConstantBuffer); 1450 this->writeWord(type, fConstantBuffer); 1451 this->writeWord(result, fConstantBuffer); 1452 for (int i = 0; i < c.fType.columns(); i++) { 1453 this->writeWord(arguments[0], fConstantBuffer); 1454 } 1455 } else { 1456 this->writeOpCode(SpvOpConstantComposite, 3 + (int32_t) c.fArguments.size(), 1457 fConstantBuffer); 1458 this->writeWord(type, fConstantBuffer); 1459 this->writeWord(result, fConstantBuffer); 1460 for (SpvId id : arguments) { 1461 this->writeWord(id, fConstantBuffer); 1462 } 1463 } 1464 return result; 1465} 1466 1467SpvId SPIRVCodeGenerator::writeFloatConstructor(const Constructor& c, SkWStream& out) { 1468 ASSERT(c.fType == *fContext.fFloat_Type); 1469 ASSERT(c.fArguments.size() == 1); 1470 ASSERT(c.fArguments[0]->fType.isNumber()); 1471 SpvId result = this->nextId(); 1472 SpvId parameter = this->writeExpression(*c.fArguments[0], out); 1473 if (c.fArguments[0]->fType == *fContext.fInt_Type) { 1474 this->writeInstruction(SpvOpConvertSToF, this->getType(c.fType), result, parameter, 1475 out); 1476 } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) { 1477 this->writeInstruction(SpvOpConvertUToF, this->getType(c.fType), result, parameter, 1478 out); 1479 } else if (c.fArguments[0]->fType == *fContext.fFloat_Type) { 1480 return parameter; 1481 } 1482 return result; 1483} 1484 1485SpvId SPIRVCodeGenerator::writeIntConstructor(const Constructor& c, SkWStream& out) { 1486 ASSERT(c.fType == *fContext.fInt_Type); 1487 ASSERT(c.fArguments.size() == 1); 1488 ASSERT(c.fArguments[0]->fType.isNumber()); 1489 SpvId result = this->nextId(); 1490 SpvId parameter = this->writeExpression(*c.fArguments[0], out); 1491 if (c.fArguments[0]->fType == *fContext.fFloat_Type) { 1492 this->writeInstruction(SpvOpConvertFToS, this->getType(c.fType), result, parameter, 1493 out); 1494 } else if (c.fArguments[0]->fType == *fContext.fUInt_Type) { 1495 this->writeInstruction(SpvOpSatConvertUToS, this->getType(c.fType), result, parameter, 1496 out); 1497 } else if (c.fArguments[0]->fType == *fContext.fInt_Type) { 1498 return parameter; 1499 } 1500 return result; 1501} 1502 1503SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, SkWStream& out) { 1504 ASSERT(c.fType.kind() == Type::kMatrix_Kind); 1505 // go ahead and write the arguments so we don't try to write new instructions in the middle of 1506 // an instruction 1507 std::vector<SpvId> arguments; 1508 for (size_t i = 0; i < c.fArguments.size(); i++) { 1509 arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1510 } 1511 SpvId result = this->nextId(); 1512 int rows = c.fType.rows(); 1513 int columns = c.fType.columns(); 1514 // FIXME this won't work to create a matrix from another matrix 1515 if (arguments.size() == 1) { 1516 // with a single argument, a matrix will have all of its diagonal entries equal to the 1517 // argument and its other values equal to zero 1518 // FIXME this won't work for int matrices 1519 FloatLiteral zero(fContext, Position(), 0); 1520 SpvId zeroId = this->writeFloatLiteral(zero); 1521 std::vector<SpvId> columnIds; 1522 for (int column = 0; column < columns; column++) { 1523 this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.rows(), 1524 out); 1525 this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows, 1)), 1526 out); 1527 SpvId columnId = this->nextId(); 1528 this->writeWord(columnId, out); 1529 columnIds.push_back(columnId); 1530 for (int row = 0; row < c.fType.columns(); row++) { 1531 this->writeWord(row == column ? arguments[0] : zeroId, out); 1532 } 1533 } 1534 this->writeOpCode(SpvOpCompositeConstruct, 3 + columns, 1535 out); 1536 this->writeWord(this->getType(c.fType), out); 1537 this->writeWord(result, out); 1538 for (SpvId id : columnIds) { 1539 this->writeWord(id, out); 1540 } 1541 } else { 1542 std::vector<SpvId> columnIds; 1543 int currentCount = 0; 1544 for (size_t i = 0; i < arguments.size(); i++) { 1545 if (c.fArguments[i]->fType.kind() == Type::kVector_Kind) { 1546 ASSERT(currentCount == 0); 1547 columnIds.push_back(arguments[i]); 1548 currentCount = 0; 1549 } else { 1550 ASSERT(c.fArguments[i]->fType.kind() == Type::kScalar_Kind); 1551 if (currentCount == 0) { 1552 this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.rows(), out); 1553 this->writeWord(this->getType(c.fType.componentType().toCompound(fContext, rows, 1554 1)), 1555 out); 1556 SpvId id = this->nextId(); 1557 this->writeWord(id, out); 1558 columnIds.push_back(id); 1559 } 1560 this->writeWord(arguments[i], out); 1561 currentCount = (currentCount + 1) % rows; 1562 } 1563 } 1564 ASSERT(columnIds.size() == (size_t) columns); 1565 this->writeOpCode(SpvOpCompositeConstruct, 3 + columns, out); 1566 this->writeWord(this->getType(c.fType), out); 1567 this->writeWord(result, out); 1568 for (SpvId id : columnIds) { 1569 this->writeWord(id, out); 1570 } 1571 } 1572 return result; 1573} 1574 1575SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, SkWStream& out) { 1576 ASSERT(c.fType.kind() == Type::kVector_Kind); 1577 if (c.isConstant()) { 1578 return this->writeConstantVector(c); 1579 } 1580 // go ahead and write the arguments so we don't try to write new instructions in the middle of 1581 // an instruction 1582 std::vector<SpvId> arguments; 1583 for (size_t i = 0; i < c.fArguments.size(); i++) { 1584 arguments.push_back(this->writeExpression(*c.fArguments[i], out)); 1585 } 1586 SpvId result = this->nextId(); 1587 if (arguments.size() == 1 && c.fArguments[0]->fType.kind() == Type::kScalar_Kind) { 1588 this->writeOpCode(SpvOpCompositeConstruct, 3 + c.fType.columns(), out); 1589 this->writeWord(this->getType(c.fType), out); 1590 this->writeWord(result, out); 1591 for (int i = 0; i < c.fType.columns(); i++) { 1592 this->writeWord(arguments[0], out); 1593 } 1594 } else { 1595 this->writeOpCode(SpvOpCompositeConstruct, 3 + (int32_t) c.fArguments.size(), out); 1596 this->writeWord(this->getType(c.fType), out); 1597 this->writeWord(result, out); 1598 for (SpvId id : arguments) { 1599 this->writeWord(id, out); 1600 } 1601 } 1602 return result; 1603} 1604 1605SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, SkWStream& out) { 1606 if (c.fType == *fContext.fFloat_Type) { 1607 return this->writeFloatConstructor(c, out); 1608 } else if (c.fType == *fContext.fInt_Type) { 1609 return this->writeIntConstructor(c, out); 1610 } 1611 switch (c.fType.kind()) { 1612 case Type::kVector_Kind: 1613 return this->writeVectorConstructor(c, out); 1614 case Type::kMatrix_Kind: 1615 return this->writeMatrixConstructor(c, out); 1616 default: 1617 ABORT("unsupported constructor: %s", c.description().c_str()); 1618 } 1619} 1620 1621SpvStorageClass_ get_storage_class(const Modifiers& modifiers) { 1622 if (modifiers.fFlags & Modifiers::kIn_Flag) { 1623 ASSERT(!modifiers.fLayout.fPushConstant); 1624 return SpvStorageClassInput; 1625 } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 1626 ASSERT(!modifiers.fLayout.fPushConstant); 1627 return SpvStorageClassOutput; 1628 } else if (modifiers.fFlags & Modifiers::kUniform_Flag) { 1629 if (modifiers.fLayout.fPushConstant) { 1630 return SpvStorageClassPushConstant; 1631 } 1632 return SpvStorageClassUniform; 1633 } else { 1634 return SpvStorageClassFunction; 1635 } 1636} 1637 1638SpvStorageClass_ get_storage_class(const Expression& expr) { 1639 switch (expr.fKind) { 1640 case Expression::kVariableReference_Kind: 1641 return get_storage_class(((VariableReference&) expr).fVariable.fModifiers); 1642 case Expression::kFieldAccess_Kind: 1643 return get_storage_class(*((FieldAccess&) expr).fBase); 1644 case Expression::kIndex_Kind: 1645 return get_storage_class(*((IndexExpression&) expr).fBase); 1646 default: 1647 return SpvStorageClassFunction; 1648 } 1649} 1650 1651std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, SkWStream& out) { 1652 std::vector<SpvId> chain; 1653 switch (expr.fKind) { 1654 case Expression::kIndex_Kind: { 1655 IndexExpression& indexExpr = (IndexExpression&) expr; 1656 chain = this->getAccessChain(*indexExpr.fBase, out); 1657 chain.push_back(this->writeExpression(*indexExpr.fIndex, out)); 1658 break; 1659 } 1660 case Expression::kFieldAccess_Kind: { 1661 FieldAccess& fieldExpr = (FieldAccess&) expr; 1662 chain = this->getAccessChain(*fieldExpr.fBase, out); 1663 IntLiteral index(fContext, Position(), fieldExpr.fFieldIndex); 1664 chain.push_back(this->writeIntLiteral(index)); 1665 break; 1666 } 1667 default: 1668 chain.push_back(this->getLValue(expr, out)->getPointer()); 1669 } 1670 return chain; 1671} 1672 1673class PointerLValue : public SPIRVCodeGenerator::LValue { 1674public: 1675 PointerLValue(SPIRVCodeGenerator& gen, SpvId pointer, SpvId type) 1676 : fGen(gen) 1677 , fPointer(pointer) 1678 , fType(type) {} 1679 1680 virtual SpvId getPointer() override { 1681 return fPointer; 1682 } 1683 1684 virtual SpvId load(SkWStream& out) override { 1685 SpvId result = fGen.nextId(); 1686 fGen.writeInstruction(SpvOpLoad, fType, result, fPointer, out); 1687 return result; 1688 } 1689 1690 virtual void store(SpvId value, SkWStream& out) override { 1691 fGen.writeInstruction(SpvOpStore, fPointer, value, out); 1692 } 1693 1694private: 1695 SPIRVCodeGenerator& fGen; 1696 const SpvId fPointer; 1697 const SpvId fType; 1698}; 1699 1700class SwizzleLValue : public SPIRVCodeGenerator::LValue { 1701public: 1702 SwizzleLValue(SPIRVCodeGenerator& gen, SpvId vecPointer, const std::vector<int>& components, 1703 const Type& baseType, const Type& swizzleType) 1704 : fGen(gen) 1705 , fVecPointer(vecPointer) 1706 , fComponents(components) 1707 , fBaseType(baseType) 1708 , fSwizzleType(swizzleType) {} 1709 1710 virtual SpvId getPointer() override { 1711 return 0; 1712 } 1713 1714 virtual SpvId load(SkWStream& out) override { 1715 SpvId base = fGen.nextId(); 1716 fGen.writeInstruction(SpvOpLoad, fGen.getType(fBaseType), base, fVecPointer, out); 1717 SpvId result = fGen.nextId(); 1718 fGen.writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) fComponents.size(), out); 1719 fGen.writeWord(fGen.getType(fSwizzleType), out); 1720 fGen.writeWord(result, out); 1721 fGen.writeWord(base, out); 1722 fGen.writeWord(base, out); 1723 for (int component : fComponents) { 1724 fGen.writeWord(component, out); 1725 } 1726 return result; 1727 } 1728 1729 virtual void store(SpvId value, SkWStream& out) override { 1730 // use OpVectorShuffle to mix and match the vector components. We effectively create 1731 // a virtual vector out of the concatenation of the left and right vectors, and then 1732 // select components from this virtual vector to make the result vector. For 1733 // instance, given: 1734 // vec3 L = ...; 1735 // vec3 R = ...; 1736 // L.xz = R.xy; 1737 // we end up with the virtual vector (L.x, L.y, L.z, R.x, R.y, R.z). Then we want 1738 // our result vector to look like (R.x, L.y, R.y), so we need to select indices 1739 // (3, 1, 4). 1740 SpvId base = fGen.nextId(); 1741 fGen.writeInstruction(SpvOpLoad, fGen.getType(fBaseType), base, fVecPointer, out); 1742 SpvId shuffle = fGen.nextId(); 1743 fGen.writeOpCode(SpvOpVectorShuffle, 5 + fBaseType.columns(), out); 1744 fGen.writeWord(fGen.getType(fBaseType), out); 1745 fGen.writeWord(shuffle, out); 1746 fGen.writeWord(base, out); 1747 fGen.writeWord(value, out); 1748 for (int i = 0; i < fBaseType.columns(); i++) { 1749 // current offset into the virtual vector, defaults to pulling the unmodified 1750 // value from the left side 1751 int offset = i; 1752 // check to see if we are writing this component 1753 for (size_t j = 0; j < fComponents.size(); j++) { 1754 if (fComponents[j] == i) { 1755 // we're writing to this component, so adjust the offset to pull from 1756 // the correct component of the right side instead of preserving the 1757 // value from the left 1758 offset = (int) (j + fBaseType.columns()); 1759 break; 1760 } 1761 } 1762 fGen.writeWord(offset, out); 1763 } 1764 fGen.writeInstruction(SpvOpStore, fVecPointer, shuffle, out); 1765 } 1766 1767private: 1768 SPIRVCodeGenerator& fGen; 1769 const SpvId fVecPointer; 1770 const std::vector<int>& fComponents; 1771 const Type& fBaseType; 1772 const Type& fSwizzleType; 1773}; 1774 1775std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const Expression& expr, 1776 SkWStream& out) { 1777 switch (expr.fKind) { 1778 case Expression::kVariableReference_Kind: { 1779 const Variable& var = ((VariableReference&) expr).fVariable; 1780 auto entry = fVariableMap.find(&var); 1781 ASSERT(entry != fVariableMap.end()); 1782 return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1783 *this, 1784 entry->second, 1785 this->getType(expr.fType))); 1786 } 1787 case Expression::kIndex_Kind: // fall through 1788 case Expression::kFieldAccess_Kind: { 1789 std::vector<SpvId> chain = this->getAccessChain(expr, out); 1790 SpvId member = this->nextId(); 1791 this->writeOpCode(SpvOpAccessChain, (SpvId) (3 + chain.size()), out); 1792 this->writeWord(this->getPointerType(expr.fType, get_storage_class(expr)), out); 1793 this->writeWord(member, out); 1794 for (SpvId idx : chain) { 1795 this->writeWord(idx, out); 1796 } 1797 return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1798 *this, 1799 member, 1800 this->getType(expr.fType))); 1801 } 1802 1803 case Expression::kSwizzle_Kind: { 1804 Swizzle& swizzle = (Swizzle&) expr; 1805 size_t count = swizzle.fComponents.size(); 1806 SpvId base = this->getLValue(*swizzle.fBase, out)->getPointer(); 1807 ASSERT(base); 1808 if (count == 1) { 1809 IntLiteral index(fContext, Position(), swizzle.fComponents[0]); 1810 SpvId member = this->nextId(); 1811 this->writeInstruction(SpvOpAccessChain, 1812 this->getPointerType(swizzle.fType, 1813 get_storage_class(*swizzle.fBase)), 1814 member, 1815 base, 1816 this->writeIntLiteral(index), 1817 out); 1818 return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1819 *this, 1820 member, 1821 this->getType(expr.fType))); 1822 } else { 1823 return std::unique_ptr<SPIRVCodeGenerator::LValue>(new SwizzleLValue( 1824 *this, 1825 base, 1826 swizzle.fComponents, 1827 swizzle.fBase->fType, 1828 expr.fType)); 1829 } 1830 } 1831 1832 default: 1833 // expr isn't actually an lvalue, create a dummy variable for it. This case happens due 1834 // to the need to store values in temporary variables during function calls (see 1835 // comments in getFunctionType); erroneous uses of rvalues as lvalues should have been 1836 // caught by IRGenerator 1837 SpvId result = this->nextId(); 1838 SpvId type = this->getPointerType(expr.fType, SpvStorageClassFunction); 1839 this->writeInstruction(SpvOpVariable, type, result, SpvStorageClassFunction, 1840 fVariableBuffer); 1841 this->writeInstruction(SpvOpStore, result, this->writeExpression(expr, out), out); 1842 return std::unique_ptr<SPIRVCodeGenerator::LValue>(new PointerLValue( 1843 *this, 1844 result, 1845 this->getType(expr.fType))); 1846 } 1847} 1848 1849SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, SkWStream& out) { 1850 SpvId result = this->nextId(); 1851 auto entry = fVariableMap.find(&ref.fVariable); 1852 ASSERT(entry != fVariableMap.end()); 1853 SpvId var = entry->second; 1854 this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable.fType), result, var, out); 1855 if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN && 1856 fProgram.fSettings.fFlipY) { 1857 // need to remap to a top-left coordinate system 1858 if (fRTHeightStructId == (SpvId) -1) { 1859 // height variable hasn't been written yet 1860 std::shared_ptr<SymbolTable> st(new SymbolTable(fErrors)); 1861 ASSERT(fRTHeightFieldIndex == (SpvId) -1); 1862 std::vector<Type::Field> fields; 1863 fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), 1864 fContext.fFloat_Type.get()); 1865 SkString name("sksl_synthetic_uniforms"); 1866 Type intfStruct(Position(), name, fields); 1867 Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified, 1868 false); 1869 Variable intfVar(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name, 1870 intfStruct, Variable::kGlobal_Storage); 1871 InterfaceBlock intf(Position(), intfVar, st); 1872 fRTHeightStructId = this->writeInterfaceBlock(intf); 1873 fRTHeightFieldIndex = 0; 1874 } 1875 ASSERT(fRTHeightFieldIndex != (SpvId) -1); 1876 // write vec4(gl_FragCoord.x, u_skRTHeight - gl_FragCoord.y, 0.0, 1.0) 1877 SpvId xId = this->nextId(); 1878 this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId, 1879 result, 0, out); 1880 IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex); 1881 SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); 1882 SpvId heightPtr = this->nextId(); 1883 this->writeOpCode(SpvOpAccessChain, 5, out); 1884 this->writeWord(this->getPointerType(*fContext.fFloat_Type, SpvStorageClassUniform), out); 1885 this->writeWord(heightPtr, out); 1886 this->writeWord(fRTHeightStructId, out); 1887 this->writeWord(fieldIndexId, out); 1888 SpvId heightRead = this->nextId(); 1889 this->writeInstruction(SpvOpLoad, this->getType(*fContext.fFloat_Type), heightRead, 1890 heightPtr, out); 1891 SpvId rawYId = this->nextId(); 1892 this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), rawYId, 1893 result, 1, out); 1894 SpvId flippedYId = this->nextId(); 1895 this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId, 1896 heightRead, rawYId, out); 1897 FloatLiteral zero(fContext, Position(), 0.0); 1898 SpvId zeroId = writeFloatLiteral(zero); 1899 FloatLiteral one(fContext, Position(), 1.0); 1900 SpvId oneId = writeFloatLiteral(one); 1901 SpvId flipped = this->nextId(); 1902 this->writeOpCode(SpvOpCompositeConstruct, 7, out); 1903 this->writeWord(this->getType(*fContext.fVec4_Type), out); 1904 this->writeWord(flipped, out); 1905 this->writeWord(xId, out); 1906 this->writeWord(flippedYId, out); 1907 this->writeWord(zeroId, out); 1908 this->writeWord(oneId, out); 1909 return flipped; 1910 } 1911 return result; 1912} 1913 1914SpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, SkWStream& out) { 1915 return getLValue(expr, out)->load(out); 1916} 1917 1918SpvId SPIRVCodeGenerator::writeFieldAccess(const FieldAccess& f, SkWStream& out) { 1919 return getLValue(f, out)->load(out); 1920} 1921 1922SpvId SPIRVCodeGenerator::writeSwizzle(const Swizzle& swizzle, SkWStream& out) { 1923 SpvId base = this->writeExpression(*swizzle.fBase, out); 1924 SpvId result = this->nextId(); 1925 size_t count = swizzle.fComponents.size(); 1926 if (count == 1) { 1927 this->writeInstruction(SpvOpCompositeExtract, this->getType(swizzle.fType), result, base, 1928 swizzle.fComponents[0], out); 1929 } else { 1930 this->writeOpCode(SpvOpVectorShuffle, 5 + (int32_t) count, out); 1931 this->writeWord(this->getType(swizzle.fType), out); 1932 this->writeWord(result, out); 1933 this->writeWord(base, out); 1934 this->writeWord(base, out); 1935 for (int component : swizzle.fComponents) { 1936 this->writeWord(component, out); 1937 } 1938 } 1939 return result; 1940} 1941 1942SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType, 1943 const Type& operandType, SpvId lhs, 1944 SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, 1945 SpvOp_ ifUInt, SpvOp_ ifBool, SkWStream& out) { 1946 SpvId result = this->nextId(); 1947 if (is_float(fContext, operandType)) { 1948 this->writeInstruction(ifFloat, this->getType(resultType), result, lhs, rhs, out); 1949 } else if (is_signed(fContext, operandType)) { 1950 this->writeInstruction(ifInt, this->getType(resultType), result, lhs, rhs, out); 1951 } else if (is_unsigned(fContext, operandType)) { 1952 this->writeInstruction(ifUInt, this->getType(resultType), result, lhs, rhs, out); 1953 } else if (operandType == *fContext.fBool_Type) { 1954 this->writeInstruction(ifBool, this->getType(resultType), result, lhs, rhs, out); 1955 } else { 1956 ABORT("invalid operandType: %s", operandType.description().c_str()); 1957 } 1958 return result; 1959} 1960 1961bool is_assignment(Token::Kind op) { 1962 switch (op) { 1963 case Token::EQ: // fall through 1964 case Token::PLUSEQ: // fall through 1965 case Token::MINUSEQ: // fall through 1966 case Token::STAREQ: // fall through 1967 case Token::SLASHEQ: // fall through 1968 case Token::PERCENTEQ: // fall through 1969 case Token::SHLEQ: // fall through 1970 case Token::SHREQ: // fall through 1971 case Token::BITWISEOREQ: // fall through 1972 case Token::BITWISEXOREQ: // fall through 1973 case Token::BITWISEANDEQ: // fall through 1974 case Token::LOGICALOREQ: // fall through 1975 case Token::LOGICALXOREQ: // fall through 1976 case Token::LOGICALANDEQ: 1977 return true; 1978 default: 1979 return false; 1980 } 1981} 1982 1983SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, SkWStream& out) { 1984 // handle cases where we don't necessarily evaluate both LHS and RHS 1985 switch (b.fOperator) { 1986 case Token::EQ: { 1987 SpvId rhs = this->writeExpression(*b.fRight, out); 1988 this->getLValue(*b.fLeft, out)->store(rhs, out); 1989 return rhs; 1990 } 1991 case Token::LOGICALAND: 1992 return this->writeLogicalAnd(b, out); 1993 case Token::LOGICALOR: 1994 return this->writeLogicalOr(b, out); 1995 default: 1996 break; 1997 } 1998 1999 // "normal" operators 2000 const Type& resultType = b.fType; 2001 std::unique_ptr<LValue> lvalue; 2002 SpvId lhs; 2003 if (is_assignment(b.fOperator)) { 2004 lvalue = this->getLValue(*b.fLeft, out); 2005 lhs = lvalue->load(out); 2006 } else { 2007 lvalue = nullptr; 2008 lhs = this->writeExpression(*b.fLeft, out); 2009 } 2010 SpvId rhs = this->writeExpression(*b.fRight, out); 2011 // component type we are operating on: float, int, uint 2012 const Type* operandType; 2013 // IR allows mismatched types in expressions (e.g. vec2 * float), but they need special handling 2014 // in SPIR-V 2015 if (b.fLeft->fType != b.fRight->fType) { 2016 if (b.fLeft->fType.kind() == Type::kVector_Kind && 2017 b.fRight->fType.isNumber()) { 2018 // promote number to vector 2019 SpvId vec = this->nextId(); 2020 this->writeOpCode(SpvOpCompositeConstruct, 3 + b.fType.columns(), out); 2021 this->writeWord(this->getType(resultType), out); 2022 this->writeWord(vec, out); 2023 for (int i = 0; i < resultType.columns(); i++) { 2024 this->writeWord(rhs, out); 2025 } 2026 rhs = vec; 2027 operandType = &b.fRight->fType; 2028 } else if (b.fRight->fType.kind() == Type::kVector_Kind && 2029 b.fLeft->fType.isNumber()) { 2030 // promote number to vector 2031 SpvId vec = this->nextId(); 2032 this->writeOpCode(SpvOpCompositeConstruct, 3 + b.fType.columns(), out); 2033 this->writeWord(this->getType(resultType), out); 2034 this->writeWord(vec, out); 2035 for (int i = 0; i < resultType.columns(); i++) { 2036 this->writeWord(lhs, out); 2037 } 2038 lhs = vec; 2039 ASSERT(!lvalue); 2040 operandType = &b.fLeft->fType; 2041 } else if (b.fLeft->fType.kind() == Type::kMatrix_Kind) { 2042 SpvOp_ op; 2043 if (b.fRight->fType.kind() == Type::kMatrix_Kind) { 2044 op = SpvOpMatrixTimesMatrix; 2045 } else if (b.fRight->fType.kind() == Type::kVector_Kind) { 2046 op = SpvOpMatrixTimesVector; 2047 } else { 2048 ASSERT(b.fRight->fType.kind() == Type::kScalar_Kind); 2049 op = SpvOpMatrixTimesScalar; 2050 } 2051 SpvId result = this->nextId(); 2052 this->writeInstruction(op, this->getType(b.fType), result, lhs, rhs, out); 2053 if (b.fOperator == Token::STAREQ) { 2054 lvalue->store(result, out); 2055 } else { 2056 ASSERT(b.fOperator == Token::STAR); 2057 } 2058 return result; 2059 } else if (b.fRight->fType.kind() == Type::kMatrix_Kind) { 2060 SpvId result = this->nextId(); 2061 if (b.fLeft->fType.kind() == Type::kVector_Kind) { 2062 this->writeInstruction(SpvOpVectorTimesMatrix, this->getType(b.fType), result, 2063 lhs, rhs, out); 2064 } else { 2065 ASSERT(b.fLeft->fType.kind() == Type::kScalar_Kind); 2066 this->writeInstruction(SpvOpMatrixTimesScalar, this->getType(b.fType), result, rhs, 2067 lhs, out); 2068 } 2069 if (b.fOperator == Token::STAREQ) { 2070 lvalue->store(result, out); 2071 } else { 2072 ASSERT(b.fOperator == Token::STAR); 2073 } 2074 return result; 2075 } else { 2076 ABORT("unsupported binary expression: %s", b.description().c_str()); 2077 } 2078 } else { 2079 operandType = &b.fLeft->fType; 2080 ASSERT(*operandType == b.fRight->fType); 2081 } 2082 switch (b.fOperator) { 2083 case Token::EQEQ: 2084 ASSERT(resultType == *fContext.fBool_Type); 2085 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdEqual, 2086 SpvOpIEqual, SpvOpIEqual, SpvOpLogicalEqual, out); 2087 case Token::NEQ: 2088 ASSERT(resultType == *fContext.fBool_Type); 2089 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdNotEqual, 2090 SpvOpINotEqual, SpvOpINotEqual, SpvOpLogicalNotEqual, 2091 out); 2092 case Token::GT: 2093 ASSERT(resultType == *fContext.fBool_Type); 2094 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 2095 SpvOpFOrdGreaterThan, SpvOpSGreaterThan, 2096 SpvOpUGreaterThan, SpvOpUndef, out); 2097 case Token::LT: 2098 ASSERT(resultType == *fContext.fBool_Type); 2099 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFOrdLessThan, 2100 SpvOpSLessThan, SpvOpULessThan, SpvOpUndef, out); 2101 case Token::GTEQ: 2102 ASSERT(resultType == *fContext.fBool_Type); 2103 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 2104 SpvOpFOrdGreaterThanEqual, SpvOpSGreaterThanEqual, 2105 SpvOpUGreaterThanEqual, SpvOpUndef, out); 2106 case Token::LTEQ: 2107 ASSERT(resultType == *fContext.fBool_Type); 2108 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, 2109 SpvOpFOrdLessThanEqual, SpvOpSLessThanEqual, 2110 SpvOpULessThanEqual, SpvOpUndef, out); 2111 case Token::PLUS: 2112 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd, 2113 SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); 2114 case Token::MINUS: 2115 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub, 2116 SpvOpISub, SpvOpISub, SpvOpUndef, out); 2117 case Token::STAR: 2118 if (b.fLeft->fType.kind() == Type::kMatrix_Kind && 2119 b.fRight->fType.kind() == Type::kMatrix_Kind) { 2120 // matrix multiply 2121 SpvId result = this->nextId(); 2122 this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(resultType), result, 2123 lhs, rhs, out); 2124 return result; 2125 } 2126 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul, 2127 SpvOpIMul, SpvOpIMul, SpvOpUndef, out); 2128 case Token::SLASH: 2129 return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv, 2130 SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out); 2131 case Token::PLUSEQ: { 2132 SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFAdd, 2133 SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); 2134 ASSERT(lvalue); 2135 lvalue->store(result, out); 2136 return result; 2137 } 2138 case Token::MINUSEQ: { 2139 SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFSub, 2140 SpvOpISub, SpvOpISub, SpvOpUndef, out); 2141 ASSERT(lvalue); 2142 lvalue->store(result, out); 2143 return result; 2144 } 2145 case Token::STAREQ: { 2146 if (b.fLeft->fType.kind() == Type::kMatrix_Kind && 2147 b.fRight->fType.kind() == Type::kMatrix_Kind) { 2148 // matrix multiply 2149 SpvId result = this->nextId(); 2150 this->writeInstruction(SpvOpMatrixTimesMatrix, this->getType(resultType), result, 2151 lhs, rhs, out); 2152 ASSERT(lvalue); 2153 lvalue->store(result, out); 2154 return result; 2155 } 2156 SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFMul, 2157 SpvOpIMul, SpvOpIMul, SpvOpUndef, out); 2158 ASSERT(lvalue); 2159 lvalue->store(result, out); 2160 return result; 2161 } 2162 case Token::SLASHEQ: { 2163 SpvId result = this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpFDiv, 2164 SpvOpSDiv, SpvOpUDiv, SpvOpUndef, out); 2165 ASSERT(lvalue); 2166 lvalue->store(result, out); 2167 return result; 2168 } 2169 default: 2170 // FIXME: missing support for some operators (bitwise, &&=, ||=, shift...) 2171 ABORT("unsupported binary expression: %s", b.description().c_str()); 2172 } 2173} 2174 2175SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, SkWStream& out) { 2176 ASSERT(a.fOperator == Token::LOGICALAND); 2177 BoolLiteral falseLiteral(fContext, Position(), false); 2178 SpvId falseConstant = this->writeBoolLiteral(falseLiteral); 2179 SpvId lhs = this->writeExpression(*a.fLeft, out); 2180 SpvId rhsLabel = this->nextId(); 2181 SpvId end = this->nextId(); 2182 SpvId lhsBlock = fCurrentBlock; 2183 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2184 this->writeInstruction(SpvOpBranchConditional, lhs, rhsLabel, end, out); 2185 this->writeLabel(rhsLabel, out); 2186 SpvId rhs = this->writeExpression(*a.fRight, out); 2187 SpvId rhsBlock = fCurrentBlock; 2188 this->writeInstruction(SpvOpBranch, end, out); 2189 this->writeLabel(end, out); 2190 SpvId result = this->nextId(); 2191 this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, falseConstant, 2192 lhsBlock, rhs, rhsBlock, out); 2193 return result; 2194} 2195 2196SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, SkWStream& out) { 2197 ASSERT(o.fOperator == Token::LOGICALOR); 2198 BoolLiteral trueLiteral(fContext, Position(), true); 2199 SpvId trueConstant = this->writeBoolLiteral(trueLiteral); 2200 SpvId lhs = this->writeExpression(*o.fLeft, out); 2201 SpvId rhsLabel = this->nextId(); 2202 SpvId end = this->nextId(); 2203 SpvId lhsBlock = fCurrentBlock; 2204 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2205 this->writeInstruction(SpvOpBranchConditional, lhs, end, rhsLabel, out); 2206 this->writeLabel(rhsLabel, out); 2207 SpvId rhs = this->writeExpression(*o.fRight, out); 2208 SpvId rhsBlock = fCurrentBlock; 2209 this->writeInstruction(SpvOpBranch, end, out); 2210 this->writeLabel(end, out); 2211 SpvId result = this->nextId(); 2212 this->writeInstruction(SpvOpPhi, this->getType(*fContext.fBool_Type), result, trueConstant, 2213 lhsBlock, rhs, rhsBlock, out); 2214 return result; 2215} 2216 2217SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, SkWStream& out) { 2218 SpvId test = this->writeExpression(*t.fTest, out); 2219 if (t.fIfTrue->isConstant() && t.fIfFalse->isConstant()) { 2220 // both true and false are constants, can just use OpSelect 2221 SpvId result = this->nextId(); 2222 SpvId trueId = this->writeExpression(*t.fIfTrue, out); 2223 SpvId falseId = this->writeExpression(*t.fIfFalse, out); 2224 this->writeInstruction(SpvOpSelect, this->getType(t.fType), result, test, trueId, falseId, 2225 out); 2226 return result; 2227 } 2228 // was originally using OpPhi to choose the result, but for some reason that is crashing on 2229 // Adreno. Switched to storing the result in a temp variable as glslang does. 2230 SpvId var = this->nextId(); 2231 this->writeInstruction(SpvOpVariable, this->getPointerType(t.fType, SpvStorageClassFunction), 2232 var, SpvStorageClassFunction, fVariableBuffer); 2233 SpvId trueLabel = this->nextId(); 2234 SpvId falseLabel = this->nextId(); 2235 SpvId end = this->nextId(); 2236 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2237 this->writeInstruction(SpvOpBranchConditional, test, trueLabel, falseLabel, out); 2238 this->writeLabel(trueLabel, out); 2239 this->writeInstruction(SpvOpStore, var, this->writeExpression(*t.fIfTrue, out), out); 2240 this->writeInstruction(SpvOpBranch, end, out); 2241 this->writeLabel(falseLabel, out); 2242 this->writeInstruction(SpvOpStore, var, this->writeExpression(*t.fIfFalse, out), out); 2243 this->writeInstruction(SpvOpBranch, end, out); 2244 this->writeLabel(end, out); 2245 SpvId result = this->nextId(); 2246 this->writeInstruction(SpvOpLoad, this->getType(t.fType), result, var, out); 2247 return result; 2248} 2249 2250std::unique_ptr<Expression> create_literal_1(const Context& context, const Type& type) { 2251 if (type == *context.fInt_Type) { 2252 return std::unique_ptr<Expression>(new IntLiteral(context, Position(), 1)); 2253 } 2254 else if (type == *context.fFloat_Type) { 2255 return std::unique_ptr<Expression>(new FloatLiteral(context, Position(), 1.0)); 2256 } else { 2257 ABORT("math is unsupported on type '%s'") 2258 } 2259} 2260 2261SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, SkWStream& out) { 2262 if (p.fOperator == Token::MINUS) { 2263 SpvId result = this->nextId(); 2264 SpvId typeId = this->getType(p.fType); 2265 SpvId expr = this->writeExpression(*p.fOperand, out); 2266 if (is_float(fContext, p.fType)) { 2267 this->writeInstruction(SpvOpFNegate, typeId, result, expr, out); 2268 } else if (is_signed(fContext, p.fType)) { 2269 this->writeInstruction(SpvOpSNegate, typeId, result, expr, out); 2270 } else { 2271 ABORT("unsupported prefix expression %s", p.description().c_str()); 2272 }; 2273 return result; 2274 } 2275 switch (p.fOperator) { 2276 case Token::PLUS: 2277 return this->writeExpression(*p.fOperand, out); 2278 case Token::PLUSPLUS: { 2279 std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out); 2280 SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); 2281 SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one, 2282 SpvOpFAdd, SpvOpIAdd, SpvOpIAdd, SpvOpUndef, 2283 out); 2284 lv->store(result, out); 2285 return result; 2286 } 2287 case Token::MINUSMINUS: { 2288 std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out); 2289 SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); 2290 SpvId result = this->writeBinaryOperation(p.fType, p.fType, lv->load(out), one, 2291 SpvOpFSub, SpvOpISub, SpvOpISub, SpvOpUndef, 2292 out); 2293 lv->store(result, out); 2294 return result; 2295 } 2296 case Token::LOGICALNOT: { 2297 ASSERT(p.fOperand->fType == *fContext.fBool_Type); 2298 SpvId result = this->nextId(); 2299 this->writeInstruction(SpvOpLogicalNot, this->getType(p.fOperand->fType), result, 2300 this->writeExpression(*p.fOperand, out), out); 2301 return result; 2302 } 2303 case Token::BITWISENOT: { 2304 SpvId result = this->nextId(); 2305 this->writeInstruction(SpvOpNot, this->getType(p.fOperand->fType), result, 2306 this->writeExpression(*p.fOperand, out), out); 2307 return result; 2308 } 2309 default: 2310 ABORT("unsupported prefix expression: %s", p.description().c_str()); 2311 } 2312} 2313 2314SpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, SkWStream& out) { 2315 std::unique_ptr<LValue> lv = this->getLValue(*p.fOperand, out); 2316 SpvId result = lv->load(out); 2317 SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); 2318 switch (p.fOperator) { 2319 case Token::PLUSPLUS: { 2320 SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFAdd, 2321 SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out); 2322 lv->store(temp, out); 2323 return result; 2324 } 2325 case Token::MINUSMINUS: { 2326 SpvId temp = this->writeBinaryOperation(p.fType, p.fType, result, one, SpvOpFSub, 2327 SpvOpISub, SpvOpISub, SpvOpUndef, out); 2328 lv->store(temp, out); 2329 return result; 2330 } 2331 default: 2332 ABORT("unsupported postfix expression %s", p.description().c_str()); 2333 } 2334} 2335 2336SpvId SPIRVCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 2337 if (b.fValue) { 2338 if (fBoolTrue == 0) { 2339 fBoolTrue = this->nextId(); 2340 this->writeInstruction(SpvOpConstantTrue, this->getType(b.fType), fBoolTrue, 2341 fConstantBuffer); 2342 } 2343 return fBoolTrue; 2344 } else { 2345 if (fBoolFalse == 0) { 2346 fBoolFalse = this->nextId(); 2347 this->writeInstruction(SpvOpConstantFalse, this->getType(b.fType), fBoolFalse, 2348 fConstantBuffer); 2349 } 2350 return fBoolFalse; 2351 } 2352} 2353 2354SpvId SPIRVCodeGenerator::writeIntLiteral(const IntLiteral& i) { 2355 if (i.fType == *fContext.fInt_Type) { 2356 auto entry = fIntConstants.find(i.fValue); 2357 if (entry == fIntConstants.end()) { 2358 SpvId result = this->nextId(); 2359 this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue, 2360 fConstantBuffer); 2361 fIntConstants[i.fValue] = result; 2362 return result; 2363 } 2364 return entry->second; 2365 } else { 2366 ASSERT(i.fType == *fContext.fUInt_Type); 2367 auto entry = fUIntConstants.find(i.fValue); 2368 if (entry == fUIntConstants.end()) { 2369 SpvId result = this->nextId(); 2370 this->writeInstruction(SpvOpConstant, this->getType(i.fType), result, (SpvId) i.fValue, 2371 fConstantBuffer); 2372 fUIntConstants[i.fValue] = result; 2373 return result; 2374 } 2375 return entry->second; 2376 } 2377} 2378 2379SpvId SPIRVCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 2380 if (f.fType == *fContext.fFloat_Type) { 2381 float value = (float) f.fValue; 2382 auto entry = fFloatConstants.find(value); 2383 if (entry == fFloatConstants.end()) { 2384 SpvId result = this->nextId(); 2385 uint32_t bits; 2386 ASSERT(sizeof(bits) == sizeof(value)); 2387 memcpy(&bits, &value, sizeof(bits)); 2388 this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, bits, 2389 fConstantBuffer); 2390 fFloatConstants[value] = result; 2391 return result; 2392 } 2393 return entry->second; 2394 } else { 2395 ASSERT(f.fType == *fContext.fDouble_Type); 2396 auto entry = fDoubleConstants.find(f.fValue); 2397 if (entry == fDoubleConstants.end()) { 2398 SpvId result = this->nextId(); 2399 uint64_t bits; 2400 ASSERT(sizeof(bits) == sizeof(f.fValue)); 2401 memcpy(&bits, &f.fValue, sizeof(bits)); 2402 this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, 2403 bits & 0xffffffff, bits >> 32, fConstantBuffer); 2404 fDoubleConstants[f.fValue] = result; 2405 return result; 2406 } 2407 return entry->second; 2408 } 2409} 2410 2411SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, SkWStream& out) { 2412 SpvId result = fFunctionMap[&f]; 2413 this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result, 2414 SpvFunctionControlMaskNone, this->getFunctionType(f), out); 2415 this->writeInstruction(SpvOpName, result, f.fName.c_str(), fNameBuffer); 2416 for (size_t i = 0; i < f.fParameters.size(); i++) { 2417 SpvId id = this->nextId(); 2418 fVariableMap[f.fParameters[i]] = id; 2419 SpvId type; 2420 type = this->getPointerType(f.fParameters[i]->fType, SpvStorageClassFunction); 2421 this->writeInstruction(SpvOpFunctionParameter, type, id, out); 2422 } 2423 return result; 2424} 2425 2426SpvId SPIRVCodeGenerator::writeFunction(const FunctionDefinition& f, SkWStream& out) { 2427 SpvId result = this->writeFunctionStart(f.fDeclaration, out); 2428 this->writeLabel(this->nextId(), out); 2429 if (f.fDeclaration.fName == "main") { 2430 write_data(*fGlobalInitializersBuffer.detachAsData(), out); 2431 } 2432 SkDynamicMemoryWStream bodyBuffer; 2433 this->writeBlock(*f.fBody, bodyBuffer); 2434 write_data(*fVariableBuffer.detachAsData(), out); 2435 write_data(*bodyBuffer.detachAsData(), out); 2436 if (fCurrentBlock) { 2437 this->writeInstruction(SpvOpReturn, out); 2438 } 2439 this->writeInstruction(SpvOpFunctionEnd, out); 2440 return result; 2441} 2442 2443void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target) { 2444 if (layout.fLocation >= 0) { 2445 this->writeInstruction(SpvOpDecorate, target, SpvDecorationLocation, layout.fLocation, 2446 fDecorationBuffer); 2447 } 2448 if (layout.fBinding >= 0) { 2449 this->writeInstruction(SpvOpDecorate, target, SpvDecorationBinding, layout.fBinding, 2450 fDecorationBuffer); 2451 } 2452 if (layout.fIndex >= 0) { 2453 this->writeInstruction(SpvOpDecorate, target, SpvDecorationIndex, layout.fIndex, 2454 fDecorationBuffer); 2455 } 2456 if (layout.fSet >= 0) { 2457 this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet, 2458 fDecorationBuffer); 2459 } 2460 if (layout.fInputAttachmentIndex >= 0) { 2461 this->writeInstruction(SpvOpDecorate, target, SpvDecorationInputAttachmentIndex, 2462 layout.fInputAttachmentIndex, fDecorationBuffer); 2463 } 2464 if (layout.fBuiltin >= 0 && layout.fBuiltin != SK_FRAGCOLOR_BUILTIN) { 2465 this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin, 2466 fDecorationBuffer); 2467 } 2468} 2469 2470void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, int member) { 2471 if (layout.fLocation >= 0) { 2472 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationLocation, 2473 layout.fLocation, fDecorationBuffer); 2474 } 2475 if (layout.fBinding >= 0) { 2476 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBinding, 2477 layout.fBinding, fDecorationBuffer); 2478 } 2479 if (layout.fIndex >= 0) { 2480 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationIndex, 2481 layout.fIndex, fDecorationBuffer); 2482 } 2483 if (layout.fSet >= 0) { 2484 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationDescriptorSet, 2485 layout.fSet, fDecorationBuffer); 2486 } 2487 if (layout.fInputAttachmentIndex >= 0) { 2488 this->writeInstruction(SpvOpDecorate, target, member, SpvDecorationInputAttachmentIndex, 2489 layout.fInputAttachmentIndex, fDecorationBuffer); 2490 } 2491 if (layout.fBuiltin >= 0) { 2492 this->writeInstruction(SpvOpMemberDecorate, target, member, SpvDecorationBuiltIn, 2493 layout.fBuiltin, fDecorationBuffer); 2494 } 2495} 2496 2497SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 2498 MemoryLayout layout = intf.fVariable.fModifiers.fLayout.fPushConstant ? 2499 MemoryLayout(MemoryLayout::k430_Standard) : 2500 fDefaultLayout; 2501 SpvId result = this->nextId(); 2502 const Type* type = &intf.fVariable.fType; 2503 if (fProgram.fInputs.fRTHeight) { 2504 ASSERT(fRTHeightStructId == (SpvId) -1); 2505 ASSERT(fRTHeightFieldIndex == (SpvId) -1); 2506 std::vector<Type::Field> fields = type->fields(); 2507 fRTHeightStructId = result; 2508 fRTHeightFieldIndex = fields.size(); 2509 fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get()); 2510 type = new Type(type->fPosition, type->name(), fields); 2511 } 2512 SpvId typeId = this->getType(*type, layout); 2513 this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer); 2514 SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers); 2515 SpvId ptrType = this->nextId(); 2516 this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, typeId, fConstantBuffer); 2517 this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConstantBuffer); 2518 this->writeLayout(intf.fVariable.fModifiers.fLayout, result); 2519 fVariableMap[&intf.fVariable] = result; 2520 return result; 2521} 2522 2523#define BUILTIN_IGNORE 9999 2524void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl, 2525 SkWStream& out) { 2526 for (size_t i = 0; i < decl.fVars.size(); i++) { 2527 const VarDeclaration& varDecl = decl.fVars[i]; 2528 const Variable* var = varDecl.fVar; 2529 // These haven't been implemented in our SPIR-V generator yet and we only currently use them 2530 // in the OpenGL backend. 2531 ASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag | 2532 Modifiers::kWriteOnly_Flag | 2533 Modifiers::kCoherent_Flag | 2534 Modifiers::kVolatile_Flag | 2535 Modifiers::kRestrict_Flag))); 2536 if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) { 2537 continue; 2538 } 2539 if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN && 2540 kind != Program::kFragment_Kind) { 2541 continue; 2542 } 2543 if (!var->fIsReadFrom && !var->fIsWrittenTo && 2544 !(var->fModifiers.fFlags & (Modifiers::kIn_Flag | 2545 Modifiers::kOut_Flag | 2546 Modifiers::kUniform_Flag))) { 2547 // variable is dead and not an input / output var (the Vulkan debug layers complain if 2548 // we elide an interface var, even if it's dead) 2549 continue; 2550 } 2551 SpvStorageClass_ storageClass; 2552 if (var->fModifiers.fFlags & Modifiers::kIn_Flag) { 2553 storageClass = SpvStorageClassInput; 2554 } else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) { 2555 storageClass = SpvStorageClassOutput; 2556 } else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) { 2557 if (var->fType.kind() == Type::kSampler_Kind) { 2558 storageClass = SpvStorageClassUniformConstant; 2559 } else { 2560 storageClass = SpvStorageClassUniform; 2561 } 2562 } else { 2563 storageClass = SpvStorageClassPrivate; 2564 } 2565 SpvId id = this->nextId(); 2566 fVariableMap[var] = id; 2567 SpvId type = this->getPointerType(var->fType, storageClass); 2568 this->writeInstruction(SpvOpVariable, type, id, storageClass, fConstantBuffer); 2569 this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); 2570 if (var->fType.kind() == Type::kMatrix_Kind) { 2571 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationColMajor, 2572 fDecorationBuffer); 2573 this->writeInstruction(SpvOpMemberDecorate, id, (SpvId) i, SpvDecorationMatrixStride, 2574 (SpvId) fDefaultLayout.stride(var->fType), fDecorationBuffer); 2575 } 2576 if (varDecl.fValue) { 2577 ASSERT(!fCurrentBlock); 2578 fCurrentBlock = -1; 2579 SpvId value = this->writeExpression(*varDecl.fValue, fGlobalInitializersBuffer); 2580 this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer); 2581 fCurrentBlock = 0; 2582 } 2583 this->writeLayout(var->fModifiers.fLayout, id); 2584 } 2585} 2586 2587void SPIRVCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, SkWStream& out) { 2588 for (const auto& varDecl : decl.fVars) { 2589 const Variable* var = varDecl.fVar; 2590 // These haven't been implemented in our SPIR-V generator yet and we only currently use them 2591 // in the OpenGL backend. 2592 ASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag | 2593 Modifiers::kWriteOnly_Flag | 2594 Modifiers::kCoherent_Flag | 2595 Modifiers::kVolatile_Flag | 2596 Modifiers::kRestrict_Flag))); 2597 SpvId id = this->nextId(); 2598 fVariableMap[var] = id; 2599 SpvId type = this->getPointerType(var->fType, SpvStorageClassFunction); 2600 this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer); 2601 this->writeInstruction(SpvOpName, id, var->fName.c_str(), fNameBuffer); 2602 if (varDecl.fValue) { 2603 SpvId value = this->writeExpression(*varDecl.fValue, out); 2604 this->writeInstruction(SpvOpStore, id, value, out); 2605 } 2606 } 2607} 2608 2609void SPIRVCodeGenerator::writeStatement(const Statement& s, SkWStream& out) { 2610 switch (s.fKind) { 2611 case Statement::kBlock_Kind: 2612 this->writeBlock((Block&) s, out); 2613 break; 2614 case Statement::kExpression_Kind: 2615 this->writeExpression(*((ExpressionStatement&) s).fExpression, out); 2616 break; 2617 case Statement::kReturn_Kind: 2618 this->writeReturnStatement((ReturnStatement&) s, out); 2619 break; 2620 case Statement::kVarDeclarations_Kind: 2621 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, out); 2622 break; 2623 case Statement::kIf_Kind: 2624 this->writeIfStatement((IfStatement&) s, out); 2625 break; 2626 case Statement::kFor_Kind: 2627 this->writeForStatement((ForStatement&) s, out); 2628 break; 2629 case Statement::kWhile_Kind: 2630 this->writeWhileStatement((WhileStatement&) s, out); 2631 break; 2632 case Statement::kDo_Kind: 2633 this->writeDoStatement((DoStatement&) s, out); 2634 break; 2635 case Statement::kBreak_Kind: 2636 this->writeInstruction(SpvOpBranch, fBreakTarget.top(), out); 2637 break; 2638 case Statement::kContinue_Kind: 2639 this->writeInstruction(SpvOpBranch, fContinueTarget.top(), out); 2640 break; 2641 case Statement::kDiscard_Kind: 2642 this->writeInstruction(SpvOpKill, out); 2643 break; 2644 default: 2645 ABORT("unsupported statement: %s", s.description().c_str()); 2646 } 2647} 2648 2649void SPIRVCodeGenerator::writeBlock(const Block& b, SkWStream& out) { 2650 for (size_t i = 0; i < b.fStatements.size(); i++) { 2651 this->writeStatement(*b.fStatements[i], out); 2652 } 2653} 2654 2655void SPIRVCodeGenerator::writeIfStatement(const IfStatement& stmt, SkWStream& out) { 2656 SpvId test = this->writeExpression(*stmt.fTest, out); 2657 SpvId ifTrue = this->nextId(); 2658 SpvId ifFalse = this->nextId(); 2659 if (stmt.fIfFalse) { 2660 SpvId end = this->nextId(); 2661 this->writeInstruction(SpvOpSelectionMerge, end, SpvSelectionControlMaskNone, out); 2662 this->writeInstruction(SpvOpBranchConditional, test, ifTrue, ifFalse, out); 2663 this->writeLabel(ifTrue, out); 2664 this->writeStatement(*stmt.fIfTrue, out); 2665 if (fCurrentBlock) { 2666 this->writeInstruction(SpvOpBranch, end, out); 2667 } 2668 this->writeLabel(ifFalse, out); 2669 this->writeStatement(*stmt.fIfFalse, out); 2670 if (fCurrentBlock) { 2671 this->writeInstruction(SpvOpBranch, end, out); 2672 } 2673 this->writeLabel(end, out); 2674 } else { 2675 this->writeInstruction(SpvOpSelectionMerge, ifFalse, SpvSelectionControlMaskNone, out); 2676 this->writeInstruction(SpvOpBranchConditional, test, ifTrue, ifFalse, out); 2677 this->writeLabel(ifTrue, out); 2678 this->writeStatement(*stmt.fIfTrue, out); 2679 if (fCurrentBlock) { 2680 this->writeInstruction(SpvOpBranch, ifFalse, out); 2681 } 2682 this->writeLabel(ifFalse, out); 2683 } 2684} 2685 2686void SPIRVCodeGenerator::writeForStatement(const ForStatement& f, SkWStream& out) { 2687 if (f.fInitializer) { 2688 this->writeStatement(*f.fInitializer, out); 2689 } 2690 SpvId header = this->nextId(); 2691 SpvId start = this->nextId(); 2692 SpvId body = this->nextId(); 2693 SpvId next = this->nextId(); 2694 fContinueTarget.push(next); 2695 SpvId end = this->nextId(); 2696 fBreakTarget.push(end); 2697 this->writeInstruction(SpvOpBranch, header, out); 2698 this->writeLabel(header, out); 2699 this->writeInstruction(SpvOpLoopMerge, end, next, SpvLoopControlMaskNone, out); 2700 this->writeInstruction(SpvOpBranch, start, out); 2701 this->writeLabel(start, out); 2702 if (f.fTest) { 2703 SpvId test = this->writeExpression(*f.fTest, out); 2704 this->writeInstruction(SpvOpBranchConditional, test, body, end, out); 2705 } 2706 this->writeLabel(body, out); 2707 this->writeStatement(*f.fStatement, out); 2708 if (fCurrentBlock) { 2709 this->writeInstruction(SpvOpBranch, next, out); 2710 } 2711 this->writeLabel(next, out); 2712 if (f.fNext) { 2713 this->writeExpression(*f.fNext, out); 2714 } 2715 this->writeInstruction(SpvOpBranch, header, out); 2716 this->writeLabel(end, out); 2717 fBreakTarget.pop(); 2718 fContinueTarget.pop(); 2719} 2720 2721void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, SkWStream& out) { 2722 // We believe the while loop code below will work, but Skia doesn't actually use them and 2723 // adequately testing this code in the absence of Skia exercising it isn't straightforward. For 2724 // the time being, we just fail with an error due to the lack of testing. If you encounter this 2725 // message, simply remove the error call below to see whether our while loop support actually 2726 // works. 2727 fErrors.error(w.fPosition, "internal error: while loop support has been disabled in SPIR-V, " 2728 "see SkSLSPIRVCodeGenerator.cpp for details"); 2729 2730 SpvId header = this->nextId(); 2731 SpvId start = this->nextId(); 2732 SpvId body = this->nextId(); 2733 fContinueTarget.push(start); 2734 SpvId end = this->nextId(); 2735 fBreakTarget.push(end); 2736 this->writeInstruction(SpvOpBranch, header, out); 2737 this->writeLabel(header, out); 2738 this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out); 2739 this->writeInstruction(SpvOpBranch, start, out); 2740 this->writeLabel(start, out); 2741 SpvId test = this->writeExpression(*w.fTest, out); 2742 this->writeInstruction(SpvOpBranchConditional, test, body, end, out); 2743 this->writeLabel(body, out); 2744 this->writeStatement(*w.fStatement, out); 2745 if (fCurrentBlock) { 2746 this->writeInstruction(SpvOpBranch, start, out); 2747 } 2748 this->writeLabel(end, out); 2749 fBreakTarget.pop(); 2750 fContinueTarget.pop(); 2751} 2752 2753void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, SkWStream& out) { 2754 // We believe the do loop code below will work, but Skia doesn't actually use them and 2755 // adequately testing this code in the absence of Skia exercising it isn't straightforward. For 2756 // the time being, we just fail with an error due to the lack of testing. If you encounter this 2757 // message, simply remove the error call below to see whether our do loop support actually 2758 // works. 2759 fErrors.error(d.fPosition, "internal error: do loop support has been disabled in SPIR-V, see " 2760 "SkSLSPIRVCodeGenerator.cpp for details"); 2761 2762 SpvId header = this->nextId(); 2763 SpvId start = this->nextId(); 2764 SpvId next = this->nextId(); 2765 fContinueTarget.push(next); 2766 SpvId end = this->nextId(); 2767 fBreakTarget.push(end); 2768 this->writeInstruction(SpvOpBranch, header, out); 2769 this->writeLabel(header, out); 2770 this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out); 2771 this->writeInstruction(SpvOpBranch, start, out); 2772 this->writeLabel(start, out); 2773 this->writeStatement(*d.fStatement, out); 2774 if (fCurrentBlock) { 2775 this->writeInstruction(SpvOpBranch, next, out); 2776 } 2777 this->writeLabel(next, out); 2778 SpvId test = this->writeExpression(*d.fTest, out); 2779 this->writeInstruction(SpvOpBranchConditional, test, start, end, out); 2780 this->writeLabel(end, out); 2781 fBreakTarget.pop(); 2782 fContinueTarget.pop(); 2783} 2784 2785void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, SkWStream& out) { 2786 if (r.fExpression) { 2787 this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpression, out), 2788 out); 2789 } else { 2790 this->writeInstruction(SpvOpReturn, out); 2791 } 2792} 2793 2794void SPIRVCodeGenerator::writeInstructions(const Program& program, SkWStream& out) { 2795 fGLSLExtendedInstructions = this->nextId(); 2796 SkDynamicMemoryWStream body; 2797 std::vector<SpvId> interfaceVars; 2798 // assign IDs to functions 2799 for (size_t i = 0; i < program.fElements.size(); i++) { 2800 if (program.fElements[i]->fKind == ProgramElement::kFunction_Kind) { 2801 FunctionDefinition& f = (FunctionDefinition&) *program.fElements[i]; 2802 fFunctionMap[&f.fDeclaration] = this->nextId(); 2803 } 2804 } 2805 for (size_t i = 0; i < program.fElements.size(); i++) { 2806 if (program.fElements[i]->fKind == ProgramElement::kInterfaceBlock_Kind) { 2807 InterfaceBlock& intf = (InterfaceBlock&) *program.fElements[i]; 2808 SpvId id = this->writeInterfaceBlock(intf); 2809 if ((intf.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) || 2810 (intf.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) { 2811 interfaceVars.push_back(id); 2812 } 2813 } 2814 } 2815 for (size_t i = 0; i < program.fElements.size(); i++) { 2816 if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) { 2817 this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]), 2818 body); 2819 } 2820 } 2821 for (size_t i = 0; i < program.fElements.size(); i++) { 2822 if (program.fElements[i]->fKind == ProgramElement::kFunction_Kind) { 2823 this->writeFunction(((FunctionDefinition&) *program.fElements[i]), body); 2824 } 2825 } 2826 const FunctionDeclaration* main = nullptr; 2827 for (auto entry : fFunctionMap) { 2828 if (entry.first->fName == "main") { 2829 main = entry.first; 2830 } 2831 } 2832 ASSERT(main); 2833 for (auto entry : fVariableMap) { 2834 const Variable* var = entry.first; 2835 if (var->fStorage == Variable::kGlobal_Storage && 2836 ((var->fModifiers.fFlags & Modifiers::kIn_Flag) || 2837 (var->fModifiers.fFlags & Modifiers::kOut_Flag))) { 2838 interfaceVars.push_back(entry.second); 2839 } 2840 } 2841 this->writeCapabilities(out); 2842 this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out); 2843 this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out); 2844 this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (strlen(main->fName.c_str()) + 4) / 4) + 2845 (int32_t) interfaceVars.size(), out); 2846 switch (program.fKind) { 2847 case Program::kVertex_Kind: 2848 this->writeWord(SpvExecutionModelVertex, out); 2849 break; 2850 case Program::kFragment_Kind: 2851 this->writeWord(SpvExecutionModelFragment, out); 2852 break; 2853 } 2854 this->writeWord(fFunctionMap[main], out); 2855 this->writeString(main->fName.c_str(), out); 2856 for (int var : interfaceVars) { 2857 this->writeWord(var, out); 2858 } 2859 if (program.fKind == Program::kFragment_Kind) { 2860 this->writeInstruction(SpvOpExecutionMode, 2861 fFunctionMap[main], 2862 SpvExecutionModeOriginUpperLeft, 2863 out); 2864 } 2865 for (size_t i = 0; i < program.fElements.size(); i++) { 2866 if (program.fElements[i]->fKind == ProgramElement::kExtension_Kind) { 2867 this->writeInstruction(SpvOpSourceExtension, 2868 ((Extension&) *program.fElements[i]).fName.c_str(), 2869 out); 2870 } 2871 } 2872 2873 write_data(*fExtraGlobalsBuffer.detachAsData(), out); 2874 write_data(*fNameBuffer.detachAsData(), out); 2875 write_data(*fDecorationBuffer.detachAsData(), out); 2876 write_data(*fConstantBuffer.detachAsData(), out); 2877 write_data(*fExternalFunctionsBuffer.detachAsData(), out); 2878 write_data(*body.detachAsData(), out); 2879} 2880 2881bool SPIRVCodeGenerator::generateCode() { 2882 ASSERT(!fErrors.errorCount()); 2883 this->writeWord(SpvMagicNumber, *fOut); 2884 this->writeWord(SpvVersion, *fOut); 2885 this->writeWord(SKSL_MAGIC, *fOut); 2886 SkDynamicMemoryWStream buffer; 2887 this->writeInstructions(fProgram, buffer); 2888 this->writeWord(fIdCount, *fOut); 2889 this->writeWord(0, *fOut); // reserved, always zero 2890 write_data(*buffer.detachAsData(), *fOut); 2891 return 0 == fErrors.errorCount(); 2892} 2893 2894} 2895