1 /* 2 * Copyright 2019 Google LLC 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 #ifndef SkVM_DEFINED 9 #define SkVM_DEFINED 10 11 #include "include/core/SkBlendMode.h" 12 #include "include/core/SkColor.h" 13 #include "include/private/SkMacros.h" 14 #include "include/private/SkTArray.h" 15 #include "include/private/SkTHash.h" 16 #include "src/core/SkSpan.h" 17 #include "src/core/SkVM_fwd.h" 18 #include <vector> // std::vector 19 20 class SkWStream; 21 22 #if defined(SKVM_JIT_WHEN_POSSIBLE) 23 #if defined(__x86_64__) || defined(_M_X64) 24 #if defined(_WIN32) || defined(__linux) || defined(__APPLE__) 25 #if !defined(SK_BUILD_FOR_IOS) // Exclude iOS simulator. 26 #define SKVM_JIT 27 #endif 28 #endif 29 #endif 30 #if defined(__aarch64__) 31 #if defined(__ANDROID__) 32 #define SKVM_JIT 33 #endif 34 #endif 35 #endif 36 37 #if 0 38 #define SKVM_LLVM 39 #endif 40 41 #if 0 42 #undef SKVM_JIT 43 #endif 44 45 namespace skvm { 46 47 bool fma_supported(); 48 49 class Assembler { 50 public: 51 explicit Assembler(void* buf); 52 53 size_t size() const; 54 55 // Order matters... GP64, Xmm, Ymm values match 4-bit register encoding for each. 56 enum GP64 { 57 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, 58 r8 , r9 , r10, r11, r12, r13, r14, r15, 59 }; 60 enum Xmm { 61 xmm0, xmm1, xmm2 , xmm3 , xmm4 , xmm5 , xmm6 , xmm7 , 62 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, 63 }; 64 enum Ymm { 65 ymm0, ymm1, ymm2 , ymm3 , ymm4 , ymm5 , ymm6 , ymm7 , 66 ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15, 67 }; 68 69 // X and V values match 5-bit encoding for each (nothing tricky). 70 enum X { 71 x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 , 72 x8 , x9 , x10, x11, x12, x13, x14, x15, 73 x16, x17, x18, x19, x20, x21, x22, x23, 74 x24, x25, x26, x27, x28, x29, x30, xzr, sp=xzr, 75 }; 76 enum V { 77 v0 , v1 , v2 , v3 , v4 , v5 , v6 , v7 , 78 v8 , v9 , v10, v11, v12, v13, v14, v15, 79 v16, v17, v18, v19, v20, v21, v22, v23, 80 v24, v25, v26, v27, v28, v29, v30, v31, 81 }; 82 83 void bytes(const void*, int); 84 void byte(uint8_t); 85 void word(uint32_t); 86 87 struct Label { 88 int offset = 0; 89 enum { NotYetSet, ARMDisp19, X86Disp32 } kind = NotYetSet; 90 SkSTArray<2, int> references; 91 }; 92 93 // x86-64 94 95 void align(int mod); 96 97 void int3(); 98 void vzeroupper(); 99 void ret(); 100 101 // Mem represents a value at base + disp + scale*index, 102 // or simply at base + disp if index=rsp. 103 enum Scale { ONE, TWO, FOUR, EIGHT }; 104 struct Mem { 105 GP64 base; 106 int disp = 0; 107 GP64 index = rsp; 108 Scale scale = ONE; 109 }; 110 111 struct Operand { 112 union { 113 int reg; 114 Mem mem; 115 Label* label; 116 }; 117 enum { REG, MEM, LABEL } kind; 118 OperandOperand119 Operand(GP64 r) : reg (r), kind(REG ) {} OperandOperand120 Operand(Xmm r) : reg (r), kind(REG ) {} OperandOperand121 Operand(Ymm r) : reg (r), kind(REG ) {} OperandOperand122 Operand(Mem m) : mem (m), kind(MEM ) {} OperandOperand123 Operand(Label* l) : label(l), kind(LABEL) {} 124 }; 125 126 void vpand (Ymm dst, Ymm x, Operand y); 127 void vpandn(Ymm dst, Ymm x, Operand y); 128 void vpor (Ymm dst, Ymm x, Operand y); 129 void vpxor (Ymm dst, Ymm x, Operand y); 130 131 void vpaddd (Ymm dst, Ymm x, Operand y); 132 void vpsubd (Ymm dst, Ymm x, Operand y); 133 void vpmulld(Ymm dst, Ymm x, Operand y); 134 135 void vpaddw (Ymm dst, Ymm x, Operand y); 136 void vpsubw (Ymm dst, Ymm x, Operand y); 137 void vpmullw (Ymm dst, Ymm x, Operand y); 138 139 void vpabsw (Ymm dst, Operand x); 140 void vpavgw (Ymm dst, Ymm x, Operand y); // dst = (x+y+1)>>1, unsigned. 141 void vpmulhrsw(Ymm dst, Ymm x, Operand y); // dst = (x*y + (1<<14)) >> 15, signed. 142 void vpminsw (Ymm dst, Ymm x, Operand y); 143 void vpminuw (Ymm dst, Ymm x, Operand y); 144 void vpmaxsw (Ymm dst, Ymm x, Operand y); 145 void vpmaxuw (Ymm dst, Ymm x, Operand y); 146 147 void vaddps(Ymm dst, Ymm x, Operand y); 148 void vsubps(Ymm dst, Ymm x, Operand y); 149 void vmulps(Ymm dst, Ymm x, Operand y); 150 void vdivps(Ymm dst, Ymm x, Operand y); 151 void vminps(Ymm dst, Ymm x, Operand y); 152 void vmaxps(Ymm dst, Ymm x, Operand y); 153 154 void vsqrtps(Ymm dst, Operand x); 155 156 void vfmadd132ps(Ymm dst, Ymm x, Operand y); 157 void vfmadd213ps(Ymm dst, Ymm x, Operand y); 158 void vfmadd231ps(Ymm dst, Ymm x, Operand y); 159 160 void vfmsub132ps(Ymm dst, Ymm x, Operand y); 161 void vfmsub213ps(Ymm dst, Ymm x, Operand y); 162 void vfmsub231ps(Ymm dst, Ymm x, Operand y); 163 164 void vfnmadd132ps(Ymm dst, Ymm x, Operand y); 165 void vfnmadd213ps(Ymm dst, Ymm x, Operand y); 166 void vfnmadd231ps(Ymm dst, Ymm x, Operand y); 167 168 void vpackusdw(Ymm dst, Ymm x, Operand y); 169 void vpackuswb(Ymm dst, Ymm x, Operand y); 170 171 void vpunpckldq(Ymm dst, Ymm x, Operand y); 172 void vpunpckhdq(Ymm dst, Ymm x, Operand y); 173 174 void vpcmpeqd(Ymm dst, Ymm x, Operand y); 175 void vpcmpgtd(Ymm dst, Ymm x, Operand y); 176 void vpcmpeqw(Ymm dst, Ymm x, Operand y); 177 void vpcmpgtw(Ymm dst, Ymm x, Operand y); 178 179 void vcmpps (Ymm dst, Ymm x, Operand y, int imm); vcmpeqps(Ymm dst,Ymm x,Operand y)180 void vcmpeqps (Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,0); } vcmpltps(Ymm dst,Ymm x,Operand y)181 void vcmpltps (Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,1); } vcmpleps(Ymm dst,Ymm x,Operand y)182 void vcmpleps (Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,2); } vcmpneqps(Ymm dst,Ymm x,Operand y)183 void vcmpneqps(Ymm dst, Ymm x, Operand y) { this->vcmpps(dst,x,y,4); } 184 185 // Sadly, the x parameter cannot be a general Operand for these shifts. 186 void vpslld(Ymm dst, Ymm x, int imm); 187 void vpsrld(Ymm dst, Ymm x, int imm); 188 void vpsrad(Ymm dst, Ymm x, int imm); 189 190 void vpsllw(Ymm dst, Ymm x, int imm); 191 void vpsrlw(Ymm dst, Ymm x, int imm); 192 void vpsraw(Ymm dst, Ymm x, int imm); 193 194 void vpermq (Ymm dst, Operand x, int imm); 195 void vperm2f128(Ymm dst, Ymm x, Operand y, int imm); 196 void vpermps (Ymm dst, Ymm ix, Operand src); // dst[i] = src[ix[i]] 197 198 enum Rounding { NEAREST, FLOOR, CEIL, TRUNC, CURRENT }; 199 void vroundps(Ymm dst, Operand x, Rounding); 200 201 void vmovdqa(Ymm dst, Operand x); 202 void vmovups(Ymm dst, Operand x); 203 void vmovups(Xmm dst, Operand x); 204 void vmovups(Operand dst, Ymm x); 205 void vmovups(Operand dst, Xmm x); 206 207 void vcvtdq2ps (Ymm dst, Operand x); 208 void vcvttps2dq(Ymm dst, Operand x); 209 void vcvtps2dq (Ymm dst, Operand x); 210 211 void vcvtps2ph(Operand dst, Ymm x, Rounding); 212 void vcvtph2ps(Ymm dst, Operand x); 213 214 void vpblendvb(Ymm dst, Ymm x, Operand y, Ymm z); 215 216 void vpshufb(Ymm dst, Ymm x, Operand y); 217 218 void vptest(Ymm x, Operand y); 219 220 void vbroadcastss(Ymm dst, Operand y); 221 222 void vpmovzxwd(Ymm dst, Operand src); // dst = src, 128-bit, uint16_t -> int 223 void vpmovzxbd(Ymm dst, Operand src); // dst = src, 64-bit, uint8_t -> int 224 225 void vmovq(Operand dst, Xmm src); // dst = src, 64-bit 226 void vmovd(Operand dst, Xmm src); // dst = src, 32-bit 227 void vmovd(Xmm dst, Operand src); // dst = src, 32-bit 228 229 void vpinsrd(Xmm dst, Xmm src, Operand y, int imm); // dst = src; dst[imm] = y, 32-bit 230 void vpinsrw(Xmm dst, Xmm src, Operand y, int imm); // dst = src; dst[imm] = y, 16-bit 231 void vpinsrb(Xmm dst, Xmm src, Operand y, int imm); // dst = src; dst[imm] = y, 8-bit 232 233 void vextracti128(Operand dst, Ymm src, int imm); // dst = src[imm], 128-bit 234 void vpextrd (Operand dst, Xmm src, int imm); // dst = src[imm], 32-bit 235 void vpextrw (Operand dst, Xmm src, int imm); // dst = src[imm], 16-bit 236 void vpextrb (Operand dst, Xmm src, int imm); // dst = src[imm], 8-bit 237 238 // if (mask & 0x8000'0000) { 239 // dst = base[scale*ix]; 240 // } 241 // mask = 0; 242 void vgatherdps(Ymm dst, Scale scale, Ymm ix, GP64 base, Ymm mask); 243 244 245 void label(Label*); 246 247 void jmp(Label*); 248 void je (Label*); 249 void jne(Label*); 250 void jl (Label*); 251 void jc (Label*); 252 253 void add (Operand dst, int imm); 254 void sub (Operand dst, int imm); 255 void cmp (Operand dst, int imm); 256 void mov (Operand dst, int imm); 257 void movb(Operand dst, int imm); 258 259 void add (Operand dst, GP64 x); 260 void sub (Operand dst, GP64 x); 261 void cmp (Operand dst, GP64 x); 262 void mov (Operand dst, GP64 x); 263 void movb(Operand dst, GP64 x); 264 265 void add (GP64 dst, Operand x); 266 void sub (GP64 dst, Operand x); 267 void cmp (GP64 dst, Operand x); 268 void mov (GP64 dst, Operand x); 269 void movb(GP64 dst, Operand x); 270 271 // Disambiguators... choice is arbitrary (but generates different code!). add(GP64 dst,GP64 x)272 void add (GP64 dst, GP64 x) { this->add (Operand(dst), x); } sub(GP64 dst,GP64 x)273 void sub (GP64 dst, GP64 x) { this->sub (Operand(dst), x); } cmp(GP64 dst,GP64 x)274 void cmp (GP64 dst, GP64 x) { this->cmp (Operand(dst), x); } mov(GP64 dst,GP64 x)275 void mov (GP64 dst, GP64 x) { this->mov (Operand(dst), x); } movb(GP64 dst,GP64 x)276 void movb(GP64 dst, GP64 x) { this->movb(Operand(dst), x); } 277 278 void movzbq(GP64 dst, Operand x); // dst = x, uint8_t -> int 279 void movzwq(GP64 dst, Operand x); // dst = x, uint16_t -> int 280 281 // aarch64 282 283 // d = op(n,m) 284 using DOpNM = void(V d, V n, V m); 285 DOpNM and16b, orr16b, eor16b, bic16b, bsl16b, 286 add4s, sub4s, mul4s, 287 cmeq4s, cmgt4s, 288 sub8h, mul8h, 289 fadd4s, fsub4s, fmul4s, fdiv4s, fmin4s, fmax4s, 290 fcmeq4s, fcmgt4s, fcmge4s, 291 tbl; 292 293 // TODO: there are also float ==,<,<=,>,>= instructions with an immediate 0.0f, 294 // and the register comparison > and >= can also compare absolute values. Interesting. 295 296 // d += n*m 297 void fmla4s(V d, V n, V m); 298 299 // d -= n*m 300 void fmls4s(V d, V n, V m); 301 302 // d = op(n,imm) 303 using DOpNImm = void(V d, V n, int imm); 304 DOpNImm sli4s, 305 shl4s, sshr4s, ushr4s, 306 ushr8h; 307 308 // d = op(n) 309 using DOpN = void(V d, V n); 310 DOpN not16b, // d = ~n 311 fneg4s, // d = -n 312 scvtf4s, // int -> float 313 fcvtzs4s, // truncate float -> int 314 fcvtns4s, // round float -> int (nearest even) 315 xtns2h, // u32 -> u16 316 xtnh2b, // u16 -> u8 317 uxtlb2h, // u8 -> u16 318 uxtlh2s, // u16 -> u32 319 uminv4s; // dst[0] = min(n[0],n[1],n[2],n[3]), n as unsigned 320 321 void brk (int imm16); 322 void ret (X); 323 void add (X d, X n, int imm12); 324 void sub (X d, X n, int imm12); 325 void subs(X d, X n, int imm12); // subtract setting condition flags 326 327 // There's another encoding for unconditional branches that can jump further, 328 // but this one encoded as b.al is simple to implement and should be fine. b(Label * l)329 void b (Label* l) { this->b(Condition::al, l); } bne(Label * l)330 void bne(Label* l) { this->b(Condition::ne, l); } blt(Label * l)331 void blt(Label* l) { this->b(Condition::lt, l); } 332 333 // "cmp ..." is just an assembler mnemonic for "subs xzr, ..."! cmp(X n,int imm12)334 void cmp(X n, int imm12) { this->subs(xzr, n, imm12); } 335 336 // Compare and branch if zero/non-zero, as if 337 // cmp(t,0) 338 // beq/bne(l) 339 // but without setting condition flags. 340 void cbz (X t, Label* l); 341 void cbnz(X t, Label* l); 342 343 void ldrq(V dst, Label*); // 128-bit PC-relative load 344 345 void ldrq(V dst, X src, int imm12=0); // 128-bit dst = *(src+imm12*16) 346 void ldrs(V dst, X src, int imm12=0); // 32-bit dst = *(src+imm12*4) 347 void ldrb(V dst, X src, int imm12=0); // 8-bit dst = *(src+imm12) 348 349 void strq(V src, X dst, int imm12=0); // 128-bit *(dst+imm12*16) = src 350 void strs(V src, X dst, int imm12=0); // 32-bit *(dst+imm12*4) = src 351 void strb(V src, X dst, int imm12=0); // 8-bit *(dst+imm12) = src 352 353 void fmovs(X dst, V src); // dst = 32-bit src[0] 354 355 private: 356 // TODO: can probably track two of these three? 357 uint8_t* fCode; 358 uint8_t* fCurr; 359 size_t fSize; 360 361 // x86-64 362 enum W { W0, W1 }; // Are the lanes 64-bit (W1) or default (W0)? Intel Vol 2A 2.3.5.5 363 enum L { L128, L256 }; // Is this a 128- or 256-bit operation? Intel Vol 2A 2.3.6.2 364 365 // Helpers for vector instructions. 366 void op(int prefix, int map, int opcode, int dst, int x, Operand y, W,L); 367 void op(int p, int m, int o, Ymm d, Ymm x, Operand y, W w=W0) { op(p,m,o, d,x,y,w,L256); } 368 void op(int p, int m, int o, Ymm d, Operand y, W w=W0) { op(p,m,o, d,0,y,w,L256); } 369 void op(int p, int m, int o, Xmm d, Xmm x, Operand y, W w=W0) { op(p,m,o, d,x,y,w,L128); } 370 void op(int p, int m, int o, Xmm d, Operand y, W w=W0) { op(p,m,o, d,0,y,w,L128); } 371 372 // Helpers for GP64 instructions. 373 void op(int opcode, Operand dst, GP64 x); 374 void op(int opcode, int opcode_ext, Operand dst, int imm); 375 376 void jump(uint8_t condition, Label*); 377 int disp32(Label*); 378 void imm_byte_after_operand(const Operand&, int byte); 379 380 // aarch64 381 382 // Opcode for 3-arguments ops is split between hi and lo: 383 // [11 bits hi] [5 bits m] [6 bits lo] [5 bits n] [5 bits d] 384 void op(uint32_t hi, V m, uint32_t lo, V n, V d); 385 386 // 0,1,2-argument ops, with or without an immediate: 387 // [ 22 bits op ] [5 bits n] [5 bits d] 388 // Any immediate falls in the middle somewhere overlapping with either op, n, or both. 389 void op(uint32_t op22, V n, V d, int imm=0); 390 void op(uint32_t op22, X n, V d, int imm=0) { this->op(op22,(V)n, d,imm); } 391 void op(uint32_t op22, V n, X d, int imm=0) { this->op(op22, n,(V)d,imm); } 392 void op(uint32_t op22, X n, X d, int imm=0) { this->op(op22,(V)n,(V)d,imm); } 393 void op(uint32_t op22, int imm=0) { this->op(op22,(V)0,(V)0,imm); } 394 // (1-argument ops don't seem to have a consistent convention of passing as n or d.) 395 396 397 // Order matters... value is 4-bit encoding for condition code. 398 enum class Condition { eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,al }; 399 void b(Condition, Label*); 400 int disp19(Label*); 401 }; 402 403 // Order matters a little: Ops <=store128 are treated as having side effects. 404 #define SKVM_OPS(M) \ 405 M(assert_true) \ 406 M(store8) M(store16) M(store32) M(store64) M(store128) \ 407 M(index) \ 408 M(load8) M(load16) M(load32) M(load64) M(load128) \ 409 M(gather8) M(gather16) M(gather32) \ 410 M(uniform8) M(uniform16) M(uniform32) \ 411 M(splat) M(splat_q14) \ 412 M(add_f32) M(add_i32) M(add_q14) \ 413 M(sub_f32) M(sub_i32) M(sub_q14) \ 414 M(mul_f32) M(mul_i32) M(mul_q14) \ 415 M(div_f32) \ 416 M(min_f32) M(max_f32) \ 417 M(min_q14) M(max_q14) M(uavg_q14) \ 418 M(fma_f32) M(fms_f32) M(fnma_f32) \ 419 M(sqrt_f32) \ 420 M(shl_i32) M(shr_i32) M(sra_i32) \ 421 M(shl_q14) M(shr_q14) M(sra_q14) \ 422 M(ceil) M(floor) M(trunc) M(round) M(to_half) M(from_half) \ 423 M(to_f32) M(to_q14) M(from_q14) \ 424 M(neq_f32) M(eq_f32) M(eq_i32) M(eq_q14) \ 425 M(gte_f32) M(gt_f32) M(gt_i32) M(gt_q14) \ 426 M(bit_and) M(bit_or) M(bit_xor) M(bit_clear) \ 427 M(bit_and_q14) M(bit_or_q14) M(bit_xor_q14) M(bit_clear_q14) \ 428 M(select) M(select_q14) M(pack) \ 429 // End of SKVM_OPS 430 431 enum class Op : int { 432 #define M(op) op, 433 SKVM_OPS(M) 434 #undef M 435 }; 436 has_side_effect(Op op)437 static inline bool has_side_effect(Op op) { 438 return op <= Op::store128; 439 } is_always_varying(Op op)440 static inline bool is_always_varying(Op op) { 441 return op <= Op::gather32 && op != Op::assert_true; 442 } 443 444 using Val = int; 445 // We reserve an impossibe Val ID as a sentinel 446 // NA meaning none, n/a, null, nil, etc. 447 static const Val NA = -1; 448 449 struct Arg { int ix; }; 450 451 struct I32 { 452 Builder* builder = nullptr; 453 Val id = NA; 454 explicit operator bool() const { return id != NA; } 455 Builder* operator->() const { return builder; } 456 }; 457 458 struct F32 { 459 Builder* builder = nullptr; 460 Val id = NA; 461 explicit operator bool() const { return id != NA; } 462 Builder* operator->() const { return builder; } 463 }; 464 465 struct Q14 { 466 Builder* builder = nullptr; 467 Val id = NA; 468 explicit operator bool() const { return id != NA; } 469 Builder* operator->() const { return builder; } 470 }; 471 472 // Some operations make sense with immediate arguments, 473 // so we use I32a and F32a to receive them transparently. 474 // 475 // We omit overloads that may indicate a bug or performance issue. 476 // In general it does not make sense to pass immediates to unary operations, 477 // and even sometimes not for binary operations, e.g. 478 // 479 // div(x,y) -- normal every day divide 480 // div(3.0f,y) -- yep, makes sense 481 // div(x,3.0f) -- omitted as a reminder you probably want mul(x, 1/3.0f). 482 // 483 // You can of course always splat() to override these opinions. 484 struct I32a { I32aI32a485 I32a(I32 v) : SkDEBUGCODE(builder(v.builder),) id(v.id) {} I32aI32a486 I32a(int v) : imm(v) {} 487 488 SkDEBUGCODE(Builder* builder = nullptr;) 489 Val id = NA; 490 int imm = 0; 491 }; 492 493 struct F32a { F32aF32a494 F32a(F32 v) : SkDEBUGCODE(builder(v.builder),) id(v.id) {} F32aF32a495 F32a(float v) : imm(v) {} 496 497 SkDEBUGCODE(Builder* builder = nullptr;) 498 Val id = NA; 499 float imm = 0; 500 }; 501 502 struct Q14a { Q14aQ14a503 Q14a(Q14 v) : SkDEBUGCODE(builder(v.builder),) id(v.id) {} Q14aQ14a504 Q14a(int bits) : imm{SkTo<int16_t>(bits)} {} // 0x0000'4000 -> 0x4000 Q14aQ14a505 Q14a(float f) : Q14a{(int)(f * 16384.0f)} {} // 1.0f -> 0x4000 506 507 SkDEBUGCODE(Builder* builder = nullptr;) 508 Val id = NA; 509 int16_t imm = 0; 510 }; 511 512 struct Color { 513 F32 r,g,b,a; 514 explicit operator bool() const { return r && g && b && a; } 515 Builder* operator->() const { return a.operator->(); } 516 }; 517 518 struct HSLA { 519 F32 h,s,l,a; 520 explicit operator bool() const { return h && s && l && a; } 521 Builder* operator->() const { return a.operator->(); } 522 }; 523 524 struct Color_Q14 { 525 Q14 r,g,b,a; 526 explicit operator bool() const { return r && g && b && a; } 527 Builder* operator->() const { return a.operator->(); } 528 }; 529 530 struct Coord { 531 F32 x,y; 532 explicit operator bool() const { return x && y; } 533 Builder* operator->() const { return x.operator->(); } 534 }; 535 536 struct Uniform { 537 Arg ptr; 538 int offset; 539 }; 540 struct Uniforms { 541 Arg base; 542 std::vector<int> buf; 543 UniformsUniforms544 explicit Uniforms(int init) : base(Arg{0}), buf(init) {} 545 pushUniforms546 Uniform push(int val) { 547 buf.push_back(val); 548 return {base, (int)( sizeof(int)*(buf.size() - 1) )}; 549 } 550 pushFUniforms551 Uniform pushF(float val) { 552 int bits; 553 memcpy(&bits, &val, sizeof(int)); 554 return this->push(bits); 555 } 556 pushPtrUniforms557 Uniform pushPtr(const void* ptr) { 558 // Jam the pointer into 1 or 2 ints. 559 int ints[sizeof(ptr) / sizeof(int)]; 560 memcpy(ints, &ptr, sizeof(ptr)); 561 for (int bits : ints) { 562 buf.push_back(bits); 563 } 564 return {base, (int)( sizeof(int)*(buf.size() - SK_ARRAY_COUNT(ints)) )}; 565 } 566 }; 567 568 struct PixelFormat { 569 enum { UNORM, FLOAT} encoding; 570 int r_bits, g_bits, b_bits, a_bits, 571 r_shift, g_shift, b_shift, a_shift; 572 }; 573 bool SkColorType_to_PixelFormat(SkColorType, PixelFormat*); 574 575 SK_BEGIN_REQUIRE_DENSE 576 struct Instruction { 577 Op op; // v* = op(x,y,z,imm), where * == index of this Instruction. 578 Val x,y,z; // Enough arguments for mad(). 579 int immy,immz; // Immediate bit pattern, shift count, argument index, etc. 580 }; 581 SK_END_REQUIRE_DENSE 582 583 bool operator==(const Instruction&, const Instruction&); 584 struct InstructionHash { 585 uint32_t operator()(const Instruction&, uint32_t seed=0) const; 586 }; 587 588 struct OptimizedInstruction { 589 Op op; 590 Val x,y,z; 591 int immy,immz; 592 593 Val death; 594 bool can_hoist; 595 }; 596 597 class Builder { 598 public: 599 600 Program done(const char* debug_name = nullptr) const; 601 602 // Mostly for debugging, tests, etc. program()603 std::vector<Instruction> program() const { return fProgram; } 604 std::vector<OptimizedInstruction> optimize() const; 605 606 // Declare an argument with given stride (use stride=0 for uniforms). 607 // TODO: different types for varying and uniforms? 608 Arg arg(int stride); 609 610 // Convenience arg() wrappers for most common strides, sizeof(T) and 0. 611 template <typename T> varying()612 Arg varying() { return this->arg(sizeof(T)); } uniform()613 Arg uniform() { return this->arg(0); } 614 615 // TODO: allow uniform (i.e. Arg) offsets to store* and load*? 616 // TODO: sign extension (signed types) for <32-bit loads? 617 // TODO: unsigned integer operations where relevant (just comparisons?)? 618 619 // Assert cond is true, printing debug when not. 620 void assert_true(I32 cond, I32 debug); assert_true(I32 cond,F32 debug)621 void assert_true(I32 cond, F32 debug) { assert_true(cond, bit_cast(debug)); } assert_true(I32 cond)622 void assert_true(I32 cond) { assert_true(cond, cond); } 623 624 // Store {8,16,32,64,128}-bit varying. 625 void store8 (Arg ptr, I32 val); 626 void store16 (Arg ptr, I32 val); 627 void store32 (Arg ptr, I32 val); storeF(Arg ptr,F32 val)628 void storeF (Arg ptr, F32 val) { store32(ptr, bit_cast(val)); } 629 void store64 (Arg ptr, I32 lo, I32 hi); // *ptr = lo|(hi<<32) 630 void store128(Arg ptr, I32 lo, I32 hi, int lane); // 64-bit lane 0-1 at ptr = lo|(hi<<32). 631 632 // Returns varying {n, n-1, n-2, ..., 1}, where n is the argument to Program::eval(). 633 I32 index(); 634 635 // Load {8,16,32,64,128}-bit varying. 636 I32 load8 (Arg ptr); 637 I32 load16 (Arg ptr); 638 I32 load32 (Arg ptr); loadF(Arg ptr)639 F32 loadF (Arg ptr) { return bit_cast(load32(ptr)); } 640 I32 load64 (Arg ptr, int lane); // Load 32-bit lane 0-1 of 64-bit value. 641 I32 load128(Arg ptr, int lane); // Load 32-bit lane 0-3 of 128-bit value. 642 643 // Load u8,u16,i32 uniform with byte-count offset. 644 I32 uniform8 (Arg ptr, int offset); 645 I32 uniform16(Arg ptr, int offset); 646 I32 uniform32(Arg ptr, int offset); uniformF(Arg ptr,int offset)647 F32 uniformF (Arg ptr, int offset) { return this->bit_cast(this->uniform32(ptr,offset)); } 648 649 // Push and load this color as a uniform. 650 Color uniformColor(SkColor4f, Uniforms*); 651 652 // Gather u8,u16,i32 with varying element-count index from *(ptr + byte-count offset). 653 I32 gather8 (Arg ptr, int offset, I32 index); 654 I32 gather16(Arg ptr, int offset, I32 index); 655 I32 gather32(Arg ptr, int offset, I32 index); gatherF(Arg ptr,int offset,I32 index)656 F32 gatherF (Arg ptr, int offset, I32 index) { 657 return bit_cast(gather32(ptr, offset, index)); 658 } 659 660 // Convenience methods for working with skvm::Uniform(s). uniform8(Uniform u)661 I32 uniform8 (Uniform u) { return this->uniform8 (u.ptr, u.offset); } uniform16(Uniform u)662 I32 uniform16(Uniform u) { return this->uniform16(u.ptr, u.offset); } uniform32(Uniform u)663 I32 uniform32(Uniform u) { return this->uniform32(u.ptr, u.offset); } uniformF(Uniform u)664 F32 uniformF (Uniform u) { return this->uniformF (u.ptr, u.offset); } gather8(Uniform u,I32 index)665 I32 gather8 (Uniform u, I32 index) { return this->gather8 (u.ptr, u.offset, index); } gather16(Uniform u,I32 index)666 I32 gather16 (Uniform u, I32 index) { return this->gather16 (u.ptr, u.offset, index); } gather32(Uniform u,I32 index)667 I32 gather32 (Uniform u, I32 index) { return this->gather32 (u.ptr, u.offset, index); } gatherF(Uniform u,I32 index)668 F32 gatherF (Uniform u, I32 index) { return this->gatherF (u.ptr, u.offset, index); } 669 670 // Load an immediate constant. 671 I32 splat(int n); splat(unsigned u)672 I32 splat(unsigned u) { return splat((int)u); } splat(float f)673 F32 splat(float f) { 674 int bits; 675 memcpy(&bits, &f, 4); 676 return bit_cast(splat(bits)); 677 } 678 679 // Load an immediate Q14, expressed as either integer (16384, 0x4000) or float (1.0f). 680 Q14 splat_q14(int n); splat_q14(unsigned u)681 Q14 splat_q14(unsigned u) { return splat_q14((int)u); } splat_q14(float f)682 Q14 splat_q14(float f) { return splat_q14(Q14a{f}.imm); } 683 684 // float math, comparisons, etc. add(F32a x,F32a y)685 F32 add(F32, F32); F32 add(F32a x, F32a y) { return add(_(x), _(y)); } sub(F32a x,F32a y)686 F32 sub(F32, F32); F32 sub(F32a x, F32a y) { return sub(_(x), _(y)); } mul(F32a x,F32a y)687 F32 mul(F32, F32); F32 mul(F32a x, F32a y) { return mul(_(x), _(y)); } div(F32a x,F32 y)688 F32 div(F32, F32); F32 div(F32a x, F32 y) { return div(_(x), y ); } min(F32a x,F32a y)689 F32 min(F32, F32); F32 min(F32a x, F32a y) { return min(_(x), _(y)); } max(F32a x,F32a y)690 F32 max(F32, F32); F32 max(F32a x, F32a y) { return max(_(x), _(y)); } 691 mad(F32 x,F32 y,F32 z)692 F32 mad(F32 x, F32 y, F32 z) { return add(mul(x,y), z); } mad(F32a x,F32a y,F32a z)693 F32 mad(F32a x, F32a y, F32a z) { return mad(_(x), _(y), _(z)); } 694 695 F32 sqrt(F32); 696 F32 approx_log2(F32); 697 F32 approx_pow2(F32); approx_log(F32 x)698 F32 approx_log (F32 x) { return mul(0.69314718f, approx_log2(x)); } approx_exp(F32 x)699 F32 approx_exp (F32 x) { return approx_pow2(mul(x, 1.4426950408889634074f)); } 700 701 F32 approx_powf(F32 base, F32 exp); approx_powf(F32a base,F32a exp)702 F32 approx_powf(F32a base, F32a exp) { return approx_powf(_(base), _(exp)); } 703 704 F32 approx_sin(F32 radians); approx_cos(F32 radians)705 F32 approx_cos(F32 radians) { return approx_sin(add(radians, SK_ScalarPI/2)); } 706 F32 approx_tan(F32 radians); 707 708 F32 approx_asin(F32 x); approx_acos(F32 x)709 F32 approx_acos(F32 x) { return sub(SK_ScalarPI/2, approx_asin(x)); } 710 F32 approx_atan(F32 x); 711 F32 approx_atan2(F32 y, F32 x); 712 713 F32 lerp(F32 lo, F32 hi, F32 t); lerp(F32a lo,F32a hi,F32a t)714 F32 lerp(F32a lo, F32a hi, F32a t) { return lerp(_(lo), _(hi), _(t)); } 715 clamp(F32 x,F32 lo,F32 hi)716 F32 clamp(F32 x, F32 lo, F32 hi) { return max(lo, min(x, hi)); } clamp(F32a x,F32a lo,F32a hi)717 F32 clamp(F32a x, F32a lo, F32a hi) { return clamp(_(x), _(lo), _(hi)); } clamp01(F32 x)718 F32 clamp01(F32 x) { return clamp(x, 0.0f, 1.0f); } 719 abs(F32 x)720 F32 abs(F32 x) { return bit_cast(bit_and(bit_cast(x), 0x7fff'ffff)); } 721 F32 fract(F32 x) { return sub(x, floor(x)); } 722 F32 ceil(F32); 723 F32 floor(F32); 724 I32 is_NaN (F32 x) { return neq(x,x); } 725 I32 is_finite(F32 x) { return lt(bit_and(bit_cast(x), 0x7f80'0000), 0x7f80'0000); } 726 727 I32 trunc(F32 x); 728 I32 round(F32 x); // Round to int using current rounding mode (as if lrintf()). 729 I32 bit_cast(F32 x) { return {x.builder, x.id}; } 730 731 I32 to_half(F32 x); 732 F32 from_half(I32 x); 733 734 F32 norm(F32 x, F32 y) { 735 return sqrt(add(mul(x,x), 736 mul(y,y))); 737 } 738 F32 norm(F32a x, F32a y) { return norm(_(x), _(y)); } 739 740 I32 eq(F32, F32); I32 eq(F32a x, F32a y) { return eq(_(x), _(y)); } 741 I32 neq(F32, F32); I32 neq(F32a x, F32a y) { return neq(_(x), _(y)); } 742 I32 lt (F32, F32); I32 lt (F32a x, F32a y) { return lt (_(x), _(y)); } 743 I32 lte(F32, F32); I32 lte(F32a x, F32a y) { return lte(_(x), _(y)); } 744 I32 gt (F32, F32); I32 gt (F32a x, F32a y) { return gt (_(x), _(y)); } 745 I32 gte(F32, F32); I32 gte(F32a x, F32a y) { return gte(_(x), _(y)); } 746 747 // int math, comparisons, etc. 748 I32 add(I32, I32); I32 add(I32a x, I32a y) { return add(_(x), _(y)); } 749 I32 sub(I32, I32); I32 sub(I32a x, I32a y) { return sub(_(x), _(y)); } 750 I32 mul(I32, I32); I32 mul(I32a x, I32a y) { return mul(_(x), _(y)); } 751 752 I32 shl(I32 x, int bits); 753 I32 shr(I32 x, int bits); 754 I32 sra(I32 x, int bits); 755 756 I32 eq (I32 x, I32 y); I32 eq(I32a x, I32a y) { return eq(_(x), _(y)); } 757 I32 neq(I32 x, I32 y); I32 neq(I32a x, I32a y) { return neq(_(x), _(y)); } 758 I32 lt (I32 x, I32 y); I32 lt (I32a x, I32a y) { return lt (_(x), _(y)); } 759 I32 lte(I32 x, I32 y); I32 lte(I32a x, I32a y) { return lte(_(x), _(y)); } 760 I32 gt (I32 x, I32 y); I32 gt (I32a x, I32a y) { return gt (_(x), _(y)); } 761 I32 gte(I32 x, I32 y); I32 gte(I32a x, I32a y) { return gte(_(x), _(y)); } 762 763 F32 to_F32(I32 x); 764 F32 bit_cast(I32 x) { return {x.builder, x.id}; } 765 766 // Bitwise operations. 767 I32 bit_and (I32, I32); I32 bit_and (I32a x, I32a y) { return bit_and (_(x), _(y)); } 768 I32 bit_or (I32, I32); I32 bit_or (I32a x, I32a y) { return bit_or (_(x), _(y)); } 769 I32 bit_xor (I32, I32); I32 bit_xor (I32a x, I32a y) { return bit_xor (_(x), _(y)); } 770 I32 bit_clear(I32, I32); I32 bit_clear(I32a x, I32a y) { return bit_clear(_(x), _(y)); } 771 772 I32 min(I32 x, I32 y) { return select(lte(x,y), x, y); } 773 I32 max(I32 x, I32 y) { return select(gte(x,y), x, y); } 774 775 I32 min(I32a x, I32a y) { return min(_(x), _(y)); } 776 I32 max(I32a x, I32a y) { return max(_(x), _(y)); } 777 778 I32 select(I32 cond, I32 t, I32 f); // cond ? t : f 779 F32 select(I32 cond, F32 t, F32 f) { 780 return bit_cast(select(cond, bit_cast(t) 781 , bit_cast(f))); 782 } 783 Q14 select(Q14 cond, Q14 t, Q14 f); 784 785 I32 select(I32a cond, I32a t, I32a f) { return select(_(cond), _(t), _(f)); } 786 F32 select(I32a cond, F32a t, F32a f) { return select(_(cond), _(t), _(f)); } 787 Q14 select(Q14a cond, Q14a t, Q14a f) { return select(_(cond), _(t), _(f)); } 788 789 I32 extract(I32 x, int bits, I32 z); // (x>>bits) & z 790 I32 pack (I32 x, I32 y, int bits); // x | (y << bits), assuming (x & (y << bits)) == 0 791 792 I32 extract(I32a x, int bits, I32a z) { return extract(_(x), bits, _(z)); } 793 I32 pack (I32a x, I32a y, int bits) { return pack (_(x), _(y), bits); } 794 795 Q14 add(Q14, Q14); Q14 add(Q14a x, Q14a y) { return add(_(x), _(y)); } 796 Q14 sub(Q14, Q14); Q14 sub(Q14a x, Q14a y) { return sub(_(x), _(y)); } 797 Q14 mul(Q14, Q14); Q14 mul(Q14a x, Q14a y) { return mul(_(x), _(y)); } 798 799 Q14 min(Q14, Q14); Q14 min(Q14a x, Q14a y) { return min(_(x), _(y)); } 800 Q14 max(Q14, Q14); Q14 max(Q14a x, Q14a y) { return max(_(x), _(y)); } 801 802 Q14 shl(Q14, int bits); 803 Q14 shr(Q14, int bits); 804 Q14 sra(Q14, int bits); 805 806 Q14 eq (Q14, Q14); Q14 eq(Q14a x, Q14a y) { return eq(_(x), _(y)); } 807 Q14 neq(Q14, Q14); Q14 neq(Q14a x, Q14a y) { return neq(_(x), _(y)); } 808 Q14 lt (Q14, Q14); Q14 lt (Q14a x, Q14a y) { return lt (_(x), _(y)); } 809 Q14 lte(Q14, Q14); Q14 lte(Q14a x, Q14a y) { return lte(_(x), _(y)); } 810 Q14 gt (Q14, Q14); Q14 gt (Q14a x, Q14a y) { return gt (_(x), _(y)); } 811 Q14 gte(Q14, Q14); Q14 gte(Q14a x, Q14a y) { return gte(_(x), _(y)); } 812 813 Q14 bit_and (Q14, Q14); Q14 bit_and (Q14a x, Q14a y) { return bit_and (_(x), _(y)); } 814 Q14 bit_or (Q14, Q14); Q14 bit_or (Q14a x, Q14a y) { return bit_or (_(x), _(y)); } 815 Q14 bit_xor (Q14, Q14); Q14 bit_xor (Q14a x, Q14a y) { return bit_xor (_(x), _(y)); } 816 Q14 bit_clear(Q14, Q14); Q14 bit_clear(Q14a x, Q14a y) { return bit_clear(_(x), _(y)); } 817 818 Q14 unsigned_avg(Q14 x, Q14 y); // (x+y+1)>>1 819 Q14 unsigned_avg(Q14a x, Q14a y) { return unsigned_avg(_(x), _(y)); } 820 821 Q14 to_Q14(F32); F32 to_F32(Q14); // Converts values, e.g. 0x4000 <-> 1.0f 822 Q14 to_Q14(I32); I32 to_I32(Q14); // Preserves bits, e.g. 0x4000 <-> 0x00004000 823 824 // Common idioms used in several places, worth centralizing for consistency. 825 F32 from_unorm(int bits, I32); // E.g. from_unorm(8, x) -> x * (1/255.0f) 826 I32 to_unorm(int bits, F32); // E.g. to_unorm(8, x) -> round(x * 255) 827 828 Color load(PixelFormat, Arg ptr); 829 bool store(PixelFormat, Arg ptr, Color); 830 Color gather(PixelFormat, Arg ptr, int offset, I32 index); 831 Color gather(PixelFormat f, Uniform u, I32 index) { 832 return gather(f, u.ptr, u.offset, index); 833 } 834 835 void premul(F32* r, F32* g, F32* b, F32 a); 836 void unpremul(F32* r, F32* g, F32* b, F32 a); 837 838 Color premul(Color c) { this->premul(&c.r, &c.g, &c.b, c.a); return c; } 839 Color unpremul(Color c) { this->unpremul(&c.r, &c.g, &c.b, c.a); return c; } 840 841 Color lerp(Color lo, Color hi, F32 t); 842 Color blend(SkBlendMode, Color src, Color dst); 843 844 Color clamp01(Color c) { 845 return { clamp01(c.r), clamp01(c.g), clamp01(c.b), clamp01(c.a) }; 846 } 847 848 HSLA to_hsla(Color); 849 Color to_rgba(HSLA); 850 851 void dump(SkWStream* = nullptr) const; 852 void dot (SkWStream* = nullptr) const; 853 854 uint64_t hash() const; 855 856 Val push(Instruction); 857 private: 858 Val push(Op op, Val x, Val y=NA, Val z=NA, int immy=0, int immz=0) { 859 return this->push(Instruction{op, x,y,z, immy,immz}); 860 } 861 862 I32 _(I32a x) { 863 if (x.id != NA) { 864 SkASSERT(x.builder == this); 865 return {this, x.id}; 866 } 867 return splat(x.imm); 868 } 869 870 F32 _(F32a x) { 871 if (x.id != NA) { 872 SkASSERT(x.builder == this); 873 return {this, x.id}; 874 } 875 return splat(x.imm); 876 } 877 878 Q14 _(Q14a x) { 879 if (x.id != NA) { 880 SkASSERT(x.builder == this); 881 return {this, x.id}; 882 } 883 return splat_q14(x.imm); 884 } 885 886 bool allImm() const; 887 888 template <typename T, typename... Rest> 889 bool allImm(Val, T* imm, Rest...) const; 890 891 template <typename T> 892 bool isImm(Val id, T want) const { 893 T imm = 0; 894 return this->allImm(id, &imm) && imm == want; 895 } 896 897 SkTHashMap<Instruction, Val, InstructionHash> fIndex; 898 std::vector<Instruction> fProgram; 899 std::vector<int> fStrides; 900 }; 901 902 template <typename... Fs> 903 void dump_instructions(const std::vector<Instruction>& instructions, 904 SkWStream* o = nullptr, 905 Fs... fs); 906 907 // Optimization passes and data structures normally used by Builder::optimize(), 908 // extracted here so they can be unit tested. 909 std::vector<Instruction> eliminate_dead_code(std::vector<Instruction>); 910 std::vector<Instruction> schedule (std::vector<Instruction>); 911 std::vector<OptimizedInstruction> finalize (std::vector<Instruction>); 912 913 class Usage { 914 public: 915 Usage(const std::vector<Instruction>&); 916 917 // Return a sorted span of Vals which use result of Instruction id. 918 SkSpan<const Val> operator[](Val id) const; 919 920 private: 921 std::vector<int> fIndex; 922 std::vector<Val> fTable; 923 }; 924 925 using Reg = int; 926 927 // d = op(x, y/imm, z/imm) 928 struct InterpreterInstruction { 929 Op op; 930 Reg d,x; 931 union { Reg y; int immy; }; 932 union { Reg z; int immz; }; 933 }; 934 935 class Program { 936 public: 937 Program(const std::vector<OptimizedInstruction>& instructions, 938 const std::vector<int>& strides, 939 const char* debug_name); 940 941 Program(); 942 ~Program(); 943 944 Program(Program&&); 945 Program& operator=(Program&&); 946 947 Program(const Program&) = delete; 948 Program& operator=(const Program&) = delete; 949 950 void eval(int n, void* args[]) const; 951 952 template <typename... T> 953 void eval(int n, T*... arg) const { 954 SkASSERT(sizeof...(arg) == this->nargs()); 955 // This nullptr isn't important except that it makes args[] non-empty if you pass none. 956 void* args[] = { (void*)arg..., nullptr }; 957 this->eval(n, args); 958 } 959 960 std::vector<InterpreterInstruction> instructions() const; 961 int nargs() const; 962 int nregs() const; 963 int loop () const; 964 bool empty() const; 965 966 bool hasJIT() const; // Has this Program been JITted? 967 void dropJIT(); // If hasJIT(), drop it, forcing interpreter fallback. 968 969 void dump(SkWStream* = nullptr) const; 970 971 private: 972 void setupInterpreter(const std::vector<OptimizedInstruction>&); 973 void setupJIT (const std::vector<OptimizedInstruction>&, const char* debug_name); 974 void setupLLVM (const std::vector<OptimizedInstruction>&, const char* debug_name); 975 976 bool jit(const std::vector<OptimizedInstruction>&, 977 int* stack_hint, uint32_t* registers_used, 978 Assembler*) const; 979 980 void waitForLLVM() const; 981 982 struct Impl; 983 std::unique_ptr<Impl> fImpl; 984 }; 985 986 // TODO: control flow 987 // TODO: 64-bit values? 988 989 static inline Q14 operator+(Q14 x, Q14a y) { return x->add(x,y); } 990 static inline Q14 operator+(float x, Q14 y) { return y->add(x,y); } 991 992 static inline Q14 operator-(Q14 x, Q14a y) { return x->sub(x,y); } 993 static inline Q14 operator-(float x, Q14 y) { return y->sub(x,y); } 994 995 static inline Q14 operator*(Q14 x, Q14a y) { return x->mul(x,y); } 996 static inline Q14 operator*(float x, Q14 y) { return y->mul(x,y); } 997 min(Q14 x,Q14a y)998 static inline Q14 min(Q14 x, Q14a y) { return x->min(x,y); } min(float x,Q14 y)999 static inline Q14 min(float x, Q14 y) { return y->min(x,y); } 1000 max(Q14 x,Q14a y)1001 static inline Q14 max(Q14 x, Q14a y) { return x->max(x,y); } max(float x,Q14 y)1002 static inline Q14 max(float x, Q14 y) { return y->max(x,y); } 1003 unsigned_avg(Q14 x,Q14a y)1004 static inline Q14 unsigned_avg(Q14 x, Q14a y) { return x->unsigned_avg(x,y); } unsigned_avg(float x,Q14 y)1005 static inline Q14 unsigned_avg(float x, Q14 y) { return y->unsigned_avg(x,y); } 1006 1007 static inline Q14 operator==(Q14 x, Q14 y) { return x->eq(x,y); } 1008 static inline Q14 operator==(Q14 x, float y) { return x->eq(x,y); } 1009 static inline Q14 operator==(float x, Q14 y) { return y->eq(x,y); } 1010 1011 static inline Q14 operator!=(Q14 x, Q14 y) { return x->neq(x,y); } 1012 static inline Q14 operator!=(Q14 x, float y) { return x->neq(x,y); } 1013 static inline Q14 operator!=(float x, Q14 y) { return y->neq(x,y); } 1014 1015 static inline Q14 operator< (Q14 x, Q14a y) { return x->lt(x,y); } 1016 static inline Q14 operator< (float x, Q14 y) { return y->lt(x,y); } 1017 1018 static inline Q14 operator<=(Q14 x, Q14a y) { return x->lte(x,y); } 1019 static inline Q14 operator<=(float x, Q14 y) { return y->lte(x,y); } 1020 1021 static inline Q14 operator> (Q14 x, Q14a y) { return x->gt(x,y); } 1022 static inline Q14 operator> (float x, Q14 y) { return y->gt(x,y); } 1023 1024 static inline Q14 operator>=(Q14 x, Q14a y) { return x->gte(x,y); } 1025 static inline Q14 operator>=(float x, Q14 y) { return y->gte(x,y); } 1026 1027 1028 static inline I32 operator+(I32 x, I32a y) { return x->add(x,y); } 1029 static inline I32 operator+(int x, I32 y) { return y->add(x,y); } 1030 1031 static inline I32 operator-(I32 x, I32a y) { return x->sub(x,y); } 1032 static inline I32 operator-(int x, I32 y) { return y->sub(x,y); } 1033 1034 static inline I32 operator*(I32 x, I32a y) { return x->mul(x,y); } 1035 static inline I32 operator*(int x, I32 y) { return y->mul(x,y); } 1036 min(I32 x,I32a y)1037 static inline I32 min(I32 x, I32a y) { return x->min(x,y); } min(int x,I32 y)1038 static inline I32 min(int x, I32 y) { return y->min(x,y); } 1039 max(I32 x,I32a y)1040 static inline I32 max(I32 x, I32a y) { return x->max(x,y); } max(int x,I32 y)1041 static inline I32 max(int x, I32 y) { return y->max(x,y); } 1042 1043 static inline I32 operator==(I32 x, I32 y) { return x->eq(x,y); } 1044 static inline I32 operator==(I32 x, int y) { return x->eq(x,y); } 1045 static inline I32 operator==(int x, I32 y) { return y->eq(x,y); } 1046 1047 static inline I32 operator!=(I32 x, I32 y) { return x->neq(x,y); } 1048 static inline I32 operator!=(I32 x, int y) { return x->neq(x,y); } 1049 static inline I32 operator!=(int x, I32 y) { return y->neq(x,y); } 1050 1051 static inline I32 operator< (I32 x, I32a y) { return x->lt(x,y); } 1052 static inline I32 operator< (int x, I32 y) { return y->lt(x,y); } 1053 1054 static inline I32 operator<=(I32 x, I32a y) { return x->lte(x,y); } 1055 static inline I32 operator<=(int x, I32 y) { return y->lte(x,y); } 1056 1057 static inline I32 operator> (I32 x, I32a y) { return x->gt(x,y); } 1058 static inline I32 operator> (int x, I32 y) { return y->gt(x,y); } 1059 1060 static inline I32 operator>=(I32 x, I32a y) { return x->gte(x,y); } 1061 static inline I32 operator>=(int x, I32 y) { return y->gte(x,y); } 1062 1063 1064 static inline F32 operator+(F32 x, F32a y) { return x->add(x,y); } 1065 static inline F32 operator+(float x, F32 y) { return y->add(x,y); } 1066 1067 static inline F32 operator-(F32 x, F32a y) { return x->sub(x,y); } 1068 static inline F32 operator-(float x, F32 y) { return y->sub(x,y); } 1069 1070 static inline F32 operator*(F32 x, F32a y) { return x->mul(x,y); } 1071 static inline F32 operator*(float x, F32 y) { return y->mul(x,y); } 1072 1073 static inline F32 operator/(F32 x, F32 y) { return x->div(x,y); } 1074 static inline F32 operator/(float x, F32 y) { return y->div(x,y); } 1075 min(F32 x,F32a y)1076 static inline F32 min(F32 x, F32a y) { return x->min(x,y); } min(float x,F32 y)1077 static inline F32 min(float x, F32 y) { return y->min(x,y); } 1078 max(F32 x,F32a y)1079 static inline F32 max(F32 x, F32a y) { return x->max(x,y); } max(float x,F32 y)1080 static inline F32 max(float x, F32 y) { return y->max(x,y); } 1081 1082 static inline I32 operator==(F32 x, F32 y) { return x->eq(x,y); } 1083 static inline I32 operator==(F32 x, float y) { return x->eq(x,y); } 1084 static inline I32 operator==(float x, F32 y) { return y->eq(x,y); } 1085 1086 static inline I32 operator!=(F32 x, F32 y) { return x->neq(x,y); } 1087 static inline I32 operator!=(F32 x, float y) { return x->neq(x,y); } 1088 static inline I32 operator!=(float x, F32 y) { return y->neq(x,y); } 1089 1090 static inline I32 operator< (F32 x, F32a y) { return x->lt(x,y); } 1091 static inline I32 operator< (float x, F32 y) { return y->lt(x,y); } 1092 1093 static inline I32 operator<=(F32 x, F32a y) { return x->lte(x,y); } 1094 static inline I32 operator<=(float x, F32 y) { return y->lte(x,y); } 1095 1096 static inline I32 operator> (F32 x, F32a y) { return x->gt(x,y); } 1097 static inline I32 operator> (float x, F32 y) { return y->gt(x,y); } 1098 1099 static inline I32 operator>=(F32 x, F32a y) { return x->gte(x,y); } 1100 static inline I32 operator>=(float x, F32 y) { return y->gte(x,y); } 1101 1102 static inline Q14& operator+=(Q14& x, Q14a y) { return (x = x + y); } 1103 static inline Q14& operator-=(Q14& x, Q14a y) { return (x = x - y); } 1104 static inline Q14& operator*=(Q14& x, Q14a y) { return (x = x * y); } 1105 1106 static inline I32& operator+=(I32& x, I32a y) { return (x = x + y); } 1107 static inline I32& operator-=(I32& x, I32a y) { return (x = x - y); } 1108 static inline I32& operator*=(I32& x, I32a y) { return (x = x * y); } 1109 1110 static inline F32& operator+=(F32& x, F32a y) { return (x = x + y); } 1111 static inline F32& operator-=(F32& x, F32a y) { return (x = x - y); } 1112 static inline F32& operator*=(F32& x, F32a y) { return (x = x * y); } 1113 assert_true(I32 cond,I32 debug)1114 static inline void assert_true(I32 cond, I32 debug) { cond->assert_true(cond,debug); } assert_true(I32 cond,F32 debug)1115 static inline void assert_true(I32 cond, F32 debug) { cond->assert_true(cond,debug); } assert_true(I32 cond)1116 static inline void assert_true(I32 cond) { cond->assert_true(cond); } 1117 store8(Arg ptr,I32 val)1118 static inline void store8 (Arg ptr, I32 val) { val->store8 (ptr, val); } store16(Arg ptr,I32 val)1119 static inline void store16 (Arg ptr, I32 val) { val->store16 (ptr, val); } store32(Arg ptr,I32 val)1120 static inline void store32 (Arg ptr, I32 val) { val->store32 (ptr, val); } storeF(Arg ptr,F32 val)1121 static inline void storeF (Arg ptr, F32 val) { val->storeF (ptr, val); } store64(Arg ptr,I32 lo,I32 hi)1122 static inline void store64 (Arg ptr, I32 lo, I32 hi) { lo ->store64 (ptr, lo,hi); } store128(Arg ptr,I32 lo,I32 hi,int ix)1123 static inline void store128(Arg ptr, I32 lo, I32 hi, int ix) { lo ->store128(ptr, lo,hi, ix); } 1124 gather8(Arg ptr,int off,I32 ix)1125 static inline I32 gather8 (Arg ptr, int off, I32 ix) { return ix->gather8 (ptr, off, ix); } gather16(Arg ptr,int off,I32 ix)1126 static inline I32 gather16(Arg ptr, int off, I32 ix) { return ix->gather16(ptr, off, ix); } gather32(Arg ptr,int off,I32 ix)1127 static inline I32 gather32(Arg ptr, int off, I32 ix) { return ix->gather32(ptr, off, ix); } gatherF(Arg ptr,int off,I32 ix)1128 static inline F32 gatherF (Arg ptr, int off, I32 ix) { return ix->gatherF (ptr, off, ix); } 1129 gather8(Uniform u,I32 ix)1130 static inline I32 gather8 (Uniform u, I32 ix) { return ix->gather8 (u, ix); } gather16(Uniform u,I32 ix)1131 static inline I32 gather16(Uniform u, I32 ix) { return ix->gather16(u, ix); } gather32(Uniform u,I32 ix)1132 static inline I32 gather32(Uniform u, I32 ix) { return ix->gather32(u, ix); } gatherF(Uniform u,I32 ix)1133 static inline F32 gatherF (Uniform u, I32 ix) { return ix->gatherF (u, ix); } 1134 sqrt(F32 x)1135 static inline F32 sqrt(F32 x) { return x-> sqrt(x); } approx_log2(F32 x)1136 static inline F32 approx_log2(F32 x) { return x->approx_log2(x); } approx_pow2(F32 x)1137 static inline F32 approx_pow2(F32 x) { return x->approx_pow2(x); } approx_log(F32 x)1138 static inline F32 approx_log (F32 x) { return x->approx_log (x); } approx_exp(F32 x)1139 static inline F32 approx_exp (F32 x) { return x->approx_exp (x); } 1140 approx_powf(F32 base,F32a exp)1141 static inline F32 approx_powf(F32 base, F32a exp) { return base->approx_powf(base, exp); } approx_powf(float base,F32 exp)1142 static inline F32 approx_powf(float base, F32 exp) { return exp->approx_powf(base, exp); } 1143 approx_sin(F32 radians)1144 static inline F32 approx_sin(F32 radians) { return radians->approx_sin(radians); } approx_cos(F32 radians)1145 static inline F32 approx_cos(F32 radians) { return radians->approx_cos(radians); } approx_tan(F32 radians)1146 static inline F32 approx_tan(F32 radians) { return radians->approx_tan(radians); } 1147 approx_asin(F32 x)1148 static inline F32 approx_asin(F32 x) { return x->approx_asin(x); } approx_acos(F32 x)1149 static inline F32 approx_acos(F32 x) { return x->approx_acos(x); } approx_atan(F32 x)1150 static inline F32 approx_atan(F32 x) { return x->approx_atan(x); } approx_atan2(F32 y,F32 x)1151 static inline F32 approx_atan2(F32 y, F32 x) { return x->approx_atan2(y, x); } 1152 clamp01(F32 x)1153 static inline F32 clamp01(F32 x) { return x-> clamp01(x); } abs(F32 x)1154 static inline F32 abs(F32 x) { return x-> abs(x); } ceil(F32 x)1155 static inline F32 ceil(F32 x) { return x-> ceil(x); } fract(F32 x)1156 static inline F32 fract(F32 x) { return x-> fract(x); } floor(F32 x)1157 static inline F32 floor(F32 x) { return x-> floor(x); } is_NaN(F32 x)1158 static inline I32 is_NaN(F32 x) { return x-> is_NaN(x); } is_finite(F32 x)1159 static inline I32 is_finite(F32 x) { return x->is_finite(x); } 1160 trunc(F32 x)1161 static inline I32 trunc(F32 x) { return x-> trunc(x); } round(F32 x)1162 static inline I32 round(F32 x) { return x-> round(x); } bit_cast(F32 x)1163 static inline I32 bit_cast(F32 x) { return x-> bit_cast(x); } bit_cast(I32 x)1164 static inline F32 bit_cast(I32 x) { return x-> bit_cast(x); } to_F32(I32 x)1165 static inline F32 to_F32(I32 x) { return x-> to_F32(x); } to_half(F32 x)1166 static inline I32 to_half(F32 x) { return x-> to_half(x); } from_half(I32 x)1167 static inline F32 from_half(I32 x) { return x->from_half(x); } 1168 to_F32(Q14 x)1169 static inline F32 to_F32(Q14 x) { return x->to_F32(x); } to_I32(Q14 x)1170 static inline I32 to_I32(Q14 x) { return x->to_I32(x); } to_Q14(F32 x)1171 static inline Q14 to_Q14(F32 x) { return x->to_Q14(x); } to_Q14(I32 x)1172 static inline Q14 to_Q14(I32 x) { return x->to_Q14(x); } 1173 lerp(F32 lo,F32a hi,F32a t)1174 static inline F32 lerp(F32 lo, F32a hi, F32a t) { return lo->lerp(lo,hi,t); } lerp(float lo,F32 hi,F32a t)1175 static inline F32 lerp(float lo, F32 hi, F32a t) { return hi->lerp(lo,hi,t); } lerp(float lo,float hi,F32 t)1176 static inline F32 lerp(float lo, float hi, F32 t) { return t->lerp(lo,hi,t); } 1177 clamp(F32 x,F32a lo,F32a hi)1178 static inline F32 clamp(F32 x, F32a lo, F32a hi) { return x->clamp(x,lo,hi); } clamp(float x,F32 lo,F32a hi)1179 static inline F32 clamp(float x, F32 lo, F32a hi) { return lo->clamp(x,lo,hi); } clamp(float x,float lo,F32 hi)1180 static inline F32 clamp(float x, float lo, F32 hi) { return hi->clamp(x,lo,hi); } 1181 norm(F32 x,F32a y)1182 static inline F32 norm(F32 x, F32a y) { return x->norm(x,y); } norm(float x,F32 y)1183 static inline F32 norm(float x, F32 y) { return y->norm(x,y); } 1184 1185 static inline I32 operator<<(I32 x, int bits) { return x->shl(x, bits); } shl(I32 x,int bits)1186 static inline I32 shl(I32 x, int bits) { return x->shl(x, bits); } shr(I32 x,int bits)1187 static inline I32 shr(I32 x, int bits) { return x->shr(x, bits); } sra(I32 x,int bits)1188 static inline I32 sra(I32 x, int bits) { return x->sra(x, bits); } 1189 1190 static inline Q14 operator<<(Q14 x, int bits) { return x->shl(x, bits); } shl(Q14 x,int bits)1191 static inline Q14 shl(Q14 x, int bits) { return x->shl(x, bits); } shr(Q14 x,int bits)1192 static inline Q14 shr(Q14 x, int bits) { return x->shr(x, bits); } sra(Q14 x,int bits)1193 static inline Q14 sra(Q14 x, int bits) { return x->sra(x, bits); } 1194 static inline Q14 operator>>(Q14 x, int bits) { return x->sra(x, bits); } 1195 1196 static inline I32 operator&(I32 x, I32a y) { return x->bit_and(x,y); } 1197 static inline I32 operator&(int x, I32 y) { return y->bit_and(x,y); } 1198 1199 static inline I32 operator|(I32 x, I32a y) { return x->bit_or (x,y); } 1200 static inline I32 operator|(int x, I32 y) { return y->bit_or (x,y); } 1201 1202 static inline I32 operator^(I32 x, I32a y) { return x->bit_xor(x,y); } 1203 static inline I32 operator^(int x, I32 y) { return y->bit_xor(x,y); } 1204 1205 static inline I32& operator&=(I32& x, I32a y) { return (x = x & y); } 1206 static inline I32& operator|=(I32& x, I32a y) { return (x = x | y); } 1207 static inline I32& operator^=(I32& x, I32a y) { return (x = x ^ y); } 1208 1209 static inline Q14 operator&(Q14 x, Q14a y) { return x->bit_and(x,y); } 1210 static inline Q14 operator&(int x, Q14 y) { return y->bit_and(x,y); } 1211 1212 static inline Q14 operator|(Q14 x, Q14a y) { return x->bit_or(x,y); } 1213 static inline Q14 operator|(int x, Q14 y) { return y->bit_or(x,y); } 1214 1215 static inline Q14 operator^(Q14 x, Q14a y) { return x->bit_xor(x,y); } 1216 static inline Q14 operator^(int x, Q14 y) { return y->bit_xor(x,y); } 1217 1218 static inline Q14& operator&=(Q14& x, Q14a y) { return (x = x & y); } 1219 static inline Q14& operator|=(Q14& x, Q14a y) { return (x = x | y); } 1220 static inline Q14& operator^=(Q14& x, Q14a y) { return (x = x ^ y); } 1221 bit_clear(I32 x,I32a y)1222 static inline I32 bit_clear(I32 x, I32a y) { return x->bit_clear(x,y); } bit_clear(int x,I32 y)1223 static inline I32 bit_clear(int x, I32 y) { return y->bit_clear(x,y); } 1224 select(I32 cond,I32a t,I32a f)1225 static inline I32 select(I32 cond, I32a t, I32a f) { return cond->select(cond,t,f); } select(I32 cond,F32a t,F32a f)1226 static inline F32 select(I32 cond, F32a t, F32a f) { return cond->select(cond,t,f); } select(Q14 cond,Q14a t,Q14a f)1227 static inline Q14 select(Q14 cond, Q14a t, Q14a f) { return cond->select(cond,t,f); } 1228 extract(I32 x,int bits,I32a z)1229 static inline I32 extract(I32 x, int bits, I32a z) { return x->extract(x,bits,z); } extract(int x,int bits,I32 z)1230 static inline I32 extract(int x, int bits, I32 z) { return z->extract(x,bits,z); } pack(I32 x,I32a y,int bits)1231 static inline I32 pack (I32 x, I32a y, int bits) { return x->pack (x,y,bits); } pack(int x,I32 y,int bits)1232 static inline I32 pack (int x, I32 y, int bits) { return y->pack (x,y,bits); } 1233 1234 static inline I32 operator~(I32 x) { return ~0 ^ x; } 1235 static inline Q14 operator~(Q14 x) { return ~0 ^ x; } 1236 static inline I32 operator-(I32 x) { return 0 - x; } 1237 static inline Q14 operator-(Q14 x) { return 0 - x; } 1238 static inline F32 operator-(F32 x) { return 0.0f - x; } 1239 from_unorm(int bits,I32 x)1240 static inline F32 from_unorm(int bits, I32 x) { return x->from_unorm(bits,x); } to_unorm(int bits,F32 x)1241 static inline I32 to_unorm(int bits, F32 x) { return x-> to_unorm(bits,x); } 1242 store(PixelFormat f,Arg p,Color c)1243 static inline bool store(PixelFormat f, Arg p, Color c) { return c->store(f,p,c); } gather(PixelFormat f,Arg p,int off,I32 ix)1244 static inline Color gather(PixelFormat f, Arg p, int off, I32 ix) { 1245 return ix->gather(f,p,off,ix); 1246 } gather(PixelFormat f,Uniform u,I32 ix)1247 static inline Color gather(PixelFormat f, Uniform u, I32 ix) { 1248 return ix->gather(f,u,ix); 1249 } 1250 premul(F32 * r,F32 * g,F32 * b,F32 a)1251 static inline void premul(F32* r, F32* g, F32* b, F32 a) { a-> premul(r,g,b,a); } unpremul(F32 * r,F32 * g,F32 * b,F32 a)1252 static inline void unpremul(F32* r, F32* g, F32* b, F32 a) { a->unpremul(r,g,b,a); } 1253 premul(Color c)1254 static inline Color premul(Color c) { return c-> premul(c); } unpremul(Color c)1255 static inline Color unpremul(Color c) { return c->unpremul(c); } 1256 lerp(Color lo,Color hi,F32 t)1257 static inline Color lerp(Color lo, Color hi, F32 t) { return t->lerp(lo,hi,t); } 1258 blend(SkBlendMode m,Color s,Color d)1259 static inline Color blend(SkBlendMode m, Color s, Color d) { return s->blend(m,s,d); } 1260 clamp01(Color c)1261 static inline Color clamp01(Color c) { return c->clamp01(c); } 1262 to_hsla(Color c)1263 static inline HSLA to_hsla(Color c) { return c->to_hsla(c); } to_rgba(HSLA c)1264 static inline Color to_rgba(HSLA c) { return c->to_rgba(c); } 1265 1266 // Evaluate polynomials: ax^n + bx^(n-1) + ... for n >= 1 1267 template <typename... Rest> poly(F32 x,F32a a,F32a b,Rest...rest)1268 static inline F32 poly(F32 x, F32a a, F32a b, Rest... rest) { 1269 if constexpr (sizeof...(rest) == 0) { 1270 return x*a+b; 1271 } else { 1272 return poly(x, x*a+b, rest...); 1273 } 1274 } 1275 } // namespace skvm 1276 1277 #endif//SkVM_DEFINED 1278