blob: 9cb13a87b0696422fa97dc6603d03b1066ecefbf [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 Osman869a3e82019-07-18 17:00:34 -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")
Mike Reed634c9412019-07-18 13:20:04 -040088 case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
89 case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
90 case ByteCodeInstruction::kInverse4x4: printf("inverse4x4"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070091 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
92 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
93 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
94 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
95 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
96 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
97 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
98 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
99 case ByteCodeInstruction::kLoadSwizzle: {
100 int target = READ8();
101 int count = READ8();
102 printf("loadswizzle %d %d", target, count);
103 for (int i = 0; i < count; ++i) {
104 printf(", %d", READ8());
105 }
106 break;
107 }
108 case ByteCodeInstruction::kLoadSwizzleGlobal: {
109 int target = READ8();
110 int count = READ8();
111 printf("loadswizzleglobal %d %d", target, count);
112 for (int i = 0; i < count; ++i) {
113 printf(", %d", READ8());
114 }
115 break;
116 }
117 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
118 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
119 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400120 case ByteCodeInstruction::kMatrixToMatrix: {
121 int srcCols = READ8();
122 int srcRows = READ8();
123 int dstCols = READ8();
124 int dstRows = READ8();
125 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
126 break;
127 }
Brian Osman909231c2019-05-29 15:34:36 -0400128 case ByteCodeInstruction::kMatrixMultiply: {
129 int lCols = READ8();
130 int lRows = READ8();
131 int rCols = READ8();
132 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
133 break;
134 }
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400135 VECTOR_DISASSEMBLE(kMix, "mix")
Brian Osman1e855b22019-05-29 15:21:52 -0400136 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700137 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Brian Osman1e855b22019-05-29 15:21:52 -0400138 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
Brian Osman3e833e12019-05-23 13:23:24 -0700139 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400140 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400141 case ByteCodeInstruction::kOrB: printf("orb"); break;
Brian Osman1e855b22019-05-29 15:21:52 -0400142 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700143 case ByteCodeInstruction::kPushImmediate: {
144 uint32_t v = READ32();
145 union { uint32_t u; float f; } pun = { v };
146 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
147 break;
148 }
149 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
150 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
151 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
152 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
153 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
154 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
155 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400156 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700157 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400158 case ByteCodeInstruction::kScalarToMatrix: {
159 int cols = READ8();
160 int rows = READ8();
161 printf("scalartomatrix %dx%d", cols, rows);
162 break;
163 }
Brian Osman3e833e12019-05-23 13:23:24 -0700164 VECTOR_DISASSEMBLE(kSin, "sin")
165 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
166 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
167 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
168 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
169 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
170 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
171 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
172 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
173 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
174 case ByteCodeInstruction::kStoreSwizzle: {
175 int target = READ8();
176 int count = READ8();
177 printf("storeswizzle %d %d", target, count);
178 for (int i = 0; i < count; ++i) {
179 printf(", %d", READ8());
180 }
181 break;
182 }
183 case ByteCodeInstruction::kStoreSwizzleGlobal: {
184 int target = READ8();
185 int count = READ8();
186 printf("storeswizzleglobal %d %d", target, count);
187 for (int i = 0; i < count; ++i) {
188 printf(", %d", READ8());
189 }
190 break;
191 }
192 case ByteCodeInstruction::kStoreSwizzleIndirect: {
193 int count = READ8();
194 printf("storeswizzleindirect %d", count);
195 for (int i = 0; i < count; ++i) {
196 printf(", %d", READ8());
197 }
198 break;
199 }
200 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
201 int count = READ8();
202 printf("storeswizzleindirectglobal %d", count);
203 for (int i = 0; i < count; ++i) {
204 printf(", %d", READ8());
205 }
206 break;
207 }
208 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
209 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
210 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400211 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700212 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
213 case ByteCodeInstruction::kSwizzle: {
214 printf("swizzle %d, ", READ8());
215 int count = READ8();
216 printf("%d", count);
217 for (int i = 0; i < count; ++i) {
218 printf(", %d", READ8());
219 }
220 break;
221 }
222 VECTOR_DISASSEMBLE(kTan, "tan")
223 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
224 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
225 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
226 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400227 case ByteCodeInstruction::kXorB: printf("xorb"); break;
228 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
229 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
230 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
231 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
232 case ByteCodeInstruction::kBranchIfAllFalse:
233 printf("branchifallfalse %d", READ16());
234 break;
235 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
236 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
237 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
238 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
239 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
240 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700241 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
242 }
243 return ip;
244}
245
Mike Klein459aed12019-05-21 15:46:36 -0500246#define VECTOR_BINARY_OP(base, field, op) \
Mike Kleine7007382019-05-21 08:36:32 -0500247 case ByteCodeInstruction::base ## 4: \
Mike Klein459aed12019-05-21 15:46:36 -0500248 sp[-4] = sp[-4].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500249 POP(); \
250 /* fall through */ \
251 case ByteCodeInstruction::base ## 3: { \
252 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500253 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500254 POP(); \
255 } /* fall through */ \
256 case ByteCodeInstruction::base ## 2: { \
257 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500258 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500259 POP(); \
260 } /* fall through */ \
261 case ByteCodeInstruction::base: { \
262 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
Mike Klein459aed12019-05-21 15:46:36 -0500263 sp[count] = sp[count].field op sp[0].field; \
Mike Kleine7007382019-05-21 08:36:32 -0500264 POP(); \
265 break; \
266 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400267
Brian Osman1e855b22019-05-29 15:21:52 -0400268#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
269 VECTOR_BINARY_OP(base, field, op) \
270 case ByteCodeInstruction::base ## N: { \
271 int count = READ8(); \
272 for (int i = count; i > 0; --i) { \
273 sp[-count] = sp[-count].field op sp[0].field; \
274 POP(); \
275 } \
276 break; \
277 }
278
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400279#define VECTOR_BINARY_FN(base, field, fn) \
280 case ByteCodeInstruction::base ## 4: \
281 sp[-4] = fn(sp[-4].field, sp[0].field); \
282 POP(); \
283 /* fall through */ \
284 case ByteCodeInstruction::base ## 3: { \
285 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
286 sp[target] = fn(sp[target].field, sp[0].field); \
287 POP(); \
288 } /* fall through */ \
289 case ByteCodeInstruction::base ## 2: { \
290 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
291 sp[target] = fn(sp[target].field, sp[0].field); \
292 POP(); \
293 } /* fall through */ \
294 case ByteCodeInstruction::base: { \
295 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
296 sp[target] = fn(sp[target].field, sp[0].field); \
297 POP(); \
298 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500299 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400300
Mike Klein459aed12019-05-21 15:46:36 -0500301#define VECTOR_UNARY_FN(base, fn, field) \
302 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
303 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
304 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
305 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400306 break;
307
Brian Osman569f12f2019-06-13 11:23:57 -0400308#define VECTOR_UNARY_FN_VEC(base, fn) \
309 case ByteCodeInstruction::base ## 4: \
310 case ByteCodeInstruction::base ## 3: \
311 case ByteCodeInstruction::base ## 2: \
312 case ByteCodeInstruction::base : { \
313 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
314 float* v = (float*)sp - count + 1; \
315 for (int i = VecWidth * count; i > 0; --i, ++v) { \
316 *v = fn(*v); \
317 } \
318 break; \
319 }
320
321union VValue {
322 VValue() {}
323
324 VValue(F32 f)
325 : fFloat(f) {
326 }
327
328 VValue(I32 s)
329 : fSigned(s) {
330 }
331
332 VValue(U32 u)
333 : fUnsigned(u) {
334 }
335
336 F32 fFloat;
337 I32 fSigned;
338 U32 fUnsigned;
339};
340
Brian Osman226668a2019-05-14 16:47:30 -0400341struct StackFrame {
342 const uint8_t* fCode;
343 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400344 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400345 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400346};
347
Brian Osman569f12f2019-06-13 11:23:57 -0400348static F32 mix(F32 start, F32 end, F32 t) {
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400349 return start * (1 - t) + end * t;
350}
351
Brian Osman569f12f2019-06-13 11:23:57 -0400352// TODO: trunc on integers?
353template <typename T>
354static T vec_mod(T a, T b) {
355 return a - skvx::trunc(a / b) * b;
356}
Mike Kleine7007382019-05-21 08:36:32 -0500357
Mike Reed634c9412019-07-18 13:20:04 -0400358#define spf(index) sp[index].fFloat
359
Brian Osman869a3e82019-07-18 17:00:34 -0400360static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400361 float* outReturn[], VValue globals[], bool stripedOutput, int N,
362 int baseIndex) {
Brian Osman4b202a32019-06-21 09:50:29 -0400363 // Needs to be the first N non-negative integers, at least as large as VecWidth
364 static const Interpreter::I32 gLanes = {
365 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
366 };
367
Brian Osman569f12f2019-06-13 11:23:57 -0400368 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
369
370 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
371 auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
Mike Kleine7007382019-05-21 08:36:32 -0500372
Brian Osman80164412019-06-07 13:00:23 -0400373 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400374 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400375 std::vector<StackFrame> frames;
376
Brian Osman569f12f2019-06-13 11:23:57 -0400377 I32 condStack[16]; // Independent condition masks
378 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
379 I32 contStack[16]; // Continue flags for loops
380 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400381 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400382 contStack[0] = I32( 0);
383 loopStack[0] = I32(~0);
384 I32* condPtr = condStack;
385 I32* maskPtr = maskStack;
386 I32* contPtr = contStack;
387 I32* loopPtr = loopStack;
388
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400389 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
390 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osman869a3e82019-07-18 17:00:34 -0400391 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400392 }
393
Brian Osman569f12f2019-06-13 11:23:57 -0400394 auto mask = [&]() { return *maskPtr & *loopPtr; };
395
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400396 for (;;) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400397#ifdef TRACE
Brian Osman3e833e12019-05-23 13:23:24 -0700398 printf("at %3d ", (int) (ip - code));
399 disassemble_instruction(ip);
400 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400401#endif
Brian Osmane85b6a52019-05-22 14:50:59 -0700402 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400403 switch (inst) {
Mike Kleinc1999982019-05-21 13:03:49 -0500404 VECTOR_BINARY_OP(kAddI, fSigned, +)
Brian Osman1e855b22019-05-29 15:21:52 -0400405 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400406
407 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
Brian Osman32c526b2019-06-03 16:13:52 -0400408 case ByteCodeInstruction::kAndB:
Brian Osman569f12f2019-06-13 11:23:57 -0400409 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
410 POP();
411 break;
412 case ByteCodeInstruction::kNotB:
413 sp[0] = ~sp[0].fSigned;
414 break;
415 case ByteCodeInstruction::kOrB:
416 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
417 POP();
418 break;
419 case ByteCodeInstruction::kXorB:
420 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
Brian Osman32c526b2019-06-03 16:13:52 -0400421 POP();
422 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400423
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400424 case ByteCodeInstruction::kBranch:
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400425 ip = code + READ16();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400426 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400427
Brian Osman226668a2019-05-14 16:47:30 -0400428 case ByteCodeInstruction::kCall: {
Brian Osmand3494ed2019-06-20 15:41:34 -0400429 // Precursor code reserved space for the return value, and pushed all parameters to
430 // the stack. Update our bottom of stack to point at the first parameter, and our
431 // sp to point past those parameters (plus space for locals).
Mike Kleine7007382019-05-21 08:36:32 -0500432 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400433 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
Brian Osman569f12f2019-06-13 11:23:57 -0400434 if (skvx::any(mask())) {
Brian Osmand3494ed2019-06-20 15:41:34 -0400435 frames.push_back({ code, ip, stack, fun->fParameterCount });
Brian Osman569f12f2019-06-13 11:23:57 -0400436 ip = code = fun->fCode.data();
437 stack = sp - fun->fParameterCount + 1;
438 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
Brian Osman569f12f2019-06-13 11:23:57 -0400439 }
Brian Osman226668a2019-05-14 16:47:30 -0400440 break;
441 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400442
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400443 case ByteCodeInstruction::kCallExternal: {
444 int argumentCount = READ8();
445 int returnCount = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500446 int target = READ8();
Brian Osman80164412019-06-07 13:00:23 -0400447 ExternalValue* v = byteCode->fExternalValues[target];
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400448 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500449
Brian Osman1a79f0b2019-06-24 16:32:14 -0400450 float tmpArgs[4];
451 float tmpReturn[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400452 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
453 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
454
455 I32 m = mask();
456 for (int i = 0; i < VecWidth; ++i) {
457 if (m[i]) {
458 for (int j = 0; j < argumentCount; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400459 tmpArgs[j] = sp[j].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400460 }
Brian Osman1a79f0b2019-06-24 16:32:14 -0400461 v->call(baseIndex + i, tmpArgs, tmpReturn);
Brian Osman569f12f2019-06-13 11:23:57 -0400462 for (int j = 0; j < returnCount; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400463 sp[j].fFloat[i] = tmpReturn[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400464 }
465 }
466 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -0400467 sp += returnCount - 1;
468 break;
469 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400470
Brian Osman869a3e82019-07-18 17:00:34 -0400471 case ByteCodeInstruction::kClampIndex: {
472 int length = READ8();
473 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
474 return false;
475 }
476 break;
477 }
478
Mike Kleinc1999982019-05-21 13:03:49 -0500479 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
Brian Osman1e855b22019-05-29 15:21:52 -0400480 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
Mike Kleinc1999982019-05-21 13:03:49 -0500481 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
Brian Osman1e855b22019-05-29 15:21:52 -0400482 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
Mike Kleinc1999982019-05-21 13:03:49 -0500483 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
484 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
485 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
486 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
487 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
488 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
489 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
490 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
491 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
492 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
493 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
494 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400495
Brian Osman569f12f2019-06-13 11:23:57 -0400496 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
497 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
498 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
499 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400500 break;
501
Brian Osman569f12f2019-06-13 11:23:57 -0400502 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
503 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
504 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
505 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400506 break;
507
Brian Osman569f12f2019-06-13 11:23:57 -0400508 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
509 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
510 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
511 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400512 break;
513
Brian Osman569f12f2019-06-13 11:23:57 -0400514 VECTOR_UNARY_FN_VEC(kCos, cosf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400515
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400516 case ByteCodeInstruction::kCross: {
Brian Osman569f12f2019-06-13 11:23:57 -0400517 F32 ax = sp[-5].fFloat, ay = sp[-4].fFloat, az = sp[-3].fFloat,
518 bx = sp[-2].fFloat, by = sp[-1].fFloat, bz = sp[ 0].fFloat;
519 F32 cx = ay*bz - az*by,
520 cy = az*bx - ax*bz,
521 cz = ax*by - ay*bx;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400522 sp -= 3;
Brian Osman569f12f2019-06-13 11:23:57 -0400523 sp[-2] = cx;
524 sp[-1] = cy;
525 sp[ 0] = cz;
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400526 break;
527 }
528
Mike Kleinc1999982019-05-21 13:03:49 -0500529 VECTOR_BINARY_OP(kDivideS, fSigned, /)
530 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
Brian Osman1e855b22019-05-29 15:21:52 -0400531 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
Mike Kleine7007382019-05-21 08:36:32 -0500532
533 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
534 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
535 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
536 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
537 break;
538
Brian Osman07c117b2019-05-23 12:51:06 -0700539 case ByteCodeInstruction::kDupN: {
540 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400541 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -0700542 sp += count;
543 break;
544 }
545
Mike Reed634c9412019-07-18 13:20:04 -0400546 case ByteCodeInstruction::kInverse2x2: {
547 F32 a = sp[-3].fFloat,
548 b = sp[-2].fFloat,
549 c = sp[-1].fFloat,
550 d = sp[ 0].fFloat;
551 F32 idet = F32(1) / (a*d - b*c);
552 sp[-3].fFloat = d * idet;
553 sp[-2].fFloat = -b * idet;
554 sp[-1].fFloat = -c * idet;
555 sp[ 0].fFloat = a * idet;
556 break;
557 }
558 case ByteCodeInstruction::kInverse3x3: {
559 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
560 a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
561 a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
562 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
563 a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
564 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
565 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
566 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
567 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
568 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
569 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
570 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
571 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
572 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
573 break;
574 }
575 case ByteCodeInstruction::kInverse4x4: {
576 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
577 a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
578 a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
579 a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf( 0);
580
581 F32 b00 = a00 * a11 - a01 * a10,
582 b01 = a00 * a12 - a02 * a10,
583 b02 = a00 * a13 - a03 * a10,
584 b03 = a01 * a12 - a02 * a11,
585 b04 = a01 * a13 - a03 * a11,
586 b05 = a02 * a13 - a03 * a12,
587 b06 = a20 * a31 - a21 * a30,
588 b07 = a20 * a32 - a22 * a30,
589 b08 = a20 * a33 - a23 * a30,
590 b09 = a21 * a32 - a22 * a31,
591 b10 = a21 * a33 - a23 * a31,
592 b11 = a22 * a33 - a23 * a32;
593
594 F32 idet = F32(1) /
595 (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
596
597 b00 *= idet;
598 b01 *= idet;
599 b02 *= idet;
600 b03 *= idet;
601 b04 *= idet;
602 b05 *= idet;
603 b06 *= idet;
604 b07 *= idet;
605 b08 *= idet;
606 b09 *= idet;
607 b10 *= idet;
608 b11 *= idet;
609
610 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
611 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
612 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
613 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
614 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
615 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
616 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
617 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
618 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
619 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
620 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
621 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
622 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
623 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
624 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
625 spf( 0) = a20 * b03 - a21 * b01 + a22 * b00;
626 break;
627 }
628
Mike Kleine7007382019-05-21 08:36:32 -0500629 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
630 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
631 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
632 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
633 ++ip;
634 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
635 break;
636
Brian Osman80164412019-06-07 13:00:23 -0400637 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
638 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
639 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
640 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
Mike Kleine7007382019-05-21 08:36:32 -0500641 ++ip;
Brian Osman07c117b2019-05-23 12:51:06 -0700642 sp += (int)inst -
643 (int)ByteCodeInstruction::kLoadGlobal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500644 break;
645
Brian Osman07c117b2019-05-23 12:51:06 -0700646 case ByteCodeInstruction::kLoadExtended: {
647 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400648 I32 src = POP().fSigned;
649 I32 m = mask();
650 for (int i = 0; i < count; ++i) {
651 for (int j = 0; j < VecWidth; ++j) {
652 if (m[j]) {
653 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
654 }
655 }
656 }
Brian Osman07c117b2019-05-23 12:51:06 -0700657 sp += count;
658 break;
659 }
660
661 case ByteCodeInstruction::kLoadExtendedGlobal: {
662 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400663 I32 src = POP().fSigned;
664 I32 m = mask();
665 for (int i = 0; i < count; ++i) {
666 for (int j = 0; j < VecWidth; ++j) {
667 if (m[j]) {
668 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
669 }
670 }
671 }
Brian Osman07c117b2019-05-23 12:51:06 -0700672 sp += count;
673 break;
674 }
675
Mike Kleine7007382019-05-21 08:36:32 -0500676 case ByteCodeInstruction::kLoadSwizzle: {
677 int src = READ8();
678 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400679 for (int i = 0; i < count; ++i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400680 PUSH(stack[src + *(ip + i)]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400681 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400682 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400683 break;
Mike Kleine7007382019-05-21 08:36:32 -0500684 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400685
Mike Kleine7007382019-05-21 08:36:32 -0500686 case ByteCodeInstruction::kLoadSwizzleGlobal: {
687 int src = READ8();
Mike Kleine7007382019-05-21 08:36:32 -0500688 int count = READ8();
Brian Osmanb7451292019-05-15 13:02:13 -0400689 for (int i = 0; i < count; ++i) {
Brian Osman80164412019-06-07 13:00:23 -0400690 PUSH(globals[src + *(ip + i)]);
Brian Osmanb7451292019-05-15 13:02:13 -0400691 }
692 ip += count;
693 break;
Mike Kleine7007382019-05-21 08:36:32 -0500694 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400695
Brian Osman29e013d2019-05-28 17:16:03 -0400696 case ByteCodeInstruction::kMatrixToMatrix: {
697 int srcCols = READ8();
698 int srcRows = READ8();
699 int dstCols = READ8();
700 int dstRows = READ8();
701 SkASSERT(srcCols >= 2 && srcCols <= 4);
702 SkASSERT(srcRows >= 2 && srcRows <= 4);
703 SkASSERT(dstCols >= 2 && dstCols <= 4);
704 SkASSERT(dstRows >= 2 && dstRows <= 4);
Brian Osman569f12f2019-06-13 11:23:57 -0400705 F32 tmp[16];
706 memset(tmp, 0, sizeof(tmp));
707 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
Brian Osman29e013d2019-05-28 17:16:03 -0400708 for (int c = srcCols - 1; c >= 0; --c) {
709 for (int r = srcRows - 1; r >= 0; --r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400710 tmp[c*4 + r] = POP().fFloat;
Brian Osman29e013d2019-05-28 17:16:03 -0400711 }
712 }
713 for (int c = 0; c < dstCols; ++c) {
714 for (int r = 0; r < dstRows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400715 PUSH(tmp[c*4 + r]);
Brian Osman29e013d2019-05-28 17:16:03 -0400716 }
717 }
718 break;
719 }
720
Brian Osman909231c2019-05-29 15:34:36 -0400721 case ByteCodeInstruction::kMatrixMultiply: {
722 int lCols = READ8();
723 int lRows = READ8();
724 int rCols = READ8();
725 int rRows = lCols;
Brian Osman569f12f2019-06-13 11:23:57 -0400726 F32 tmp[16] = { 0.0f };
727 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
728 F32* A = B - (lCols * lRows);
Brian Osman909231c2019-05-29 15:34:36 -0400729 for (int c = 0; c < rCols; ++c) {
730 for (int r = 0; r < lRows; ++r) {
731 for (int j = 0; j < lCols; ++j) {
732 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
733 }
734 }
735 }
736 sp -= (lCols * lRows) + (rCols * rRows);
Brian Osman569f12f2019-06-13 11:23:57 -0400737 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
Brian Osman909231c2019-05-29 15:34:36 -0400738 sp += (rCols * lRows);
739 break;
740 }
741
Ethan Nicholasae9633b2019-05-24 12:46:34 -0400742 // stack looks like: X1 Y1 Z1 W1 X2 Y2 Z2 W2 T
743 case ByteCodeInstruction::kMix4:
744 sp[-5] = mix(sp[-5].fFloat, sp[-1].fFloat, sp[0].fFloat);
745 // fall through
746 case ByteCodeInstruction::kMix3: {
747 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
748 int target = 2 - count * 2;
749 sp[target] = mix(sp[target].fFloat, sp[2 - count].fFloat, sp[0].fFloat);
750 // fall through
751 }
752 case ByteCodeInstruction::kMix2: {
753 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
754 int target = 1 - count * 2;
755 sp[target] = mix(sp[target].fFloat, sp[1 - count].fFloat, sp[0].fFloat);
756 // fall through
757 }
758 case ByteCodeInstruction::kMix: {
759 int count = (int) inst - (int) ByteCodeInstruction::kMix + 1;
760 int target = -count * 2;
761 sp[target] = mix(sp[target].fFloat, sp[-count].fFloat, sp[0].fFloat);
762 sp -= 1 + count;
763 break;
764 }
765
Mike Kleinc1999982019-05-21 13:03:49 -0500766 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
Brian Osman1e855b22019-05-29 15:21:52 -0400767 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400768
Mike Kleinc1999982019-05-21 13:03:49 -0500769 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
770 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
771 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
772 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
Mike Kleine7007382019-05-21 08:36:32 -0500773 break;
774
Brian Osman1e855b22019-05-29 15:21:52 -0400775 case ByteCodeInstruction::kNegateFN: {
776 int count = READ8();
777 for (int i = count - 1; i >= 0; --i) {
778 sp[-i] = -sp[-i].fFloat;
779 }
780 break;
781 }
782
Mike Kleinc1999982019-05-21 13:03:49 -0500783 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
784 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
785 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
Brian Osman569f12f2019-06-13 11:23:57 -0400786 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
Mike Kleine7007382019-05-21 08:36:32 -0500787 break;
788
789 case ByteCodeInstruction::kPop4: POP();
790 case ByteCodeInstruction::kPop3: POP();
791 case ByteCodeInstruction::kPop2: POP();
792 case ByteCodeInstruction::kPop : POP();
793 break;
794
Brian Osman07c117b2019-05-23 12:51:06 -0700795 case ByteCodeInstruction::kPopN:
796 sp -= READ8();
797 break;
798
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400799 case ByteCodeInstruction::kPushImmediate:
Brian Osman569f12f2019-06-13 11:23:57 -0400800 PUSH(U32(READ32()));
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400801 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400802
Brian Osman569f12f2019-06-13 11:23:57 -0400803 case ByteCodeInstruction::kReadExternal:
804 case ByteCodeInstruction::kReadExternal2:
805 case ByteCodeInstruction::kReadExternal3:
Mike Kleine7007382019-05-21 08:36:32 -0500806 case ByteCodeInstruction::kReadExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -0400807 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -0500808 int src = READ8();
Brian Osman1a79f0b2019-06-24 16:32:14 -0400809 float tmp[4];
Brian Osman569f12f2019-06-13 11:23:57 -0400810 I32 m = mask();
811 for (int i = 0; i < VecWidth; ++i) {
812 if (m[i]) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400813 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
Brian Osman569f12f2019-06-13 11:23:57 -0400814 for (int j = 0; j < count; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -0400815 sp[j + 1].fFloat[i] = tmp[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400816 }
817 }
818 }
819 sp += count;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400820 break;
Mike Kleine7007382019-05-21 08:36:32 -0500821 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400822
Brian Osman569f12f2019-06-13 11:23:57 -0400823 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
824 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
825 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400826
Brian Osmand3494ed2019-06-20 15:41:34 -0400827 case ByteCodeInstruction::kReserve:
828 sp += READ8();
829 break;
830
Mike Kleine7007382019-05-21 08:36:32 -0500831 case ByteCodeInstruction::kReturn: {
832 int count = READ8();
Brian Osman226668a2019-05-14 16:47:30 -0400833 if (frames.empty()) {
834 if (outReturn) {
Brian Osman569f12f2019-06-13 11:23:57 -0400835 VValue* src = sp - count + 1;
Mike Reed3fd3cc92019-06-20 12:40:30 -0400836 if (stripedOutput) {
837 for (int i = 0; i < count; ++i) {
Brian Osman4b202a32019-06-21 09:50:29 -0400838 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
839 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -0400840 }
Mike Reed3fd3cc92019-06-20 12:40:30 -0400841 } else {
842 float* outPtr = outReturn[0];
843 for (int i = 0; i < count; ++i) {
Brian Osman4b202a32019-06-21 09:50:29 -0400844 for (int j = 0; j < N; ++j) {
845 outPtr[count * j] = src->fFloat[j];
Mike Reed3fd3cc92019-06-20 12:40:30 -0400846 }
847 ++outPtr;
848 ++src;
849 }
Brian Osman569f12f2019-06-13 11:23:57 -0400850 }
Brian Osman226668a2019-05-14 16:47:30 -0400851 }
Brian Osman869a3e82019-07-18 17:00:34 -0400852 return true;
Brian Osman226668a2019-05-14 16:47:30 -0400853 } else {
Brian Osmand3494ed2019-06-20 15:41:34 -0400854 // When we were called, the caller reserved stack space for their copy of our
855 // return value, then 'stack' was positioned after that, where our parameters
856 // were placed. Copy our return values to their reserved area.
857 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Brian Osman226668a2019-05-14 16:47:30 -0400858
Brian Osmand3494ed2019-06-20 15:41:34 -0400859 // Now move the stack pointer to the end of the passed-in parameters. This odd
860 // calling convention requires the caller to pop the arguments after calling,
861 // but allows them to store any out-parameters back during that unwinding.
862 // After that sequence finishes, the return value will be the top of the stack.
Brian Osman226668a2019-05-14 16:47:30 -0400863 const StackFrame& frame(frames.back());
Brian Osmand3494ed2019-06-20 15:41:34 -0400864 sp = stack + frame.fParameterCount - 1;
Brian Osman226668a2019-05-14 16:47:30 -0400865 stack = frame.fStack;
866 code = frame.fCode;
867 ip = frame.fIP;
868 frames.pop_back();
869 break;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400870 }
Mike Kleine7007382019-05-21 08:36:32 -0500871 }
872
Brian Osman29e013d2019-05-28 17:16:03 -0400873 case ByteCodeInstruction::kScalarToMatrix: {
874 int cols = READ8();
875 int rows = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400876 VValue v = POP();
Brian Osman29e013d2019-05-28 17:16:03 -0400877 for (int c = 0; c < cols; ++c) {
878 for (int r = 0; r < rows; ++r) {
Brian Osman569f12f2019-06-13 11:23:57 -0400879 PUSH(c == r ? v : F32(0.0f));
Brian Osman29e013d2019-05-28 17:16:03 -0400880 }
881 }
882 break;
883 }
884
Brian Osman569f12f2019-06-13 11:23:57 -0400885 VECTOR_UNARY_FN_VEC(kSin, sinf)
886 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400887
Brian Osman569f12f2019-06-13 11:23:57 -0400888 case ByteCodeInstruction::kStore4:
889 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
890 case ByteCodeInstruction::kStore3:
891 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
892 case ByteCodeInstruction::kStore2:
893 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
894 case ByteCodeInstruction::kStore :
895 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
896 ++ip;
897 break;
Mike Kleine7007382019-05-21 08:36:32 -0500898
Brian Osman569f12f2019-06-13 11:23:57 -0400899 case ByteCodeInstruction::kStoreGlobal4:
900 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
901 case ByteCodeInstruction::kStoreGlobal3:
902 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
903 case ByteCodeInstruction::kStoreGlobal2:
904 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
905 case ByteCodeInstruction::kStoreGlobal :
906 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
907 ++ip;
908 break;
Mike Kleine7007382019-05-21 08:36:32 -0500909
Brian Osman07c117b2019-05-23 12:51:06 -0700910 case ByteCodeInstruction::kStoreExtended: {
911 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400912 I32 target = POP().fSigned;
913 VValue* src = sp - count + 1;
914 I32 m = mask();
915 for (int i = 0; i < count; ++i) {
916 for (int j = 0; j < VecWidth; ++j) {
917 if (m[j]) {
918 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
919 }
920 }
921 }
Brian Osman07c117b2019-05-23 12:51:06 -0700922 sp -= count;
923 break;
924 }
925 case ByteCodeInstruction::kStoreExtendedGlobal: {
926 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400927 I32 target = POP().fSigned;
928 VValue* src = sp - count + 1;
929 I32 m = mask();
930 for (int i = 0; i < count; ++i) {
931 for (int j = 0; j < VecWidth; ++j) {
932 if (m[j]) {
933 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
934 }
935 }
936 }
Brian Osman07c117b2019-05-23 12:51:06 -0700937 sp -= count;
938 break;
939 }
940
Mike Kleine7007382019-05-21 08:36:32 -0500941 case ByteCodeInstruction::kStoreSwizzle: {
942 int target = READ8();
943 int count = READ8();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400944 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400945 stack[target + *(ip + i)] = skvx::if_then_else(
946 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400947 }
Brian Osman1091f022019-05-16 09:42:16 -0400948 ip += count;
949 break;
Mike Kleine7007382019-05-21 08:36:32 -0500950 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400951
Mike Kleine7007382019-05-21 08:36:32 -0500952 case ByteCodeInstruction::kStoreSwizzleGlobal: {
953 int target = READ8();
954 int count = READ8();
Brian Osman1091f022019-05-16 09:42:16 -0400955 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400956 globals[target + *(ip + i)] = skvx::if_then_else(
957 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
Brian Osman1091f022019-05-16 09:42:16 -0400958 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400959 ip += count;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -0400960 break;
Mike Kleine7007382019-05-21 08:36:32 -0500961 }
Brian Osman569f12f2019-06-13 11:23:57 -0400962
Brian Osman07c117b2019-05-23 12:51:06 -0700963 case ByteCodeInstruction::kStoreSwizzleIndirect: {
Brian Osman07c117b2019-05-23 12:51:06 -0700964 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400965 I32 target = POP().fSigned;
966 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700967 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400968 I32 v = POP().fSigned;
969 for (int j = 0; j < VecWidth; ++j) {
970 if (m[j]) {
971 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
972 }
973 }
Brian Osman07c117b2019-05-23 12:51:06 -0700974 }
975 ip += count;
976 break;
977 }
Brian Osman569f12f2019-06-13 11:23:57 -0400978
Brian Osman07c117b2019-05-23 12:51:06 -0700979 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
Brian Osman07c117b2019-05-23 12:51:06 -0700980 int count = READ8();
Brian Osman569f12f2019-06-13 11:23:57 -0400981 I32 target = POP().fSigned;
982 I32 m = mask();
Brian Osman07c117b2019-05-23 12:51:06 -0700983 for (int i = count - 1; i >= 0; --i) {
Brian Osman569f12f2019-06-13 11:23:57 -0400984 I32 v = POP().fSigned;
985 for (int j = 0; j < VecWidth; ++j) {
986 if (m[j]) {
987 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
988 }
989 }
Brian Osman07c117b2019-05-23 12:51:06 -0700990 }
991 ip += count;
992 break;
993 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400994
Mike Kleinc1999982019-05-21 13:03:49 -0500995 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
Brian Osman1e855b22019-05-29 15:21:52 -0400996 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400997
Mike Kleine7007382019-05-21 08:36:32 -0500998 case ByteCodeInstruction::kSwizzle: {
Brian Osman569f12f2019-06-13 11:23:57 -0400999 VValue tmp[4];
Ethan Nicholas7e603db2019-05-03 12:57:47 -04001000 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -04001001 tmp[i] = POP();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001002 }
Ethan Nicholas7e603db2019-05-03 12:57:47 -04001003 for (int i = READ8() - 1; i >= 0; --i) {
Ethan Nicholas48a75aa2019-05-16 17:15:56 -04001004 PUSH(tmp[READ8()]);
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001005 }
1006 break;
Mike Kleine7007382019-05-21 08:36:32 -05001007 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -04001008
Brian Osman569f12f2019-06-13 11:23:57 -04001009 VECTOR_UNARY_FN_VEC(kTan, tanf)
Ethan Nicholas82162ee2019-05-21 16:05:08 -04001010
Brian Osman569f12f2019-06-13 11:23:57 -04001011 case ByteCodeInstruction::kWriteExternal:
1012 case ByteCodeInstruction::kWriteExternal2:
1013 case ByteCodeInstruction::kWriteExternal3:
Mike Kleine7007382019-05-21 08:36:32 -05001014 case ByteCodeInstruction::kWriteExternal4: {
Brian Osman569f12f2019-06-13 11:23:57 -04001015 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
Mike Kleine7007382019-05-21 08:36:32 -05001016 int target = READ8();
Brian Osman1a79f0b2019-06-24 16:32:14 -04001017 float tmp[4];
Brian Osman569f12f2019-06-13 11:23:57 -04001018 I32 m = mask();
Ethan Nicholas48a75aa2019-05-16 17:15:56 -04001019 sp -= count;
Brian Osman569f12f2019-06-13 11:23:57 -04001020 for (int i = 0; i < VecWidth; ++i) {
1021 if (m[i]) {
1022 for (int j = 0; j < count; ++j) {
Brian Osman1a79f0b2019-06-24 16:32:14 -04001023 tmp[j] = sp[j + 1].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -04001024 }
Brian Osman1a79f0b2019-06-24 16:32:14 -04001025 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
Brian Osman569f12f2019-06-13 11:23:57 -04001026 }
1027 }
1028 break;
1029 }
1030
1031 case ByteCodeInstruction::kMaskPush:
1032 condPtr[1] = POP().fSigned;
1033 maskPtr[1] = maskPtr[0] & condPtr[1];
1034 ++condPtr; ++maskPtr;
1035 break;
1036 case ByteCodeInstruction::kMaskPop:
1037 --condPtr; --maskPtr;
1038 break;
1039 case ByteCodeInstruction::kMaskNegate:
1040 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
1041 break;
1042 case ByteCodeInstruction::kMaskBlend: {
1043 int count = READ8();
1044 I32 m = condPtr[0];
1045 --condPtr; --maskPtr;
1046 for (int i = 0; i < count; ++i) {
1047 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1048 --sp;
1049 }
1050 break;
1051 }
1052 case ByteCodeInstruction::kBranchIfAllFalse: {
1053 int target = READ16();
1054 if (!skvx::any(mask())) {
1055 ip = code + target;
1056 }
1057 break;
1058 }
1059
1060 case ByteCodeInstruction::kLoopBegin:
Brian Osman8d564572019-06-19 11:00:28 -04001061 contPtr[1] = 0;
1062 loopPtr[1] = loopPtr[0];
1063 ++contPtr; ++loopPtr;
Brian Osman569f12f2019-06-13 11:23:57 -04001064 break;
1065 case ByteCodeInstruction::kLoopNext:
1066 *loopPtr |= *contPtr;
1067 *contPtr = 0;
1068 break;
1069 case ByteCodeInstruction::kLoopMask:
1070 *loopPtr &= POP().fSigned;
1071 break;
1072 case ByteCodeInstruction::kLoopEnd:
1073 --contPtr; --loopPtr;
1074 break;
1075 case ByteCodeInstruction::kLoopBreak:
1076 *loopPtr &= ~mask();
1077 break;
1078 case ByteCodeInstruction::kLoopContinue: {
1079 I32 m = mask();
1080 *contPtr |= m;
1081 *loopPtr &= ~m;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001082 break;
Mike Kleine7007382019-05-21 08:36:32 -05001083 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -04001084
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001085 default:
Mike Kleine7007382019-05-21 08:36:32 -05001086 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
Brian Osman869a3e82019-07-18 17:00:34 -04001087 return false;
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001088 }
Brian Osman569f12f2019-06-13 11:23:57 -04001089 }
Brian Osman869a3e82019-07-18 17:00:34 -04001090 // Unreachable
1091 return false;
Brian Osman569f12f2019-06-13 11:23:57 -04001092}
1093
Brian Osman08a84962019-06-14 10:17:16 -04001094} // namespace Interpreter
1095
Brian Osman489cf882019-07-09 10:48:28 -04001096#endif // SK_ENABLE_SKSL_INTERPRETER
1097
Mike Reed634c9412019-07-18 13:20:04 -04001098#undef spf
1099
Brian Osman08a84962019-06-14 10:17:16 -04001100void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001101#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001102 const uint8_t* ip = fCode.data();
1103 while (ip < fCode.data() + fCode.size()) {
1104 printf("%d: ", (int)(ip - fCode.data()));
1105 ip = Interpreter::disassemble_instruction(ip);
1106 printf("\n");
1107 }
Brian Osman489cf882019-07-09 10:48:28 -04001108#endif
Brian Osman08a84962019-06-14 10:17:16 -04001109}
1110
Brian Osman869a3e82019-07-18 17:00:34 -04001111bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
Brian Osman08a84962019-06-14 10:17:16 -04001112 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001113#if defined(SK_ENABLE_SKSL_INTERPRETER)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001114#ifdef TRACE
Brian Osman08a84962019-06-14 10:17:16 -04001115 f->disassemble();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001116#endif
Brian Osman4b202a32019-06-21 09:50:29 -04001117 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001118 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1119 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001120 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001121 }
Brian Osmanef787f72019-06-13 13:07:12 -04001122
Brian Osman869a3e82019-07-18 17:00:34 -04001123 if (uniformCount != (int)fInputSlots.size()) {
1124 return false;
1125 }
1126
Brian Osman08a84962019-06-14 10:17:16 -04001127 Interpreter::VValue globals[32];
Brian Osman869a3e82019-07-18 17:00:34 -04001128 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1129 return false;
1130 }
Brian Osman08a84962019-06-14 10:17:16 -04001131 for (uint8_t slot : fInputSlots) {
1132 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001133 }
1134
Brian Osman1a79f0b2019-06-24 16:32:14 -04001135 int baseIndex = 0;
1136
Brian Osman569f12f2019-06-13 11:23:57 -04001137 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001138 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001139
1140 // Transpose args into stack
1141 {
Brian Osman08a84962019-06-14 10:17:16 -04001142 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001143 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001144 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001145 for (int j = f->fParameterCount; j > 0; --j) {
1146 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001147 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001148 }
1149 }
1150 }
1151
Mike Reed3fd3cc92019-06-20 12:40:30 -04001152 bool stripedOutput = false;
1153 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman869a3e82019-07-18 17:00:34 -04001154 if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
1155 return false;
1156 }
Brian Osman569f12f2019-06-13 11:23:57 -04001157
1158 // Transpose out parameters back
1159 {
Brian Osman08a84962019-06-14 10:17:16 -04001160 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001161 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001162 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001163 for (const auto& p : f->fParameters) {
1164 if (p.fIsOutParameter) {
1165 for (int j = p.fSlotCount; j > 0; --j) {
1166 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001167 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001168 }
1169 } else {
1170 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001171 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001172 }
1173 }
1174 }
1175 }
1176
1177 args += f->fParameterCount * w;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001178 if (outReturn) {
1179 outReturn += f->fReturnCount * w;
1180 }
Brian Osman4b202a32019-06-21 09:50:29 -04001181 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001182 baseIndex += w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001183 }
Brian Osman869a3e82019-07-18 17:00:34 -04001184 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001185#else
1186 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001187 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001188#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001189}
1190
Brian Osman869a3e82019-07-18 17:00:34 -04001191bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
Mike Reed3fd3cc92019-06-20 12:40:30 -04001192 const float* uniforms, int uniformCount,
1193 float* outArgs[], int outCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001194#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001195#ifdef TRACE
Brian Osmanecb3bb52019-06-20 14:59:12 -04001196 f->disassemble();
Brian Osman2b1a5442019-06-19 11:40:33 -04001197#endif
1198 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001199 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1200 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001201 return false;
1202 }
1203
1204 if (nargs != f->fParameterCount ||
1205 outCount != f->fReturnCount ||
1206 uniformCount != (int)fInputSlots.size()) {
1207 return false;
1208 }
1209
1210 Interpreter::VValue globals[32];
1211 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1212 return false;
1213 }
1214 for (uint8_t slot : fInputSlots) {
1215 globals[slot].fFloat = *uniforms++;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001216 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001217
Mike Reed3fd3cc92019-06-20 12:40:30 -04001218 // innerRun just takes outArgs, so clear it if the count is zero
1219 if (outCount == 0) {
1220 outArgs = nullptr;
1221 }
1222
Brian Osman1a79f0b2019-06-24 16:32:14 -04001223 int baseIndex = 0;
1224
Brian Osman2b1a5442019-06-19 11:40:33 -04001225 while (N) {
1226 int w = std::min(N, Interpreter::VecWidth);
1227
1228 // Copy args into stack
1229 for (int i = 0; i < nargs; ++i) {
1230 memcpy(stack + i, args[i], w * sizeof(float));
1231 }
1232
Mike Reed3fd3cc92019-06-20 12:40:30 -04001233 bool stripedOutput = true;
Brian Osman869a3e82019-07-18 17:00:34 -04001234 if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
1235 return false;
1236 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001237
1238 // Copy out parameters back
1239 int slot = 0;
1240 for (const auto& p : f->fParameters) {
1241 if (p.fIsOutParameter) {
1242 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1243 memcpy(args[i], stack + i, w * sizeof(float));
1244 }
1245 }
1246 slot += p.fSlotCount;
1247 }
1248
1249 // Step each argument pointer ahead
1250 for (int i = 0; i < nargs; ++i) {
1251 args[i] += w;
1252 }
1253 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001254 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001255 }
Brian Osman869a3e82019-07-18 17:00:34 -04001256
1257 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001258#else
1259 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001260 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001261#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001262}
1263
Brian Osman80164412019-06-07 13:00:23 -04001264} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001265
1266#endif