blob: 80699b98b3b45b50ed6e00ad619d40b58fc3fa95 [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
Ethan Nicholasadecf4b2019-09-05 12:43:34 -040031// GCC and Clang support the "labels as values" extension which we need to implement the interpreter
32// using threaded code. Otherwise, we fall back to using a switch statement in a for loop.
33#if defined(__GNUC__) || defined(__clang__)
34 #define THREADED
35#endif
36
Mike Kleine7007382019-05-21 08:36:32 -050037#define READ8() (*(ip++))
Mike Klein7a177b42019-06-17 17:17:47 -050038#define READ16() (ip += 2, sk_unaligned_load<uint16_t>(ip - 2))
39#define READ32() (ip += 4, sk_unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040040
Ethan Nicholasadecf4b2019-09-05 12:43:34 -040041#define VECTOR_DISASSEMBLE(op, text) \
42 case ByteCodeInstruction::op: printf(text); ++ip; break; \
43 case ByteCodeInstruction::op##2: printf(text "2"); ++ip; break; \
44 case ByteCodeInstruction::op##3: printf(text "3"); ++ip; break; \
45 case ByteCodeInstruction::op##4: printf(text "4"); ++ip; break;
46
47#define VECTOR_DISASSEMBLE_NO_COUNT(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040048 case ByteCodeInstruction::op: printf(text); break; \
49 case ByteCodeInstruction::op##2: printf(text "2"); break; \
50 case ByteCodeInstruction::op##3: printf(text "3"); break; \
51 case ByteCodeInstruction::op##4: printf(text "4"); break;
52
Ethan Nicholasadecf4b2019-09-05 12:43:34 -040053#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
54 VECTOR_DISASSEMBLE(op, text) \
55 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
56
57#define VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(op, text) \
58 VECTOR_DISASSEMBLE_NO_COUNT(op, text) \
Brian Osman1e855b22019-05-29 15:21:52 -040059 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
60
Brian Osman3e833e12019-05-23 13:23:24 -070061static const uint8_t* disassemble_instruction(const uint8_t* ip) {
62 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -040063 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070064 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040065 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070066 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
67 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
68 case ByteCodeInstruction::kCallExternal: {
69 int argumentCount = READ8();
70 int returnCount = READ8();
71 int externalValue = READ8();
72 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
73 break;
74 }
Brian Osman869a3e82019-07-18 17:00:34 -040075 case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -070076 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
77 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040078 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
79 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070080 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
81 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
82 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
83 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
84 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
85 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
86 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
87 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
88 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
89 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
90 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
91 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholasadecf4b2019-09-05 12:43:34 -040092 VECTOR_DISASSEMBLE_NO_COUNT(kConvertFtoI, "convertftoi")
93 VECTOR_DISASSEMBLE_NO_COUNT(kConvertStoF, "convertstof")
94 VECTOR_DISASSEMBLE_NO_COUNT(kConvertUtoF, "convertutof")
Brian Osman3e833e12019-05-23 13:23:24 -070095 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osman1e855b22019-05-29 15:21:52 -040096 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070097 VECTOR_DISASSEMBLE(kDivideS, "divideS")
98 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040099 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Mike Reed634c9412019-07-18 13:20:04 -0400100 case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
101 case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
102 case ByteCodeInstruction::kInverse4x4: printf("inverse4x4"); break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400103 case ByteCodeInstruction::kLoad: printf("load %d", READ16() >> 8); break;
104 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ16() >> 8); break;
105 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ16() >> 8); break;
106 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ16() >> 8); break;
107 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ16() >> 8); break;
108 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ16() >> 8); break;
109 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ16() >> 8); break;
110 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ16() >> 8); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700111 case ByteCodeInstruction::kLoadSwizzle: {
112 int target = READ8();
113 int count = READ8();
114 printf("loadswizzle %d %d", target, count);
115 for (int i = 0; i < count; ++i) {
116 printf(", %d", READ8());
117 }
118 break;
119 }
120 case ByteCodeInstruction::kLoadSwizzleGlobal: {
121 int target = READ8();
122 int count = READ8();
123 printf("loadswizzleglobal %d %d", target, count);
124 for (int i = 0; i < count; ++i) {
125 printf(", %d", READ8());
126 }
127 break;
128 }
129 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
130 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
131 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400132 case ByteCodeInstruction::kMatrixToMatrix: {
133 int srcCols = READ8();
134 int srcRows = READ8();
135 int dstCols = READ8();
136 int dstRows = READ8();
137 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
138 break;
139 }
Brian Osman909231c2019-05-29 15:34:36 -0400140 case ByteCodeInstruction::kMatrixMultiply: {
141 int lCols = READ8();
142 int lRows = READ8();
143 int rCols = READ8();
144 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
145 break;
146 }
Brian Osman1e855b22019-05-29 15:21:52 -0400147 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700148 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400149 VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(kNegateF, "negatef")
150 VECTOR_DISASSEMBLE_NO_COUNT(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400151 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400152 case ByteCodeInstruction::kOrB: printf("orb"); break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400153 VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700154 case ByteCodeInstruction::kPushImmediate: {
155 uint32_t v = READ32();
156 union { uint32_t u; float f; } pun = { v };
157 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
158 break;
159 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400160 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ16() >> 8); break;
161 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ16() >> 8); break;
162 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ16() >> 8); break;
163 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ16() >> 8); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700164 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
165 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
166 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400167 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700168 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400169 case ByteCodeInstruction::kScalarToMatrix: {
170 int cols = READ8();
171 int rows = READ8();
172 printf("scalartomatrix %dx%d", cols, rows);
173 break;
174 }
Brian Osman3e833e12019-05-23 13:23:24 -0700175 VECTOR_DISASSEMBLE(kSin, "sin")
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400176 VECTOR_DISASSEMBLE_NO_COUNT(kSqrt, "sqrt")
Brian Osman3e833e12019-05-23 13:23:24 -0700177 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
178 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
179 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
180 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
181 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
182 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
183 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
184 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
185 case ByteCodeInstruction::kStoreSwizzle: {
186 int target = READ8();
187 int count = READ8();
188 printf("storeswizzle %d %d", target, count);
189 for (int i = 0; i < count; ++i) {
190 printf(", %d", READ8());
191 }
192 break;
193 }
194 case ByteCodeInstruction::kStoreSwizzleGlobal: {
195 int target = READ8();
196 int count = READ8();
197 printf("storeswizzleglobal %d %d", target, count);
198 for (int i = 0; i < count; ++i) {
199 printf(", %d", READ8());
200 }
201 break;
202 }
203 case ByteCodeInstruction::kStoreSwizzleIndirect: {
204 int count = READ8();
205 printf("storeswizzleindirect %d", count);
206 for (int i = 0; i < count; ++i) {
207 printf(", %d", READ8());
208 }
209 break;
210 }
211 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
212 int count = READ8();
213 printf("storeswizzleindirectglobal %d", count);
214 for (int i = 0; i < count; ++i) {
215 printf(", %d", READ8());
216 }
217 break;
218 }
219 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
220 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
221 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400222 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700223 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
224 case ByteCodeInstruction::kSwizzle: {
225 printf("swizzle %d, ", READ8());
226 int count = READ8();
227 printf("%d", count);
228 for (int i = 0; i < count; ++i) {
229 printf(", %d", READ8());
230 }
231 break;
232 }
233 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400234 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ16() >> 8); break;
235 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ16() >> 8); break;
236 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ16() >> 8); break;
237 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ16() >> 8); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400238 case ByteCodeInstruction::kXorB: printf("xorb"); break;
239 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
240 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
241 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
242 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
243 case ByteCodeInstruction::kBranchIfAllFalse:
244 printf("branchifallfalse %d", READ16());
245 break;
246 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
247 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
248 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
249 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
250 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
251 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400252 default:
253 ip -= 2;
254 printf("unknown(%d)\n", READ16());
255 SkASSERT(false);
Brian Osman3e833e12019-05-23 13:23:24 -0700256 }
257 return ip;
258}
259
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400260#ifdef THREADED
261 #define LABEL(name) name:
262 #ifdef TRACE
263 #define NEXT() goto next
264 #else
265 #define NEXT() goto *((char*) base + READ16())
266 #endif
267#else
268 #define LABEL(name) case ByteCodeInstruction::name:
269 #define NEXT() continue
270#endif
271
272#define VECTOR_BINARY_OP(base, field, op) \
273 LABEL(base ## 4) \
274 sp[-4] = sp[-4].field op sp[0].field; \
275 POP(); \
276 /* fall through */ \
277 LABEL(base ## 3) { \
278 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
279 POP(); \
280 } /* fall through */ \
281 LABEL(base ## 2) { \
282 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
283 POP(); \
284 } /* fall through */ \
285 LABEL(base) { \
286 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
287 POP(); \
288 ++ip; \
289 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500290 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400291
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400292#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
293 VECTOR_BINARY_OP(base, field, op) \
294 LABEL(base ## N) { \
295 int count = READ8(); \
296 for (int i = count; i > 0; --i) { \
297 sp[-count] = sp[-count].field op sp[0].field; \
298 POP(); \
299 } \
300 NEXT(); \
Brian Osman1e855b22019-05-29 15:21:52 -0400301 }
302
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400303#define VECTOR_BINARY_FN(base, field, fn) \
304 LABEL(base ## 4) \
305 sp[-4] = fn(sp[-4].field, sp[0].field); \
306 POP(); \
307 /* fall through */ \
308 LABEL(base ## 3) { \
309 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
310 POP(); \
311 } /* fall through */ \
312 LABEL(base ## 2) { \
313 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
314 POP(); \
315 } /* fall through */ \
316 LABEL(base) { \
317 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
318 POP(); \
319 ++ip; \
320 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500321 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400322
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400323#define VECTOR_UNARY_FN(base, fn, field) \
324 LABEL(base ## 4) sp[-3] = fn(sp[-3].field); \
325 LABEL(base ## 3) sp[-2] = fn(sp[-2].field); \
326 LABEL(base ## 2) sp[-1] = fn(sp[-1].field); \
327 LABEL(base) sp[ 0] = fn(sp[ 0].field); \
328 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400329
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400330#define VECTOR_UNARY_FN_VEC(base, fn) \
331 LABEL(base ## 4) \
332 LABEL(base ## 3) \
333 LABEL(base ## 2) \
334 LABEL(base) { \
335 int count = READ8(); \
336 float* v = (float*)sp - count + 1; \
337 for (int i = VecWidth * count; i > 0; --i, ++v) { \
338 *v = fn(*v); \
339 } \
340 NEXT(); \
Brian Osman569f12f2019-06-13 11:23:57 -0400341 }
342
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400343#define VECTOR_LABELS(base) \
344 &&base ## 4, \
345 &&base ## 3, \
346 &&base ## 2, \
347 &&base
348
349#define VECTOR_MATRIX_LABELS(base) \
350 VECTOR_LABELS(base), \
351 &&base ## N
352
353// If you trip this assert, it means that the order of the opcodes listed in ByteCodeInstruction
354// does not match the order of the opcodes listed in the 'labels' array in innerRun().
355#define CHECK_LABEL(name) \
356 SkASSERT(labels[(int) ByteCodeInstruction::name] == &&name)
357
358#define CHECK_VECTOR_LABELS(name) \
359 CHECK_LABEL(name ## 4); \
360 CHECK_LABEL(name ## 3); \
361 CHECK_LABEL(name ## 2); \
362 CHECK_LABEL(name)
363
364#define CHECK_VECTOR_MATRIX_LABELS(name) \
365 CHECK_VECTOR_LABELS(name); \
366 CHECK_LABEL(name ## N)
367
Brian Osman569f12f2019-06-13 11:23:57 -0400368union VValue {
369 VValue() {}
370
371 VValue(F32 f)
372 : fFloat(f) {
373 }
374
375 VValue(I32 s)
376 : fSigned(s) {
377 }
378
379 VValue(U32 u)
380 : fUnsigned(u) {
381 }
382
383 F32 fFloat;
384 I32 fSigned;
385 U32 fUnsigned;
386};
387
Brian Osman226668a2019-05-14 16:47:30 -0400388struct StackFrame {
389 const uint8_t* fCode;
390 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400391 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400392 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400393};
394
Brian Osman569f12f2019-06-13 11:23:57 -0400395// TODO: trunc on integers?
396template <typename T>
397static T vec_mod(T a, T b) {
398 return a - skvx::trunc(a / b) * b;
399}
Mike Kleine7007382019-05-21 08:36:32 -0500400
Mike Reed634c9412019-07-18 13:20:04 -0400401#define spf(index) sp[index].fFloat
402
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400403static void call_external(const ByteCode* byteCode, const uint8_t*& ip, VValue*& sp,
404 int baseIndex, I32 mask) {
405 int argumentCount = READ8();
406 int returnCount = READ8();
407 int target = READ8();
408 ExternalValue* v = byteCode->fExternalValues[target];
409 sp -= argumentCount - 1;
410
411 float tmpArgs[4];
412 float tmpReturn[4];
413 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
414 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
415
416 for (int i = 0; i < VecWidth; ++i) {
417 if (mask[i]) {
418 for (int j = 0; j < argumentCount; ++j) {
419 tmpArgs[j] = sp[j].fFloat[i];
420 }
421 v->call(baseIndex + i, tmpArgs, tmpReturn);
422 for (int j = 0; j < returnCount; ++j) {
423 sp[j].fFloat[i] = tmpReturn[j];
424 }
425 }
426 }
427 sp += returnCount - 1;
428}
429
430static void inverse2x2(VValue* sp) {
431 F32 a = sp[-3].fFloat,
432 b = sp[-2].fFloat,
433 c = sp[-1].fFloat,
434 d = sp[ 0].fFloat;
435 F32 idet = F32(1) / (a*d - b*c);
436 sp[-3].fFloat = d * idet;
437 sp[-2].fFloat = -b * idet;
438 sp[-1].fFloat = -c * idet;
439 sp[ 0].fFloat = a * idet;
440}
441
442static void inverse3x3(VValue* sp) {
443 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
444 a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
445 a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
446 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
447 a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
448 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
449 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
450 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
451 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
452 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
453 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
454 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
455 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
456 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
457}
458
459static void inverse4x4(VValue* sp) {
460 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
461 a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
462 a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
463 a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf( 0);
464
465 F32 b00 = a00 * a11 - a01 * a10,
466 b01 = a00 * a12 - a02 * a10,
467 b02 = a00 * a13 - a03 * a10,
468 b03 = a01 * a12 - a02 * a11,
469 b04 = a01 * a13 - a03 * a11,
470 b05 = a02 * a13 - a03 * a12,
471 b06 = a20 * a31 - a21 * a30,
472 b07 = a20 * a32 - a22 * a30,
473 b08 = a20 * a33 - a23 * a30,
474 b09 = a21 * a32 - a22 * a31,
475 b10 = a21 * a33 - a23 * a31,
476 b11 = a22 * a33 - a23 * a32;
477
478 F32 idet = F32(1) /
479 (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
480
481 b00 *= idet;
482 b01 *= idet;
483 b02 *= idet;
484 b03 *= idet;
485 b04 *= idet;
486 b05 *= idet;
487 b06 *= idet;
488 b07 *= idet;
489 b08 *= idet;
490 b09 *= idet;
491 b10 *= idet;
492 b11 *= idet;
493
494 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
495 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
496 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
497 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
498 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
499 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
500 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
501 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
502 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
503 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
504 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
505 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
506 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
507 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
508 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
509 spf( 0) = a20 * b03 - a21 * b01 + a22 * b00;
510}
511
Brian Osman869a3e82019-07-18 17:00:34 -0400512static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400513 float* outReturn[], VValue globals[], bool stripedOutput, int N,
514 int baseIndex) {
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400515#ifdef THREADED
516 static const void* labels[] = {
517 // If you aren't familiar with it, the &&label syntax is the GCC / Clang "labels as values"
518 // extension. If you add anything to this array, be sure to add the corresponding
519 // CHECK_LABEL() or CHECK_*_LABELS() assert below.
520 VECTOR_MATRIX_LABELS(kAddF),
521 VECTOR_LABELS(kAddI),
522 &&kAndB,
523 &&kBranch,
524 &&kCall,
525 &&kCallExternal,
526 &&kClampIndex,
527 VECTOR_LABELS(kCompareIEQ),
528 VECTOR_LABELS(kCompareINEQ),
529 VECTOR_MATRIX_LABELS(kCompareFEQ),
530 VECTOR_MATRIX_LABELS(kCompareFNEQ),
531 VECTOR_LABELS(kCompareFGT),
532 VECTOR_LABELS(kCompareFGTEQ),
533 VECTOR_LABELS(kCompareFLT),
534 VECTOR_LABELS(kCompareFLTEQ),
535 VECTOR_LABELS(kCompareSGT),
536 VECTOR_LABELS(kCompareSGTEQ),
537 VECTOR_LABELS(kCompareSLT),
538 VECTOR_LABELS(kCompareSLTEQ),
539 VECTOR_LABELS(kCompareUGT),
540 VECTOR_LABELS(kCompareUGTEQ),
541 VECTOR_LABELS(kCompareULT),
542 VECTOR_LABELS(kCompareULTEQ),
543 VECTOR_LABELS(kConvertFtoI),
544 VECTOR_LABELS(kConvertStoF),
545 VECTOR_LABELS(kConvertUtoF),
546 VECTOR_LABELS(kCos),
547 VECTOR_MATRIX_LABELS(kDivideF),
548 VECTOR_LABELS(kDivideS),
549 VECTOR_LABELS(kDivideU),
550 VECTOR_MATRIX_LABELS(kDup),
551 &&kInverse2x2,
552 &&kInverse3x3,
553 &&kInverse4x4,
554 VECTOR_LABELS(kLoad),
555 VECTOR_LABELS(kLoadGlobal),
556 &&kLoadSwizzle,
557 &&kLoadSwizzleGlobal,
558 &&kLoadExtended,
559 &&kLoadExtendedGlobal,
560 &&kMatrixToMatrix,
561 &&kMatrixMultiply,
562 VECTOR_MATRIX_LABELS(kNegateF),
563 VECTOR_LABELS(kNegateI),
564 VECTOR_MATRIX_LABELS(kMultiplyF),
565 VECTOR_LABELS(kMultiplyI),
566 &&kNotB,
567 &&kOrB,
568 VECTOR_MATRIX_LABELS(kPop),
569 &&kPushImmediate,
570 VECTOR_LABELS(kReadExternal),
571 VECTOR_LABELS(kRemainderF),
572 VECTOR_LABELS(kRemainderS),
573 VECTOR_LABELS(kRemainderU),
574 &&kReserve,
575 &&kReturn,
576 &&kScalarToMatrix,
577 VECTOR_LABELS(kSin),
578 VECTOR_LABELS(kSqrt),
579 VECTOR_LABELS(kStore),
580 VECTOR_LABELS(kStoreGlobal),
581 &&kStoreExtended,
582 &&kStoreExtendedGlobal,
583 &&kStoreSwizzle,
584 &&kStoreSwizzleGlobal,
585 &&kStoreSwizzleIndirect,
586 &&kStoreSwizzleIndirectGlobal,
587 &&kSwizzle,
588 VECTOR_MATRIX_LABELS(kSubtractF),
589 VECTOR_LABELS(kSubtractI),
590 VECTOR_LABELS(kTan),
591 VECTOR_LABELS(kWriteExternal),
592 &&kXorB,
593
594 &&kMaskPush,
595 &&kMaskPop,
596 &&kMaskNegate,
597 &&kMaskBlend,
598 &&kBranchIfAllFalse,
599
600 &&kLoopBegin,
601 &&kLoopNext,
602 &&kLoopMask,
603 &&kLoopEnd,
604 &&kLoopBreak,
605 &&kLoopContinue,
606 };
607 // Verify that the order of the labels array matches the order of the ByteCodeInstruction enum.
608 CHECK_VECTOR_MATRIX_LABELS(kAddF);
609 CHECK_VECTOR_LABELS(kAddI);
610 CHECK_LABEL(kAndB);
611 CHECK_LABEL(kBranch);
612 CHECK_LABEL(kCall);
613 CHECK_LABEL(kCallExternal);
614 CHECK_LABEL(kClampIndex);
615 CHECK_VECTOR_LABELS(kCompareIEQ);
616 CHECK_VECTOR_LABELS(kCompareINEQ);
617 CHECK_VECTOR_MATRIX_LABELS(kCompareFEQ);
618 CHECK_VECTOR_MATRIX_LABELS(kCompareFNEQ);
619 CHECK_VECTOR_LABELS(kCompareFGT);
620 CHECK_VECTOR_LABELS(kCompareFGTEQ);
621 CHECK_VECTOR_LABELS(kCompareFLT);
622 CHECK_VECTOR_LABELS(kCompareFLTEQ);
623 CHECK_VECTOR_LABELS(kCompareSGT);
624 CHECK_VECTOR_LABELS(kCompareSGTEQ);
625 CHECK_VECTOR_LABELS(kCompareSLT);
626 CHECK_VECTOR_LABELS(kCompareSLTEQ);
627 CHECK_VECTOR_LABELS(kCompareUGT);
628 CHECK_VECTOR_LABELS(kCompareUGTEQ);
629 CHECK_VECTOR_LABELS(kCompareULT);
630 CHECK_VECTOR_LABELS(kCompareULTEQ);
631 CHECK_VECTOR_LABELS(kConvertFtoI);
632 CHECK_VECTOR_LABELS(kConvertStoF);
633 CHECK_VECTOR_LABELS(kConvertUtoF);
634 CHECK_VECTOR_LABELS(kCos);
635 CHECK_VECTOR_MATRIX_LABELS(kDivideF);
636 CHECK_VECTOR_LABELS(kDivideS);
637 CHECK_VECTOR_LABELS(kDivideU);
638 CHECK_VECTOR_MATRIX_LABELS(kDup);
639 CHECK_LABEL(kInverse2x2);
640 CHECK_LABEL(kInverse3x3);
641 CHECK_LABEL(kInverse4x4);
642 CHECK_VECTOR_LABELS(kLoad);
643 CHECK_VECTOR_LABELS(kLoadGlobal);
644 CHECK_LABEL(kLoadSwizzle);
645 CHECK_LABEL(kLoadSwizzleGlobal);
646 CHECK_LABEL(kLoadExtended);
647 CHECK_LABEL(kLoadExtendedGlobal);
648 CHECK_LABEL(kMatrixToMatrix);
649 CHECK_LABEL(kMatrixMultiply);
650 CHECK_VECTOR_MATRIX_LABELS(kNegateF);
651 CHECK_VECTOR_LABELS(kNegateI);
652 CHECK_VECTOR_MATRIX_LABELS(kMultiplyF);
653 CHECK_VECTOR_LABELS(kMultiplyI);
654 CHECK_LABEL(kNotB);
655 CHECK_LABEL(kOrB);
656 CHECK_VECTOR_MATRIX_LABELS(kPop);
657 CHECK_LABEL(kPushImmediate);
658 CHECK_VECTOR_LABELS(kReadExternal);
659 CHECK_VECTOR_LABELS(kRemainderF);
660 CHECK_VECTOR_LABELS(kRemainderS);
661 CHECK_VECTOR_LABELS(kRemainderU);
662 CHECK_LABEL(kReserve);
663 CHECK_LABEL(kReturn);
664 CHECK_LABEL(kScalarToMatrix);
665 CHECK_VECTOR_LABELS(kSin);
666 CHECK_VECTOR_LABELS(kSqrt);
667 CHECK_VECTOR_LABELS(kStore);
668 CHECK_VECTOR_LABELS(kStoreGlobal);
669 CHECK_LABEL(kStoreExtended);
670 CHECK_LABEL(kStoreExtendedGlobal);
671 CHECK_LABEL(kStoreSwizzle);
672 CHECK_LABEL(kStoreSwizzleGlobal);
673 CHECK_LABEL(kStoreSwizzleIndirect);
674 CHECK_LABEL(kStoreSwizzleIndirectGlobal);
675 CHECK_LABEL(kSwizzle);
676 CHECK_VECTOR_MATRIX_LABELS(kSubtractF);
677 CHECK_VECTOR_LABELS(kSubtractI);
678 CHECK_VECTOR_LABELS(kTan);
679 CHECK_VECTOR_LABELS(kWriteExternal);
680 CHECK_LABEL(kXorB);
681 CHECK_LABEL(kMaskPush);
682 CHECK_LABEL(kMaskPop);
683 CHECK_LABEL(kMaskNegate);
684 CHECK_LABEL(kMaskBlend);
685 CHECK_LABEL(kBranchIfAllFalse);
686 CHECK_LABEL(kLoopBegin);
687 CHECK_LABEL(kLoopNext);
688 CHECK_LABEL(kLoopMask);
689 CHECK_LABEL(kLoopEnd);
690 CHECK_LABEL(kLoopBreak);
691 CHECK_LABEL(kLoopContinue);
692 static void* base = 0;
693 static SkOnce once;
694 once([] {
695 // Find the smallest label. Due to optimization, we can't just assume labels[0] comes first.
696 base = (void*) ~0;
697 for (size_t i = 0; i < SK_ARRAY_COUNT(labels); ++i) {
698 base = (void*) std::min((uintptr_t) base, (uintptr_t) labels[i]);
699 }
700 });
701 if (!f->fPreprocessed) {
702 ((ByteCodeFunction*) f)->preprocess(labels, base);
703 }
704#endif
705
Brian Osman4b202a32019-06-21 09:50:29 -0400706 // Needs to be the first N non-negative integers, at least as large as VecWidth
707 static const Interpreter::I32 gLanes = {
708 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
709 };
710
Brian Osman569f12f2019-06-13 11:23:57 -0400711 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
712
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400713 #define POP() (*(sp--))
714 #define PUSH(v) (sp[1] = v, ++sp)
Mike Kleine7007382019-05-21 08:36:32 -0500715
Brian Osman80164412019-06-07 13:00:23 -0400716 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400717 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400718 std::vector<StackFrame> frames;
719
Brian Osman569f12f2019-06-13 11:23:57 -0400720 I32 condStack[16]; // Independent condition masks
721 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
722 I32 contStack[16]; // Continue flags for loops
723 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400724 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400725 contStack[0] = I32( 0);
726 loopStack[0] = I32(~0);
727 I32* condPtr = condStack;
728 I32* maskPtr = maskStack;
729 I32* contPtr = contStack;
730 I32* loopPtr = loopStack;
731
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400732 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
733 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osman869a3e82019-07-18 17:00:34 -0400734 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400735 }
736
Brian Osman569f12f2019-06-13 11:23:57 -0400737 auto mask = [&]() { return *maskPtr & *loopPtr; };
738
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400739#ifdef THREADED
740 // If the "labels as values" extension is available, we implement this using threaded code.
741 // Instead of opcodes, the code directly contains the addresses of the labels to jump to. Then
742 // the code for each opcode simply grabs the address of the next opcode and uses a goto to jump
743 // there.
744 NEXT();
745#else
746 // Otherwise, we have to use a switch statement and a loop to execute the right label.
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400747 for (;;) {
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400748 #ifdef TRACE
749 printf("at %3d ", (int) (ip - code));
750 disassemble_instruction(ip);
751 printf(" (stack: %d)\n", (int) (sp - stack) + 1);
752 #endif
753 switch ((ByteCodeInstruction) READ16()) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400754#endif
Brian Osman569f12f2019-06-13 11:23:57 -0400755
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400756 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
757 VECTOR_BINARY_OP(kAddI, fSigned, +)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400758
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400759 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
760 LABEL(kAndB)
761 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
762 POP();
763 NEXT();
764 LABEL(kNotB)
765 sp[0] = ~sp[0].fSigned;
766 NEXT();
767 LABEL(kOrB)
768 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
769 POP();
770 NEXT();
771 LABEL(kXorB)
772 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
773 POP();
774 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400775
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400776 LABEL(kBranch)
777 ip = code + READ16();
778 NEXT();
779
780 LABEL(kCall) {
781 // Precursor code reserved space for the return value, and pushed all parameters to
782 // the stack. Update our bottom of stack to point at the first parameter, and our
783 // sp to point past those parameters (plus space for locals).
784 int target = READ8();
785 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
786#ifdef THREADED
787 if (!fun->fPreprocessed) {
788 ((ByteCodeFunction*) fun)->preprocess(labels, base);
789 }
790#endif
791 if (skvx::any(mask())) {
792 frames.push_back({ code, ip, stack, fun->fParameterCount });
793 ip = code = fun->fCode.data();
794 stack = sp - fun->fParameterCount + 1;
795 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
796 }
797 NEXT();
798 }
799
800 LABEL(kCallExternal) {
801 call_external(byteCode, ip, sp, baseIndex, mask());
802 NEXT();
803 }
804
805 LABEL(kClampIndex) {
806 int length = READ8();
807 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
808 return false;
809 }
810 NEXT();
811 }
812
813 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
814 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
815 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
816 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
817 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
818 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
819 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
820 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
821 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
822 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
823 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
824 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
825 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
826 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
827 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
828 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
829
830 LABEL(kConvertFtoI4) sp[-3] = skvx::cast<int>(sp[-3].fFloat);
831 LABEL(kConvertFtoI3) sp[-2] = skvx::cast<int>(sp[-2].fFloat);
832 LABEL(kConvertFtoI2) sp[-1] = skvx::cast<int>(sp[-1].fFloat);
833 LABEL(kConvertFtoI) sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
834 NEXT();
835
836 LABEL(kConvertStoF4) sp[-3] = skvx::cast<float>(sp[-3].fSigned);
837 LABEL(kConvertStoF3) sp[-2] = skvx::cast<float>(sp[-2].fSigned);
838 LABEL(kConvertStoF2) sp[-1] = skvx::cast<float>(sp[-1].fSigned);
839 LABEL(kConvertStoF) sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
840 NEXT();
841
842 LABEL(kConvertUtoF4) sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
843 LABEL(kConvertUtoF3) sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
844 LABEL(kConvertUtoF2) sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
845 LABEL(kConvertUtoF) sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
846 NEXT();
847
848 VECTOR_UNARY_FN_VEC(kCos, cosf)
849
850 VECTOR_BINARY_OP(kDivideS, fSigned, /)
851 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
852 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
853
854 LABEL(kDup4) PUSH(sp[1 - ip[0]]);
855 LABEL(kDup3) PUSH(sp[1 - ip[0]]);
856 LABEL(kDup2) PUSH(sp[1 - ip[0]]);
857 LABEL(kDup) PUSH(sp[1 - ip[0]]);
858 ++ip;
859 NEXT();
860
861 LABEL(kDupN) {
862 int count = READ8();
863 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
864 sp += count;
865 NEXT();
866 }
867
868 LABEL(kInverse2x2) {
869 inverse2x2(sp);
870 NEXT();
871 }
872 LABEL(kInverse3x3) {
873 inverse3x3(sp);
874 NEXT();
875 }
876 LABEL(kInverse4x4) {
877 inverse4x4(sp);
878 NEXT();
879 }
880
881 LABEL(kLoad4) sp[4] = stack[ip[1] + 3];
882 LABEL(kLoad3) sp[3] = stack[ip[1] + 2];
883 LABEL(kLoad2) sp[2] = stack[ip[1] + 1];
884 LABEL(kLoad) sp[1] = stack[ip[1] + 0];
885 sp += ip[0];
886 ip += 2;
887 NEXT();
888
889 LABEL(kLoadGlobal4) sp[4] = globals[ip[1] + 3];
890 LABEL(kLoadGlobal3) sp[3] = globals[ip[1] + 2];
891 LABEL(kLoadGlobal2) sp[2] = globals[ip[1] + 1];
892 LABEL(kLoadGlobal) sp[1] = globals[ip[1] + 0];
893 sp += ip[0];
894 ip += 2;
895 NEXT();
896
897 LABEL(kLoadExtended) {
898 int count = READ8();
899 I32 src = POP().fSigned;
900 I32 m = mask();
901 for (int i = 0; i < count; ++i) {
902 for (int j = 0; j < VecWidth; ++j) {
903 if (m[j]) {
904 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400905 }
Brian Osman226668a2019-05-14 16:47:30 -0400906 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400907 }
908 sp += count;
909 NEXT();
910 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400911
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400912 LABEL(kLoadExtendedGlobal) {
913 int count = READ8();
914 I32 src = POP().fSigned;
915 I32 m = mask();
916 for (int i = 0; i < count; ++i) {
917 for (int j = 0; j < VecWidth; ++j) {
918 if (m[j]) {
919 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
920 }
921 }
922 }
923 sp += count;
924 NEXT();
925 }
Mike Kleine7007382019-05-21 08:36:32 -0500926
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400927 LABEL(kLoadSwizzle) {
928 int src = READ8();
929 int count = READ8();
930 for (int i = 0; i < count; ++i) {
931 PUSH(stack[src + *(ip + i)]);
932 }
933 ip += count;
934 NEXT();
935 }
Brian Osman569f12f2019-06-13 11:23:57 -0400936
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400937 LABEL(kLoadSwizzleGlobal) {
938 int src = READ8();
939 int count = READ8();
940 for (int i = 0; i < count; ++i) {
941 PUSH(globals[src + *(ip + i)]);
942 }
943 ip += count;
944 NEXT();
945 }
946
947 LABEL(kMatrixToMatrix) {
948 int srcCols = READ8();
949 int srcRows = READ8();
950 int dstCols = READ8();
951 int dstRows = READ8();
952 SkASSERT(srcCols >= 2 && srcCols <= 4);
953 SkASSERT(srcRows >= 2 && srcRows <= 4);
954 SkASSERT(dstCols >= 2 && dstCols <= 4);
955 SkASSERT(dstRows >= 2 && dstRows <= 4);
956 F32 tmp[16];
957 memset(tmp, 0, sizeof(tmp));
958 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
959 for (int c = srcCols - 1; c >= 0; --c) {
960 for (int r = srcRows - 1; r >= 0; --r) {
961 tmp[c*4 + r] = POP().fFloat;
962 }
963 }
964 for (int c = 0; c < dstCols; ++c) {
965 for (int r = 0; r < dstRows; ++r) {
966 PUSH(tmp[c*4 + r]);
967 }
968 }
969 NEXT();
970 }
971
972 LABEL(kMatrixMultiply) {
973 int lCols = READ8();
974 int lRows = READ8();
975 int rCols = READ8();
976 int rRows = lCols;
977 F32 tmp[16] = { 0.0f };
978 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
979 F32* A = B - (lCols * lRows);
980 for (int c = 0; c < rCols; ++c) {
981 for (int r = 0; r < lRows; ++r) {
982 for (int j = 0; j < lCols; ++j) {
983 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
984 }
985 }
986 }
987 sp -= (lCols * lRows) + (rCols * rRows);
988 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
989 sp += (rCols * lRows);
990 NEXT();
991 }
992
993 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
994 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
995
996 LABEL(kNegateF4) sp[-3] = -sp[-3].fFloat;
997 LABEL(kNegateF3) sp[-2] = -sp[-2].fFloat;
998 LABEL(kNegateF2) sp[-1] = -sp[-1].fFloat;
999 LABEL(kNegateF) sp[ 0] = -sp[ 0].fFloat;
1000 NEXT();
1001
1002 LABEL(kNegateFN) {
1003 int count = READ8();
1004 for (int i = count - 1; i >= 0; --i) {
1005 sp[-i] = -sp[-i].fFloat;
1006 }
1007 NEXT();
1008 }
1009
1010 LABEL(kNegateI4) sp[-3] = -sp[-3].fSigned;
1011 LABEL(kNegateI3) sp[-2] = -sp[-2].fSigned;
1012 LABEL(kNegateI2) sp[-1] = -sp[-1].fSigned;
1013 LABEL(kNegateI) sp[ 0] = -sp[ 0].fSigned;
1014 NEXT();
1015
1016 LABEL(kPop4) POP();
1017 LABEL(kPop3) POP();
1018 LABEL(kPop2) POP();
1019 LABEL(kPop) POP();
1020 NEXT();
1021
1022 LABEL(kPopN)
1023 sp -= READ8();
1024 NEXT();
1025
1026 LABEL(kPushImmediate)
1027 PUSH(U32(READ32()));
1028 NEXT();
1029
1030 LABEL(kReadExternal)
1031 LABEL(kReadExternal2)
1032 LABEL(kReadExternal3)
1033 LABEL(kReadExternal4) {
1034 int count = READ8();
1035 int src = READ8();
1036 float tmp[4];
1037 I32 m = mask();
1038 for (int i = 0; i < VecWidth; ++i) {
1039 if (m[i]) {
1040 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
1041 for (int j = 0; j < count; ++j) {
1042 sp[j + 1].fFloat[i] = tmp[j];
1043 }
1044 }
1045 }
1046 sp += count;
1047 NEXT();
1048 }
1049
1050 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
1051 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
1052 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
1053
1054 LABEL(kReserve)
1055 sp += READ8();
1056 NEXT();
1057
1058 LABEL(kReturn) {
1059 int count = READ8();
1060 if (frames.empty()) {
1061 if (outReturn) {
1062 VValue* src = sp - count + 1;
1063 if (stripedOutput) {
1064 for (int i = 0; i < count; ++i) {
1065 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
1066 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -04001067 }
Brian Osman226668a2019-05-14 16:47:30 -04001068 } else {
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001069 float* outPtr = outReturn[0];
1070 for (int i = 0; i < count; ++i) {
1071 for (int j = 0; j < N; ++j) {
1072 outPtr[count * j] = src->fFloat[j];
Brian Osman569f12f2019-06-13 11:23:57 -04001073 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001074 ++outPtr;
1075 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -04001076 }
1077 }
Brian Osman07c117b2019-05-23 12:51:06 -07001078 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001079 return true;
1080 } else {
1081 // When we were called, the caller reserved stack space for their copy of our
1082 // return value, then 'stack' was positioned after that, where our parameters
1083 // were placed. Copy our return values to their reserved area.
1084 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Brian Osman07c117b2019-05-23 12:51:06 -07001085
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001086 // Now move the stack pointer to the end of the passed-in parameters. This odd
1087 // calling convention requires the caller to pop the arguments after calling,
1088 // but allows them to store any out-parameters back during that unwinding.
1089 // After that sequence finishes, the return value will be the top of the stack.
1090 const StackFrame& frame(frames.back());
1091 sp = stack + frame.fParameterCount - 1;
1092 stack = frame.fStack;
1093 code = frame.fCode;
1094 ip = frame.fIP;
1095 frames.pop_back();
1096 NEXT();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001097 }
Brian Osman569f12f2019-06-13 11:23:57 -04001098 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001099
1100 LABEL(kScalarToMatrix) {
1101 int cols = READ8();
1102 int rows = READ8();
1103 VValue v = POP();
1104 for (int c = 0; c < cols; ++c) {
1105 for (int r = 0; r < rows; ++r) {
1106 PUSH(c == r ? v : F32(0.0f));
1107 }
1108 }
1109 NEXT();
1110 }
1111
1112 VECTOR_UNARY_FN_VEC(kSin, sinf)
1113 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
1114
1115 LABEL(kStore4)
1116 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
1117 LABEL(kStore3)
1118 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
1119 LABEL(kStore2)
1120 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
1121 LABEL(kStore)
1122 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
1123 ++ip;
1124 NEXT();
1125
1126 LABEL(kStoreGlobal4)
1127 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
1128 LABEL(kStoreGlobal3)
1129 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
1130 LABEL(kStoreGlobal2)
1131 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
1132 LABEL(kStoreGlobal)
1133 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
1134 ++ip;
1135 NEXT();
1136
1137 LABEL(kStoreExtended) {
1138 int count = READ8();
1139 I32 target = POP().fSigned;
1140 VValue* src = sp - count + 1;
1141 I32 m = mask();
1142 for (int i = 0; i < count; ++i) {
1143 for (int j = 0; j < VecWidth; ++j) {
1144 if (m[j]) {
1145 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
1146 }
1147 }
1148 }
1149 sp -= count;
1150 NEXT();
1151 }
1152 LABEL(kStoreExtendedGlobal) {
1153 int count = READ8();
1154 I32 target = POP().fSigned;
1155 VValue* src = sp - count + 1;
1156 I32 m = mask();
1157 for (int i = 0; i < count; ++i) {
1158 for (int j = 0; j < VecWidth; ++j) {
1159 if (m[j]) {
1160 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
1161 }
1162 }
1163 }
1164 sp -= count;
1165 NEXT();
1166 }
1167
1168 LABEL(kStoreSwizzle) {
1169 int target = READ8();
1170 int count = READ8();
1171 for (int i = count - 1; i >= 0; --i) {
1172 stack[target + *(ip + i)] = skvx::if_then_else(
1173 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
1174 }
1175 ip += count;
1176 NEXT();
1177 }
1178
1179 LABEL(kStoreSwizzleGlobal) {
1180 int target = READ8();
1181 int count = READ8();
1182 for (int i = count - 1; i >= 0; --i) {
1183 globals[target + *(ip + i)] = skvx::if_then_else(
1184 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
1185 }
1186 ip += count;
1187 NEXT();
1188 }
1189
1190 LABEL(kStoreSwizzleIndirect) {
1191 int count = READ8();
1192 I32 target = POP().fSigned;
1193 I32 m = mask();
1194 for (int i = count - 1; i >= 0; --i) {
1195 I32 v = POP().fSigned;
1196 for (int j = 0; j < VecWidth; ++j) {
1197 if (m[j]) {
1198 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
1199 }
1200 }
1201 }
1202 ip += count;
1203 NEXT();
1204 }
1205
1206 LABEL(kStoreSwizzleIndirectGlobal) {
1207 int count = READ8();
1208 I32 target = POP().fSigned;
1209 I32 m = mask();
1210 for (int i = count - 1; i >= 0; --i) {
1211 I32 v = POP().fSigned;
1212 for (int j = 0; j < VecWidth; ++j) {
1213 if (m[j]) {
1214 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
1215 }
1216 }
1217 }
1218 ip += count;
1219 NEXT();
1220 }
1221
1222 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
1223 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
1224
1225 LABEL(kSwizzle) {
1226 VValue tmp[4];
1227 for (int i = READ8() - 1; i >= 0; --i) {
1228 tmp[i] = POP();
1229 }
1230 for (int i = READ8() - 1; i >= 0; --i) {
1231 PUSH(tmp[READ8()]);
1232 }
1233 NEXT();
1234 }
1235
1236 VECTOR_UNARY_FN_VEC(kTan, tanf)
1237
1238 LABEL(kWriteExternal4)
1239 LABEL(kWriteExternal3)
1240 LABEL(kWriteExternal2)
1241 LABEL(kWriteExternal) {
1242 int count = READ8();
1243 int target = READ8();
1244 float tmp[4];
1245 I32 m = mask();
1246 sp -= count;
1247 for (int i = 0; i < VecWidth; ++i) {
1248 if (m[i]) {
1249 for (int j = 0; j < count; ++j) {
1250 tmp[j] = sp[j + 1].fFloat[i];
1251 }
1252 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
1253 }
1254 }
1255 NEXT();
1256 }
1257
1258 LABEL(kMaskPush)
1259 condPtr[1] = POP().fSigned;
1260 maskPtr[1] = maskPtr[0] & condPtr[1];
1261 ++condPtr; ++maskPtr;
1262 NEXT();
1263 LABEL(kMaskPop)
1264 --condPtr; --maskPtr;
1265 NEXT();
1266 LABEL(kMaskNegate)
1267 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
1268 NEXT();
1269 LABEL(kMaskBlend) {
1270 int count = READ8();
1271 I32 m = condPtr[0];
1272 --condPtr; --maskPtr;
1273 for (int i = 0; i < count; ++i) {
1274 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1275 --sp;
1276 }
1277 NEXT();
1278 }
1279 LABEL(kBranchIfAllFalse) {
1280 int target = READ16();
1281 if (!skvx::any(mask())) {
1282 ip = code + target;
1283 }
1284 NEXT();
1285 }
1286
1287 LABEL(kLoopBegin)
1288 contPtr[1] = 0;
1289 loopPtr[1] = loopPtr[0];
1290 ++contPtr; ++loopPtr;
1291 NEXT();
1292 LABEL(kLoopNext)
1293 *loopPtr |= *contPtr;
1294 *contPtr = 0;
1295 NEXT();
1296 LABEL(kLoopMask)
1297 *loopPtr &= POP().fSigned;
1298 NEXT();
1299 LABEL(kLoopEnd)
1300 --contPtr; --loopPtr;
1301 NEXT();
1302 LABEL(kLoopBreak)
1303 *loopPtr &= ~mask();
1304 NEXT();
1305 LABEL(kLoopContinue) {
1306 I32 m = mask();
1307 *contPtr |= m;
1308 *loopPtr &= ~m;
1309 NEXT();
1310 }
1311#ifdef THREADED
1312 #ifdef TRACE
1313 next:
1314 printf("at %3d (stack: %d) (disable threaded code for disassembly)\n",
1315 (int) (ip - code), (int) (sp - stack) + 1);
1316 goto *((char*) base + READ16());
1317 #endif
1318#else
1319 }
1320 }
1321#endif
Brian Osman569f12f2019-06-13 11:23:57 -04001322}
1323
Brian Osman08a84962019-06-14 10:17:16 -04001324} // namespace Interpreter
1325
Brian Osman489cf882019-07-09 10:48:28 -04001326#endif // SK_ENABLE_SKSL_INTERPRETER
1327
Mike Reed634c9412019-07-18 13:20:04 -04001328#undef spf
1329
Brian Osman08a84962019-06-14 10:17:16 -04001330void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001331#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001332 const uint8_t* ip = fCode.data();
1333 while (ip < fCode.data() + fCode.size()) {
1334 printf("%d: ", (int)(ip - fCode.data()));
1335 ip = Interpreter::disassemble_instruction(ip);
1336 printf("\n");
1337 }
Brian Osman489cf882019-07-09 10:48:28 -04001338#endif
Brian Osman08a84962019-06-14 10:17:16 -04001339}
1340
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001341#define VECTOR_PREPROCESS(base) \
1342 case ByteCodeInstruction::base ## 4: \
1343 case ByteCodeInstruction::base ## 3: \
1344 case ByteCodeInstruction::base ## 2: \
1345 case ByteCodeInstruction::base: READ8(); break;
1346
1347#define VECTOR_PREPROCESS_NO_COUNT(base) \
1348 case ByteCodeInstruction::base ## 4: \
1349 case ByteCodeInstruction::base ## 3: \
1350 case ByteCodeInstruction::base ## 2: \
1351 case ByteCodeInstruction::base: break;
1352
1353#define VECTOR_MATRIX_PREPROCESS(base) \
1354 VECTOR_PREPROCESS(base) \
1355 case ByteCodeInstruction::base ## N: READ8(); break;
1356
1357#define VECTOR_MATRIX_PREPROCESS_NO_COUNT(base) \
1358 VECTOR_PREPROCESS_NO_COUNT(base) \
1359 case ByteCodeInstruction::base ## N: READ8(); break;
1360
1361void ByteCodeFunction::preprocess(const void* labels[], const void* base) {
1362#if defined(SK_ENABLE_SKSL_INTERPRETER)
1363#ifdef TRACE
1364 this->disassemble();
1365#endif
1366 fPreprocessed = true;
1367 uint8_t* ip = fCode.data();
1368 while (ip < fCode.data() + fCode.size()) {
1369 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
1370 intptr_t offset = (char*) labels[(int) inst] - (char*) base;
1371 // if you trip this assert, the code in innerRun has gotten too big for 64K offsets.
1372 SkASSERT(offset >= 0 && offset <= 65535);
1373 *(ip - 2) = offset & 0xFF;
1374 *(ip - 1) = offset >> 8;
1375 switch (inst) {
1376 VECTOR_MATRIX_PREPROCESS(kAddF)
1377 VECTOR_PREPROCESS(kAddI)
1378 case ByteCodeInstruction::kAndB: break;
1379 case ByteCodeInstruction::kBranch: READ16(); break;
1380 case ByteCodeInstruction::kCall: READ8(); break;
1381 case ByteCodeInstruction::kCallExternal: {
1382 READ8();
1383 READ8();
1384 READ8();
1385 break;
1386 }
1387 case ByteCodeInstruction::kClampIndex: READ8(); break;
1388 VECTOR_PREPROCESS(kCompareIEQ)
1389 VECTOR_PREPROCESS(kCompareINEQ)
1390 VECTOR_MATRIX_PREPROCESS(kCompareFEQ)
1391 VECTOR_MATRIX_PREPROCESS(kCompareFNEQ)
1392 VECTOR_PREPROCESS(kCompareFGT)
1393 VECTOR_PREPROCESS(kCompareFGTEQ)
1394 VECTOR_PREPROCESS(kCompareFLT)
1395 VECTOR_PREPROCESS(kCompareFLTEQ)
1396 VECTOR_PREPROCESS(kCompareSGT)
1397 VECTOR_PREPROCESS(kCompareSGTEQ)
1398 VECTOR_PREPROCESS(kCompareSLT)
1399 VECTOR_PREPROCESS(kCompareSLTEQ)
1400 VECTOR_PREPROCESS(kCompareUGT)
1401 VECTOR_PREPROCESS(kCompareUGTEQ)
1402 VECTOR_PREPROCESS(kCompareULT)
1403 VECTOR_PREPROCESS(kCompareULTEQ)
1404 VECTOR_PREPROCESS_NO_COUNT(kConvertFtoI)
1405 VECTOR_PREPROCESS_NO_COUNT(kConvertStoF)
1406 VECTOR_PREPROCESS_NO_COUNT(kConvertUtoF)
1407 VECTOR_PREPROCESS(kCos)
1408 VECTOR_MATRIX_PREPROCESS(kDivideF)
1409 VECTOR_PREPROCESS(kDivideS)
1410 VECTOR_PREPROCESS(kDivideU)
1411 VECTOR_MATRIX_PREPROCESS(kDup)
1412
1413 case ByteCodeInstruction::kInverse2x2:
1414 case ByteCodeInstruction::kInverse3x3:
1415 case ByteCodeInstruction::kInverse4x4: break;
1416
1417 case ByteCodeInstruction::kLoad:
1418 case ByteCodeInstruction::kLoad2:
1419 case ByteCodeInstruction::kLoad3:
1420 case ByteCodeInstruction::kLoad4:
1421 case ByteCodeInstruction::kLoadGlobal:
1422 case ByteCodeInstruction::kLoadGlobal2:
1423 case ByteCodeInstruction::kLoadGlobal3:
1424 case ByteCodeInstruction::kLoadGlobal4: READ16(); break;
1425
1426 case ByteCodeInstruction::kLoadSwizzle:
1427 case ByteCodeInstruction::kLoadSwizzleGlobal: {
1428 READ8();
1429 int count = READ8();
1430 ip += count;
1431 break;
1432 }
1433
1434 case ByteCodeInstruction::kLoadExtended:
1435 case ByteCodeInstruction::kLoadExtendedGlobal:
1436 READ8();
1437 break;
1438
1439 case ByteCodeInstruction::kMatrixToMatrix: {
1440 READ8();
1441 READ8();
1442 READ8();
1443 READ8();
1444 break;
1445 }
1446 case ByteCodeInstruction::kMatrixMultiply: {
1447 READ8();
1448 READ8();
1449 READ8();
1450 break;
1451 }
1452 VECTOR_MATRIX_PREPROCESS(kMultiplyF)
1453 VECTOR_PREPROCESS(kMultiplyI)
1454 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kNegateF)
1455 VECTOR_PREPROCESS_NO_COUNT(kNegateI)
1456 case ByteCodeInstruction::kNotB: break;
1457 case ByteCodeInstruction::kOrB: break;
1458 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kPop)
1459 case ByteCodeInstruction::kPushImmediate: READ32(); break;
1460
1461 case ByteCodeInstruction::kReadExternal:
1462 case ByteCodeInstruction::kReadExternal2:
1463 case ByteCodeInstruction::kReadExternal3:
1464 case ByteCodeInstruction::kReadExternal4: READ16(); break;
1465
1466 VECTOR_PREPROCESS(kRemainderF)
1467 VECTOR_PREPROCESS(kRemainderS)
1468 VECTOR_PREPROCESS(kRemainderU)
1469 case ByteCodeInstruction::kReserve: READ8(); break;
1470 case ByteCodeInstruction::kReturn: READ8(); break;
1471 case ByteCodeInstruction::kScalarToMatrix: READ8(); READ8(); break;
1472 VECTOR_PREPROCESS(kSin)
1473 VECTOR_PREPROCESS_NO_COUNT(kSqrt)
1474
1475 case ByteCodeInstruction::kStore:
1476 case ByteCodeInstruction::kStore2:
1477 case ByteCodeInstruction::kStore3:
1478 case ByteCodeInstruction::kStore4:
1479 case ByteCodeInstruction::kStoreGlobal:
1480 case ByteCodeInstruction::kStoreGlobal2:
1481 case ByteCodeInstruction::kStoreGlobal3:
1482 case ByteCodeInstruction::kStoreGlobal4: READ8(); break;
1483
1484 case ByteCodeInstruction::kStoreSwizzle:
1485 case ByteCodeInstruction::kStoreSwizzleGlobal: {
1486 READ8();
1487 int count = READ8();
1488 ip += count;
1489 break;
1490 }
1491
1492 case ByteCodeInstruction::kStoreSwizzleIndirect:
1493 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
1494 int count = READ8();
1495 ip += count;
1496 break;
1497 }
1498
1499 case ByteCodeInstruction::kStoreExtended: READ8(); break;
1500 case ByteCodeInstruction::kStoreExtendedGlobal: READ8(); break;
1501
1502 VECTOR_MATRIX_PREPROCESS(kSubtractF)
1503 VECTOR_PREPROCESS(kSubtractI)
1504
1505 case ByteCodeInstruction::kSwizzle: {
1506 READ8();
1507 int count = READ8();
1508 ip += count;
1509 break;
1510 }
1511 VECTOR_PREPROCESS(kTan)
1512 case ByteCodeInstruction::kWriteExternal:
1513 case ByteCodeInstruction::kWriteExternal2:
1514 case ByteCodeInstruction::kWriteExternal3:
1515 case ByteCodeInstruction::kWriteExternal4: READ16(); break;
1516
1517 case ByteCodeInstruction::kXorB: break;
1518 case ByteCodeInstruction::kMaskPush: break;
1519 case ByteCodeInstruction::kMaskPop: break;
1520 case ByteCodeInstruction::kMaskNegate: break;
1521 case ByteCodeInstruction::kMaskBlend: READ8(); break;
1522 case ByteCodeInstruction::kBranchIfAllFalse: READ16(); break;
1523 case ByteCodeInstruction::kLoopBegin: break;
1524 case ByteCodeInstruction::kLoopNext: break;
1525 case ByteCodeInstruction::kLoopMask: break;
1526 case ByteCodeInstruction::kLoopEnd: break;
1527 case ByteCodeInstruction::kLoopContinue: break;
1528 case ByteCodeInstruction::kLoopBreak: break;
1529 default:
1530 ip -= 2;
1531 printf("unknown(%d)\n", READ16());
1532 SkASSERT(false);
1533 }
1534 }
1535#endif
1536}
1537
Brian Osman869a3e82019-07-18 17:00:34 -04001538bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
Brian Osman08a84962019-06-14 10:17:16 -04001539 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001540#if defined(SK_ENABLE_SKSL_INTERPRETER)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001541#ifdef TRACE
Brian Osman08a84962019-06-14 10:17:16 -04001542 f->disassemble();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001543#endif
Brian Osman4b202a32019-06-21 09:50:29 -04001544 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001545 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1546 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001547 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001548 }
Brian Osmanef787f72019-06-13 13:07:12 -04001549
Brian Osman869a3e82019-07-18 17:00:34 -04001550 if (uniformCount != (int)fInputSlots.size()) {
1551 return false;
1552 }
1553
Brian Osman08a84962019-06-14 10:17:16 -04001554 Interpreter::VValue globals[32];
Brian Osman869a3e82019-07-18 17:00:34 -04001555 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1556 return false;
1557 }
Brian Osman08a84962019-06-14 10:17:16 -04001558 for (uint8_t slot : fInputSlots) {
1559 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001560 }
1561
Brian Osman1a79f0b2019-06-24 16:32:14 -04001562 int baseIndex = 0;
1563
Brian Osman569f12f2019-06-13 11:23:57 -04001564 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001565 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001566
1567 // Transpose args into stack
1568 {
Brian Osman08a84962019-06-14 10:17:16 -04001569 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001570 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001571 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001572 for (int j = f->fParameterCount; j > 0; --j) {
1573 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001574 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001575 }
1576 }
1577 }
1578
Mike Reed3fd3cc92019-06-20 12:40:30 -04001579 bool stripedOutput = false;
1580 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman869a3e82019-07-18 17:00:34 -04001581 if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
1582 return false;
1583 }
Brian Osman569f12f2019-06-13 11:23:57 -04001584
1585 // Transpose out parameters back
1586 {
Brian Osman08a84962019-06-14 10:17:16 -04001587 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001588 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001589 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001590 for (const auto& p : f->fParameters) {
1591 if (p.fIsOutParameter) {
1592 for (int j = p.fSlotCount; j > 0; --j) {
1593 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001594 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001595 }
1596 } else {
1597 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001598 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001599 }
1600 }
1601 }
1602 }
1603
1604 args += f->fParameterCount * w;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001605 if (outReturn) {
1606 outReturn += f->fReturnCount * w;
1607 }
Brian Osman4b202a32019-06-21 09:50:29 -04001608 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001609 baseIndex += w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001610 }
Brian Osman869a3e82019-07-18 17:00:34 -04001611 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001612#else
1613 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001614 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001615#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001616}
1617
Brian Osman869a3e82019-07-18 17:00:34 -04001618bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
Mike Reed3fd3cc92019-06-20 12:40:30 -04001619 const float* uniforms, int uniformCount,
1620 float* outArgs[], int outCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001621#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001622#ifdef TRACE
Brian Osmanecb3bb52019-06-20 14:59:12 -04001623 f->disassemble();
Brian Osman2b1a5442019-06-19 11:40:33 -04001624#endif
1625 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001626 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1627 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001628 return false;
1629 }
1630
1631 if (nargs != f->fParameterCount ||
1632 outCount != f->fReturnCount ||
1633 uniformCount != (int)fInputSlots.size()) {
1634 return false;
1635 }
1636
1637 Interpreter::VValue globals[32];
1638 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1639 return false;
1640 }
1641 for (uint8_t slot : fInputSlots) {
1642 globals[slot].fFloat = *uniforms++;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001643 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001644
Mike Reed3fd3cc92019-06-20 12:40:30 -04001645 // innerRun just takes outArgs, so clear it if the count is zero
1646 if (outCount == 0) {
1647 outArgs = nullptr;
1648 }
1649
Brian Osman1a79f0b2019-06-24 16:32:14 -04001650 int baseIndex = 0;
1651
Brian Osman2b1a5442019-06-19 11:40:33 -04001652 while (N) {
1653 int w = std::min(N, Interpreter::VecWidth);
1654
1655 // Copy args into stack
1656 for (int i = 0; i < nargs; ++i) {
1657 memcpy(stack + i, args[i], w * sizeof(float));
1658 }
1659
Mike Reed3fd3cc92019-06-20 12:40:30 -04001660 bool stripedOutput = true;
Brian Osman869a3e82019-07-18 17:00:34 -04001661 if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
1662 return false;
1663 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001664
1665 // Copy out parameters back
1666 int slot = 0;
1667 for (const auto& p : f->fParameters) {
1668 if (p.fIsOutParameter) {
1669 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1670 memcpy(args[i], stack + i, w * sizeof(float));
1671 }
1672 }
1673 slot += p.fSlotCount;
1674 }
1675
1676 // Step each argument pointer ahead
1677 for (int i = 0; i < nargs; ++i) {
1678 args[i] += w;
1679 }
1680 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001681 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001682 }
Brian Osman869a3e82019-07-18 17:00:34 -04001683
1684 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001685#else
1686 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001687 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001688#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001689}
1690
Brian Osman80164412019-06-07 13:00:23 -04001691} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001692
1693#endif