blob: 91d7abb5db5a5b1ab779779791f2c289b6983873 [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 }
Brian Osmanf42de9e2019-07-18 10:25:39 -040062 case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -070063 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
64 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040065 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
66 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070067 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
68 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
69 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
70 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
71 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
72 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
73 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
74 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
75 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
76 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
77 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
78 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Brian Osman3e833e12019-05-23 13:23:24 -070079 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
80 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
81 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
82 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osmanecb3bb52019-06-20 14:59:12 -040083 case ByteCodeInstruction::kCross: printf("cross"); break;
Brian Osman1e855b22019-05-29 15:21:52 -040084 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070085 VECTOR_DISASSEMBLE(kDivideS, "divideS")
86 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040087 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Brian Osman3e833e12019-05-23 13:23:24 -070088 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
89 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
90 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
91 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
92 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
93 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
94 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
95 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
96 case ByteCodeInstruction::kLoadSwizzle: {
97 int target = READ8();
98 int count = READ8();
99 printf("loadswizzle %d %d", target, count);
100 for (int i = 0; i < count; ++i) {
101 printf(", %d", READ8());
102 }
103 break;
104 }
105 case ByteCodeInstruction::kLoadSwizzleGlobal: {
106 int target = READ8();
107 int count = READ8();
108 printf("loadswizzleglobal %d %d", target, count);
109 for (int i = 0; i < count; ++i) {
110 printf(", %d", READ8());
111 }
112 break;
113 }
114 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
115 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
116 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400117 case ByteCodeInstruction::kMatrixToMatrix: {
118 int srcCols = READ8();
119 int srcRows = READ8();
120 int dstCols = READ8();
121 int dstRows = READ8();
122 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
123 break;
124 }
Brian Osman909231c2019-05-29 15:34:36 -0400125 case ByteCodeInstruction::kMatrixMultiply: {
126 int lCols = READ8();
127 int lRows = READ8();
128 int rCols = READ8();
129 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
130 break;
131 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400132 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400133 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700134 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400135 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700136 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400137 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400138 case ByteCodeInstruction::kOrB: printf("orb"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400139 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700140 case ByteCodeInstruction::kPushImmediate: {
141 uint32_t v = READ32();
142 union { uint32_t u; float f; } pun = { v };
143 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
144 break;
145 }
146 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
147 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
148 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
149 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
150 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
151 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
152 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400153 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700154 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400155 case ByteCodeInstruction::kScalarToMatrix: {
156 int cols = READ8();
157 int rows = READ8();
158 printf("scalartomatrix %dx%d", cols, rows);
159 break;
160 }
Brian Osman3e833e12019-05-23 13:23:24 -0700161 VECTOR_DISASSEMBLE(kSin, "sin")
162 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
163 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
164 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
165 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
166 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
167 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
168 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
169 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
170 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
171 case ByteCodeInstruction::kStoreSwizzle: {
172 int target = READ8();
173 int count = READ8();
174 printf("storeswizzle %d %d", target, count);
175 for (int i = 0; i < count; ++i) {
176 printf(", %d", READ8());
177 }
178 break;
179 }
180 case ByteCodeInstruction::kStoreSwizzleGlobal: {
181 int target = READ8();
182 int count = READ8();
183 printf("storeswizzleglobal %d %d", target, count);
184 for (int i = 0; i < count; ++i) {
185 printf(", %d", READ8());
186 }
187 break;
188 }
189 case ByteCodeInstruction::kStoreSwizzleIndirect: {
190 int count = READ8();
191 printf("storeswizzleindirect %d", count);
192 for (int i = 0; i < count; ++i) {
193 printf(", %d", READ8());
194 }
195 break;
196 }
197 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
198 int count = READ8();
199 printf("storeswizzleindirectglobal %d", count);
200 for (int i = 0; i < count; ++i) {
201 printf(", %d", READ8());
202 }
203 break;
204 }
205 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
206 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
207 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400208 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700209 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
210 case ByteCodeInstruction::kSwizzle: {
211 printf("swizzle %d, ", READ8());
212 int count = READ8();
213 printf("%d", count);
214 for (int i = 0; i < count; ++i) {
215 printf(", %d", READ8());
216 }
217 break;
218 }
219 VECTOR_DISASSEMBLE(kTan, "tan")
220 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
221 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
222 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
223 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400224 case ByteCodeInstruction::kXorB: printf("xorb"); break;
225 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
226 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
227 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
228 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
229 case ByteCodeInstruction::kBranchIfAllFalse:
230 printf("branchifallfalse %d", READ16());
231 break;
232 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
233 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
234 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
235 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
236 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
237 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700238 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
239 }
240 return ip;
241}
242
Mike Klein459aed12019-05-21 15:46:36 -0500243#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500244 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500245 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500246 POP(); \
247 /* fall through */ \
248 case ByteCodeInstruction::base ## 3: { \
249 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500250 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500251 POP(); \
252 } /* fall through */ \
253 case ByteCodeInstruction::base ## 2: { \
254 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500255 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500256 POP(); \
257 } /* fall through */ \
258 case ByteCodeInstruction::base: { \
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 break; \
263 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400264
Brian Osman1e855b22019-05-29 15:21:52 -0400265#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
266 VECTOR_BINARY_OP(base, field, op) \
267 case ByteCodeInstruction::base ## N: { \
268 int count = READ8(); \
269 for (int i = count; i > 0; --i) { \
270 sp[-count] = sp[-count].field op sp[0].field; \
271 POP(); \
272 } \
273 break; \
274 }
275
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400276#define VECTOR_BINARY_FN(base, field, fn) \
277 case ByteCodeInstruction::base ## 4: \
278 sp[-4] = fn(sp[-4].field, sp[0].field); \
279 POP(); \
280 /* fall through */ \
281 case ByteCodeInstruction::base ## 3: { \
282 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
283 sp[target] = fn(sp[target].field, sp[0].field); \
284 POP(); \
285 } /* fall through */ \
286 case ByteCodeInstruction::base ## 2: { \
287 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
288 sp[target] = fn(sp[target].field, sp[0].field); \
289 POP(); \
290 } /* fall through */ \
291 case ByteCodeInstruction::base: { \
292 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
293 sp[target] = fn(sp[target].field, sp[0].field); \
294 POP(); \
295 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500296 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400297
Mike Klein459aed12019-05-21 15:46:36 -0500298#define VECTOR_UNARY_FN(base, fn, field) \
299 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
300 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
301 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
302 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400303 break;
304
Brian Osman569f12f2019-06-13 11:23:57 -0400305#define VECTOR_UNARY_FN_VEC(base, fn) \
306 case ByteCodeInstruction::base ## 4: \
307 case ByteCodeInstruction::base ## 3: \
308 case ByteCodeInstruction::base ## 2: \
309 case ByteCodeInstruction::base : { \
310 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
311 float* v = (float*)sp - count + 1; \
312 for (int i = VecWidth * count; i > 0; --i, ++v) { \
313 *v = fn(*v); \
314 } \
315 break; \
316 }
317
318union VValue {
319 VValue() {}
320
321 VValue(F32 f)
322 : fFloat(f) {
323 }
324
325 VValue(I32 s)
326 : fSigned(s) {
327 }
328
329 VValue(U32 u)
330 : fUnsigned(u) {
331 }
332
333 F32 fFloat;
334 I32 fSigned;
335 U32 fUnsigned;
336};
337
Brian Osman226668a2019-05-14 16:47:30 -0400338struct StackFrame {
339 const uint8_t* fCode;
340 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400341 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400342 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400343};
344
Brian Osman569f12f2019-06-13 11:23:57 -0400345static F32 mix(F32 start, F32 end, F32 t) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400346 return start * (1 - t) + end * t;
347}
348
Brian Osman569f12f2019-06-13 11:23:57 -0400349// TODO: trunc on integers?
350template <typename T>
351static T vec_mod(T a, T b) {
352 return a - skvx::trunc(a / b) * b;
353}
Mike Kleine7007382019-05-21 08:36:32 -0500354
Brian Osmanf42de9e2019-07-18 10:25:39 -0400355static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400356 float* outReturn[], VValue globals[], bool stripedOutput, int N,
357 int baseIndex) {
Brian Osman4b202a32019-06-21 09:50:29 -0400358 // Needs to be the first N non-negative integers, at least as large as VecWidth
359 static const Interpreter::I32 gLanes = {
360 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
361 };
362
Brian Osman569f12f2019-06-13 11:23:57 -0400363 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
364
365 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
366 auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
Mike Kleine7007382019-05-21 08:36:32 -0500367
Brian Osman80164412019-06-07 13:00:23 -0400368 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400369 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400370 std::vector<StackFrame> frames;
371
Brian Osman569f12f2019-06-13 11:23:57 -0400372 I32 condStack[16]; // Independent condition masks
373 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
374 I32 contStack[16]; // Continue flags for loops
375 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400376 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400377 contStack[0] = I32( 0);
378 loopStack[0] = I32(~0);
379 I32* condPtr = condStack;
380 I32* maskPtr = maskStack;
381 I32* contPtr = contStack;
382 I32* loopPtr = loopStack;
383
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400384 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
385 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osmanf42de9e2019-07-18 10:25:39 -0400386 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400387 }
388
Brian Osman569f12f2019-06-13 11:23:57 -0400389 auto mask = [&]() { return *maskPtr & *loopPtr; };
390
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400391 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400392#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700393 printf("at %3d ", (int) (ip - code));
394 disassemble_instruction(ip);
395 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400396#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700397 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400398 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500399 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400400 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400401
402 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
Brian Osman32c526b2019-06-03 16:13:52 -0400403 case ByteCodeInstruction::kAndB:
Brian Osman569f12f2019-06-13 11:23:57 -0400404 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
405 POP();
406 break;
407 case ByteCodeInstruction::kNotB:
408 sp[0] = ~sp[0].fSigned;
409 break;
410 case ByteCodeInstruction::kOrB:
411 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
412 POP();
413 break;
414 case ByteCodeInstruction::kXorB:
415 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
Brian Osman32c526b2019-06-03 16:13:52 -0400416 POP();
417 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400418
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400419 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400420 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400421 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400422
Brian Osman226668a2019-05-14 16:47:30 -0400423 case ByteCodeInstruction::kCall: {
Brian Osmand3494ed2019-06-20 15:41:34 -0400424 // Precursor code reserved space for the return value, and pushed all parameters to
425 // the stack. Update our bottom of stack to point at the first parameter, and our
426 // sp to point past those parameters (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500427 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400428 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
Brian Osman569f12f2019-06-13 11:23:57 -0400429 if (skvx::any(mask())) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400430 frames.push_back({ code, ip, stack, fun->fParameterCount });
Brian Osman569f12f2019-06-13 11:23:57 -0400431 ip = code = fun->fCode.data();
432 stack = sp - fun->fParameterCount + 1;
433 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
Brian Osman569f12f2019-06-13 11:23:57 -0400434 }
Brian Osman226668a2019-05-14 16:47:30 -0400435 break;
436 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400437
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400438 case ByteCodeInstruction::kCallExternal: {
439 int argumentCount = READ8();
440 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500441 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400442 ExternalValue* v = byteCode->fExternalValues[target];
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400443 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500444
Brian Osman1a79f0b2019-06-24 16:32:14 -0400445 float tmpArgs[4];
446 float tmpReturn[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400447 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
448 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
449
450 I32 m = mask();
451 for (int i = 0; i < VecWidth; ++i) {
452 if (m[i]) {
453 for (int j = 0; j < argumentCount; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400454 tmpArgs[j] = sp[j].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400455 }
Brian Osman1a79f0b2019-06-24 16:32:14 -0400456 v->call(baseIndex + i, tmpArgs, tmpReturn);
Brian Osman569f12f2019-06-13 11:23:57 -0400457 for (int j = 0; j < returnCount; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400458 sp[j].fFloat[i] = tmpReturn[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400459 }
460 }
461 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400462 sp += returnCount - 1;
463 break;
464 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400465
Brian Osmanf42de9e2019-07-18 10:25:39 -0400466 case ByteCodeInstruction::kClampIndex: {
467 int length = READ8();
468 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
469 return false;
470 }
471 break;
472 }
473
Mike Kleinc1999982019-05-21 13:03:49 -0500474 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400475 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500476 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400477 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500478 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
479 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
480 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
481 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
482 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
483 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
484 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
485 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
486 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
487 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
488 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
489 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400490
Brian Osman569f12f2019-06-13 11:23:57 -0400491 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
492 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
493 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
494 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400495 break;
496
Brian Osman569f12f2019-06-13 11:23:57 -0400497 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
498 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
499 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
500 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400501 break;
502
Brian Osman569f12f2019-06-13 11:23:57 -0400503 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
504 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
505 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
506 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400507 break;
508
Brian Osman569f12f2019-06-13 11:23:57 -0400509 VECTOR_UNARY_FN_VEC(kCos, cosf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400510
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400511 case ByteCodeInstruction::kCross: {
Brian Osman569f12f2019-06-13 11:23:57 -0400512 F32 ax = sp[-5].fFloat, ay = sp[-4].fFloat, az = sp[-3].fFloat,
513 bx = sp[-2].fFloat, by = sp[-1].fFloat, bz = sp[ 0].fFloat;
514 F32 cx = ay*bz - az*by,
515 cy = az*bx - ax*bz,
516 cz = ax*by - ay*bx;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400517 sp -= 3;
Brian Osman569f12f2019-06-13 11:23:57 -0400518 sp[-2] = cx;
519 sp[-1] = cy;
520 sp[ 0] = cz;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400521 break;
522 }
523
Mike Kleinc1999982019-05-21 13:03:49 -0500524 VECTOR_BINARY_OP(kDivideS, fSigned, /)
525 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400526 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500527
528 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
529 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
530 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
531 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
532 break;
533
Brian Osman07c117b2019-05-23 12:51:06 -0700534 case ByteCodeInstruction::kDupN: {
535 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400536 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -0700537 sp += count;
538 break;
539 }
540
Mike Kleine7007382019-05-21 08:36:32 -0500541 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
542 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
543 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
544 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
545 ++ip;
546 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
547 break;
548
Brian Osman80164412019-06-07 13:00:23 -0400549 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
550 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
551 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
552 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
Mike Kleine7007382019-05-21 08:36:32 -0500553 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700554 sp += (int)inst -
555 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500556 break;
557
Brian Osman07c117b2019-05-23 12:51:06 -0700558 case ByteCodeInstruction::kLoadExtended: {
559 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400560 I32 src = POP().fSigned;
561 I32 m = mask();
562 for (int i = 0; i < count; ++i) {
563 for (int j = 0; j < VecWidth; ++j) {
564 if (m[j]) {
565 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
566 }
567 }
568 }
Brian Osman07c117b2019-05-23 12:51:06 -0700569 sp += count;
570 break;
571 }
572
573 case ByteCodeInstruction::kLoadExtendedGlobal: {
574 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400575 I32 src = POP().fSigned;
576 I32 m = mask();
577 for (int i = 0; i < count; ++i) {
578 for (int j = 0; j < VecWidth; ++j) {
579 if (m[j]) {
580 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
581 }
582 }
583 }
Brian Osman07c117b2019-05-23 12:51:06 -0700584 sp += count;
585 break;
586 }
587
Mike Kleine7007382019-05-21 08:36:32 -0500588 case ByteCodeInstruction::kLoadSwizzle: {
589 int src = READ8();
590 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400591 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400592 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400593 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400594 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400595 break;
Mike Kleine7007382019-05-21 08:36:32 -0500596 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400597
Mike Kleine7007382019-05-21 08:36:32 -0500598 case ByteCodeInstruction::kLoadSwizzleGlobal: {
599 int src = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500600 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400601 for (int i = 0; i < count; ++i) {
Brian Osman80164412019-06-07 13:00:23 -0400602 PUSH(globals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400603 }
604 ip += count;
605 break;
Mike Kleine7007382019-05-21 08:36:32 -0500606 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400607
Brian Osman29e013d2019-05-28 17:16:03 -0400608 case ByteCodeInstruction::kMatrixToMatrix: {
609 int srcCols = READ8();
610 int srcRows = READ8();
611 int dstCols = READ8();
612 int dstRows = READ8();
613 SkASSERT(srcCols >= 2 && srcCols <= 4);
614 SkASSERT(srcRows >= 2 && srcRows <= 4);
615 SkASSERT(dstCols >= 2 && dstCols <= 4);
616 SkASSERT(dstRows >= 2 && dstRows <= 4);
Brian Osman569f12f2019-06-13 11:23:57 -0400617 F32 tmp[16];
618 memset(tmp, 0, sizeof(tmp));
619 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
Brian Osman29e013d2019-05-28 17:16:03 -0400620 for (int c = srcCols - 1; c >= 0; --c) {
621 for (int r = srcRows - 1; r >= 0; --r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400622 tmp[c*4 + r] = POP().fFloat;
Brian Osman29e013d2019-05-28 17:16:03 -0400623 }
624 }
625 for (int c = 0; c < dstCols; ++c) {
626 for (int r = 0; r < dstRows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400627 PUSH(tmp[c*4 + r]);
Brian Osman29e013d2019-05-28 17:16:03 -0400628 }
629 }
630 break;
631 }
632
Brian Osman909231c2019-05-29 15:34:36 -0400633 case ByteCodeInstruction::kMatrixMultiply: {
634 int lCols = READ8();
635 int lRows = READ8();
636 int rCols = READ8();
637 int rRows = lCols;
Brian Osman569f12f2019-06-13 11:23:57 -0400638 F32 tmp[16] = { 0.0f };
639 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
640 F32* A = B - (lCols * lRows);
Brian Osman909231c2019-05-29 15:34:36 -0400641 for (int c = 0; c < rCols; ++c) {
642 for (int r = 0; r < lRows; ++r) {
643 for (int j = 0; j < lCols; ++j) {
644 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
645 }
646 }
647 }
648 sp -= (lCols * lRows) + (rCols * rRows);
Brian Osman569f12f2019-06-13 11:23:57 -0400649 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
Brian Osman909231c2019-05-29 15:34:36 -0400650 sp += (rCols * lRows);
651 break;
652 }
653
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400654 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
655 case ByteCodeInstruction::kMix4:
656 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
657 // fall through
658 case ByteCodeInstruction::kMix3: {
659 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
660 int target = 2 - count * 2;
661 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
662 // fall through
663 }
664 case ByteCodeInstruction::kMix2: {
665 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
666 int target = 1 - count * 2;
667 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
668 // fall through
669 }
670 case ByteCodeInstruction::kMix: {
671 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
672 int target = -count * 2;
673 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
674 sp -= 1 + count;
675 break;
676 }
677
Mike Kleinc1999982019-05-21 13:03:49 -0500678 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400679 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400680
Mike Kleinc1999982019-05-21 13:03:49 -0500681 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
682 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
683 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
684 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500685 break;
686
Brian Osman1e855b22019-05-29 15:21:52 -0400687 case ByteCodeInstruction::kNegateFN: {
688 int count = READ8();
689 for (int i = count - 1; i >= 0; --i) {
690 sp[-i] = -sp[-i].fFloat;
691 }
692 break;
693 }
694
Mike Kleinc1999982019-05-21 13:03:49 -0500695 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
696 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
697 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
Brian Osman569f12f2019-06-13 11:23:57 -0400698 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500699 break;
700
701 case ByteCodeInstruction::kPop4: POP();
702 case ByteCodeInstruction::kPop3: POP();
703 case ByteCodeInstruction::kPop2: POP();
704 case ByteCodeInstruction::kPop : POP();
705 break;
706
Brian Osman07c117b2019-05-23 12:51:06 -0700707 case ByteCodeInstruction::kPopN:
708 sp -= READ8();
709 break;
710
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400711 case ByteCodeInstruction::kPushImmediate:
Brian Osman569f12f2019-06-13 11:23:57 -0400712 PUSH(U32(READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400713 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400714
Brian Osman569f12f2019-06-13 11:23:57 -0400715 case ByteCodeInstruction::kReadExternal:
716 case ByteCodeInstruction::kReadExternal2:
717 case ByteCodeInstruction::kReadExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500718 case ByteCodeInstruction::kReadExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400719 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500720 int src = READ8();
Brian Osman1a79f0b2019-06-24 16:32:14 -0400721 float tmp[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400722 I32 m = mask();
723 for (int i = 0; i < VecWidth; ++i) {
724 if (m[i]) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400725 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
Brian Osman569f12f2019-06-13 11:23:57 -0400726 for (int j = 0; j < count; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400727 sp[j + 1].fFloat[i] = tmp[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400728 }
729 }
730 }
731 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400732 break;
Mike Kleine7007382019-05-21 08:36:32 -0500733 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400734
Brian Osman569f12f2019-06-13 11:23:57 -0400735 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
736 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
737 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400738
Brian Osmand3494ed2019-06-20 15:41:34 -0400739 case ByteCodeInstruction::kReserve:
740 sp += READ8();
741 break;
742
Mike Kleine7007382019-05-21 08:36:32 -0500743 case ByteCodeInstruction::kReturn: {
744 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400745 if (frames.empty()) {
746 if (outReturn) {
Brian Osman569f12f2019-06-13 11:23:57 -0400747 VValue* src = sp - count + 1;
Mike Reed3fd3cc92019-06-20 12:40:30 -0400748 if (stripedOutput) {
749 for (int i = 0; i < count; ++i) {
Brian Osman4b202a32019-06-21 09:50:29 -0400750 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
751 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -0400752 }
Mike Reed3fd3cc92019-06-20 12:40:30 -0400753 } else {
754 float* outPtr = outReturn[0];
755 for (int i = 0; i < count; ++i) {
Brian Osman4b202a32019-06-21 09:50:29 -0400756 for (int j = 0; j < N; ++j) {
757 outPtr[count * j] = src->fFloat[j];
Mike Reed3fd3cc92019-06-20 12:40:30 -0400758 }
759 ++outPtr;
760 ++src;
761 }
Brian Osman569f12f2019-06-13 11:23:57 -0400762 }
Brian Osman226668a2019-05-14 16:47:30 -0400763 }
Brian Osmanf42de9e2019-07-18 10:25:39 -0400764 return true;
Brian Osman226668a2019-05-14 16:47:30 -0400765 } else {
Brian Osmand3494ed2019-06-20 15:41:34 -0400766 // When we were called, the caller reserved stack space for their copy of our
767 // return value, then 'stack' was positioned after that, where our parameters
768 // were placed. Copy our return values to their reserved area.
769 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Brian Osman226668a2019-05-14 16:47:30 -0400770
Brian Osmand3494ed2019-06-20 15:41:34 -0400771 // Now move the stack pointer to the end of the passed-in parameters. This odd
772 // calling convention requires the caller to pop the arguments after calling,
773 // but allows them to store any out-parameters back during that unwinding.
774 // After that sequence finishes, the return value will be the top of the stack.
Brian Osman226668a2019-05-14 16:47:30 -0400775 const StackFrame& frame(frames.back());
Brian Osmand3494ed2019-06-20 15:41:34 -0400776 sp = stack + frame.fParameterCount - 1;
Brian Osman226668a2019-05-14 16:47:30 -0400777 stack = frame.fStack;
778 code = frame.fCode;
779 ip = frame.fIP;
780 frames.pop_back();
781 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400782 }
Mike Kleine7007382019-05-21 08:36:32 -0500783 }
784
Brian Osman29e013d2019-05-28 17:16:03 -0400785 case ByteCodeInstruction::kScalarToMatrix: {
786 int cols = READ8();
787 int rows = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400788 VValue v = POP();
Brian Osman29e013d2019-05-28 17:16:03 -0400789 for (int c = 0; c < cols; ++c) {
790 for (int r = 0; r < rows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400791 PUSH(c == r ? v : F32(0.0f));
Brian Osman29e013d2019-05-28 17:16:03 -0400792 }
793 }
794 break;
795 }
796
Brian Osman569f12f2019-06-13 11:23:57 -0400797 VECTOR_UNARY_FN_VEC(kSin, sinf)
798 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400799
Brian Osman569f12f2019-06-13 11:23:57 -0400800 case ByteCodeInstruction::kStore4:
801 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
802 case ByteCodeInstruction::kStore3:
803 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
804 case ByteCodeInstruction::kStore2:
805 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
806 case ByteCodeInstruction::kStore :
807 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
808 ++ip;
809 break;
Mike Kleine7007382019-05-21 08:36:32 -0500810
Brian Osman569f12f2019-06-13 11:23:57 -0400811 case ByteCodeInstruction::kStoreGlobal4:
812 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
813 case ByteCodeInstruction::kStoreGlobal3:
814 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
815 case ByteCodeInstruction::kStoreGlobal2:
816 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
817 case ByteCodeInstruction::kStoreGlobal :
818 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
819 ++ip;
820 break;
Mike Kleine7007382019-05-21 08:36:32 -0500821
Brian Osman07c117b2019-05-23 12:51:06 -0700822 case ByteCodeInstruction::kStoreExtended: {
823 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400824 I32 target = POP().fSigned;
825 VValue* src = sp - count + 1;
826 I32 m = mask();
827 for (int i = 0; i < count; ++i) {
828 for (int j = 0; j < VecWidth; ++j) {
829 if (m[j]) {
830 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
831 }
832 }
833 }
Brian Osman07c117b2019-05-23 12:51:06 -0700834 sp -= count;
835 break;
836 }
837 case ByteCodeInstruction::kStoreExtendedGlobal: {
838 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400839 I32 target = POP().fSigned;
840 VValue* src = sp - count + 1;
841 I32 m = mask();
842 for (int i = 0; i < count; ++i) {
843 for (int j = 0; j < VecWidth; ++j) {
844 if (m[j]) {
845 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
846 }
847 }
848 }
Brian Osman07c117b2019-05-23 12:51:06 -0700849 sp -= count;
850 break;
851 }
852
Mike Kleine7007382019-05-21 08:36:32 -0500853 case ByteCodeInstruction::kStoreSwizzle: {
854 int target = READ8();
855 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400856 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400857 stack[target + *(ip + i)] = skvx::if_then_else(
858 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400859 }
Brian Osman1091f022019-05-16 09:42:16 -0400860 ip += count;
861 break;
Mike Kleine7007382019-05-21 08:36:32 -0500862 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400863
Mike Kleine7007382019-05-21 08:36:32 -0500864 case ByteCodeInstruction::kStoreSwizzleGlobal: {
865 int target = READ8();
866 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400867 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400868 globals[target + *(ip + i)] = skvx::if_then_else(
869 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
Brian Osman1091f022019-05-16 09:42:16 -0400870 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400871 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400872 break;
Mike Kleine7007382019-05-21 08:36:32 -0500873 }
Brian Osman569f12f2019-06-13 11:23:57 -0400874
Brian Osman07c117b2019-05-23 12:51:06 -0700875 case ByteCodeInstruction::kStoreSwizzleIndirect: {
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 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
884 }
885 }
Brian Osman07c117b2019-05-23 12:51:06 -0700886 }
887 ip += count;
888 break;
889 }
Brian Osman569f12f2019-06-13 11:23:57 -0400890
Brian Osman07c117b2019-05-23 12:51:06 -0700891 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
Brian Osman07c117b2019-05-23 12:51:06 -0700892 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400893 I32 target = POP().fSigned;
894 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700895 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400896 I32 v = POP().fSigned;
897 for (int j = 0; j < VecWidth; ++j) {
898 if (m[j]) {
899 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
900 }
901 }
Brian Osman07c117b2019-05-23 12:51:06 -0700902 }
903 ip += count;
904 break;
905 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400906
Mike Kleinc1999982019-05-21 13:03:49 -0500907 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400908 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400909
Mike Kleine7007382019-05-21 08:36:32 -0500910 case ByteCodeInstruction::kSwizzle: {
Brian Osman569f12f2019-06-13 11:23:57 -0400911 VValue tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400912 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400913 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400914 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400915 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400916 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400917 }
918 break;
Mike Kleine7007382019-05-21 08:36:32 -0500919 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400920
Brian Osman569f12f2019-06-13 11:23:57 -0400921 VECTOR_UNARY_FN_VEC(kTan, tanf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400922
Brian Osman569f12f2019-06-13 11:23:57 -0400923 case ByteCodeInstruction::kWriteExternal:
924 case ByteCodeInstruction::kWriteExternal2:
925 case ByteCodeInstruction::kWriteExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500926 case ByteCodeInstruction::kWriteExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400927 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500928 int target = READ8();
Brian Osman1a79f0b2019-06-24 16:32:14 -0400929 float tmp[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400930 I32 m = mask();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400931 sp -= count;
Brian Osman569f12f2019-06-13 11:23:57 -0400932 for (int i = 0; i < VecWidth; ++i) {
933 if (m[i]) {
934 for (int j = 0; j < count; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400935 tmp[j] = sp[j + 1].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400936 }
Brian Osman1a79f0b2019-06-24 16:32:14 -0400937 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
Brian Osman569f12f2019-06-13 11:23:57 -0400938 }
939 }
940 break;
941 }
942
943 case ByteCodeInstruction::kMaskPush:
944 condPtr[1] = POP().fSigned;
945 maskPtr[1] = maskPtr[0] & condPtr[1];
946 ++condPtr; ++maskPtr;
947 break;
948 case ByteCodeInstruction::kMaskPop:
949 --condPtr; --maskPtr;
950 break;
951 case ByteCodeInstruction::kMaskNegate:
952 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
953 break;
954 case ByteCodeInstruction::kMaskBlend: {
955 int count = READ8();
956 I32 m = condPtr[0];
957 --condPtr; --maskPtr;
958 for (int i = 0; i < count; ++i) {
959 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
960 --sp;
961 }
962 break;
963 }
964 case ByteCodeInstruction::kBranchIfAllFalse: {
965 int target = READ16();
966 if (!skvx::any(mask())) {
967 ip = code + target;
968 }
969 break;
970 }
971
972 case ByteCodeInstruction::kLoopBegin:
Brian Osman8d564572019-06-19 11:00:28 -0400973 contPtr[1] = 0;
974 loopPtr[1] = loopPtr[0];
975 ++contPtr; ++loopPtr;
Brian Osman569f12f2019-06-13 11:23:57 -0400976 break;
977 case ByteCodeInstruction::kLoopNext:
978 *loopPtr |= *contPtr;
979 *contPtr = 0;
980 break;
981 case ByteCodeInstruction::kLoopMask:
982 *loopPtr &= POP().fSigned;
983 break;
984 case ByteCodeInstruction::kLoopEnd:
985 --contPtr; --loopPtr;
986 break;
987 case ByteCodeInstruction::kLoopBreak:
988 *loopPtr &= ~mask();
989 break;
990 case ByteCodeInstruction::kLoopContinue: {
991 I32 m = mask();
992 *contPtr |= m;
993 *loopPtr &= ~m;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400994 break;
Mike Kleine7007382019-05-21 08:36:32 -0500995 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400996
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400997 default:
Mike Kleine7007382019-05-21 08:36:32 -0500998 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Brian Osmanf42de9e2019-07-18 10:25:39 -0400999 return false;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001000 }
Brian Osman569f12f2019-06-13 11:23:57 -04001001 }
Brian Osmanf42de9e2019-07-18 10:25:39 -04001002 // Unreachable
1003 return false;
Brian Osman569f12f2019-06-13 11:23:57 -04001004}
1005
Brian Osman08a84962019-06-14 10:17:16 -04001006} // namespace Interpreter
1007
Brian Osman489cf882019-07-09 10:48:28 -04001008#endif // SK_ENABLE_SKSL_INTERPRETER
1009
Brian Osman08a84962019-06-14 10:17:16 -04001010void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001011#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001012 const uint8_t* ip = fCode.data();
1013 while (ip < fCode.data() + fCode.size()) {
1014 printf("%d: ", (int)(ip - fCode.data()));
1015 ip = Interpreter::disassemble_instruction(ip);
1016 printf("\n");
1017 }
Brian Osman489cf882019-07-09 10:48:28 -04001018#endif
Brian Osman08a84962019-06-14 10:17:16 -04001019}
1020
Brian Osmanf42de9e2019-07-18 10:25:39 -04001021bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
Brian Osman08a84962019-06-14 10:17:16 -04001022 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001023#if defined(SK_ENABLE_SKSL_INTERPRETER)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001024#ifdef TRACE
Brian Osman08a84962019-06-14 10:17:16 -04001025 f->disassemble();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001026#endif
Brian Osman4b202a32019-06-21 09:50:29 -04001027 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001028 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1029 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osmanf42de9e2019-07-18 10:25:39 -04001030 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001031 }
Brian Osmanef787f72019-06-13 13:07:12 -04001032
Brian Osmanf42de9e2019-07-18 10:25:39 -04001033 if (uniformCount != (int)fInputSlots.size()) {
1034 return false;
1035 }
1036
Brian Osman08a84962019-06-14 10:17:16 -04001037 Interpreter::VValue globals[32];
Brian Osmanf42de9e2019-07-18 10:25:39 -04001038 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1039 return false;
1040 }
Brian Osman08a84962019-06-14 10:17:16 -04001041 for (uint8_t slot : fInputSlots) {
1042 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001043 }
1044
Brian Osman1a79f0b2019-06-24 16:32:14 -04001045 int baseIndex = 0;
1046
Brian Osman569f12f2019-06-13 11:23:57 -04001047 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001048 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001049
1050 // Transpose args into stack
1051 {
Brian Osman08a84962019-06-14 10:17:16 -04001052 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001053 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001054 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001055 for (int j = f->fParameterCount; j > 0; --j) {
1056 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001057 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001058 }
1059 }
1060 }
1061
Mike Reed3fd3cc92019-06-20 12:40:30 -04001062 bool stripedOutput = false;
1063 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osmanf42de9e2019-07-18 10:25:39 -04001064 if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
1065 return false;
1066 }
Brian Osman569f12f2019-06-13 11:23:57 -04001067
1068 // Transpose out parameters back
1069 {
Brian Osman08a84962019-06-14 10:17:16 -04001070 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001071 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001072 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001073 for (const auto& p : f->fParameters) {
1074 if (p.fIsOutParameter) {
1075 for (int j = p.fSlotCount; j > 0; --j) {
1076 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001077 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001078 }
1079 } else {
1080 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001081 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001082 }
1083 }
1084 }
1085 }
1086
1087 args += f->fParameterCount * w;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001088 if (outReturn) {
1089 outReturn += f->fReturnCount * w;
1090 }
Brian Osman4b202a32019-06-21 09:50:29 -04001091 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001092 baseIndex += w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001093 }
Brian Osmanf42de9e2019-07-18 10:25:39 -04001094 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001095#else
1096 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osmanf42de9e2019-07-18 10:25:39 -04001097 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001098#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001099}
1100
Brian Osmanf42de9e2019-07-18 10:25:39 -04001101bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
Mike Reed3fd3cc92019-06-20 12:40:30 -04001102 const float* uniforms, int uniformCount,
1103 float* outArgs[], int outCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001104#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001105#ifdef TRACE
Brian Osmanecb3bb52019-06-20 14:59:12 -04001106 f->disassemble();
Brian Osman2b1a5442019-06-19 11:40:33 -04001107#endif
1108 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001109 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1110 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osmanf42de9e2019-07-18 10:25:39 -04001111 return false;
1112 }
1113
1114 if (nargs != f->fParameterCount ||
1115 outCount != f->fReturnCount ||
1116 uniformCount != (int)fInputSlots.size()) {
1117 return false;
1118 }
1119
1120 Interpreter::VValue globals[32];
1121 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1122 return false;
1123 }
1124 for (uint8_t slot : fInputSlots) {
1125 globals[slot].fFloat = *uniforms++;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001126 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001127
Mike Reed3fd3cc92019-06-20 12:40:30 -04001128 // innerRun just takes outArgs, so clear it if the count is zero
1129 if (outCount == 0) {
1130 outArgs = nullptr;
1131 }
1132
Brian Osman1a79f0b2019-06-24 16:32:14 -04001133 int baseIndex = 0;
1134
Brian Osman2b1a5442019-06-19 11:40:33 -04001135 while (N) {
1136 int w = std::min(N, Interpreter::VecWidth);
1137
1138 // Copy args into stack
1139 for (int i = 0; i < nargs; ++i) {
1140 memcpy(stack + i, args[i], w * sizeof(float));
1141 }
1142
Mike Reed3fd3cc92019-06-20 12:40:30 -04001143 bool stripedOutput = true;
Brian Osmanf42de9e2019-07-18 10:25:39 -04001144 if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
1145 return false;
1146 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001147
1148 // Copy out parameters back
1149 int slot = 0;
1150 for (const auto& p : f->fParameters) {
1151 if (p.fIsOutParameter) {
1152 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1153 memcpy(args[i], stack + i, w * sizeof(float));
1154 }
1155 }
1156 slot += p.fSlotCount;
1157 }
1158
1159 // Step each argument pointer ahead
1160 for (int i = 0; i < nargs; ++i) {
1161 args[i] += w;
1162 }
1163 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001164 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001165 }
Brian Osmanf42de9e2019-07-18 10:25:39 -04001166
1167 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001168#else
1169 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osmanf42de9e2019-07-18 10:25:39 -04001170 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001171#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001172}
1173
Brian Osman80164412019-06-07 13:00:23 -04001174} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001175
1176#endif