blob: 14a8206ff85521f132d747c8ab79d5dea7f21650 [file] [log] [blame]
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001/*
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
Ethan Nicholasae9633b2019-05-24 12:46:34 -040010#include "include/core/SkPoint3.h"
Brian Osman569f12f2019-06-13 11:23:57 -040011#include "include/private/SkVx.h"
Brian Osman80164412019-06-07 13:00:23 -040012#include "src/sksl/SkSLByteCode.h"
Brian Osman07c117b2019-05-23 12:51:06 -070013#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040014#include "src/sksl/SkSLExternalValue.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/SkSLInterpreter.h"
Brian Osman80164412019-06-07 13:00:23 -040016
17#include <vector>
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040018
19namespace SkSL {
Brian Osman80164412019-06-07 13:00:23 -040020namespace Interpreter {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040021
Brian Osman569f12f2019-06-13 11:23:57 -040022constexpr int VecWidth = 16;
23
24using F32 = skvx::Vec<VecWidth, float>;
25using I32 = skvx::Vec<VecWidth, int32_t>;
26using U32 = skvx::Vec<VecWidth, uint32_t>;
27
Mike Klein76346ac2019-05-17 11:57:10 -050028template <typename T>
29static T unaligned_load(const void* ptr) {
30 T val;
31 memcpy(&val, ptr, sizeof(val));
32 return val;
33}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040034
Mike Kleine7007382019-05-21 08:36:32 -050035#define READ8() (*(ip++))
Mike Klein76346ac2019-05-17 11:57:10 -050036#define READ16() (ip += 2, unaligned_load<uint16_t>(ip - 2))
37#define READ32() (ip += 4, unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040038
Brian Osman3e833e12019-05-23 13:23:24 -070039#define VECTOR_DISASSEMBLE(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040040 case ByteCodeInstruction::op: printf(text); break; \
41 case ByteCodeInstruction::op##2: printf(text "2"); break; \
42 case ByteCodeInstruction::op##3: printf(text "3"); break; \
43 case ByteCodeInstruction::op##4: printf(text "4"); break;
44
Brian Osman1e855b22019-05-29 15:21:52 -040045#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
46 case ByteCodeInstruction::op: printf(text); break; \
47 case ByteCodeInstruction::op##2: printf(text "2"); break; \
48 case ByteCodeInstruction::op##3: printf(text "3"); break; \
49 case ByteCodeInstruction::op##4: printf(text "4"); break; \
50 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
51
Brian Osman3e833e12019-05-23 13:23:24 -070052static const uint8_t* disassemble_instruction(const uint8_t* ip) {
53 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -040054 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070055 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040056 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070057 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
58 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
59 case ByteCodeInstruction::kCallExternal: {
60 int argumentCount = READ8();
61 int returnCount = READ8();
62 int externalValue = READ8();
63 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
64 break;
65 }
66 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
67 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040068 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
69 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070070 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
71 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
72 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
73 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
74 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
75 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
76 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
77 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
78 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
79 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
80 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
81 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Brian Osman3e833e12019-05-23 13:23:24 -070082 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
83 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
84 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
85 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osman1e855b22019-05-29 15:21:52 -040086 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070087 VECTOR_DISASSEMBLE(kDivideS, "divideS")
88 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040089 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Brian Osman3e833e12019-05-23 13:23:24 -070090 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;
Brian Osman29e013d2019-05-28 17:16:03 -0400119 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 }
Brian Osman909231c2019-05-29 15:34:36 -0400127 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 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400134 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400135 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700136 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400137 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700138 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400139 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400140 case ByteCodeInstruction::kOrB: printf("orb"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400141 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700142 case ByteCodeInstruction::kPushImmediate: {
143 uint32_t v = READ32();
144 union { uint32_t u; float f; } pun = { v };
145 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
146 break;
147 }
148 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
149 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
150 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
151 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
152 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
153 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
154 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
155 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400156 case ByteCodeInstruction::kScalarToMatrix: {
157 int cols = READ8();
158 int rows = READ8();
159 printf("scalartomatrix %dx%d", cols, rows);
160 break;
161 }
Brian Osman3e833e12019-05-23 13:23:24 -0700162 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;
Brian Osman1e855b22019-05-29 15:21:52 -0400209 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700210 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;
Brian Osman569f12f2019-06-13 11:23:57 -0400225 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;
Brian Osman3e833e12019-05-23 13:23:24 -0700239 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
240 }
241 return ip;
242}
243
Brian Osman80164412019-06-07 13:00:23 -0400244void Disassemble(const ByteCodeFunction* f) {
245 const uint8_t* ip = f->fCode.data();
246 while (ip < f->fCode.data() + f->fCode.size()) {
247 printf("%d: ", (int) (ip - f->fCode.data()));
Brian Osman3e833e12019-05-23 13:23:24 -0700248 ip = disassemble_instruction(ip);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400249 printf("\n");
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400250 }
251}
252
Mike Klein459aed12019-05-21 15:46:36 -0500253#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500254 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500255 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500256 POP(); \
257 /* fall through */ \
258 case ByteCodeInstruction::base ## 3: { \
259 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500260 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500261 POP(); \
262 } /* fall through */ \
263 case ByteCodeInstruction::base ## 2: { \
264 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500265 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500266 POP(); \
267 } /* fall through */ \
268 case ByteCodeInstruction::base: { \
269 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500270 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500271 POP(); \
272 break; \
273 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400274
Brian Osman1e855b22019-05-29 15:21:52 -0400275#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
276 VECTOR_BINARY_OP(base, field, op) \
277 case ByteCodeInstruction::base ## N: { \
278 int count = READ8(); \
279 for (int i = count; i > 0; --i) { \
280 sp[-count] = sp[-count].field op sp[0].field; \
281 POP(); \
282 } \
283 break; \
284 }
285
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400286#define VECTOR_BINARY_FN(base, field, fn) \
287 case ByteCodeInstruction::base ## 4: \
288 sp[-4] = fn(sp[-4].field, sp[0].field); \
289 POP(); \
290 /* fall through */ \
291 case ByteCodeInstruction::base ## 3: { \
292 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
293 sp[target] = fn(sp[target].field, sp[0].field); \
294 POP(); \
295 } /* fall through */ \
296 case ByteCodeInstruction::base ## 2: { \
297 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
298 sp[target] = fn(sp[target].field, sp[0].field); \
299 POP(); \
300 } /* fall through */ \
301 case ByteCodeInstruction::base: { \
302 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
303 sp[target] = fn(sp[target].field, sp[0].field); \
304 POP(); \
305 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500306 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400307
Mike Klein459aed12019-05-21 15:46:36 -0500308#define VECTOR_UNARY_FN(base, fn, field) \
309 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
310 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
311 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
312 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400313 break;
314
Brian Osman569f12f2019-06-13 11:23:57 -0400315#define VECTOR_UNARY_FN_VEC(base, fn) \
316 case ByteCodeInstruction::base ## 4: \
317 case ByteCodeInstruction::base ## 3: \
318 case ByteCodeInstruction::base ## 2: \
319 case ByteCodeInstruction::base : { \
320 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
321 float* v = (float*)sp - count + 1; \
322 for (int i = VecWidth * count; i > 0; --i, ++v) { \
323 *v = fn(*v); \
324 } \
325 break; \
326 }
327
328union VValue {
329 VValue() {}
330
331 VValue(F32 f)
332 : fFloat(f) {
333 }
334
335 VValue(I32 s)
336 : fSigned(s) {
337 }
338
339 VValue(U32 u)
340 : fUnsigned(u) {
341 }
342
343 F32 fFloat;
344 I32 fSigned;
345 U32 fUnsigned;
346};
347
Brian Osman226668a2019-05-14 16:47:30 -0400348struct StackFrame {
349 const uint8_t* fCode;
350 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400351 VValue* fStack;
Brian Osman226668a2019-05-14 16:47:30 -0400352};
353
Brian Osman569f12f2019-06-13 11:23:57 -0400354static F32 mix(F32 start, F32 end, F32 t) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400355 return start * (1 - t) + end * t;
356}
357
Brian Osman569f12f2019-06-13 11:23:57 -0400358// TODO: trunc on integers?
359template <typename T>
360static T vec_mod(T a, T b) {
361 return a - skvx::trunc(a / b) * b;
362}
Mike Kleine7007382019-05-21 08:36:32 -0500363
Brian Osman569f12f2019-06-13 11:23:57 -0400364void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack, Value* outReturn,
365 I32 initMask, VValue globals[], int globalCount) {
366 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
367
368 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
369 auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
Mike Kleine7007382019-05-21 08:36:32 -0500370
Brian Osman80164412019-06-07 13:00:23 -0400371 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400372 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400373 std::vector<StackFrame> frames;
374
Brian Osman569f12f2019-06-13 11:23:57 -0400375 I32 condStack[16]; // Independent condition masks
376 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
377 I32 contStack[16]; // Continue flags for loops
378 I32 loopStack[16]; // Loop execution masks
379 condStack[0] = maskStack[0] = initMask;
380 contStack[0] = I32( 0);
381 loopStack[0] = I32(~0);
382 I32* condPtr = condStack;
383 I32* maskPtr = maskStack;
384 I32* contPtr = contStack;
385 I32* loopPtr = loopStack;
386
387 auto mask = [&]() { return *maskPtr & *loopPtr; };
388
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400389 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400390#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700391 printf("at %3d ", (int) (ip - code));
392 disassemble_instruction(ip);
393 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400394#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700395 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400396 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500397 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400398 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400399
400 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
Brian Osman32c526b2019-06-03 16:13:52 -0400401 case ByteCodeInstruction::kAndB:
Brian Osman569f12f2019-06-13 11:23:57 -0400402 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
403 POP();
404 break;
405 case ByteCodeInstruction::kNotB:
406 sp[0] = ~sp[0].fSigned;
407 break;
408 case ByteCodeInstruction::kOrB:
409 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
410 POP();
411 break;
412 case ByteCodeInstruction::kXorB:
413 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
Brian Osman32c526b2019-06-03 16:13:52 -0400414 POP();
415 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400416
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400417 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400418 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400419 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400420
Brian Osman226668a2019-05-14 16:47:30 -0400421 case ByteCodeInstruction::kCall: {
422 // Precursor code has pushed all parameters to the stack. Update our bottom of
423 // stack to point at the first parameter, and our sp to point past those parameters
424 // (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500425 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400426 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
Brian Osman569f12f2019-06-13 11:23:57 -0400427 if (skvx::any(mask())) {
428 frames.push_back({ code, ip, stack });
429 ip = code = fun->fCode.data();
430 stack = sp - fun->fParameterCount + 1;
431 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
432 } else {
433 sp -= fun->fParameterCount;
434 sp += fun->fReturnCount;
435 }
Brian Osman226668a2019-05-14 16:47:30 -0400436 break;
437 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400438
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400439 case ByteCodeInstruction::kCallExternal: {
440 int argumentCount = READ8();
441 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500442 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400443 ExternalValue* v = byteCode->fExternalValues[target];
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400444 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500445
Brian Osman569f12f2019-06-13 11:23:57 -0400446 Value tmpArgs[4];
447 Value tmpReturn[4];
448 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
449 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
450
451 I32 m = mask();
452 for (int i = 0; i < VecWidth; ++i) {
453 if (m[i]) {
454 for (int j = 0; j < argumentCount; ++j) {
455 tmpArgs[j].fSigned = sp[j].fSigned[i];
456 }
457 v->call(tmpArgs, tmpReturn);
458 for (int j = 0; j < returnCount; ++j) {
459 sp[j].fSigned[i] = tmpReturn[j].fSigned;
460 }
461 }
462 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400463 sp += returnCount - 1;
464 break;
465 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400466
Mike Kleinc1999982019-05-21 13:03:49 -0500467 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400468 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500469 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400470 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500471 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
472 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
473 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
474 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
475 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
476 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
477 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
478 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
479 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
480 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
481 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
482 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400483
Brian Osman569f12f2019-06-13 11:23:57 -0400484 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
485 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
486 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
487 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400488 break;
489
Brian Osman569f12f2019-06-13 11:23:57 -0400490 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
491 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
492 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
493 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400494 break;
495
Brian Osman569f12f2019-06-13 11:23:57 -0400496 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
497 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
498 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
499 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400500 break;
501
Brian Osman569f12f2019-06-13 11:23:57 -0400502 VECTOR_UNARY_FN_VEC(kCos, cosf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400503
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400504 case ByteCodeInstruction::kCross: {
Brian Osman569f12f2019-06-13 11:23:57 -0400505 F32 ax = sp[-5].fFloat, ay = sp[-4].fFloat, az = sp[-3].fFloat,
506 bx = sp[-2].fFloat, by = sp[-1].fFloat, bz = sp[ 0].fFloat;
507 F32 cx = ay*bz - az*by,
508 cy = az*bx - ax*bz,
509 cz = ax*by - ay*bx;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400510 sp -= 3;
Brian Osman569f12f2019-06-13 11:23:57 -0400511 sp[-2] = cx;
512 sp[-1] = cy;
513 sp[ 0] = cz;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400514 break;
515 }
516
Mike Kleinc1999982019-05-21 13:03:49 -0500517 VECTOR_BINARY_OP(kDivideS, fSigned, /)
518 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400519 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500520
521 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
522 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
523 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
524 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
525 break;
526
Brian Osman07c117b2019-05-23 12:51:06 -0700527 case ByteCodeInstruction::kDupN: {
528 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400529 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -0700530 sp += count;
531 break;
532 }
533
Mike Kleine7007382019-05-21 08:36:32 -0500534 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
535 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
536 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
537 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
538 ++ip;
539 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
540 break;
541
Brian Osman80164412019-06-07 13:00:23 -0400542 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
543 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
544 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
545 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
Mike Kleine7007382019-05-21 08:36:32 -0500546 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700547 sp += (int)inst -
548 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500549 break;
550
Brian Osman07c117b2019-05-23 12:51:06 -0700551 case ByteCodeInstruction::kLoadExtended: {
552 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400553 I32 src = POP().fSigned;
554 I32 m = mask();
555 for (int i = 0; i < count; ++i) {
556 for (int j = 0; j < VecWidth; ++j) {
557 if (m[j]) {
558 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
559 }
560 }
561 }
Brian Osman07c117b2019-05-23 12:51:06 -0700562 sp += count;
563 break;
564 }
565
566 case ByteCodeInstruction::kLoadExtendedGlobal: {
567 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400568 I32 src = POP().fSigned;
569 I32 m = mask();
570 for (int i = 0; i < count; ++i) {
571 for (int j = 0; j < VecWidth; ++j) {
572 if (m[j]) {
573 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
574 }
575 }
576 }
Brian Osman07c117b2019-05-23 12:51:06 -0700577 sp += count;
578 break;
579 }
580
Mike Kleine7007382019-05-21 08:36:32 -0500581 case ByteCodeInstruction::kLoadSwizzle: {
582 int src = READ8();
583 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400584 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400585 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400586 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400587 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400588 break;
Mike Kleine7007382019-05-21 08:36:32 -0500589 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400590
Mike Kleine7007382019-05-21 08:36:32 -0500591 case ByteCodeInstruction::kLoadSwizzleGlobal: {
592 int src = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500593 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400594 for (int i = 0; i < count; ++i) {
Brian Osman80164412019-06-07 13:00:23 -0400595 SkASSERT(src + *(ip + i) < globalCount);
596 PUSH(globals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400597 }
598 ip += count;
599 break;
Mike Kleine7007382019-05-21 08:36:32 -0500600 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400601
Brian Osman29e013d2019-05-28 17:16:03 -0400602 case ByteCodeInstruction::kMatrixToMatrix: {
603 int srcCols = READ8();
604 int srcRows = READ8();
605 int dstCols = READ8();
606 int dstRows = READ8();
607 SkASSERT(srcCols >= 2 && srcCols <= 4);
608 SkASSERT(srcRows >= 2 && srcRows <= 4);
609 SkASSERT(dstCols >= 2 && dstCols <= 4);
610 SkASSERT(dstRows >= 2 && dstRows <= 4);
Brian Osman569f12f2019-06-13 11:23:57 -0400611 F32 tmp[16];
612 memset(tmp, 0, sizeof(tmp));
613 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
Brian Osman29e013d2019-05-28 17:16:03 -0400614 for (int c = srcCols - 1; c >= 0; --c) {
615 for (int r = srcRows - 1; r >= 0; --r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400616 tmp[c*4 + r] = POP().fFloat;
Brian Osman29e013d2019-05-28 17:16:03 -0400617 }
618 }
619 for (int c = 0; c < dstCols; ++c) {
620 for (int r = 0; r < dstRows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400621 PUSH(tmp[c*4 + r]);
Brian Osman29e013d2019-05-28 17:16:03 -0400622 }
623 }
624 break;
625 }
626
Brian Osman909231c2019-05-29 15:34:36 -0400627 case ByteCodeInstruction::kMatrixMultiply: {
628 int lCols = READ8();
629 int lRows = READ8();
630 int rCols = READ8();
631 int rRows = lCols;
Brian Osman569f12f2019-06-13 11:23:57 -0400632 F32 tmp[16] = { 0.0f };
633 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
634 F32* A = B - (lCols * lRows);
Brian Osman909231c2019-05-29 15:34:36 -0400635 for (int c = 0; c < rCols; ++c) {
636 for (int r = 0; r < lRows; ++r) {
637 for (int j = 0; j < lCols; ++j) {
638 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
639 }
640 }
641 }
642 sp -= (lCols * lRows) + (rCols * rRows);
Brian Osman569f12f2019-06-13 11:23:57 -0400643 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
Brian Osman909231c2019-05-29 15:34:36 -0400644 sp += (rCols * lRows);
645 break;
646 }
647
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400648 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
649 case ByteCodeInstruction::kMix4:
650 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
651 // fall through
652 case ByteCodeInstruction::kMix3: {
653 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
654 int target = 2 - count * 2;
655 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
656 // fall through
657 }
658 case ByteCodeInstruction::kMix2: {
659 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
660 int target = 1 - count * 2;
661 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
662 // fall through
663 }
664 case ByteCodeInstruction::kMix: {
665 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
666 int target = -count * 2;
667 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
668 sp -= 1 + count;
669 break;
670 }
671
Mike Kleinc1999982019-05-21 13:03:49 -0500672 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400673 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400674
Mike Kleinc1999982019-05-21 13:03:49 -0500675 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
676 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
677 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
678 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500679 break;
680
Brian Osman1e855b22019-05-29 15:21:52 -0400681 case ByteCodeInstruction::kNegateFN: {
682 int count = READ8();
683 for (int i = count - 1; i >= 0; --i) {
684 sp[-i] = -sp[-i].fFloat;
685 }
686 break;
687 }
688
Mike Kleinc1999982019-05-21 13:03:49 -0500689 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
690 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
691 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
Brian Osman569f12f2019-06-13 11:23:57 -0400692 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500693 break;
694
695 case ByteCodeInstruction::kPop4: POP();
696 case ByteCodeInstruction::kPop3: POP();
697 case ByteCodeInstruction::kPop2: POP();
698 case ByteCodeInstruction::kPop : POP();
699 break;
700
Brian Osman07c117b2019-05-23 12:51:06 -0700701 case ByteCodeInstruction::kPopN:
702 sp -= READ8();
703 break;
704
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400705 case ByteCodeInstruction::kPushImmediate:
Brian Osman569f12f2019-06-13 11:23:57 -0400706 PUSH(U32(READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400707 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400708
Brian Osman569f12f2019-06-13 11:23:57 -0400709 case ByteCodeInstruction::kReadExternal:
710 case ByteCodeInstruction::kReadExternal2:
711 case ByteCodeInstruction::kReadExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500712 case ByteCodeInstruction::kReadExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400713 // TODO: Support striped external values, or passing lane index? This model is odd.
714 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500715 int src = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400716 int32_t tmp[4];
717 I32 m = mask();
718 for (int i = 0; i < VecWidth; ++i) {
719 if (m[i]) {
720 byteCode->fExternalValues[src]->read(tmp);
721 for (int j = 0; j < count; ++j) {
722 sp[j + 1].fSigned[i] = tmp[j];
723 }
724 }
725 }
726 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400727 break;
Mike Kleine7007382019-05-21 08:36:32 -0500728 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400729
Brian Osman569f12f2019-06-13 11:23:57 -0400730 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
731 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
732 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400733
Mike Kleine7007382019-05-21 08:36:32 -0500734 case ByteCodeInstruction::kReturn: {
735 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400736 if (frames.empty()) {
737 if (outReturn) {
Brian Osman569f12f2019-06-13 11:23:57 -0400738 // TODO: This can be smarter, knowing that mask is left-justified
739 I32 m = mask();
740 VValue* src = sp - count + 1;
741 for (int i = 0; i < count; ++i) {
742 for (int j = 0; j < VecWidth; ++j) {
743 if (m[j]) {
744 outReturn[count * j].fSigned = src->fSigned[j];
745 }
746 }
747 ++outReturn;
748 ++src;
749 }
Brian Osman226668a2019-05-14 16:47:30 -0400750 }
751 return;
752 } else {
753 // When we were called, 'stack' was positioned at the old top-of-stack (where
754 // our parameters were placed). So copy our return values to that same spot.
Brian Osman569f12f2019-06-13 11:23:57 -0400755 memmove(stack, sp - count + 1, count * sizeof(VValue));
Brian Osman226668a2019-05-14 16:47:30 -0400756
757 // Now move the stack pointer to the end of the just-pushed return values,
758 // and restore everything else.
759 const StackFrame& frame(frames.back());
760 sp = stack + count - 1;
761 stack = frame.fStack;
762 code = frame.fCode;
763 ip = frame.fIP;
764 frames.pop_back();
765 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400766 }
Mike Kleine7007382019-05-21 08:36:32 -0500767 }
768
Brian Osman29e013d2019-05-28 17:16:03 -0400769 case ByteCodeInstruction::kScalarToMatrix: {
770 int cols = READ8();
771 int rows = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400772 VValue v = POP();
Brian Osman29e013d2019-05-28 17:16:03 -0400773 for (int c = 0; c < cols; ++c) {
774 for (int r = 0; r < rows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400775 PUSH(c == r ? v : F32(0.0f));
Brian Osman29e013d2019-05-28 17:16:03 -0400776 }
777 }
778 break;
779 }
780
Brian Osman569f12f2019-06-13 11:23:57 -0400781 VECTOR_UNARY_FN_VEC(kSin, sinf)
782 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400783
Brian Osman569f12f2019-06-13 11:23:57 -0400784 case ByteCodeInstruction::kStore4:
785 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
786 case ByteCodeInstruction::kStore3:
787 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
788 case ByteCodeInstruction::kStore2:
789 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
790 case ByteCodeInstruction::kStore :
791 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
792 ++ip;
793 break;
Mike Kleine7007382019-05-21 08:36:32 -0500794
Brian Osman569f12f2019-06-13 11:23:57 -0400795 case ByteCodeInstruction::kStoreGlobal4:
796 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
797 case ByteCodeInstruction::kStoreGlobal3:
798 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
799 case ByteCodeInstruction::kStoreGlobal2:
800 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
801 case ByteCodeInstruction::kStoreGlobal :
802 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
803 ++ip;
804 break;
Mike Kleine7007382019-05-21 08:36:32 -0500805
Brian Osman07c117b2019-05-23 12:51:06 -0700806 case ByteCodeInstruction::kStoreExtended: {
807 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400808 I32 target = POP().fSigned;
809 VValue* src = sp - count + 1;
810 I32 m = mask();
811 for (int i = 0; i < count; ++i) {
812 for (int j = 0; j < VecWidth; ++j) {
813 if (m[j]) {
814 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
815 }
816 }
817 }
Brian Osman07c117b2019-05-23 12:51:06 -0700818 sp -= count;
819 break;
820 }
821 case ByteCodeInstruction::kStoreExtendedGlobal: {
822 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400823 I32 target = POP().fSigned;
824 VValue* src = sp - count + 1;
825 I32 m = mask();
826 for (int i = 0; i < count; ++i) {
827 for (int j = 0; j < VecWidth; ++j) {
828 if (m[j]) {
829 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
830 }
831 }
832 }
Brian Osman07c117b2019-05-23 12:51:06 -0700833 sp -= count;
834 break;
835 }
836
Mike Kleine7007382019-05-21 08:36:32 -0500837 case ByteCodeInstruction::kStoreSwizzle: {
838 int target = READ8();
839 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400840 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400841 stack[target + *(ip + i)] = skvx::if_then_else(
842 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400843 }
Brian Osman1091f022019-05-16 09:42:16 -0400844 ip += count;
845 break;
Mike Kleine7007382019-05-21 08:36:32 -0500846 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400847
Mike Kleine7007382019-05-21 08:36:32 -0500848 case ByteCodeInstruction::kStoreSwizzleGlobal: {
849 int target = READ8();
850 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400851 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400852 globals[target + *(ip + i)] = skvx::if_then_else(
853 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
Brian Osman1091f022019-05-16 09:42:16 -0400854 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400855 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400856 break;
Mike Kleine7007382019-05-21 08:36:32 -0500857 }
Brian Osman569f12f2019-06-13 11:23:57 -0400858
Brian Osman07c117b2019-05-23 12:51:06 -0700859 case ByteCodeInstruction::kStoreSwizzleIndirect: {
Brian Osman07c117b2019-05-23 12:51:06 -0700860 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400861 I32 target = POP().fSigned;
862 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700863 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400864 I32 v = POP().fSigned;
865 for (int j = 0; j < VecWidth; ++j) {
866 if (m[j]) {
867 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
868 }
869 }
Brian Osman07c117b2019-05-23 12:51:06 -0700870 }
871 ip += count;
872 break;
873 }
Brian Osman569f12f2019-06-13 11:23:57 -0400874
Brian Osman07c117b2019-05-23 12:51:06 -0700875 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
Brian Osman07c117b2019-05-23 12:51:06 -0700876 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400877 I32 target = POP().fSigned;
878 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700879 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400880 I32 v = POP().fSigned;
881 for (int j = 0; j < VecWidth; ++j) {
882 if (m[j]) {
883 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
884 }
885 }
Brian Osman07c117b2019-05-23 12:51:06 -0700886 }
887 ip += count;
888 break;
889 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400890
Mike Kleinc1999982019-05-21 13:03:49 -0500891 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400892 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400893
Mike Kleine7007382019-05-21 08:36:32 -0500894 case ByteCodeInstruction::kSwizzle: {
Brian Osman569f12f2019-06-13 11:23:57 -0400895 VValue tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400896 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400897 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400898 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400899 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400900 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400901 }
902 break;
Mike Kleine7007382019-05-21 08:36:32 -0500903 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400904
Brian Osman569f12f2019-06-13 11:23:57 -0400905 VECTOR_UNARY_FN_VEC(kTan, tanf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400906
Brian Osman569f12f2019-06-13 11:23:57 -0400907 case ByteCodeInstruction::kWriteExternal:
908 case ByteCodeInstruction::kWriteExternal2:
909 case ByteCodeInstruction::kWriteExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500910 case ByteCodeInstruction::kWriteExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400911 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500912 int target = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400913 int32_t tmp[4];
914 I32 m = mask();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400915 sp -= count;
Brian Osman569f12f2019-06-13 11:23:57 -0400916 for (int i = 0; i < VecWidth; ++i) {
917 if (m[i]) {
918 for (int j = 0; j < count; ++j) {
919 tmp[j] = sp[j + 1].fSigned[i];
920 }
921 byteCode->fExternalValues[target]->write(tmp);
922 }
923 }
924 break;
925 }
926
927 case ByteCodeInstruction::kMaskPush:
928 condPtr[1] = POP().fSigned;
929 maskPtr[1] = maskPtr[0] & condPtr[1];
930 ++condPtr; ++maskPtr;
931 break;
932 case ByteCodeInstruction::kMaskPop:
933 --condPtr; --maskPtr;
934 break;
935 case ByteCodeInstruction::kMaskNegate:
936 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
937 break;
938 case ByteCodeInstruction::kMaskBlend: {
939 int count = READ8();
940 I32 m = condPtr[0];
941 --condPtr; --maskPtr;
942 for (int i = 0; i < count; ++i) {
943 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
944 --sp;
945 }
946 break;
947 }
948 case ByteCodeInstruction::kBranchIfAllFalse: {
949 int target = READ16();
950 if (!skvx::any(mask())) {
951 ip = code + target;
952 }
953 break;
954 }
955
956 case ByteCodeInstruction::kLoopBegin:
957 *(++contPtr) = 0;
958 *(++loopPtr) = ~0;
959 break;
960 case ByteCodeInstruction::kLoopNext:
961 *loopPtr |= *contPtr;
962 *contPtr = 0;
963 break;
964 case ByteCodeInstruction::kLoopMask:
965 *loopPtr &= POP().fSigned;
966 break;
967 case ByteCodeInstruction::kLoopEnd:
968 --contPtr; --loopPtr;
969 break;
970 case ByteCodeInstruction::kLoopBreak:
971 *loopPtr &= ~mask();
972 break;
973 case ByteCodeInstruction::kLoopContinue: {
974 I32 m = mask();
975 *contPtr |= m;
976 *loopPtr &= ~m;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400977 break;
Mike Kleine7007382019-05-21 08:36:32 -0500978 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400979
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400980 default:
Mike Kleine7007382019-05-21 08:36:32 -0500981 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400982 }
Brian Osman569f12f2019-06-13 11:23:57 -0400983 }
984}
985
986void VecRun(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
987 int N, Value uniforms[], int uniformCount) {
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400988#ifdef TRACE
Brian Osman569f12f2019-06-13 11:23:57 -0400989 disassemble(f);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400990#endif
Brian Osman569f12f2019-06-13 11:23:57 -0400991 VValue smallStack[128];
992
Brian Osmanef787f72019-06-13 13:07:12 -0400993 // Needs to be the first N non-negative integers, at least as large as VecWidth
994 static const I32 gLanes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
995
Brian Osman569f12f2019-06-13 11:23:57 -0400996 SkASSERT(uniformCount == (int)byteCode->fInputSlots.size());
997 VValue smallGlobals[32];
998 VValue* globals = smallGlobals;
999 SkASSERT((int)SK_ARRAY_COUNT(smallGlobals) >= byteCode->fGlobalCount);
1000 for (uint8_t slot : byteCode->fInputSlots) {
1001 globals[slot].fUnsigned = (uniforms++)->fUnsigned;
1002 }
1003
1004 while (N) {
1005 VValue* stack = smallStack;
1006
1007 int w = std::min(N, VecWidth);
1008 N -= w;
1009
1010 // Transpose args into stack
1011 {
1012 uint32_t* src = (uint32_t*)args;
1013 for (int i = 0; i < w; ++i) {
1014 uint32_t* dst = (uint32_t*)stack + i;
1015 for (int j = f->fParameterCount; j > 0; --j) {
1016 *dst = *src++;
1017 dst += VecWidth;
1018 }
1019 }
1020 }
1021
1022 auto mask = w > gLanes;
1023 innerRun(byteCode, f, stack, outReturn, mask, globals, byteCode->fGlobalCount);
1024
1025 // Transpose out parameters back
1026 {
1027 uint32_t* dst = (uint32_t*)args;
1028 for (int i = 0; i < w; ++i) {
1029 uint32_t* src = (uint32_t*)stack + i;
1030 for (const auto& p : f->fParameters) {
1031 if (p.fIsOutParameter) {
1032 for (int j = p.fSlotCount; j > 0; --j) {
1033 *dst++ = *src;
1034 src += VecWidth;
1035 }
1036 } else {
1037 dst += p.fSlotCount;
1038 src += p.fSlotCount * VecWidth;
1039 }
1040 }
1041 }
1042 }
1043
1044 args += f->fParameterCount * w;
1045 outReturn += f->fReturnCount * w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001046 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001047}
1048
Brian Osman80164412019-06-07 13:00:23 -04001049void Run(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
1050 Value uniforms[], int uniformCount) {
Brian Osman569f12f2019-06-13 11:23:57 -04001051 VecRun(byteCode, f, args, outReturn, 1, uniforms, uniformCount);
Brian Osman80164412019-06-07 13:00:23 -04001052}
1053
1054} // namespace Interpreter
1055} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001056
1057#endif