• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 #ifndef SKSL_STANDALONE
9 
10 #include "include/core/SkPoint3.h"
11 #include "include/private/SkVx.h"
12 #include "src/core/SkUtils.h"   // sk_unaligned_load
13 #include "src/sksl/SkSLByteCode.h"
14 #include "src/sksl/SkSLByteCodeGenerator.h"
15 #include "src/sksl/SkSLExternalValue.h"
16 
17 #include <vector>
18 
19 namespace SkSL {
20 
21 #if defined(SK_ENABLE_SKSL_INTERPRETER)
22 
23 namespace Interpreter {
24 
25 constexpr int VecWidth = ByteCode::kVecWidth;
26 
27 using F32 = skvx::Vec<VecWidth, float>;
28 using I32 = skvx::Vec<VecWidth, int32_t>;
29 using U32 = skvx::Vec<VecWidth, uint32_t>;
30 
31 #define READ8() (*(ip++))
32 #define READ16() (ip += 2, sk_unaligned_load<uint16_t>(ip - 2))
33 #define READ32() (ip += 4, sk_unaligned_load<uint32_t>(ip - 4))
34 
35 #define VECTOR_DISASSEMBLE(op, text)                          \
36     case ByteCodeInstruction::op: printf(text); break;        \
37     case ByteCodeInstruction::op##2: printf(text "2"); break; \
38     case ByteCodeInstruction::op##3: printf(text "3"); break; \
39     case ByteCodeInstruction::op##4: printf(text "4"); break;
40 
41 #define VECTOR_MATRIX_DISASSEMBLE(op, text)                   \
42     case ByteCodeInstruction::op: printf(text); break;        \
43     case ByteCodeInstruction::op##2: printf(text "2"); break; \
44     case ByteCodeInstruction::op##3: printf(text "3"); break; \
45     case ByteCodeInstruction::op##4: printf(text "4"); break; \
46     case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
47 
disassemble_instruction(const uint8_t * ip)48 static const uint8_t* disassemble_instruction(const uint8_t* ip) {
49     switch ((ByteCodeInstruction) READ16()) {
50         VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
51         VECTOR_DISASSEMBLE(kAddI, "addi")
52         case ByteCodeInstruction::kAndB: printf("andb"); break;
53         case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
54         case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
55         case ByteCodeInstruction::kCallExternal: {
56             int argumentCount = READ8();
57             int returnCount = READ8();
58             int externalValue = READ8();
59             printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
60             break;
61         }
62         case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
63         VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
64         VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
65         VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
66         VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
67         VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
68         VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
69         VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
70         VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
71         VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
72         VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
73         VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
74         VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
75         VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
76         VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
77         VECTOR_DISASSEMBLE(kCompareULT, "compareult")
78         VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
79         VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
80         VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
81         VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
82         VECTOR_DISASSEMBLE(kCos, "cos")
83         VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
84         VECTOR_DISASSEMBLE(kDivideS, "divideS")
85         VECTOR_DISASSEMBLE(kDivideU, "divideu")
86         VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
87         case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
88         case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
89         case ByteCodeInstruction::kInverse4x4: printf("inverse4x4"); break;
90         case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
91         case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
92         case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
93         case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
94         case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
95         case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
96         case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
97         case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
98         case ByteCodeInstruction::kLoadSwizzle: {
99             int target = READ8();
100             int count = READ8();
101             printf("loadswizzle %d %d", target, count);
102             for (int i = 0; i < count; ++i) {
103                 printf(", %d", READ8());
104             }
105             break;
106         }
107         case ByteCodeInstruction::kLoadSwizzleGlobal: {
108             int target = READ8();
109             int count = READ8();
110             printf("loadswizzleglobal %d %d", target, count);
111             for (int i = 0; i < count; ++i) {
112                 printf(", %d", READ8());
113             }
114             break;
115         }
116         case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
117         case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
118             break;
119         case ByteCodeInstruction::kMatrixToMatrix: {
120             int srcCols = READ8();
121             int srcRows = READ8();
122             int dstCols = READ8();
123             int dstRows = READ8();
124             printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
125             break;
126         }
127         case ByteCodeInstruction::kMatrixMultiply: {
128             int lCols = READ8();
129             int lRows = READ8();
130             int rCols = READ8();
131             printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
132             break;
133         }
134         VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
135         VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
136         VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
137         VECTOR_DISASSEMBLE(kNegateI, "negatei")
138         case ByteCodeInstruction::kNotB: printf("notb"); break;
139         case ByteCodeInstruction::kOrB: printf("orb"); break;
140         VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
141         case ByteCodeInstruction::kPushImmediate: {
142             uint32_t v = READ32();
143             union { uint32_t u; float f; } pun = { v };
144             printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
145             break;
146         }
147         case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
148         case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
149         case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
150         case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
151         VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
152         VECTOR_DISASSEMBLE(kRemainderS, "remainders")
153         VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
154         case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
155         case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
156         case ByteCodeInstruction::kScalarToMatrix: {
157             int cols = READ8();
158             int rows = READ8();
159             printf("scalartomatrix %dx%d", cols, rows);
160             break;
161         }
162         VECTOR_DISASSEMBLE(kSin, "sin")
163         VECTOR_DISASSEMBLE(kSqrt, "sqrt")
164         case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
165         case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
166         case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
167         case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
168         case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
169         case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
170         case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
171         case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
172         case ByteCodeInstruction::kStoreSwizzle: {
173             int target = READ8();
174             int count = READ8();
175             printf("storeswizzle %d %d", target, count);
176             for (int i = 0; i < count; ++i) {
177                 printf(", %d", READ8());
178             }
179             break;
180         }
181         case ByteCodeInstruction::kStoreSwizzleGlobal: {
182             int target = READ8();
183             int count = READ8();
184             printf("storeswizzleglobal %d %d", target, count);
185             for (int i = 0; i < count; ++i) {
186                 printf(", %d", READ8());
187             }
188             break;
189         }
190         case ByteCodeInstruction::kStoreSwizzleIndirect: {
191             int count = READ8();
192             printf("storeswizzleindirect %d", count);
193             for (int i = 0; i < count; ++i) {
194                 printf(", %d", READ8());
195             }
196             break;
197         }
198         case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
199             int count = READ8();
200             printf("storeswizzleindirectglobal %d", count);
201             for (int i = 0; i < count; ++i) {
202                 printf(", %d", READ8());
203             }
204             break;
205         }
206         case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
207         case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
208             break;
209         VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
210         VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
211         case ByteCodeInstruction::kSwizzle: {
212             printf("swizzle %d, ", READ8());
213             int count = READ8();
214             printf("%d", count);
215             for (int i = 0; i < count; ++i) {
216                 printf(", %d", READ8());
217             }
218             break;
219         }
220         VECTOR_DISASSEMBLE(kTan, "tan")
221         case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
222         case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
223         case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
224         case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
225         case ByteCodeInstruction::kXorB: printf("xorb"); break;
226         case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
227         case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
228         case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
229         case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
230         case ByteCodeInstruction::kBranchIfAllFalse:
231             printf("branchifallfalse %d", READ16());
232             break;
233         case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
234         case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
235         case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
236         case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
237         case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
238         case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
239         default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
240     }
241     return ip;
242 }
243 
244 #define VECTOR_BINARY_OP(base, field, op)                             \
245     case ByteCodeInstruction::base ## 4:                              \
246         sp[-4] = sp[-4].field op sp[0].field;                         \
247         POP();                                                        \
248         /* fall through */                                            \
249     case ByteCodeInstruction::base ## 3: {                            \
250         int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
251         sp[count] = sp[count].field op sp[0].field;                   \
252         POP();                                                        \
253     }   /* fall through */                                            \
254     case ByteCodeInstruction::base ## 2: {                            \
255         int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
256         sp[count] = sp[count].field op sp[0].field;                   \
257         POP();                                                        \
258     }   /* fall through */                                            \
259     case ByteCodeInstruction::base: {                                 \
260         int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
261         sp[count] = sp[count].field op sp[0].field;                   \
262         POP();                                                        \
263         break;                                                        \
264     }
265 
266 #define VECTOR_MATRIX_BINARY_OP(base, field, op)                      \
267     VECTOR_BINARY_OP(base, field, op)                                 \
268     case ByteCodeInstruction::base ## N: {                            \
269         int count = READ8();                                          \
270         for (int i = count; i > 0; --i) {                             \
271             sp[-count] = sp[-count].field op sp[0].field;             \
272             POP();                                                    \
273         }                                                             \
274         break;                                                        \
275     }
276 
277 #define VECTOR_BINARY_FN(base, field, fn)                              \
278     case ByteCodeInstruction::base ## 4:                               \
279         sp[-4] = fn(sp[-4].field, sp[0].field);                        \
280         POP();                                                         \
281         /* fall through */                                             \
282     case ByteCodeInstruction::base ## 3: {                             \
283         int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
284         sp[target] = fn(sp[target].field, sp[0].field);                \
285         POP();                                                         \
286     }   /* fall through */                                             \
287     case ByteCodeInstruction::base ## 2: {                             \
288         int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
289         sp[target] = fn(sp[target].field, sp[0].field);                \
290         POP();                                                         \
291     }   /* fall through */                                             \
292     case ByteCodeInstruction::base: {                                  \
293         int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
294         sp[target] = fn(sp[target].field, sp[0].field);                \
295         POP();                                                         \
296         break;                                                         \
297     }
298 
299 #define VECTOR_UNARY_FN(base, fn, field)                            \
300     case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
301     case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
302     case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
303     case ByteCodeInstruction::base:      sp[ 0] = fn(sp[ 0].field); \
304                                          break;
305 
306 #define VECTOR_UNARY_FN_VEC(base, fn)                               \
307     case ByteCodeInstruction::base ## 4:                            \
308     case ByteCodeInstruction::base ## 3:                            \
309     case ByteCodeInstruction::base ## 2:                            \
310     case ByteCodeInstruction::base     : {                          \
311         int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
312         float* v = (float*)sp - count + 1;                          \
313         for (int i = VecWidth * count; i > 0; --i, ++v) {           \
314             *v = fn(*v);                                            \
315         }                                                           \
316         break;                                                      \
317     }
318 
319 union VValue {
VValue()320     VValue() {}
321 
VValue(F32 f)322     VValue(F32 f)
323         : fFloat(f) {
324     }
325 
VValue(I32 s)326     VValue(I32 s)
327         : fSigned(s) {
328     }
329 
VValue(U32 u)330     VValue(U32 u)
331         : fUnsigned(u) {
332     }
333 
334     F32 fFloat;
335     I32 fSigned;
336     U32 fUnsigned;
337 };
338 
339 struct StackFrame {
340     const uint8_t* fCode;
341     const uint8_t* fIP;
342     VValue* fStack;
343     int fParameterCount;
344 };
345 
346 // TODO: trunc on integers?
347 template <typename T>
vec_mod(T a,T b)348 static T vec_mod(T a, T b) {
349     return a - skvx::trunc(a / b) * b;
350 }
351 
352 #define spf(index)  sp[index].fFloat
353 
innerRun(const ByteCode * byteCode,const ByteCodeFunction * f,VValue * stack,float * outReturn[],VValue globals[],bool stripedOutput,int N,int baseIndex)354 static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
355                      float* outReturn[], VValue globals[], bool stripedOutput, int N,
356                      int baseIndex) {
357     // Needs to be the first N non-negative integers, at least as large as VecWidth
358     static const Interpreter::I32 gLanes = {
359         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
360     };
361 
362     VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
363 
364     auto POP =  [&]           { SkASSERT(sp     >= stack); return *(sp--); };
365     auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v;    };
366 
367     const uint8_t* code = f->fCode.data();
368     const uint8_t* ip = code;
369     std::vector<StackFrame> frames;
370 
371     I32 condStack[16];  // Independent condition masks
372     I32 maskStack[16];  // Combined masks (eg maskStack[0] & maskStack[1] & ...)
373     I32 contStack[16];  // Continue flags for loops
374     I32 loopStack[16];  // Loop execution masks
375     condStack[0] = maskStack[0] = (gLanes < N);
376     contStack[0] = I32( 0);
377     loopStack[0] = I32(~0);
378     I32* condPtr = condStack;
379     I32* maskPtr = maskStack;
380     I32* contPtr = contStack;
381     I32* loopPtr = loopStack;
382 
383     if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
384         f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
385         return false;
386     }
387 
388     auto mask = [&]() { return *maskPtr & *loopPtr; };
389 
390     for (;;) {
391 #ifdef TRACE
392         printf("at %3d  ", (int) (ip - code));
393         disassemble_instruction(ip);
394         printf("\n");
395 #endif
396         ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
397         switch (inst) {
398             VECTOR_BINARY_OP(kAddI, fSigned, +)
399             VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
400 
401             // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
402             case ByteCodeInstruction::kAndB:
403                 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
404                 POP();
405                 break;
406             case ByteCodeInstruction::kNotB:
407                 sp[0] = ~sp[0].fSigned;
408                 break;
409             case ByteCodeInstruction::kOrB:
410                 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
411                 POP();
412                 break;
413             case ByteCodeInstruction::kXorB:
414                 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
415                 POP();
416                 break;
417 
418             case ByteCodeInstruction::kBranch:
419                 ip = code + READ16();
420                 break;
421 
422             case ByteCodeInstruction::kCall: {
423                 // Precursor code reserved space for the return value, and pushed all parameters to
424                 // the stack. Update our bottom of stack to point at the first parameter, and our
425                 // sp to point past those parameters (plus space for locals).
426                 int target = READ8();
427                 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
428                 if (skvx::any(mask())) {
429                     frames.push_back({ code, ip, stack, fun->fParameterCount });
430                     ip = code = fun->fCode.data();
431                     stack = sp - fun->fParameterCount + 1;
432                     sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
433                 }
434                 break;
435             }
436 
437             case ByteCodeInstruction::kCallExternal: {
438                 int argumentCount = READ8();
439                 int returnCount = READ8();
440                 int target = READ8();
441                 ExternalValue* v = byteCode->fExternalValues[target];
442                 sp -= argumentCount - 1;
443 
444                 float tmpArgs[4];
445                 float tmpReturn[4];
446                 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
447                 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
448 
449                 I32 m = mask();
450                 for (int i = 0; i < VecWidth; ++i) {
451                     if (m[i]) {
452                         for (int j = 0; j < argumentCount; ++j) {
453                             tmpArgs[j] = sp[j].fFloat[i];
454                         }
455                         v->call(baseIndex + i, tmpArgs, tmpReturn);
456                         for (int j = 0; j < returnCount; ++j) {
457                             sp[j].fFloat[i] = tmpReturn[j];
458                         }
459                     }
460                 }
461                 sp += returnCount - 1;
462                 break;
463             }
464 
465             case ByteCodeInstruction::kClampIndex: {
466                 int length = READ8();
467                 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
468                     return false;
469                 }
470                 break;
471             }
472 
473             VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
474             VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
475             VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
476             VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
477             VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
478             VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
479             VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
480             VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
481             VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
482             VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
483             VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
484             VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
485             VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
486             VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
487             VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
488             VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
489 
490             case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
491             case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
492             case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
493             case ByteCodeInstruction::kConvertFtoI:  sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
494                                                      break;
495 
496             case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
497             case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
498             case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
499             case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
500                                                      break;
501 
502             case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
503             case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
504             case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
505             case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
506                                                      break;
507 
508             VECTOR_UNARY_FN_VEC(kCos, cosf)
509 
510             VECTOR_BINARY_OP(kDivideS, fSigned, /)
511             VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
512             VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
513 
514             case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
515             case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
516             case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
517             case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
518                                              break;
519 
520             case ByteCodeInstruction::kDupN: {
521                 int count = READ8();
522                 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
523                 sp += count;
524                 break;
525             }
526 
527             case ByteCodeInstruction::kInverse2x2: {
528                 F32 a = sp[-3].fFloat,
529                     b = sp[-2].fFloat,
530                     c = sp[-1].fFloat,
531                     d = sp[ 0].fFloat;
532                 F32 idet = F32(1) / (a*d - b*c);
533                 sp[-3].fFloat = d * idet;
534                 sp[-2].fFloat = -b * idet;
535                 sp[-1].fFloat = -c * idet;
536                 sp[ 0].fFloat = a * idet;
537                 break;
538             }
539             case ByteCodeInstruction::kInverse3x3: {
540                 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
541                     a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
542                     a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
543                 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
544                                      a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
545                 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
546                 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
547                 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
548                 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
549                 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
550                 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
551                 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
552                 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
553                 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
554                 break;
555             }
556             case ByteCodeInstruction::kInverse4x4: {
557                 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
558                     a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
559                     a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
560                     a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf(  0);
561 
562                 F32 b00 = a00 * a11 - a01 * a10,
563                     b01 = a00 * a12 - a02 * a10,
564                     b02 = a00 * a13 - a03 * a10,
565                     b03 = a01 * a12 - a02 * a11,
566                     b04 = a01 * a13 - a03 * a11,
567                     b05 = a02 * a13 - a03 * a12,
568                     b06 = a20 * a31 - a21 * a30,
569                     b07 = a20 * a32 - a22 * a30,
570                     b08 = a20 * a33 - a23 * a30,
571                     b09 = a21 * a32 - a22 * a31,
572                     b10 = a21 * a33 - a23 * a31,
573                     b11 = a22 * a33 - a23 * a32;
574 
575                 F32 idet = F32(1) /
576                            (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
577 
578                 b00 *= idet;
579                 b01 *= idet;
580                 b02 *= idet;
581                 b03 *= idet;
582                 b04 *= idet;
583                 b05 *= idet;
584                 b06 *= idet;
585                 b07 *= idet;
586                 b08 *= idet;
587                 b09 *= idet;
588                 b10 *= idet;
589                 b11 *= idet;
590 
591                 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
592                 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
593                 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
594                 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
595                 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
596                 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
597                 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
598                 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
599                 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
600                 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
601                 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
602                 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
603                 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
604                 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
605                 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
606                 spf(  0) = a20 * b03 - a21 * b01 + a22 * b00;
607                 break;
608             }
609 
610             case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
611             case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
612             case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
613             case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
614                                               ++ip;
615                                               sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
616                                               break;
617 
618             case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
619             case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
620             case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
621             case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
622                                                     ++ip;
623                                                     sp += (int)inst -
624                                                           (int)ByteCodeInstruction::kLoadGlobal + 1;
625                                                     break;
626 
627             case ByteCodeInstruction::kLoadExtended: {
628                 int count = READ8();
629                 I32 src = POP().fSigned;
630                 I32 m = mask();
631                 for (int i = 0; i < count; ++i) {
632                     for (int j = 0; j < VecWidth; ++j) {
633                         if (m[j]) {
634                             sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
635                         }
636                     }
637                 }
638                 sp += count;
639                 break;
640             }
641 
642             case ByteCodeInstruction::kLoadExtendedGlobal: {
643                 int count = READ8();
644                 I32 src = POP().fSigned;
645                 I32 m = mask();
646                 for (int i = 0; i < count; ++i) {
647                     for (int j = 0; j < VecWidth; ++j) {
648                         if (m[j]) {
649                             sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
650                         }
651                     }
652                 }
653                 sp += count;
654                 break;
655             }
656 
657             case ByteCodeInstruction::kLoadSwizzle: {
658                 int src = READ8();
659                 int count = READ8();
660                 for (int i = 0; i < count; ++i) {
661                     PUSH(stack[src + *(ip + i)]);
662                 }
663                 ip += count;
664                 break;
665             }
666 
667             case ByteCodeInstruction::kLoadSwizzleGlobal: {
668                 int src = READ8();
669                 int count = READ8();
670                 for (int i = 0; i < count; ++i) {
671                     PUSH(globals[src + *(ip + i)]);
672                 }
673                 ip += count;
674                 break;
675             }
676 
677             case ByteCodeInstruction::kMatrixToMatrix: {
678                 int srcCols = READ8();
679                 int srcRows = READ8();
680                 int dstCols = READ8();
681                 int dstRows = READ8();
682                 SkASSERT(srcCols >= 2 && srcCols <= 4);
683                 SkASSERT(srcRows >= 2 && srcRows <= 4);
684                 SkASSERT(dstCols >= 2 && dstCols <= 4);
685                 SkASSERT(dstRows >= 2 && dstRows <= 4);
686                 F32 tmp[16];
687                 memset(tmp, 0, sizeof(tmp));
688                 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
689                 for (int c = srcCols - 1; c >= 0; --c) {
690                     for (int r = srcRows - 1; r >= 0; --r) {
691                         tmp[c*4 + r] = POP().fFloat;
692                     }
693                 }
694                 for (int c = 0; c < dstCols; ++c) {
695                     for (int r = 0; r < dstRows; ++r) {
696                         PUSH(tmp[c*4 + r]);
697                     }
698                 }
699                 break;
700             }
701 
702             case ByteCodeInstruction::kMatrixMultiply: {
703                 int lCols = READ8();
704                 int lRows = READ8();
705                 int rCols = READ8();
706                 int rRows = lCols;
707                 F32 tmp[16] = { 0.0f };
708                 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
709                 F32* A = B - (lCols * lRows);
710                 for (int c = 0; c < rCols; ++c) {
711                     for (int r = 0; r < lRows; ++r) {
712                         for (int j = 0; j < lCols; ++j) {
713                             tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
714                         }
715                     }
716                 }
717                 sp -= (lCols * lRows) + (rCols * rRows);
718                 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
719                 sp += (rCols * lRows);
720                 break;
721             }
722 
723             VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
724             VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
725 
726             case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
727             case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
728             case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
729             case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
730                                                  break;
731 
732             case ByteCodeInstruction::kNegateFN: {
733                 int count = READ8();
734                 for (int i = count - 1; i >= 0; --i) {
735                     sp[-i] = -sp[-i].fFloat;
736                 }
737                 break;
738             }
739 
740             case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
741             case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
742             case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
743             case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
744                                                  break;
745 
746             case ByteCodeInstruction::kPop4: POP();
747             case ByteCodeInstruction::kPop3: POP();
748             case ByteCodeInstruction::kPop2: POP();
749             case ByteCodeInstruction::kPop : POP();
750                                              break;
751 
752             case ByteCodeInstruction::kPopN:
753                 sp -= READ8();
754                 break;
755 
756             case ByteCodeInstruction::kPushImmediate:
757                 PUSH(U32(READ32()));
758                 break;
759 
760             case ByteCodeInstruction::kReadExternal:
761             case ByteCodeInstruction::kReadExternal2:
762             case ByteCodeInstruction::kReadExternal3:
763             case ByteCodeInstruction::kReadExternal4: {
764                 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
765                 int src = READ8();
766                 float tmp[4];
767                 I32 m = mask();
768                 for (int i = 0; i < VecWidth; ++i) {
769                     if (m[i]) {
770                         byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
771                         for (int j = 0; j < count; ++j) {
772                             sp[j + 1].fFloat[i] = tmp[j];
773                         }
774                     }
775                 }
776                 sp += count;
777                 break;
778             }
779 
780             VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
781             VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
782             VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
783 
784             case ByteCodeInstruction::kReserve:
785                 sp += READ8();
786                 break;
787 
788             case ByteCodeInstruction::kReturn: {
789                 int count = READ8();
790                 if (frames.empty()) {
791                     if (outReturn) {
792                         VValue* src = sp - count + 1;
793                         if (stripedOutput) {
794                             for (int i = 0; i < count; ++i) {
795                                 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
796                                 ++src;
797                             }
798                         } else {
799                             float* outPtr = outReturn[0];
800                             for (int i = 0; i < count; ++i) {
801                                 for (int j = 0; j < N; ++j) {
802                                     outPtr[count * j] = src->fFloat[j];
803                                 }
804                                 ++outPtr;
805                                 ++src;
806                             }
807                         }
808                     }
809                     return true;
810                 } else {
811                     // When we were called, the caller reserved stack space for their copy of our
812                     // return value, then 'stack' was positioned after that, where our parameters
813                     // were placed. Copy our return values to their reserved area.
814                     memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
815 
816                     // Now move the stack pointer to the end of the passed-in parameters. This odd
817                     // calling convention requires the caller to pop the arguments after calling,
818                     // but allows them to store any out-parameters back during that unwinding.
819                     // After that sequence finishes, the return value will be the top of the stack.
820                     const StackFrame& frame(frames.back());
821                     sp = stack + frame.fParameterCount - 1;
822                     stack = frame.fStack;
823                     code = frame.fCode;
824                     ip = frame.fIP;
825                     frames.pop_back();
826                     break;
827                 }
828             }
829 
830             case ByteCodeInstruction::kScalarToMatrix: {
831                 int cols = READ8();
832                 int rows = READ8();
833                 VValue v = POP();
834                 for (int c = 0; c < cols; ++c) {
835                     for (int r = 0; r < rows; ++r) {
836                         PUSH(c == r ? v : F32(0.0f));
837                     }
838                 }
839                 break;
840             }
841 
842             VECTOR_UNARY_FN_VEC(kSin, sinf)
843             VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
844 
845             case ByteCodeInstruction::kStore4:
846                 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
847             case ByteCodeInstruction::kStore3:
848                 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
849             case ByteCodeInstruction::kStore2:
850                 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
851             case ByteCodeInstruction::kStore :
852                 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
853                 ++ip;
854                 break;
855 
856             case ByteCodeInstruction::kStoreGlobal4:
857                 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
858             case ByteCodeInstruction::kStoreGlobal3:
859                 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
860             case ByteCodeInstruction::kStoreGlobal2:
861                 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
862             case ByteCodeInstruction::kStoreGlobal :
863                 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
864                 ++ip;
865                 break;
866 
867             case ByteCodeInstruction::kStoreExtended: {
868                 int count = READ8();
869                 I32 target = POP().fSigned;
870                 VValue* src = sp - count + 1;
871                 I32 m = mask();
872                 for (int i = 0; i < count; ++i) {
873                     for (int j = 0; j < VecWidth; ++j) {
874                         if (m[j]) {
875                             stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
876                         }
877                     }
878                 }
879                 sp -= count;
880                 break;
881             }
882             case ByteCodeInstruction::kStoreExtendedGlobal: {
883                 int count = READ8();
884                 I32 target = POP().fSigned;
885                 VValue* src = sp - count + 1;
886                 I32 m = mask();
887                 for (int i = 0; i < count; ++i) {
888                     for (int j = 0; j < VecWidth; ++j) {
889                         if (m[j]) {
890                             globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
891                         }
892                     }
893                 }
894                 sp -= count;
895                 break;
896             }
897 
898             case ByteCodeInstruction::kStoreSwizzle: {
899                 int target = READ8();
900                 int count = READ8();
901                 for (int i = count - 1; i >= 0; --i) {
902                     stack[target + *(ip + i)] = skvx::if_then_else(
903                             mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
904                 }
905                 ip += count;
906                 break;
907             }
908 
909             case ByteCodeInstruction::kStoreSwizzleGlobal: {
910                 int target = READ8();
911                 int count = READ8();
912                 for (int i = count - 1; i >= 0; --i) {
913                     globals[target + *(ip + i)] = skvx::if_then_else(
914                             mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
915                 }
916                 ip += count;
917                 break;
918             }
919 
920             case ByteCodeInstruction::kStoreSwizzleIndirect: {
921                 int count = READ8();
922                 I32 target = POP().fSigned;
923                 I32 m = mask();
924                 for (int i = count - 1; i >= 0; --i) {
925                     I32 v = POP().fSigned;
926                     for (int j = 0; j < VecWidth; ++j) {
927                         if (m[j]) {
928                             stack[target[j] + *(ip + i)].fSigned[j] = v[j];
929                         }
930                     }
931                 }
932                 ip += count;
933                 break;
934             }
935 
936             case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
937                 int count = READ8();
938                 I32 target = POP().fSigned;
939                 I32 m = mask();
940                 for (int i = count - 1; i >= 0; --i) {
941                     I32 v = POP().fSigned;
942                     for (int j = 0; j < VecWidth; ++j) {
943                         if (m[j]) {
944                             globals[target[j] + *(ip + i)].fSigned[j] = v[j];
945                         }
946                     }
947                 }
948                 ip += count;
949                 break;
950             }
951 
952             VECTOR_BINARY_OP(kSubtractI, fSigned, -)
953             VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
954 
955             case ByteCodeInstruction::kSwizzle: {
956                 VValue tmp[4];
957                 for (int i = READ8() - 1; i >= 0; --i) {
958                     tmp[i] = POP();
959                 }
960                 for (int i = READ8() - 1; i >= 0; --i) {
961                     PUSH(tmp[READ8()]);
962                 }
963                 break;
964             }
965 
966             VECTOR_UNARY_FN_VEC(kTan, tanf)
967 
968             case ByteCodeInstruction::kWriteExternal:
969             case ByteCodeInstruction::kWriteExternal2:
970             case ByteCodeInstruction::kWriteExternal3:
971             case ByteCodeInstruction::kWriteExternal4: {
972                 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
973                 int target = READ8();
974                 float tmp[4];
975                 I32 m = mask();
976                 sp -= count;
977                 for (int i = 0; i < VecWidth; ++i) {
978                     if (m[i]) {
979                         for (int j = 0; j < count; ++j) {
980                             tmp[j] = sp[j + 1].fFloat[i];
981                         }
982                         byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
983                     }
984                 }
985                 break;
986             }
987 
988             case ByteCodeInstruction::kMaskPush:
989                 condPtr[1] = POP().fSigned;
990                 maskPtr[1] = maskPtr[0] & condPtr[1];
991                 ++condPtr; ++maskPtr;
992                 break;
993             case ByteCodeInstruction::kMaskPop:
994                 --condPtr; --maskPtr;
995                 break;
996             case ByteCodeInstruction::kMaskNegate:
997                 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
998                 break;
999             case ByteCodeInstruction::kMaskBlend: {
1000                 int count = READ8();
1001                 I32 m = condPtr[0];
1002                 --condPtr; --maskPtr;
1003                 for (int i = 0; i < count; ++i) {
1004                     sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1005                     --sp;
1006                 }
1007                 break;
1008             }
1009             case ByteCodeInstruction::kBranchIfAllFalse: {
1010                 int target = READ16();
1011                 if (!skvx::any(mask())) {
1012                     ip = code + target;
1013                 }
1014                 break;
1015             }
1016 
1017             case ByteCodeInstruction::kLoopBegin:
1018                 contPtr[1] = 0;
1019                 loopPtr[1] = loopPtr[0];
1020                 ++contPtr; ++loopPtr;
1021                 break;
1022             case ByteCodeInstruction::kLoopNext:
1023                 *loopPtr |= *contPtr;
1024                 *contPtr = 0;
1025                 break;
1026             case ByteCodeInstruction::kLoopMask:
1027                 *loopPtr &= POP().fSigned;
1028                 break;
1029             case ByteCodeInstruction::kLoopEnd:
1030                 --contPtr; --loopPtr;
1031                 break;
1032             case ByteCodeInstruction::kLoopBreak:
1033                 *loopPtr &= ~mask();
1034                 break;
1035             case ByteCodeInstruction::kLoopContinue: {
1036                 I32 m = mask();
1037                 *contPtr |=  m;
1038                 *loopPtr &= ~m;
1039                 break;
1040             }
1041 
1042             default:
1043                 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
1044                 return false;
1045         }
1046     }
1047     // Unreachable
1048     return false;
1049 }
1050 
1051 } // namespace Interpreter
1052 
1053 #endif // SK_ENABLE_SKSL_INTERPRETER
1054 
1055 #undef spf
1056 
disassemble() const1057 void ByteCodeFunction::disassemble() const {
1058 #if defined(SK_ENABLE_SKSL_INTERPRETER)
1059     const uint8_t* ip = fCode.data();
1060     while (ip < fCode.data() + fCode.size()) {
1061         printf("%d: ", (int)(ip - fCode.data()));
1062         ip = Interpreter::disassemble_instruction(ip);
1063         printf("\n");
1064     }
1065 #endif
1066 }
1067 
run(const ByteCodeFunction * f,float * args,float * outReturn,int N,const float * uniforms,int uniformCount) const1068 bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
1069                    const float* uniforms, int uniformCount) const {
1070 #if defined(SK_ENABLE_SKSL_INTERPRETER)
1071 #ifdef TRACE
1072     f->disassemble();
1073 #endif
1074     Interpreter::VValue stack[128];
1075     int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1076     if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
1077         return false;
1078     }
1079 
1080     if (uniformCount != (int)fInputSlots.size()) {
1081         return false;
1082     }
1083 
1084     Interpreter::VValue globals[32];
1085     if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1086         return false;
1087     }
1088     for (uint8_t slot : fInputSlots) {
1089         globals[slot].fFloat = *uniforms++;
1090     }
1091 
1092     int baseIndex = 0;
1093 
1094     while (N) {
1095         int w = std::min(N, Interpreter::VecWidth);
1096 
1097         // Transpose args into stack
1098         {
1099             float* src = args;
1100             for (int i = 0; i < w; ++i) {
1101                 float* dst = (float*)stack + i;
1102                 for (int j = f->fParameterCount; j > 0; --j) {
1103                     *dst = *src++;
1104                     dst += Interpreter::VecWidth;
1105                 }
1106             }
1107         }
1108 
1109         bool stripedOutput = false;
1110         float** outArray = outReturn ? &outReturn : nullptr;
1111         if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
1112             return false;
1113         }
1114 
1115         // Transpose out parameters back
1116         {
1117             float* dst = args;
1118             for (int i = 0; i < w; ++i) {
1119                 float* src = (float*)stack + i;
1120                 for (const auto& p : f->fParameters) {
1121                     if (p.fIsOutParameter) {
1122                         for (int j = p.fSlotCount; j > 0; --j) {
1123                             *dst++ = *src;
1124                             src += Interpreter::VecWidth;
1125                         }
1126                     } else {
1127                         dst += p.fSlotCount;
1128                         src += p.fSlotCount * Interpreter::VecWidth;
1129                     }
1130                 }
1131             }
1132         }
1133 
1134         args += f->fParameterCount * w;
1135         if (outReturn) {
1136             outReturn += f->fReturnCount * w;
1137         }
1138         N -= w;
1139         baseIndex += w;
1140     }
1141     return true;
1142 #else
1143     SkDEBUGFAIL("ByteCode interpreter not enabled");
1144     return false;
1145 #endif
1146 }
1147 
runStriped(const ByteCodeFunction * f,float * args[],int nargs,int N,const float * uniforms,int uniformCount,float * outArgs[],int outCount) const1148 bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
1149                           const float* uniforms, int uniformCount,
1150                           float* outArgs[], int outCount) const {
1151 #if defined(SK_ENABLE_SKSL_INTERPRETER)
1152 #ifdef TRACE
1153     f->disassemble();
1154 #endif
1155     Interpreter::VValue stack[128];
1156     int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1157     if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
1158         return false;
1159     }
1160 
1161     if (nargs != f->fParameterCount ||
1162         outCount != f->fReturnCount ||
1163         uniformCount != (int)fInputSlots.size()) {
1164         return false;
1165     }
1166 
1167     Interpreter::VValue globals[32];
1168     if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1169         return false;
1170     }
1171     for (uint8_t slot : fInputSlots) {
1172         globals[slot].fFloat = *uniforms++;
1173     }
1174 
1175     // innerRun just takes outArgs, so clear it if the count is zero
1176     if (outCount == 0) {
1177         outArgs = nullptr;
1178     }
1179 
1180     int baseIndex = 0;
1181 
1182     while (N) {
1183         int w = std::min(N, Interpreter::VecWidth);
1184 
1185         // Copy args into stack
1186         for (int i = 0; i < nargs; ++i) {
1187             memcpy(stack + i, args[i], w * sizeof(float));
1188         }
1189 
1190         bool stripedOutput = true;
1191         if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
1192             return false;
1193         }
1194 
1195         // Copy out parameters back
1196         int slot = 0;
1197         for (const auto& p : f->fParameters) {
1198             if (p.fIsOutParameter) {
1199                 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1200                     memcpy(args[i], stack + i, w * sizeof(float));
1201                 }
1202             }
1203             slot += p.fSlotCount;
1204         }
1205 
1206         // Step each argument pointer ahead
1207         for (int i = 0; i < nargs; ++i) {
1208             args[i] += w;
1209         }
1210         N -= w;
1211         baseIndex += w;
1212     }
1213 
1214     return true;
1215 #else
1216     SkDEBUGFAIL("ByteCode interpreter not enabled");
1217     return false;
1218 #endif
1219 }
1220 
1221 } // namespace SkSL
1222 
1223 #endif
1224