blob: 3a513dcf8c178d3f88e5abea00e04cb93bc612ed [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"
Mike Klein7a177b42019-06-17 17:17:47 -050012#include "src/core/SkUtils.h" // sk_unaligned_load
Brian Osman80164412019-06-07 13:00:23 -040013#include "src/sksl/SkSLByteCode.h"
Brian Osman07c117b2019-05-23 12:51:06 -070014#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040015#include "src/sksl/SkSLExternalValue.h"
Brian Osman80164412019-06-07 13:00:23 -040016
17#include <vector>
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040018
19namespace SkSL {
Brian Osman489cf882019-07-09 10:48:28 -040020
21#if defined(SK_ENABLE_SKSL_INTERPRETER)
22
Brian Osman80164412019-06-07 13:00:23 -040023namespace Interpreter {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040024
Mike Reed3fd3cc92019-06-20 12:40:30 -040025constexpr int VecWidth = ByteCode::kVecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -040026
27using F32 = skvx::Vec<VecWidth, float>;
28using I32 = skvx::Vec<VecWidth, int32_t>;
29using U32 = skvx::Vec<VecWidth, uint32_t>;
30
Mike Kleine7007382019-05-21 08:36:32 -050031#define READ8() (*(ip++))
Mike Klein7a177b42019-06-17 17:17:47 -050032#define READ16() (ip += 2, sk_unaligned_load<uint16_t>(ip - 2))
33#define READ32() (ip += 4, sk_unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040034
Brian Osman3e833e12019-05-23 13:23:24 -070035#define VECTOR_DISASSEMBLE(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040036 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
Brian Osman1e855b22019-05-29 15:21:52 -040041#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
Brian Osman3e833e12019-05-23 13:23:24 -070048static const uint8_t* disassemble_instruction(const uint8_t* ip) {
49 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -040050 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070051 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040052 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070053 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 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
63 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040064 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
65 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070066 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
67 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
68 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
69 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
70 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
71 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
72 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
73 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
74 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
75 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
76 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
77 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Brian Osman3e833e12019-05-23 13:23:24 -070078 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
79 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
80 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
81 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osmanecb3bb52019-06-20 14:59:12 -040082 case ByteCodeInstruction::kCross: printf("cross"); break;
Brian Osman1e855b22019-05-29 15:21:52 -040083 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070084 VECTOR_DISASSEMBLE(kDivideS, "divideS")
85 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040086 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Brian Osman3e833e12019-05-23 13:23:24 -070087 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
88 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
89 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
90 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
91 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
92 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
93 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
94 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
95 case ByteCodeInstruction::kLoadSwizzle: {
96 int target = READ8();
97 int count = READ8();
98 printf("loadswizzle %d %d", target, count);
99 for (int i = 0; i < count; ++i) {
100 printf(", %d", READ8());
101 }
102 break;
103 }
104 case ByteCodeInstruction::kLoadSwizzleGlobal: {
105 int target = READ8();
106 int count = READ8();
107 printf("loadswizzleglobal %d %d", target, count);
108 for (int i = 0; i < count; ++i) {
109 printf(", %d", READ8());
110 }
111 break;
112 }
113 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
114 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
115 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400116 case ByteCodeInstruction::kMatrixToMatrix: {
117 int srcCols = READ8();
118 int srcRows = READ8();
119 int dstCols = READ8();
120 int dstRows = READ8();
121 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
122 break;
123 }
Brian Osman909231c2019-05-29 15:34:36 -0400124 case ByteCodeInstruction::kMatrixMultiply: {
125 int lCols = READ8();
126 int lRows = READ8();
127 int rCols = READ8();
128 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
129 break;
130 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400131 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400132 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700133 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400134 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700135 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400136 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400137 case ByteCodeInstruction::kOrB: printf("orb"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400138 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700139 case ByteCodeInstruction::kPushImmediate: {
140 uint32_t v = READ32();
141 union { uint32_t u; float f; } pun = { v };
142 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
143 break;
144 }
145 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
146 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
147 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
148 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
149 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
150 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
151 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400152 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700153 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400154 case ByteCodeInstruction::kScalarToMatrix: {
155 int cols = READ8();
156 int rows = READ8();
157 printf("scalartomatrix %dx%d", cols, rows);
158 break;
159 }
Brian Osman3e833e12019-05-23 13:23:24 -0700160 VECTOR_DISASSEMBLE(kSin, "sin")
161 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
162 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
163 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
164 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
165 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
166 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
167 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
168 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
169 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
170 case ByteCodeInstruction::kStoreSwizzle: {
171 int target = READ8();
172 int count = READ8();
173 printf("storeswizzle %d %d", target, count);
174 for (int i = 0; i < count; ++i) {
175 printf(", %d", READ8());
176 }
177 break;
178 }
179 case ByteCodeInstruction::kStoreSwizzleGlobal: {
180 int target = READ8();
181 int count = READ8();
182 printf("storeswizzleglobal %d %d", target, count);
183 for (int i = 0; i < count; ++i) {
184 printf(", %d", READ8());
185 }
186 break;
187 }
188 case ByteCodeInstruction::kStoreSwizzleIndirect: {
189 int count = READ8();
190 printf("storeswizzleindirect %d", count);
191 for (int i = 0; i < count; ++i) {
192 printf(", %d", READ8());
193 }
194 break;
195 }
196 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
197 int count = READ8();
198 printf("storeswizzleindirectglobal %d", count);
199 for (int i = 0; i < count; ++i) {
200 printf(", %d", READ8());
201 }
202 break;
203 }
204 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
205 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
206 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400207 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700208 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
209 case ByteCodeInstruction::kSwizzle: {
210 printf("swizzle %d, ", READ8());
211 int count = READ8();
212 printf("%d", count);
213 for (int i = 0; i < count; ++i) {
214 printf(", %d", READ8());
215 }
216 break;
217 }
218 VECTOR_DISASSEMBLE(kTan, "tan")
219 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
220 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
221 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
222 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400223 case ByteCodeInstruction::kXorB: printf("xorb"); break;
224 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
225 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
226 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
227 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
228 case ByteCodeInstruction::kBranchIfAllFalse:
229 printf("branchifallfalse %d", READ16());
230 break;
231 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
232 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
233 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
234 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
235 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
236 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700237 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
238 }
239 return ip;
240}
241
Mike Klein459aed12019-05-21 15:46:36 -0500242#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500243 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500244 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500245 POP(); \
246 /* fall through */ \
247 case ByteCodeInstruction::base ## 3: { \
248 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500249 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500250 POP(); \
251 } /* fall through */ \
252 case ByteCodeInstruction::base ## 2: { \
253 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500254 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500255 POP(); \
256 } /* fall through */ \
257 case ByteCodeInstruction::base: { \
258 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500259 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500260 POP(); \
261 break; \
262 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400263
Brian Osman1e855b22019-05-29 15:21:52 -0400264#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
265 VECTOR_BINARY_OP(base, field, op) \
266 case ByteCodeInstruction::base ## N: { \
267 int count = READ8(); \
268 for (int i = count; i > 0; --i) { \
269 sp[-count] = sp[-count].field op sp[0].field; \
270 POP(); \
271 } \
272 break; \
273 }
274
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400275#define VECTOR_BINARY_FN(base, field, fn) \
276 case ByteCodeInstruction::base ## 4: \
277 sp[-4] = fn(sp[-4].field, sp[0].field); \
278 POP(); \
279 /* fall through */ \
280 case ByteCodeInstruction::base ## 3: { \
281 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
282 sp[target] = fn(sp[target].field, sp[0].field); \
283 POP(); \
284 } /* fall through */ \
285 case ByteCodeInstruction::base ## 2: { \
286 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
287 sp[target] = fn(sp[target].field, sp[0].field); \
288 POP(); \
289 } /* fall through */ \
290 case ByteCodeInstruction::base: { \
291 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
292 sp[target] = fn(sp[target].field, sp[0].field); \
293 POP(); \
294 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500295 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400296
Mike Klein459aed12019-05-21 15:46:36 -0500297#define VECTOR_UNARY_FN(base, fn, field) \
298 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
299 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
300 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
301 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400302 break;
303
Brian Osman569f12f2019-06-13 11:23:57 -0400304#define VECTOR_UNARY_FN_VEC(base, fn) \
305 case ByteCodeInstruction::base ## 4: \
306 case ByteCodeInstruction::base ## 3: \
307 case ByteCodeInstruction::base ## 2: \
308 case ByteCodeInstruction::base : { \
309 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
310 float* v = (float*)sp - count + 1; \
311 for (int i = VecWidth * count; i > 0; --i, ++v) { \
312 *v = fn(*v); \
313 } \
314 break; \
315 }
316
317union VValue {
318 VValue() {}
319
320 VValue(F32 f)
321 : fFloat(f) {
322 }
323
324 VValue(I32 s)
325 : fSigned(s) {
326 }
327
328 VValue(U32 u)
329 : fUnsigned(u) {
330 }
331
332 F32 fFloat;
333 I32 fSigned;
334 U32 fUnsigned;
335};
336
Brian Osman226668a2019-05-14 16:47:30 -0400337struct StackFrame {
338 const uint8_t* fCode;
339 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400340 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400341 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400342};
343
Brian Osman569f12f2019-06-13 11:23:57 -0400344static F32 mix(F32 start, F32 end, F32 t) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400345 return start * (1 - t) + end * t;
346}
347
Brian Osman569f12f2019-06-13 11:23:57 -0400348// TODO: trunc on integers?
349template <typename T>
350static T vec_mod(T a, T b) {
351 return a - skvx::trunc(a / b) * b;
352}
Mike Kleine7007382019-05-21 08:36:32 -0500353
Brian Osman4b202a32019-06-21 09:50:29 -0400354static void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400355 float* outReturn[], VValue globals[], bool stripedOutput, int N,
356 int baseIndex) {
Brian Osman4b202a32019-06-21 09:50:29 -0400357 // 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
Brian Osman569f12f2019-06-13 11:23:57 -0400362 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; };
Mike Kleine7007382019-05-21 08:36:32 -0500366
Brian Osman80164412019-06-07 13:00:23 -0400367 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400368 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400369 std::vector<StackFrame> frames;
370
Brian Osman569f12f2019-06-13 11:23:57 -0400371 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
Brian Osman4b202a32019-06-21 09:50:29 -0400375 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400376 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 auto mask = [&]() { return *maskPtr & *loopPtr; };
384
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400385 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400386#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700387 printf("at %3d ", (int) (ip - code));
388 disassemble_instruction(ip);
389 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400390#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700391 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400392 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500393 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400394 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400395
396 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
Brian Osman32c526b2019-06-03 16:13:52 -0400397 case ByteCodeInstruction::kAndB:
Brian Osman569f12f2019-06-13 11:23:57 -0400398 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
399 POP();
400 break;
401 case ByteCodeInstruction::kNotB:
402 sp[0] = ~sp[0].fSigned;
403 break;
404 case ByteCodeInstruction::kOrB:
405 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
406 POP();
407 break;
408 case ByteCodeInstruction::kXorB:
409 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
Brian Osman32c526b2019-06-03 16:13:52 -0400410 POP();
411 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400412
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400413 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400414 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400415 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400416
Brian Osman226668a2019-05-14 16:47:30 -0400417 case ByteCodeInstruction::kCall: {
Brian Osmand3494ed2019-06-20 15:41:34 -0400418 // Precursor code reserved space for the return value, and pushed all parameters to
419 // the stack. Update our bottom of stack to point at the first parameter, and our
420 // sp to point past those parameters (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500421 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400422 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
Brian Osman569f12f2019-06-13 11:23:57 -0400423 if (skvx::any(mask())) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400424 frames.push_back({ code, ip, stack, fun->fParameterCount });
Brian Osman569f12f2019-06-13 11:23:57 -0400425 ip = code = fun->fCode.data();
426 stack = sp - fun->fParameterCount + 1;
427 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
Brian Osman569f12f2019-06-13 11:23:57 -0400428 }
Brian Osman226668a2019-05-14 16:47:30 -0400429 break;
430 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400431
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400432 case ByteCodeInstruction::kCallExternal: {
433 int argumentCount = READ8();
434 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500435 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400436 ExternalValue* v = byteCode->fExternalValues[target];
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400437 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500438
Brian Osman1a79f0b2019-06-24 16:32:14 -0400439 float tmpArgs[4];
440 float tmpReturn[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400441 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
442 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
443
444 I32 m = mask();
445 for (int i = 0; i < VecWidth; ++i) {
446 if (m[i]) {
447 for (int j = 0; j < argumentCount; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400448 tmpArgs[j] = sp[j].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400449 }
Brian Osman1a79f0b2019-06-24 16:32:14 -0400450 v->call(baseIndex + i, tmpArgs, tmpReturn);
Brian Osman569f12f2019-06-13 11:23:57 -0400451 for (int j = 0; j < returnCount; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400452 sp[j].fFloat[i] = tmpReturn[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400453 }
454 }
455 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400456 sp += returnCount - 1;
457 break;
458 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400459
Mike Kleinc1999982019-05-21 13:03:49 -0500460 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400461 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500462 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400463 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500464 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
465 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
466 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
467 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
468 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
469 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
470 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
471 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
472 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
473 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
474 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
475 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400476
Brian Osman569f12f2019-06-13 11:23:57 -0400477 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
478 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
479 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
480 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400481 break;
482
Brian Osman569f12f2019-06-13 11:23:57 -0400483 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
484 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
485 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
486 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400487 break;
488
Brian Osman569f12f2019-06-13 11:23:57 -0400489 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
490 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
491 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
492 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400493 break;
494
Brian Osman569f12f2019-06-13 11:23:57 -0400495 VECTOR_UNARY_FN_VEC(kCos, cosf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400496
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400497 case ByteCodeInstruction::kCross: {
Brian Osman569f12f2019-06-13 11:23:57 -0400498 F32 ax = sp[-5].fFloat, ay = sp[-4].fFloat, az = sp[-3].fFloat,
499 bx = sp[-2].fFloat, by = sp[-1].fFloat, bz = sp[ 0].fFloat;
500 F32 cx = ay*bz - az*by,
501 cy = az*bx - ax*bz,
502 cz = ax*by - ay*bx;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400503 sp -= 3;
Brian Osman569f12f2019-06-13 11:23:57 -0400504 sp[-2] = cx;
505 sp[-1] = cy;
506 sp[ 0] = cz;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400507 break;
508 }
509
Mike Kleinc1999982019-05-21 13:03:49 -0500510 VECTOR_BINARY_OP(kDivideS, fSigned, /)
511 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400512 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500513
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
Brian Osman07c117b2019-05-23 12:51:06 -0700520 case ByteCodeInstruction::kDupN: {
521 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400522 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -0700523 sp += count;
524 break;
525 }
526
Mike Kleine7007382019-05-21 08:36:32 -0500527 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
528 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
529 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
530 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
531 ++ip;
532 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
533 break;
534
Brian Osman80164412019-06-07 13:00:23 -0400535 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
536 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
537 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
538 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
Mike Kleine7007382019-05-21 08:36:32 -0500539 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700540 sp += (int)inst -
541 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500542 break;
543
Brian Osman07c117b2019-05-23 12:51:06 -0700544 case ByteCodeInstruction::kLoadExtended: {
545 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400546 I32 src = POP().fSigned;
547 I32 m = mask();
548 for (int i = 0; i < count; ++i) {
549 for (int j = 0; j < VecWidth; ++j) {
550 if (m[j]) {
551 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
552 }
553 }
554 }
Brian Osman07c117b2019-05-23 12:51:06 -0700555 sp += count;
556 break;
557 }
558
559 case ByteCodeInstruction::kLoadExtendedGlobal: {
560 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400561 I32 src = POP().fSigned;
562 I32 m = mask();
563 for (int i = 0; i < count; ++i) {
564 for (int j = 0; j < VecWidth; ++j) {
565 if (m[j]) {
566 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
567 }
568 }
569 }
Brian Osman07c117b2019-05-23 12:51:06 -0700570 sp += count;
571 break;
572 }
573
Mike Kleine7007382019-05-21 08:36:32 -0500574 case ByteCodeInstruction::kLoadSwizzle: {
575 int src = READ8();
576 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400577 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400578 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400579 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400580 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400581 break;
Mike Kleine7007382019-05-21 08:36:32 -0500582 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400583
Mike Kleine7007382019-05-21 08:36:32 -0500584 case ByteCodeInstruction::kLoadSwizzleGlobal: {
585 int src = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500586 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400587 for (int i = 0; i < count; ++i) {
Brian Osman80164412019-06-07 13:00:23 -0400588 PUSH(globals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400589 }
590 ip += count;
591 break;
Mike Kleine7007382019-05-21 08:36:32 -0500592 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400593
Brian Osman29e013d2019-05-28 17:16:03 -0400594 case ByteCodeInstruction::kMatrixToMatrix: {
595 int srcCols = READ8();
596 int srcRows = READ8();
597 int dstCols = READ8();
598 int dstRows = READ8();
599 SkASSERT(srcCols >= 2 && srcCols <= 4);
600 SkASSERT(srcRows >= 2 && srcRows <= 4);
601 SkASSERT(dstCols >= 2 && dstCols <= 4);
602 SkASSERT(dstRows >= 2 && dstRows <= 4);
Brian Osman569f12f2019-06-13 11:23:57 -0400603 F32 tmp[16];
604 memset(tmp, 0, sizeof(tmp));
605 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
Brian Osman29e013d2019-05-28 17:16:03 -0400606 for (int c = srcCols - 1; c >= 0; --c) {
607 for (int r = srcRows - 1; r >= 0; --r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400608 tmp[c*4 + r] = POP().fFloat;
Brian Osman29e013d2019-05-28 17:16:03 -0400609 }
610 }
611 for (int c = 0; c < dstCols; ++c) {
612 for (int r = 0; r < dstRows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400613 PUSH(tmp[c*4 + r]);
Brian Osman29e013d2019-05-28 17:16:03 -0400614 }
615 }
616 break;
617 }
618
Brian Osman909231c2019-05-29 15:34:36 -0400619 case ByteCodeInstruction::kMatrixMultiply: {
620 int lCols = READ8();
621 int lRows = READ8();
622 int rCols = READ8();
623 int rRows = lCols;
Brian Osman569f12f2019-06-13 11:23:57 -0400624 F32 tmp[16] = { 0.0f };
625 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
626 F32* A = B - (lCols * lRows);
Brian Osman909231c2019-05-29 15:34:36 -0400627 for (int c = 0; c < rCols; ++c) {
628 for (int r = 0; r < lRows; ++r) {
629 for (int j = 0; j < lCols; ++j) {
630 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
631 }
632 }
633 }
634 sp -= (lCols * lRows) + (rCols * rRows);
Brian Osman569f12f2019-06-13 11:23:57 -0400635 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
Brian Osman909231c2019-05-29 15:34:36 -0400636 sp += (rCols * lRows);
637 break;
638 }
639
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400640 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
641 case ByteCodeInstruction::kMix4:
642 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
643 // fall through
644 case ByteCodeInstruction::kMix3: {
645 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
646 int target = 2 - count * 2;
647 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
648 // fall through
649 }
650 case ByteCodeInstruction::kMix2: {
651 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
652 int target = 1 - count * 2;
653 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
654 // fall through
655 }
656 case ByteCodeInstruction::kMix: {
657 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
658 int target = -count * 2;
659 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
660 sp -= 1 + count;
661 break;
662 }
663
Mike Kleinc1999982019-05-21 13:03:49 -0500664 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400665 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400666
Mike Kleinc1999982019-05-21 13:03:49 -0500667 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
668 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
669 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
670 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500671 break;
672
Brian Osman1e855b22019-05-29 15:21:52 -0400673 case ByteCodeInstruction::kNegateFN: {
674 int count = READ8();
675 for (int i = count - 1; i >= 0; --i) {
676 sp[-i] = -sp[-i].fFloat;
677 }
678 break;
679 }
680
Mike Kleinc1999982019-05-21 13:03:49 -0500681 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
682 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
683 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
Brian Osman569f12f2019-06-13 11:23:57 -0400684 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500685 break;
686
687 case ByteCodeInstruction::kPop4: POP();
688 case ByteCodeInstruction::kPop3: POP();
689 case ByteCodeInstruction::kPop2: POP();
690 case ByteCodeInstruction::kPop : POP();
691 break;
692
Brian Osman07c117b2019-05-23 12:51:06 -0700693 case ByteCodeInstruction::kPopN:
694 sp -= READ8();
695 break;
696
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400697 case ByteCodeInstruction::kPushImmediate:
Brian Osman569f12f2019-06-13 11:23:57 -0400698 PUSH(U32(READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400699 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400700
Brian Osman569f12f2019-06-13 11:23:57 -0400701 case ByteCodeInstruction::kReadExternal:
702 case ByteCodeInstruction::kReadExternal2:
703 case ByteCodeInstruction::kReadExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500704 case ByteCodeInstruction::kReadExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400705 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500706 int src = READ8();
Brian Osman1a79f0b2019-06-24 16:32:14 -0400707 float tmp[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400708 I32 m = mask();
709 for (int i = 0; i < VecWidth; ++i) {
710 if (m[i]) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400711 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
Brian Osman569f12f2019-06-13 11:23:57 -0400712 for (int j = 0; j < count; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400713 sp[j + 1].fFloat[i] = tmp[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400714 }
715 }
716 }
717 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400718 break;
Mike Kleine7007382019-05-21 08:36:32 -0500719 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400720
Brian Osman569f12f2019-06-13 11:23:57 -0400721 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
722 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
723 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400724
Brian Osmand3494ed2019-06-20 15:41:34 -0400725 case ByteCodeInstruction::kReserve:
726 sp += READ8();
727 break;
728
Mike Kleine7007382019-05-21 08:36:32 -0500729 case ByteCodeInstruction::kReturn: {
730 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400731 if (frames.empty()) {
732 if (outReturn) {
Brian Osman569f12f2019-06-13 11:23:57 -0400733 VValue* src = sp - count + 1;
Mike Reed3fd3cc92019-06-20 12:40:30 -0400734 if (stripedOutput) {
735 for (int i = 0; i < count; ++i) {
Brian Osman4b202a32019-06-21 09:50:29 -0400736 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
737 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -0400738 }
Mike Reed3fd3cc92019-06-20 12:40:30 -0400739 } else {
740 float* outPtr = outReturn[0];
741 for (int i = 0; i < count; ++i) {
Brian Osman4b202a32019-06-21 09:50:29 -0400742 for (int j = 0; j < N; ++j) {
743 outPtr[count * j] = src->fFloat[j];
Mike Reed3fd3cc92019-06-20 12:40:30 -0400744 }
745 ++outPtr;
746 ++src;
747 }
Brian Osman569f12f2019-06-13 11:23:57 -0400748 }
Brian Osman226668a2019-05-14 16:47:30 -0400749 }
750 return;
751 } else {
Brian Osmand3494ed2019-06-20 15:41:34 -0400752 // When we were called, the caller reserved stack space for their copy of our
753 // return value, then 'stack' was positioned after that, where our parameters
754 // were placed. Copy our return values to their reserved area.
755 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Brian Osman226668a2019-05-14 16:47:30 -0400756
Brian Osmand3494ed2019-06-20 15:41:34 -0400757 // Now move the stack pointer to the end of the passed-in parameters. This odd
758 // calling convention requires the caller to pop the arguments after calling,
759 // but allows them to store any out-parameters back during that unwinding.
760 // After that sequence finishes, the return value will be the top of the stack.
Brian Osman226668a2019-05-14 16:47:30 -0400761 const StackFrame& frame(frames.back());
Brian Osmand3494ed2019-06-20 15:41:34 -0400762 sp = stack + frame.fParameterCount - 1;
Brian Osman226668a2019-05-14 16:47:30 -0400763 stack = frame.fStack;
764 code = frame.fCode;
765 ip = frame.fIP;
766 frames.pop_back();
767 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400768 }
Mike Kleine7007382019-05-21 08:36:32 -0500769 }
770
Brian Osman29e013d2019-05-28 17:16:03 -0400771 case ByteCodeInstruction::kScalarToMatrix: {
772 int cols = READ8();
773 int rows = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400774 VValue v = POP();
Brian Osman29e013d2019-05-28 17:16:03 -0400775 for (int c = 0; c < cols; ++c) {
776 for (int r = 0; r < rows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400777 PUSH(c == r ? v : F32(0.0f));
Brian Osman29e013d2019-05-28 17:16:03 -0400778 }
779 }
780 break;
781 }
782
Brian Osman569f12f2019-06-13 11:23:57 -0400783 VECTOR_UNARY_FN_VEC(kSin, sinf)
784 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400785
Brian Osman569f12f2019-06-13 11:23:57 -0400786 case ByteCodeInstruction::kStore4:
787 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
788 case ByteCodeInstruction::kStore3:
789 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
790 case ByteCodeInstruction::kStore2:
791 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
792 case ByteCodeInstruction::kStore :
793 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
794 ++ip;
795 break;
Mike Kleine7007382019-05-21 08:36:32 -0500796
Brian Osman569f12f2019-06-13 11:23:57 -0400797 case ByteCodeInstruction::kStoreGlobal4:
798 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
799 case ByteCodeInstruction::kStoreGlobal3:
800 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
801 case ByteCodeInstruction::kStoreGlobal2:
802 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
803 case ByteCodeInstruction::kStoreGlobal :
804 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
805 ++ip;
806 break;
Mike Kleine7007382019-05-21 08:36:32 -0500807
Brian Osman07c117b2019-05-23 12:51:06 -0700808 case ByteCodeInstruction::kStoreExtended: {
809 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400810 I32 target = POP().fSigned;
811 VValue* src = sp - count + 1;
812 I32 m = mask();
813 for (int i = 0; i < count; ++i) {
814 for (int j = 0; j < VecWidth; ++j) {
815 if (m[j]) {
816 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
817 }
818 }
819 }
Brian Osman07c117b2019-05-23 12:51:06 -0700820 sp -= count;
821 break;
822 }
823 case ByteCodeInstruction::kStoreExtendedGlobal: {
824 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400825 I32 target = POP().fSigned;
826 VValue* src = sp - count + 1;
827 I32 m = mask();
828 for (int i = 0; i < count; ++i) {
829 for (int j = 0; j < VecWidth; ++j) {
830 if (m[j]) {
831 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
832 }
833 }
834 }
Brian Osman07c117b2019-05-23 12:51:06 -0700835 sp -= count;
836 break;
837 }
838
Mike Kleine7007382019-05-21 08:36:32 -0500839 case ByteCodeInstruction::kStoreSwizzle: {
840 int target = READ8();
841 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400842 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400843 stack[target + *(ip + i)] = skvx::if_then_else(
844 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400845 }
Brian Osman1091f022019-05-16 09:42:16 -0400846 ip += count;
847 break;
Mike Kleine7007382019-05-21 08:36:32 -0500848 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400849
Mike Kleine7007382019-05-21 08:36:32 -0500850 case ByteCodeInstruction::kStoreSwizzleGlobal: {
851 int target = READ8();
852 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400853 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400854 globals[target + *(ip + i)] = skvx::if_then_else(
855 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
Brian Osman1091f022019-05-16 09:42:16 -0400856 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400857 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400858 break;
Mike Kleine7007382019-05-21 08:36:32 -0500859 }
Brian Osman569f12f2019-06-13 11:23:57 -0400860
Brian Osman07c117b2019-05-23 12:51:06 -0700861 case ByteCodeInstruction::kStoreSwizzleIndirect: {
Brian Osman07c117b2019-05-23 12:51:06 -0700862 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400863 I32 target = POP().fSigned;
864 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700865 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400866 I32 v = POP().fSigned;
867 for (int j = 0; j < VecWidth; ++j) {
868 if (m[j]) {
869 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
870 }
871 }
Brian Osman07c117b2019-05-23 12:51:06 -0700872 }
873 ip += count;
874 break;
875 }
Brian Osman569f12f2019-06-13 11:23:57 -0400876
Brian Osman07c117b2019-05-23 12:51:06 -0700877 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
Brian Osman07c117b2019-05-23 12:51:06 -0700878 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400879 I32 target = POP().fSigned;
880 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700881 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400882 I32 v = POP().fSigned;
883 for (int j = 0; j < VecWidth; ++j) {
884 if (m[j]) {
885 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
886 }
887 }
Brian Osman07c117b2019-05-23 12:51:06 -0700888 }
889 ip += count;
890 break;
891 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400892
Mike Kleinc1999982019-05-21 13:03:49 -0500893 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400894 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400895
Mike Kleine7007382019-05-21 08:36:32 -0500896 case ByteCodeInstruction::kSwizzle: {
Brian Osman569f12f2019-06-13 11:23:57 -0400897 VValue tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400898 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400899 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400900 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400901 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400902 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400903 }
904 break;
Mike Kleine7007382019-05-21 08:36:32 -0500905 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400906
Brian Osman569f12f2019-06-13 11:23:57 -0400907 VECTOR_UNARY_FN_VEC(kTan, tanf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400908
Brian Osman569f12f2019-06-13 11:23:57 -0400909 case ByteCodeInstruction::kWriteExternal:
910 case ByteCodeInstruction::kWriteExternal2:
911 case ByteCodeInstruction::kWriteExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500912 case ByteCodeInstruction::kWriteExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400913 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500914 int target = READ8();
Brian Osman1a79f0b2019-06-24 16:32:14 -0400915 float tmp[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400916 I32 m = mask();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400917 sp -= count;
Brian Osman569f12f2019-06-13 11:23:57 -0400918 for (int i = 0; i < VecWidth; ++i) {
919 if (m[i]) {
920 for (int j = 0; j < count; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400921 tmp[j] = sp[j + 1].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400922 }
Brian Osman1a79f0b2019-06-24 16:32:14 -0400923 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
Brian Osman569f12f2019-06-13 11:23:57 -0400924 }
925 }
926 break;
927 }
928
929 case ByteCodeInstruction::kMaskPush:
930 condPtr[1] = POP().fSigned;
931 maskPtr[1] = maskPtr[0] & condPtr[1];
932 ++condPtr; ++maskPtr;
933 break;
934 case ByteCodeInstruction::kMaskPop:
935 --condPtr; --maskPtr;
936 break;
937 case ByteCodeInstruction::kMaskNegate:
938 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
939 break;
940 case ByteCodeInstruction::kMaskBlend: {
941 int count = READ8();
942 I32 m = condPtr[0];
943 --condPtr; --maskPtr;
944 for (int i = 0; i < count; ++i) {
945 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
946 --sp;
947 }
948 break;
949 }
950 case ByteCodeInstruction::kBranchIfAllFalse: {
951 int target = READ16();
952 if (!skvx::any(mask())) {
953 ip = code + target;
954 }
955 break;
956 }
957
958 case ByteCodeInstruction::kLoopBegin:
Brian Osman8d564572019-06-19 11:00:28 -0400959 contPtr[1] = 0;
960 loopPtr[1] = loopPtr[0];
961 ++contPtr; ++loopPtr;
Brian Osman569f12f2019-06-13 11:23:57 -0400962 break;
963 case ByteCodeInstruction::kLoopNext:
964 *loopPtr |= *contPtr;
965 *contPtr = 0;
966 break;
967 case ByteCodeInstruction::kLoopMask:
968 *loopPtr &= POP().fSigned;
969 break;
970 case ByteCodeInstruction::kLoopEnd:
971 --contPtr; --loopPtr;
972 break;
973 case ByteCodeInstruction::kLoopBreak:
974 *loopPtr &= ~mask();
975 break;
976 case ByteCodeInstruction::kLoopContinue: {
977 I32 m = mask();
978 *contPtr |= m;
979 *loopPtr &= ~m;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400980 break;
Mike Kleine7007382019-05-21 08:36:32 -0500981 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400982
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400983 default:
Mike Kleine7007382019-05-21 08:36:32 -0500984 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400985 }
Brian Osman569f12f2019-06-13 11:23:57 -0400986 }
987}
988
Brian Osman08a84962019-06-14 10:17:16 -0400989} // namespace Interpreter
990
Brian Osman489cf882019-07-09 10:48:28 -0400991#endif // SK_ENABLE_SKSL_INTERPRETER
992
Brian Osman08a84962019-06-14 10:17:16 -0400993void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -0400994#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -0400995 const uint8_t* ip = fCode.data();
996 while (ip < fCode.data() + fCode.size()) {
997 printf("%d: ", (int)(ip - fCode.data()));
998 ip = Interpreter::disassemble_instruction(ip);
999 printf("\n");
1000 }
Brian Osman489cf882019-07-09 10:48:28 -04001001#endif
Brian Osman08a84962019-06-14 10:17:16 -04001002}
1003
1004void ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
1005 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001006#if defined(SK_ENABLE_SKSL_INTERPRETER)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001007#ifdef TRACE
Brian Osman08a84962019-06-14 10:17:16 -04001008 f->disassemble();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001009#endif
Brian Osman4b202a32019-06-21 09:50:29 -04001010 Interpreter::VValue stack[128];
Brian Osmanef787f72019-06-13 13:07:12 -04001011
Brian Osman08a84962019-06-14 10:17:16 -04001012 SkASSERT(uniformCount == (int)fInputSlots.size());
1013 Interpreter::VValue globals[32];
1014 SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
1015 for (uint8_t slot : fInputSlots) {
1016 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001017 }
1018
Brian Osman1a79f0b2019-06-24 16:32:14 -04001019 int baseIndex = 0;
1020
Brian Osman569f12f2019-06-13 11:23:57 -04001021 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001022 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001023
1024 // Transpose args into stack
1025 {
Brian Osman08a84962019-06-14 10:17:16 -04001026 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001027 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001028 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001029 for (int j = f->fParameterCount; j > 0; --j) {
1030 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001031 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001032 }
1033 }
1034 }
1035
Mike Reed3fd3cc92019-06-20 12:40:30 -04001036 bool stripedOutput = false;
1037 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001038 innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex);
Brian Osman569f12f2019-06-13 11:23:57 -04001039
1040 // Transpose out parameters back
1041 {
Brian Osman08a84962019-06-14 10:17:16 -04001042 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001043 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001044 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001045 for (const auto& p : f->fParameters) {
1046 if (p.fIsOutParameter) {
1047 for (int j = p.fSlotCount; j > 0; --j) {
1048 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001049 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001050 }
1051 } else {
1052 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001053 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001054 }
1055 }
1056 }
1057 }
1058
1059 args += f->fParameterCount * w;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001060 if (outReturn) {
1061 outReturn += f->fReturnCount * w;
1062 }
Brian Osman4b202a32019-06-21 09:50:29 -04001063 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001064 baseIndex += w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001065 }
Brian Osman489cf882019-07-09 10:48:28 -04001066#else
1067 SkDEBUGFAIL("ByteCode interpreter not enabled");
1068#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001069}
1070
Brian Osman2b1a5442019-06-19 11:40:33 -04001071void ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
Mike Reed3fd3cc92019-06-20 12:40:30 -04001072 const float* uniforms, int uniformCount,
1073 float* outArgs[], int outCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001074#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001075#ifdef TRACE
Brian Osmanecb3bb52019-06-20 14:59:12 -04001076 f->disassemble();
Brian Osman2b1a5442019-06-19 11:40:33 -04001077#endif
1078 Interpreter::VValue stack[128];
1079
Mike Reed3fd3cc92019-06-20 12:40:30 -04001080 // innerRun just takes outArgs, so clear it if the count is zero
1081 if (outCount == 0) {
1082 outArgs = nullptr;
1083 }
1084
Brian Osman2b1a5442019-06-19 11:40:33 -04001085 SkASSERT(nargs == f->fParameterCount);
Mike Reed3fd3cc92019-06-20 12:40:30 -04001086 SkASSERT(outCount == f->fReturnCount);
Brian Osman2b1a5442019-06-19 11:40:33 -04001087 SkASSERT(uniformCount == (int)fInputSlots.size());
1088 Interpreter::VValue globals[32];
1089 SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
1090 for (uint8_t slot : fInputSlots) {
1091 globals[slot].fFloat = *uniforms++;
1092 }
1093
Brian Osman1a79f0b2019-06-24 16:32:14 -04001094 int baseIndex = 0;
1095
Brian Osman2b1a5442019-06-19 11:40:33 -04001096 while (N) {
1097 int w = std::min(N, Interpreter::VecWidth);
1098
1099 // Copy args into stack
1100 for (int i = 0; i < nargs; ++i) {
1101 memcpy(stack + i, args[i], w * sizeof(float));
1102 }
1103
Mike Reed3fd3cc92019-06-20 12:40:30 -04001104 bool stripedOutput = true;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001105 innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex);
Brian Osman2b1a5442019-06-19 11:40:33 -04001106
1107 // Copy out parameters back
1108 int slot = 0;
1109 for (const auto& p : f->fParameters) {
1110 if (p.fIsOutParameter) {
1111 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1112 memcpy(args[i], stack + i, w * sizeof(float));
1113 }
1114 }
1115 slot += p.fSlotCount;
1116 }
1117
1118 // Step each argument pointer ahead
1119 for (int i = 0; i < nargs; ++i) {
1120 args[i] += w;
1121 }
1122 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001123 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001124 }
Brian Osman489cf882019-07-09 10:48:28 -04001125#else
1126 SkDEBUGFAIL("ByteCode interpreter not enabled");
1127#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001128}
1129
Brian Osman80164412019-06-07 13:00:23 -04001130} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001131
1132#endif