blob: 1f0841fda0afdda0b50acdafff57fb045e5db7ae [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
Mike Reed3fd3cc92019-06-20 12:40:30 -040023constexpr int VecWidth = ByteCode::kVecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -040024
Brian Osman9b8b4552019-09-30 13:23:14 -040025struct Interpreter {
26
Brian Osman569f12f2019-06-13 11:23:57 -040027using 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 Nicholasc70027b2019-09-05 16:50:52 -040034#define READ_INST() (ip += sizeof(instruction), \
35 sk_unaligned_load<instruction>(ip - sizeof(instruction)))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040036
Ethan Nicholasc70027b2019-09-05 16:50:52 -040037#define VECTOR_DISASSEMBLE(op, text) \
38 case ByteCodeInstruction::op: printf(text); ++ip; break; \
39 case ByteCodeInstruction::op##2: printf(text "2"); ++ip; break; \
40 case ByteCodeInstruction::op##3: printf(text "3"); ++ip; break; \
41 case ByteCodeInstruction::op##4: printf(text "4"); ++ip; break;
42
43#define VECTOR_DISASSEMBLE_NO_COUNT(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040044 case ByteCodeInstruction::op: printf(text); break; \
45 case ByteCodeInstruction::op##2: printf(text "2"); break; \
46 case ByteCodeInstruction::op##3: printf(text "3"); break; \
47 case ByteCodeInstruction::op##4: printf(text "4"); break;
48
Ethan Nicholasc70027b2019-09-05 16:50:52 -040049#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
50 VECTOR_DISASSEMBLE(op, text) \
51 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
52
53#define VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(op, text) \
54 VECTOR_DISASSEMBLE_NO_COUNT(op, text) \
Brian Osman1e855b22019-05-29 15:21:52 -040055 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
56
Brian Osman9b8b4552019-09-30 13:23:14 -040057static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -040058 switch ((ByteCodeInstruction) (intptr_t) READ_INST()) {
Brian Osman1e855b22019-05-29 15:21:52 -040059 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070060 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040061 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070062 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
63 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
64 case ByteCodeInstruction::kCallExternal: {
65 int argumentCount = READ8();
66 int returnCount = READ8();
67 int externalValue = READ8();
68 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
69 break;
70 }
Brian Osman869a3e82019-07-18 17:00:34 -040071 case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -070072 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
73 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040074 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
75 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070076 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
77 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
78 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
79 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
80 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
81 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
82 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
83 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
84 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
85 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
86 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
87 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholasc70027b2019-09-05 16:50:52 -040088 VECTOR_DISASSEMBLE_NO_COUNT(kConvertFtoI, "convertftoi")
89 VECTOR_DISASSEMBLE_NO_COUNT(kConvertStoF, "convertstof")
90 VECTOR_DISASSEMBLE_NO_COUNT(kConvertUtoF, "convertutof")
Brian Osman3e833e12019-05-23 13:23:24 -070091 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osman1e855b22019-05-29 15:21:52 -040092 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070093 VECTOR_DISASSEMBLE(kDivideS, "divideS")
94 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040095 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Mike Reed634c9412019-07-18 13:20:04 -040096 case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
97 case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
98 case ByteCodeInstruction::kInverse4x4: printf("inverse4x4"); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -040099 case ByteCodeInstruction::kLoad: printf("load %d", READ16() >> 8); break;
100 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ16() >> 8); break;
101 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ16() >> 8); break;
102 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ16() >> 8); break;
103 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ16() >> 8); break;
104 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ16() >> 8); break;
105 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ16() >> 8); break;
106 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ16() >> 8); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700107 case ByteCodeInstruction::kLoadSwizzle: {
108 int target = READ8();
109 int count = READ8();
110 printf("loadswizzle %d %d", target, count);
111 for (int i = 0; i < count; ++i) {
112 printf(", %d", READ8());
113 }
114 break;
115 }
116 case ByteCodeInstruction::kLoadSwizzleGlobal: {
117 int target = READ8();
118 int count = READ8();
119 printf("loadswizzleglobal %d %d", target, count);
120 for (int i = 0; i < count; ++i) {
121 printf(", %d", READ8());
122 }
123 break;
124 }
125 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
126 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
127 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400128 case ByteCodeInstruction::kMatrixToMatrix: {
129 int srcCols = READ8();
130 int srcRows = READ8();
131 int dstCols = READ8();
132 int dstRows = READ8();
133 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
134 break;
135 }
Brian Osman909231c2019-05-29 15:34:36 -0400136 case ByteCodeInstruction::kMatrixMultiply: {
137 int lCols = READ8();
138 int lRows = READ8();
139 int rCols = READ8();
140 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
141 break;
142 }
Brian Osman1e855b22019-05-29 15:21:52 -0400143 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700144 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400145 VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(kNegateF, "negatef")
146 VECTOR_DISASSEMBLE_NO_COUNT(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400147 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400148 case ByteCodeInstruction::kOrB: printf("orb"); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400149 VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700150 case ByteCodeInstruction::kPushImmediate: {
151 uint32_t v = READ32();
152 union { uint32_t u; float f; } pun = { v };
153 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
154 break;
155 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400156 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ16() >> 8); break;
157 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ16() >> 8); break;
158 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ16() >> 8); break;
159 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ16() >> 8); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700160 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
161 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
162 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400163 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700164 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400165 case ByteCodeInstruction::kScalarToMatrix: {
166 int cols = READ8();
167 int rows = READ8();
168 printf("scalartomatrix %dx%d", cols, rows);
169 break;
170 }
Brian Osman4c2146f2019-09-24 09:39:38 -0400171 case ByteCodeInstruction::kShiftLeft: printf("shl %d", READ8()); break;
172 case ByteCodeInstruction::kShiftRightS: printf("shrs %d", READ8()); break;
173 case ByteCodeInstruction::kShiftRightU: printf("shru %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700174 VECTOR_DISASSEMBLE(kSin, "sin")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400175 VECTOR_DISASSEMBLE_NO_COUNT(kSqrt, "sqrt")
Brian Osman3e833e12019-05-23 13:23:24 -0700176 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
177 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
178 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
179 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
180 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
181 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
182 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
183 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
184 case ByteCodeInstruction::kStoreSwizzle: {
185 int target = READ8();
186 int count = READ8();
187 printf("storeswizzle %d %d", target, count);
188 for (int i = 0; i < count; ++i) {
189 printf(", %d", READ8());
190 }
191 break;
192 }
193 case ByteCodeInstruction::kStoreSwizzleGlobal: {
194 int target = READ8();
195 int count = READ8();
196 printf("storeswizzleglobal %d %d", target, count);
197 for (int i = 0; i < count; ++i) {
198 printf(", %d", READ8());
199 }
200 break;
201 }
202 case ByteCodeInstruction::kStoreSwizzleIndirect: {
203 int count = READ8();
204 printf("storeswizzleindirect %d", count);
205 for (int i = 0; i < count; ++i) {
206 printf(", %d", READ8());
207 }
208 break;
209 }
210 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
211 int count = READ8();
212 printf("storeswizzleindirectglobal %d", count);
213 for (int i = 0; i < count; ++i) {
214 printf(", %d", READ8());
215 }
216 break;
217 }
218 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
219 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
220 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400221 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700222 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
223 case ByteCodeInstruction::kSwizzle: {
224 printf("swizzle %d, ", READ8());
225 int count = READ8();
226 printf("%d", count);
227 for (int i = 0; i < count; ++i) {
228 printf(", %d", READ8());
229 }
230 break;
231 }
232 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400233 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ16() >> 8); break;
234 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ16() >> 8); break;
235 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ16() >> 8); break;
236 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ16() >> 8); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400237 case ByteCodeInstruction::kXorB: printf("xorb"); break;
238 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
239 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
240 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
241 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
242 case ByteCodeInstruction::kBranchIfAllFalse:
243 printf("branchifallfalse %d", READ16());
244 break;
245 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
246 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
247 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
248 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
249 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
250 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400251 default:
252 ip -= sizeof(instruction);
253 printf("unknown(%d)\n", (int) (intptr_t) READ_INST());
254 SkASSERT(false);
Brian Osman3e833e12019-05-23 13:23:24 -0700255 }
256 return ip;
257}
258
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400259#ifdef SKSLC_THREADED_CODE
260 #define LABEL(name) name:
261 #ifdef TRACE
262 #define NEXT() goto next
263 #else
264 #define NEXT() goto *READ_INST()
265 #endif
266#else
267 #define LABEL(name) case ByteCodeInstruction::name:
268 #define NEXT() continue
269#endif
270
271#define VECTOR_BINARY_OP(base, field, op) \
272 LABEL(base ## 4) \
273 sp[-4] = sp[-4].field op sp[0].field; \
274 POP(); \
275 /* fall through */ \
276 LABEL(base ## 3) { \
277 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
278 POP(); \
279 } /* fall through */ \
280 LABEL(base ## 2) { \
281 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
282 POP(); \
283 } /* fall through */ \
284 LABEL(base) { \
285 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
286 POP(); \
287 ++ip; \
288 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500289 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400290
Ethan Nicholas6f624122019-09-24 13:07:06 -0400291// A naive implementation of / or % using skvx operations will likely crash with a divide by zero
292// in inactive vector lanesm, so we need to be sure to avoid masked-off lanes.
293#define VECTOR_BINARY_MASKED_OP(base, field, op) \
294 LABEL(base ## 4) \
295 for (int i = 0; i < VecWidth; ++i) { \
296 if (mask()[i]) { \
297 sp[-4].field[i] op ## = sp[0].field[i]; \
298 } \
299 } \
300 POP(); \
301 /* fall through */ \
302 LABEL(base ## 3) { \
303 for (int i = 0; i < VecWidth; ++i) { \
304 if (mask()[i]) { \
305 sp[-ip[0]].field[i] op ## = sp[0].field[i]; \
306 } \
307 } \
308 POP(); \
309 } /* fall through */ \
310 LABEL(base ## 2) { \
311 for (int i = 0; i < VecWidth; ++i) { \
312 if (mask()[i]) { \
313 sp[-ip[0]].field[i] op ## = sp[0].field[i]; \
314 } \
315 } \
316 POP(); \
317 } /* fall through */ \
318 LABEL(base) { \
319 for (int i = 0; i < VecWidth; ++i) { \
320 if (mask()[i]) { \
321 sp[-ip[0]].field[i] op ## = sp[0].field[i]; \
322 } \
323 } \
324 POP(); \
325 ++ip; \
326 NEXT(); \
327 }
328
329
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400330#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
331 VECTOR_BINARY_OP(base, field, op) \
332 LABEL(base ## N) { \
333 int count = READ8(); \
334 for (int i = count; i > 0; --i) { \
335 sp[-count] = sp[-count].field op sp[0].field; \
336 POP(); \
337 } \
338 NEXT(); \
Brian Osman1e855b22019-05-29 15:21:52 -0400339 }
340
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400341#define VECTOR_BINARY_FN(base, field, fn) \
342 LABEL(base ## 4) \
343 sp[-4] = fn(sp[-4].field, sp[0].field); \
344 POP(); \
345 /* fall through */ \
346 LABEL(base ## 3) { \
347 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
348 POP(); \
349 } /* fall through */ \
350 LABEL(base ## 2) { \
351 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
352 POP(); \
353 } /* fall through */ \
354 LABEL(base) { \
355 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
356 POP(); \
357 ++ip; \
358 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500359 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400360
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400361#define VECTOR_UNARY_FN(base, fn, field) \
362 LABEL(base ## 4) sp[-3] = fn(sp[-3].field); \
363 LABEL(base ## 3) sp[-2] = fn(sp[-2].field); \
364 LABEL(base ## 2) sp[-1] = fn(sp[-1].field); \
365 LABEL(base) sp[ 0] = fn(sp[ 0].field); \
366 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400367
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400368#define VECTOR_UNARY_FN_VEC(base, fn) \
369 LABEL(base ## 4) \
370 LABEL(base ## 3) \
371 LABEL(base ## 2) \
372 LABEL(base) { \
373 int count = READ8(); \
374 float* v = (float*)sp - count + 1; \
375 for (int i = VecWidth * count; i > 0; --i, ++v) { \
376 *v = fn(*v); \
377 } \
378 NEXT(); \
Brian Osman569f12f2019-06-13 11:23:57 -0400379 }
380
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400381#define VECTOR_LABELS(base) \
382 &&base ## 4, \
383 &&base ## 3, \
384 &&base ## 2, \
385 &&base
386
387#define VECTOR_MATRIX_LABELS(base) \
388 VECTOR_LABELS(base), \
389 &&base ## N
390
391// If you trip this assert, it means that the order of the opcodes listed in ByteCodeInstruction
392// does not match the order of the opcodes listed in the 'labels' array in innerRun().
393#define CHECK_LABEL(name) \
394 SkASSERT(labels[(int) ByteCodeInstruction::name] == &&name)
395
396#define CHECK_VECTOR_LABELS(name) \
397 CHECK_LABEL(name ## 4); \
398 CHECK_LABEL(name ## 3); \
399 CHECK_LABEL(name ## 2); \
400 CHECK_LABEL(name)
401
402#define CHECK_VECTOR_MATRIX_LABELS(name) \
403 CHECK_VECTOR_LABELS(name); \
404 CHECK_LABEL(name ## N)
405
Brian Osman569f12f2019-06-13 11:23:57 -0400406union VValue {
407 VValue() {}
Brian Osman9b8b4552019-09-30 13:23:14 -0400408 VValue(F32 f) : fFloat(f) {}
409 VValue(I32 s) : fSigned(s) {}
410 VValue(U32 u) : fUnsigned(u) {}
Brian Osman569f12f2019-06-13 11:23:57 -0400411
412 F32 fFloat;
413 I32 fSigned;
414 U32 fUnsigned;
415};
416
Brian Osman226668a2019-05-14 16:47:30 -0400417struct StackFrame {
418 const uint8_t* fCode;
419 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400420 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400421 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400422};
423
Brian Osman9b8b4552019-09-30 13:23:14 -0400424static F32 VecMod(F32 a, F32 b) {
Brian Osman569f12f2019-06-13 11:23:57 -0400425 return a - skvx::trunc(a / b) * b;
426}
Mike Kleine7007382019-05-21 08:36:32 -0500427
Mike Reed634c9412019-07-18 13:20:04 -0400428#define spf(index) sp[index].fFloat
429
Brian Osman9b8b4552019-09-30 13:23:14 -0400430static void CallExternal(const ByteCode* byteCode, const uint8_t*& ip, VValue*& sp,
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400431 int baseIndex, I32 mask) {
432 int argumentCount = READ8();
433 int returnCount = READ8();
434 int target = READ8();
435 ExternalValue* v = byteCode->fExternalValues[target];
436 sp -= argumentCount - 1;
437
438 float tmpArgs[4];
439 float tmpReturn[4];
440 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
441 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
442
443 for (int i = 0; i < VecWidth; ++i) {
444 if (mask[i]) {
445 for (int j = 0; j < argumentCount; ++j) {
446 tmpArgs[j] = sp[j].fFloat[i];
447 }
448 v->call(baseIndex + i, tmpArgs, tmpReturn);
449 for (int j = 0; j < returnCount; ++j) {
450 sp[j].fFloat[i] = tmpReturn[j];
451 }
452 }
453 }
454 sp += returnCount - 1;
455}
456
Brian Osman9b8b4552019-09-30 13:23:14 -0400457static void Inverse2x2(VValue* sp) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400458 F32 a = sp[-3].fFloat,
459 b = sp[-2].fFloat,
460 c = sp[-1].fFloat,
461 d = sp[ 0].fFloat;
462 F32 idet = F32(1) / (a*d - b*c);
463 sp[-3].fFloat = d * idet;
464 sp[-2].fFloat = -b * idet;
465 sp[-1].fFloat = -c * idet;
466 sp[ 0].fFloat = a * idet;
467}
468
Brian Osman9b8b4552019-09-30 13:23:14 -0400469static void Inverse3x3(VValue* sp) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400470 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
471 a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
472 a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
473 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
474 a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
475 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
476 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
477 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
478 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
479 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
480 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
481 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
482 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
483 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
484}
485
Brian Osman9b8b4552019-09-30 13:23:14 -0400486static void Inverse4x4(VValue* sp) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400487 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
488 a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
489 a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
490 a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf( 0);
491
492 F32 b00 = a00 * a11 - a01 * a10,
493 b01 = a00 * a12 - a02 * a10,
494 b02 = a00 * a13 - a03 * a10,
495 b03 = a01 * a12 - a02 * a11,
496 b04 = a01 * a13 - a03 * a11,
497 b05 = a02 * a13 - a03 * a12,
498 b06 = a20 * a31 - a21 * a30,
499 b07 = a20 * a32 - a22 * a30,
500 b08 = a20 * a33 - a23 * a30,
501 b09 = a21 * a32 - a22 * a31,
502 b10 = a21 * a33 - a23 * a31,
503 b11 = a22 * a33 - a23 * a32;
504
505 F32 idet = F32(1) /
506 (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
507
508 b00 *= idet;
509 b01 *= idet;
510 b02 *= idet;
511 b03 *= idet;
512 b04 *= idet;
513 b05 *= idet;
514 b06 *= idet;
515 b07 *= idet;
516 b08 *= idet;
517 b09 *= idet;
518 b10 *= idet;
519 b11 *= idet;
520
521 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
522 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
523 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
524 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
525 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
526 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
527 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
528 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
529 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
530 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
531 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
532 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
533 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
534 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
535 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
536 spf( 0) = a20 * b03 - a21 * b01 + a22 * b00;
537}
538
Brian Osman9b8b4552019-09-30 13:23:14 -0400539static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400540 float* outReturn[], VValue globals[], bool stripedOutput, int N,
541 int baseIndex) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400542#ifdef SKSLC_THREADED_CODE
543 static const void* labels[] = {
544 // If you aren't familiar with it, the &&label syntax is the GCC / Clang "labels as values"
545 // extension. If you add anything to this array, be sure to add the corresponding
546 // CHECK_LABEL() or CHECK_*_LABELS() assert below.
547 VECTOR_MATRIX_LABELS(kAddF),
548 VECTOR_LABELS(kAddI),
549 &&kAndB,
550 &&kBranch,
551 &&kCall,
552 &&kCallExternal,
553 &&kClampIndex,
554 VECTOR_LABELS(kCompareIEQ),
555 VECTOR_LABELS(kCompareINEQ),
556 VECTOR_MATRIX_LABELS(kCompareFEQ),
557 VECTOR_MATRIX_LABELS(kCompareFNEQ),
558 VECTOR_LABELS(kCompareFGT),
559 VECTOR_LABELS(kCompareFGTEQ),
560 VECTOR_LABELS(kCompareFLT),
561 VECTOR_LABELS(kCompareFLTEQ),
562 VECTOR_LABELS(kCompareSGT),
563 VECTOR_LABELS(kCompareSGTEQ),
564 VECTOR_LABELS(kCompareSLT),
565 VECTOR_LABELS(kCompareSLTEQ),
566 VECTOR_LABELS(kCompareUGT),
567 VECTOR_LABELS(kCompareUGTEQ),
568 VECTOR_LABELS(kCompareULT),
569 VECTOR_LABELS(kCompareULTEQ),
570 VECTOR_LABELS(kConvertFtoI),
571 VECTOR_LABELS(kConvertStoF),
572 VECTOR_LABELS(kConvertUtoF),
573 VECTOR_LABELS(kCos),
574 VECTOR_MATRIX_LABELS(kDivideF),
575 VECTOR_LABELS(kDivideS),
576 VECTOR_LABELS(kDivideU),
577 VECTOR_MATRIX_LABELS(kDup),
578 &&kInverse2x2,
579 &&kInverse3x3,
580 &&kInverse4x4,
581 VECTOR_LABELS(kLoad),
582 VECTOR_LABELS(kLoadGlobal),
583 &&kLoadSwizzle,
584 &&kLoadSwizzleGlobal,
585 &&kLoadExtended,
586 &&kLoadExtendedGlobal,
587 &&kMatrixToMatrix,
588 &&kMatrixMultiply,
589 VECTOR_MATRIX_LABELS(kNegateF),
590 VECTOR_LABELS(kNegateI),
591 VECTOR_MATRIX_LABELS(kMultiplyF),
592 VECTOR_LABELS(kMultiplyI),
593 &&kNotB,
594 &&kOrB,
595 VECTOR_MATRIX_LABELS(kPop),
596 &&kPushImmediate,
597 VECTOR_LABELS(kReadExternal),
598 VECTOR_LABELS(kRemainderF),
599 VECTOR_LABELS(kRemainderS),
600 VECTOR_LABELS(kRemainderU),
601 &&kReserve,
602 &&kReturn,
603 &&kScalarToMatrix,
Brian Osman4c2146f2019-09-24 09:39:38 -0400604 &&kShiftLeft,
605 &&kShiftRightS,
606 &&kShiftRightU,
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400607 VECTOR_LABELS(kSin),
608 VECTOR_LABELS(kSqrt),
609 VECTOR_LABELS(kStore),
610 VECTOR_LABELS(kStoreGlobal),
611 &&kStoreExtended,
612 &&kStoreExtendedGlobal,
613 &&kStoreSwizzle,
614 &&kStoreSwizzleGlobal,
615 &&kStoreSwizzleIndirect,
616 &&kStoreSwizzleIndirectGlobal,
617 &&kSwizzle,
618 VECTOR_MATRIX_LABELS(kSubtractF),
619 VECTOR_LABELS(kSubtractI),
620 VECTOR_LABELS(kTan),
621 VECTOR_LABELS(kWriteExternal),
622 &&kXorB,
623
624 &&kMaskPush,
625 &&kMaskPop,
626 &&kMaskNegate,
627 &&kMaskBlend,
628 &&kBranchIfAllFalse,
629
630 &&kLoopBegin,
631 &&kLoopNext,
632 &&kLoopMask,
633 &&kLoopEnd,
634 &&kLoopBreak,
635 &&kLoopContinue,
636 };
637 // Verify that the order of the labels array matches the order of the ByteCodeInstruction enum.
638 CHECK_VECTOR_MATRIX_LABELS(kAddF);
639 CHECK_VECTOR_LABELS(kAddI);
640 CHECK_LABEL(kAndB);
641 CHECK_LABEL(kBranch);
642 CHECK_LABEL(kCall);
643 CHECK_LABEL(kCallExternal);
644 CHECK_LABEL(kClampIndex);
645 CHECK_VECTOR_LABELS(kCompareIEQ);
646 CHECK_VECTOR_LABELS(kCompareINEQ);
647 CHECK_VECTOR_MATRIX_LABELS(kCompareFEQ);
648 CHECK_VECTOR_MATRIX_LABELS(kCompareFNEQ);
649 CHECK_VECTOR_LABELS(kCompareFGT);
650 CHECK_VECTOR_LABELS(kCompareFGTEQ);
651 CHECK_VECTOR_LABELS(kCompareFLT);
652 CHECK_VECTOR_LABELS(kCompareFLTEQ);
653 CHECK_VECTOR_LABELS(kCompareSGT);
654 CHECK_VECTOR_LABELS(kCompareSGTEQ);
655 CHECK_VECTOR_LABELS(kCompareSLT);
656 CHECK_VECTOR_LABELS(kCompareSLTEQ);
657 CHECK_VECTOR_LABELS(kCompareUGT);
658 CHECK_VECTOR_LABELS(kCompareUGTEQ);
659 CHECK_VECTOR_LABELS(kCompareULT);
660 CHECK_VECTOR_LABELS(kCompareULTEQ);
661 CHECK_VECTOR_LABELS(kConvertFtoI);
662 CHECK_VECTOR_LABELS(kConvertStoF);
663 CHECK_VECTOR_LABELS(kConvertUtoF);
664 CHECK_VECTOR_LABELS(kCos);
665 CHECK_VECTOR_MATRIX_LABELS(kDivideF);
666 CHECK_VECTOR_LABELS(kDivideS);
667 CHECK_VECTOR_LABELS(kDivideU);
668 CHECK_VECTOR_MATRIX_LABELS(kDup);
669 CHECK_LABEL(kInverse2x2);
670 CHECK_LABEL(kInverse3x3);
671 CHECK_LABEL(kInverse4x4);
672 CHECK_VECTOR_LABELS(kLoad);
673 CHECK_VECTOR_LABELS(kLoadGlobal);
674 CHECK_LABEL(kLoadSwizzle);
675 CHECK_LABEL(kLoadSwizzleGlobal);
676 CHECK_LABEL(kLoadExtended);
677 CHECK_LABEL(kLoadExtendedGlobal);
678 CHECK_LABEL(kMatrixToMatrix);
679 CHECK_LABEL(kMatrixMultiply);
680 CHECK_VECTOR_MATRIX_LABELS(kNegateF);
681 CHECK_VECTOR_LABELS(kNegateI);
682 CHECK_VECTOR_MATRIX_LABELS(kMultiplyF);
683 CHECK_VECTOR_LABELS(kMultiplyI);
684 CHECK_LABEL(kNotB);
685 CHECK_LABEL(kOrB);
686 CHECK_VECTOR_MATRIX_LABELS(kPop);
687 CHECK_LABEL(kPushImmediate);
688 CHECK_VECTOR_LABELS(kReadExternal);
689 CHECK_VECTOR_LABELS(kRemainderF);
690 CHECK_VECTOR_LABELS(kRemainderS);
691 CHECK_VECTOR_LABELS(kRemainderU);
692 CHECK_LABEL(kReserve);
693 CHECK_LABEL(kReturn);
694 CHECK_LABEL(kScalarToMatrix);
Brian Osman4c2146f2019-09-24 09:39:38 -0400695 CHECK_LABEL(kShiftLeft);
696 CHECK_LABEL(kShiftRightS);
697 CHECK_LABEL(kShiftRightU);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400698 CHECK_VECTOR_LABELS(kSin);
699 CHECK_VECTOR_LABELS(kSqrt);
700 CHECK_VECTOR_LABELS(kStore);
701 CHECK_VECTOR_LABELS(kStoreGlobal);
702 CHECK_LABEL(kStoreExtended);
703 CHECK_LABEL(kStoreExtendedGlobal);
704 CHECK_LABEL(kStoreSwizzle);
705 CHECK_LABEL(kStoreSwizzleGlobal);
706 CHECK_LABEL(kStoreSwizzleIndirect);
707 CHECK_LABEL(kStoreSwizzleIndirectGlobal);
708 CHECK_LABEL(kSwizzle);
709 CHECK_VECTOR_MATRIX_LABELS(kSubtractF);
710 CHECK_VECTOR_LABELS(kSubtractI);
711 CHECK_VECTOR_LABELS(kTan);
712 CHECK_VECTOR_LABELS(kWriteExternal);
713 CHECK_LABEL(kXorB);
714 CHECK_LABEL(kMaskPush);
715 CHECK_LABEL(kMaskPop);
716 CHECK_LABEL(kMaskNegate);
717 CHECK_LABEL(kMaskBlend);
718 CHECK_LABEL(kBranchIfAllFalse);
719 CHECK_LABEL(kLoopBegin);
720 CHECK_LABEL(kLoopNext);
721 CHECK_LABEL(kLoopMask);
722 CHECK_LABEL(kLoopEnd);
723 CHECK_LABEL(kLoopBreak);
724 CHECK_LABEL(kLoopContinue);
Brian Osman11b877e2019-09-17 10:21:06 -0400725 f->fPreprocessOnce([f] { ((ByteCodeFunction*)f)->preprocess(labels); });
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400726#endif
727
Brian Osman4b202a32019-06-21 09:50:29 -0400728 // Needs to be the first N non-negative integers, at least as large as VecWidth
729 static const Interpreter::I32 gLanes = {
730 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
731 };
732
Brian Osman569f12f2019-06-13 11:23:57 -0400733 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
734
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400735 #define POP() (*(sp--))
736 #define PUSH(v) (sp[1] = v, ++sp)
Mike Kleine7007382019-05-21 08:36:32 -0500737
Brian Osman80164412019-06-07 13:00:23 -0400738 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400739 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400740 std::vector<StackFrame> frames;
741
Brian Osman569f12f2019-06-13 11:23:57 -0400742 I32 condStack[16]; // Independent condition masks
743 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
744 I32 contStack[16]; // Continue flags for loops
745 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400746 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400747 contStack[0] = I32( 0);
748 loopStack[0] = I32(~0);
749 I32* condPtr = condStack;
750 I32* maskPtr = maskStack;
751 I32* contPtr = contStack;
752 I32* loopPtr = loopStack;
753
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400754 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
755 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osman869a3e82019-07-18 17:00:34 -0400756 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400757 }
758
Brian Osman569f12f2019-06-13 11:23:57 -0400759 auto mask = [&]() { return *maskPtr & *loopPtr; };
760
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400761#ifdef SKSLC_THREADED_CODE
762 // If the "labels as values" extension is available, we implement this using threaded code.
763 // Instead of opcodes, the code directly contains the addresses of the labels to jump to. Then
764 // the code for each opcode simply grabs the address of the next opcode and uses a goto to jump
765 // there.
766 NEXT();
767#else
768 // Otherwise, we have to use a switch statement and a loop to execute the right label.
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400769 for (;;) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400770 #ifdef TRACE
771 printf("at %3d ", (int) (ip - code));
772 disassemble_instruction(ip);
773 printf(" (stack: %d)\n", (int) (sp - stack) + 1);
774 #endif
775 switch ((ByteCodeInstruction) READ16()) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400776#endif
Brian Osman569f12f2019-06-13 11:23:57 -0400777
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400778 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
779 VECTOR_BINARY_OP(kAddI, fSigned, +)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400780
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400781 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
782 LABEL(kAndB)
783 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
784 POP();
785 NEXT();
786 LABEL(kNotB)
787 sp[0] = ~sp[0].fSigned;
788 NEXT();
789 LABEL(kOrB)
790 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
791 POP();
792 NEXT();
793 LABEL(kXorB)
794 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
795 POP();
796 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400797
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400798 LABEL(kBranch)
799 ip = code + READ16();
800 NEXT();
801
802 LABEL(kCall) {
803 // Precursor code reserved space for the return value, and pushed all parameters to
804 // the stack. Update our bottom of stack to point at the first parameter, and our
805 // sp to point past those parameters (plus space for locals).
806 int target = READ8();
807 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
808#ifdef SKSLC_THREADED_CODE
Brian Osman11b877e2019-09-17 10:21:06 -0400809 fun->fPreprocessOnce([fun] { ((ByteCodeFunction*)fun)->preprocess(labels); });
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400810#endif
811 if (skvx::any(mask())) {
812 frames.push_back({ code, ip, stack, fun->fParameterCount });
813 ip = code = fun->fCode.data();
814 stack = sp - fun->fParameterCount + 1;
815 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
816 }
817 NEXT();
818 }
819
820 LABEL(kCallExternal) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400821 CallExternal(byteCode, ip, sp, baseIndex, mask());
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400822 NEXT();
823 }
824
825 LABEL(kClampIndex) {
826 int length = READ8();
827 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
828 return false;
829 }
830 NEXT();
831 }
832
833 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
834 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
835 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
836 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
837 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
838 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
839 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
840 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
841 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
842 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
843 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
844 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
845 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
846 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
847 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
848 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
849
850 LABEL(kConvertFtoI4) sp[-3] = skvx::cast<int>(sp[-3].fFloat);
851 LABEL(kConvertFtoI3) sp[-2] = skvx::cast<int>(sp[-2].fFloat);
852 LABEL(kConvertFtoI2) sp[-1] = skvx::cast<int>(sp[-1].fFloat);
853 LABEL(kConvertFtoI) sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
854 NEXT();
855
856 LABEL(kConvertStoF4) sp[-3] = skvx::cast<float>(sp[-3].fSigned);
857 LABEL(kConvertStoF3) sp[-2] = skvx::cast<float>(sp[-2].fSigned);
858 LABEL(kConvertStoF2) sp[-1] = skvx::cast<float>(sp[-1].fSigned);
859 LABEL(kConvertStoF) sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
860 NEXT();
861
862 LABEL(kConvertUtoF4) sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
863 LABEL(kConvertUtoF3) sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
864 LABEL(kConvertUtoF2) sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
865 LABEL(kConvertUtoF) sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
866 NEXT();
867
868 VECTOR_UNARY_FN_VEC(kCos, cosf)
869
Ethan Nicholas6f624122019-09-24 13:07:06 -0400870 VECTOR_BINARY_MASKED_OP(kDivideS, fSigned, /)
871 VECTOR_BINARY_MASKED_OP(kDivideU, fUnsigned, /)
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400872 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
873
874 LABEL(kDup4) PUSH(sp[1 - ip[0]]);
875 LABEL(kDup3) PUSH(sp[1 - ip[0]]);
876 LABEL(kDup2) PUSH(sp[1 - ip[0]]);
877 LABEL(kDup) PUSH(sp[1 - ip[0]]);
878 ++ip;
879 NEXT();
880
881 LABEL(kDupN) {
882 int count = READ8();
883 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
884 sp += count;
885 NEXT();
886 }
887
888 LABEL(kInverse2x2) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400889 Inverse2x2(sp);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400890 NEXT();
891 }
892 LABEL(kInverse3x3) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400893 Inverse3x3(sp);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400894 NEXT();
895 }
896 LABEL(kInverse4x4) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400897 Inverse4x4(sp);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400898 NEXT();
899 }
900
901 LABEL(kLoad4) sp[4] = stack[ip[1] + 3];
902 LABEL(kLoad3) sp[3] = stack[ip[1] + 2];
903 LABEL(kLoad2) sp[2] = stack[ip[1] + 1];
904 LABEL(kLoad) sp[1] = stack[ip[1] + 0];
905 sp += ip[0];
906 ip += 2;
907 NEXT();
908
909 LABEL(kLoadGlobal4) sp[4] = globals[ip[1] + 3];
910 LABEL(kLoadGlobal3) sp[3] = globals[ip[1] + 2];
911 LABEL(kLoadGlobal2) sp[2] = globals[ip[1] + 1];
912 LABEL(kLoadGlobal) sp[1] = globals[ip[1] + 0];
913 sp += ip[0];
914 ip += 2;
915 NEXT();
916
917 LABEL(kLoadExtended) {
918 int count = READ8();
919 I32 src = POP().fSigned;
920 I32 m = mask();
921 for (int i = 0; i < count; ++i) {
922 for (int j = 0; j < VecWidth; ++j) {
923 if (m[j]) {
924 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400925 }
Brian Osman226668a2019-05-14 16:47:30 -0400926 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400927 }
928 sp += count;
929 NEXT();
930 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400931
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400932 LABEL(kLoadExtendedGlobal) {
933 int count = READ8();
934 I32 src = POP().fSigned;
935 I32 m = mask();
936 for (int i = 0; i < count; ++i) {
937 for (int j = 0; j < VecWidth; ++j) {
938 if (m[j]) {
939 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
940 }
941 }
942 }
943 sp += count;
944 NEXT();
945 }
Mike Kleine7007382019-05-21 08:36:32 -0500946
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400947 LABEL(kLoadSwizzle) {
948 int src = READ8();
949 int count = READ8();
950 for (int i = 0; i < count; ++i) {
951 PUSH(stack[src + *(ip + i)]);
952 }
953 ip += count;
954 NEXT();
955 }
Brian Osman569f12f2019-06-13 11:23:57 -0400956
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400957 LABEL(kLoadSwizzleGlobal) {
958 int src = READ8();
959 int count = READ8();
960 for (int i = 0; i < count; ++i) {
961 PUSH(globals[src + *(ip + i)]);
962 }
963 ip += count;
964 NEXT();
965 }
966
967 LABEL(kMatrixToMatrix) {
968 int srcCols = READ8();
969 int srcRows = READ8();
970 int dstCols = READ8();
971 int dstRows = READ8();
972 SkASSERT(srcCols >= 2 && srcCols <= 4);
973 SkASSERT(srcRows >= 2 && srcRows <= 4);
974 SkASSERT(dstCols >= 2 && dstCols <= 4);
975 SkASSERT(dstRows >= 2 && dstRows <= 4);
976 F32 tmp[16];
977 memset(tmp, 0, sizeof(tmp));
978 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
979 for (int c = srcCols - 1; c >= 0; --c) {
980 for (int r = srcRows - 1; r >= 0; --r) {
981 tmp[c*4 + r] = POP().fFloat;
982 }
983 }
984 for (int c = 0; c < dstCols; ++c) {
985 for (int r = 0; r < dstRows; ++r) {
986 PUSH(tmp[c*4 + r]);
987 }
988 }
989 NEXT();
990 }
991
992 LABEL(kMatrixMultiply) {
993 int lCols = READ8();
994 int lRows = READ8();
995 int rCols = READ8();
996 int rRows = lCols;
997 F32 tmp[16] = { 0.0f };
998 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
999 F32* A = B - (lCols * lRows);
1000 for (int c = 0; c < rCols; ++c) {
1001 for (int r = 0; r < lRows; ++r) {
1002 for (int j = 0; j < lCols; ++j) {
1003 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
1004 }
1005 }
1006 }
1007 sp -= (lCols * lRows) + (rCols * rRows);
1008 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
1009 sp += (rCols * lRows);
1010 NEXT();
1011 }
1012
1013 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
1014 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
1015
1016 LABEL(kNegateF4) sp[-3] = -sp[-3].fFloat;
1017 LABEL(kNegateF3) sp[-2] = -sp[-2].fFloat;
1018 LABEL(kNegateF2) sp[-1] = -sp[-1].fFloat;
1019 LABEL(kNegateF) sp[ 0] = -sp[ 0].fFloat;
1020 NEXT();
1021
1022 LABEL(kNegateFN) {
1023 int count = READ8();
1024 for (int i = count - 1; i >= 0; --i) {
1025 sp[-i] = -sp[-i].fFloat;
1026 }
1027 NEXT();
1028 }
1029
1030 LABEL(kNegateI4) sp[-3] = -sp[-3].fSigned;
1031 LABEL(kNegateI3) sp[-2] = -sp[-2].fSigned;
1032 LABEL(kNegateI2) sp[-1] = -sp[-1].fSigned;
1033 LABEL(kNegateI) sp[ 0] = -sp[ 0].fSigned;
1034 NEXT();
1035
1036 LABEL(kPop4) POP();
1037 LABEL(kPop3) POP();
1038 LABEL(kPop2) POP();
1039 LABEL(kPop) POP();
1040 NEXT();
1041
1042 LABEL(kPopN)
1043 sp -= READ8();
1044 NEXT();
1045
1046 LABEL(kPushImmediate)
1047 PUSH(U32(READ32()));
1048 NEXT();
1049
1050 LABEL(kReadExternal)
1051 LABEL(kReadExternal2)
1052 LABEL(kReadExternal3)
1053 LABEL(kReadExternal4) {
1054 int count = READ8();
1055 int src = READ8();
1056 float tmp[4];
1057 I32 m = mask();
1058 for (int i = 0; i < VecWidth; ++i) {
1059 if (m[i]) {
1060 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
1061 for (int j = 0; j < count; ++j) {
1062 sp[j + 1].fFloat[i] = tmp[j];
1063 }
1064 }
1065 }
1066 sp += count;
1067 NEXT();
1068 }
1069
Brian Osman9b8b4552019-09-30 13:23:14 -04001070 VECTOR_BINARY_FN(kRemainderF, fFloat, VecMod)
Ethan Nicholas6f624122019-09-24 13:07:06 -04001071 VECTOR_BINARY_MASKED_OP(kRemainderS, fSigned, %)
1072 VECTOR_BINARY_MASKED_OP(kRemainderU, fUnsigned, %)
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001073
1074 LABEL(kReserve)
1075 sp += READ8();
1076 NEXT();
1077
1078 LABEL(kReturn) {
1079 int count = READ8();
1080 if (frames.empty()) {
1081 if (outReturn) {
1082 VValue* src = sp - count + 1;
1083 if (stripedOutput) {
1084 for (int i = 0; i < count; ++i) {
1085 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
1086 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -04001087 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001088 } else {
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001089 float* outPtr = outReturn[0];
1090 for (int i = 0; i < count; ++i) {
1091 for (int j = 0; j < N; ++j) {
1092 outPtr[count * j] = src->fFloat[j];
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001093 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001094 ++outPtr;
1095 ++src;
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001096 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001097 }
1098 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001099 return true;
1100 } else {
1101 // When we were called, the caller reserved stack space for their copy of our
1102 // return value, then 'stack' was positioned after that, where our parameters
1103 // were placed. Copy our return values to their reserved area.
1104 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001105
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001106 // Now move the stack pointer to the end of the passed-in parameters. This odd
1107 // calling convention requires the caller to pop the arguments after calling,
1108 // but allows them to store any out-parameters back during that unwinding.
1109 // After that sequence finishes, the return value will be the top of the stack.
1110 const StackFrame& frame(frames.back());
1111 sp = stack + frame.fParameterCount - 1;
1112 stack = frame.fStack;
1113 code = frame.fCode;
1114 ip = frame.fIP;
1115 frames.pop_back();
1116 NEXT();
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001117 }
1118 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001119
1120 LABEL(kScalarToMatrix) {
1121 int cols = READ8();
1122 int rows = READ8();
1123 VValue v = POP();
1124 for (int c = 0; c < cols; ++c) {
1125 for (int r = 0; r < rows; ++r) {
1126 PUSH(c == r ? v : F32(0.0f));
1127 }
1128 }
1129 NEXT();
1130 }
1131
Brian Osman4c2146f2019-09-24 09:39:38 -04001132 LABEL(kShiftLeft)
1133 sp[0] = sp[0].fSigned << READ8();
1134 NEXT();
1135 LABEL(kShiftRightS)
1136 sp[0] = sp[0].fSigned >> READ8();
1137 NEXT();
1138 LABEL(kShiftRightU)
1139 sp[0] = sp[0].fUnsigned >> READ8();
1140 NEXT();
1141
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001142 VECTOR_UNARY_FN_VEC(kSin, sinf)
1143 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
1144
1145 LABEL(kStore4)
1146 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
1147 LABEL(kStore3)
1148 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
1149 LABEL(kStore2)
1150 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
1151 LABEL(kStore)
1152 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
1153 ++ip;
1154 NEXT();
1155
1156 LABEL(kStoreGlobal4)
1157 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
1158 LABEL(kStoreGlobal3)
1159 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
1160 LABEL(kStoreGlobal2)
1161 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
1162 LABEL(kStoreGlobal)
1163 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
1164 ++ip;
1165 NEXT();
1166
1167 LABEL(kStoreExtended) {
1168 int count = READ8();
1169 I32 target = POP().fSigned;
1170 VValue* src = sp - count + 1;
1171 I32 m = mask();
1172 for (int i = 0; i < count; ++i) {
1173 for (int j = 0; j < VecWidth; ++j) {
1174 if (m[j]) {
1175 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
1176 }
1177 }
1178 }
1179 sp -= count;
1180 NEXT();
1181 }
1182 LABEL(kStoreExtendedGlobal) {
1183 int count = READ8();
1184 I32 target = POP().fSigned;
1185 VValue* src = sp - count + 1;
1186 I32 m = mask();
1187 for (int i = 0; i < count; ++i) {
1188 for (int j = 0; j < VecWidth; ++j) {
1189 if (m[j]) {
1190 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
1191 }
1192 }
1193 }
1194 sp -= count;
1195 NEXT();
1196 }
1197
1198 LABEL(kStoreSwizzle) {
1199 int target = READ8();
1200 int count = READ8();
1201 for (int i = count - 1; i >= 0; --i) {
1202 stack[target + *(ip + i)] = skvx::if_then_else(
1203 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
1204 }
1205 ip += count;
1206 NEXT();
1207 }
1208
1209 LABEL(kStoreSwizzleGlobal) {
1210 int target = READ8();
1211 int count = READ8();
1212 for (int i = count - 1; i >= 0; --i) {
1213 globals[target + *(ip + i)] = skvx::if_then_else(
1214 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
1215 }
1216 ip += count;
1217 NEXT();
1218 }
1219
1220 LABEL(kStoreSwizzleIndirect) {
1221 int count = READ8();
1222 I32 target = POP().fSigned;
1223 I32 m = mask();
1224 for (int i = count - 1; i >= 0; --i) {
1225 I32 v = POP().fSigned;
1226 for (int j = 0; j < VecWidth; ++j) {
1227 if (m[j]) {
1228 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
1229 }
1230 }
1231 }
1232 ip += count;
1233 NEXT();
1234 }
1235
1236 LABEL(kStoreSwizzleIndirectGlobal) {
1237 int count = READ8();
1238 I32 target = POP().fSigned;
1239 I32 m = mask();
1240 for (int i = count - 1; i >= 0; --i) {
1241 I32 v = POP().fSigned;
1242 for (int j = 0; j < VecWidth; ++j) {
1243 if (m[j]) {
1244 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
1245 }
1246 }
1247 }
1248 ip += count;
1249 NEXT();
1250 }
1251
1252 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
1253 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
1254
1255 LABEL(kSwizzle) {
1256 VValue tmp[4];
1257 for (int i = READ8() - 1; i >= 0; --i) {
1258 tmp[i] = POP();
1259 }
1260 for (int i = READ8() - 1; i >= 0; --i) {
1261 PUSH(tmp[READ8()]);
1262 }
1263 NEXT();
1264 }
1265
1266 VECTOR_UNARY_FN_VEC(kTan, tanf)
1267
1268 LABEL(kWriteExternal4)
1269 LABEL(kWriteExternal3)
1270 LABEL(kWriteExternal2)
1271 LABEL(kWriteExternal) {
1272 int count = READ8();
1273 int target = READ8();
1274 float tmp[4];
1275 I32 m = mask();
1276 sp -= count;
1277 for (int i = 0; i < VecWidth; ++i) {
1278 if (m[i]) {
1279 for (int j = 0; j < count; ++j) {
1280 tmp[j] = sp[j + 1].fFloat[i];
1281 }
1282 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
1283 }
1284 }
1285 NEXT();
1286 }
1287
1288 LABEL(kMaskPush)
1289 condPtr[1] = POP().fSigned;
1290 maskPtr[1] = maskPtr[0] & condPtr[1];
1291 ++condPtr; ++maskPtr;
1292 NEXT();
1293 LABEL(kMaskPop)
1294 --condPtr; --maskPtr;
1295 NEXT();
1296 LABEL(kMaskNegate)
1297 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
1298 NEXT();
1299 LABEL(kMaskBlend) {
1300 int count = READ8();
1301 I32 m = condPtr[0];
1302 --condPtr; --maskPtr;
1303 for (int i = 0; i < count; ++i) {
1304 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1305 --sp;
1306 }
1307 NEXT();
1308 }
1309 LABEL(kBranchIfAllFalse) {
1310 int target = READ16();
1311 if (!skvx::any(mask())) {
1312 ip = code + target;
1313 }
1314 NEXT();
1315 }
1316
1317 LABEL(kLoopBegin)
1318 contPtr[1] = 0;
1319 loopPtr[1] = loopPtr[0];
1320 ++contPtr; ++loopPtr;
1321 NEXT();
1322 LABEL(kLoopNext)
1323 *loopPtr |= *contPtr;
1324 *contPtr = 0;
1325 NEXT();
1326 LABEL(kLoopMask)
1327 *loopPtr &= POP().fSigned;
1328 NEXT();
1329 LABEL(kLoopEnd)
1330 --contPtr; --loopPtr;
1331 NEXT();
1332 LABEL(kLoopBreak)
1333 *loopPtr &= ~mask();
1334 NEXT();
1335 LABEL(kLoopContinue) {
1336 I32 m = mask();
1337 *contPtr |= m;
1338 *loopPtr &= ~m;
1339 NEXT();
1340 }
1341#ifdef SKSLC_THREADED_CODE
1342 #ifdef TRACE
1343 next:
1344 printf("at %3d (stack: %d) (disable threaded code for disassembly)\n",
1345 (int) (ip - code), (int) (sp - stack) + 1);
1346 goto *READ_INST();
1347 #endif
1348#else
1349 }
1350 }
1351#endif
Brian Osman569f12f2019-06-13 11:23:57 -04001352}
1353
Brian Osman9b8b4552019-09-30 13:23:14 -04001354}; // class Interpreter
Brian Osman08a84962019-06-14 10:17:16 -04001355
Brian Osman489cf882019-07-09 10:48:28 -04001356#endif // SK_ENABLE_SKSL_INTERPRETER
1357
Mike Reed634c9412019-07-18 13:20:04 -04001358#undef spf
1359
Brian Osman08a84962019-06-14 10:17:16 -04001360void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001361#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001362 const uint8_t* ip = fCode.data();
1363 while (ip < fCode.data() + fCode.size()) {
1364 printf("%d: ", (int)(ip - fCode.data()));
Brian Osman9b8b4552019-09-30 13:23:14 -04001365 ip = Interpreter::DisassembleInstruction(ip);
Brian Osman08a84962019-06-14 10:17:16 -04001366 printf("\n");
1367 }
Brian Osman489cf882019-07-09 10:48:28 -04001368#endif
Brian Osman08a84962019-06-14 10:17:16 -04001369}
1370
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001371#define VECTOR_PREPROCESS(base) \
1372 case ByteCodeInstruction::base ## 4: \
1373 case ByteCodeInstruction::base ## 3: \
1374 case ByteCodeInstruction::base ## 2: \
1375 case ByteCodeInstruction::base: READ8(); break;
1376
1377#define VECTOR_PREPROCESS_NO_COUNT(base) \
1378 case ByteCodeInstruction::base ## 4: \
1379 case ByteCodeInstruction::base ## 3: \
1380 case ByteCodeInstruction::base ## 2: \
1381 case ByteCodeInstruction::base: break;
1382
1383#define VECTOR_MATRIX_PREPROCESS(base) \
1384 VECTOR_PREPROCESS(base) \
1385 case ByteCodeInstruction::base ## N: READ8(); break;
1386
1387#define VECTOR_MATRIX_PREPROCESS_NO_COUNT(base) \
1388 VECTOR_PREPROCESS_NO_COUNT(base) \
1389 case ByteCodeInstruction::base ## N: READ8(); break;
1390
1391void ByteCodeFunction::preprocess(const void* labels[]) {
1392#if defined(SK_ENABLE_SKSL_INTERPRETER)
1393#ifdef TRACE
1394 this->disassemble();
1395#endif
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001396 uint8_t* ip = fCode.data();
1397 while (ip < fCode.data() + fCode.size()) {
1398 ByteCodeInstruction inst = (ByteCodeInstruction) (intptr_t) READ_INST();
1399 const void* label = labels[(int) inst];
1400 memcpy(ip - sizeof(instruction), &label, sizeof(label));
1401 switch (inst) {
1402 VECTOR_MATRIX_PREPROCESS(kAddF)
1403 VECTOR_PREPROCESS(kAddI)
1404 case ByteCodeInstruction::kAndB: break;
1405 case ByteCodeInstruction::kBranch: READ16(); break;
1406 case ByteCodeInstruction::kCall: READ8(); break;
1407 case ByteCodeInstruction::kCallExternal: {
1408 READ8();
1409 READ8();
1410 READ8();
1411 break;
1412 }
1413 case ByteCodeInstruction::kClampIndex: READ8(); break;
1414 VECTOR_PREPROCESS(kCompareIEQ)
1415 VECTOR_PREPROCESS(kCompareINEQ)
1416 VECTOR_MATRIX_PREPROCESS(kCompareFEQ)
1417 VECTOR_MATRIX_PREPROCESS(kCompareFNEQ)
1418 VECTOR_PREPROCESS(kCompareFGT)
1419 VECTOR_PREPROCESS(kCompareFGTEQ)
1420 VECTOR_PREPROCESS(kCompareFLT)
1421 VECTOR_PREPROCESS(kCompareFLTEQ)
1422 VECTOR_PREPROCESS(kCompareSGT)
1423 VECTOR_PREPROCESS(kCompareSGTEQ)
1424 VECTOR_PREPROCESS(kCompareSLT)
1425 VECTOR_PREPROCESS(kCompareSLTEQ)
1426 VECTOR_PREPROCESS(kCompareUGT)
1427 VECTOR_PREPROCESS(kCompareUGTEQ)
1428 VECTOR_PREPROCESS(kCompareULT)
1429 VECTOR_PREPROCESS(kCompareULTEQ)
1430 VECTOR_PREPROCESS_NO_COUNT(kConvertFtoI)
1431 VECTOR_PREPROCESS_NO_COUNT(kConvertStoF)
1432 VECTOR_PREPROCESS_NO_COUNT(kConvertUtoF)
1433 VECTOR_PREPROCESS(kCos)
1434 VECTOR_MATRIX_PREPROCESS(kDivideF)
1435 VECTOR_PREPROCESS(kDivideS)
1436 VECTOR_PREPROCESS(kDivideU)
1437 VECTOR_MATRIX_PREPROCESS(kDup)
1438
1439 case ByteCodeInstruction::kInverse2x2:
1440 case ByteCodeInstruction::kInverse3x3:
1441 case ByteCodeInstruction::kInverse4x4: break;
1442
1443 case ByteCodeInstruction::kLoad:
1444 case ByteCodeInstruction::kLoad2:
1445 case ByteCodeInstruction::kLoad3:
1446 case ByteCodeInstruction::kLoad4:
1447 case ByteCodeInstruction::kLoadGlobal:
1448 case ByteCodeInstruction::kLoadGlobal2:
1449 case ByteCodeInstruction::kLoadGlobal3:
1450 case ByteCodeInstruction::kLoadGlobal4: READ16(); break;
1451
1452 case ByteCodeInstruction::kLoadSwizzle:
1453 case ByteCodeInstruction::kLoadSwizzleGlobal: {
1454 READ8();
1455 int count = READ8();
1456 ip += count;
1457 break;
1458 }
1459
1460 case ByteCodeInstruction::kLoadExtended:
1461 case ByteCodeInstruction::kLoadExtendedGlobal:
1462 READ8();
1463 break;
1464
1465 case ByteCodeInstruction::kMatrixToMatrix: {
1466 READ8();
1467 READ8();
1468 READ8();
1469 READ8();
1470 break;
1471 }
1472 case ByteCodeInstruction::kMatrixMultiply: {
1473 READ8();
1474 READ8();
1475 READ8();
1476 break;
1477 }
1478 VECTOR_MATRIX_PREPROCESS(kMultiplyF)
1479 VECTOR_PREPROCESS(kMultiplyI)
1480 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kNegateF)
1481 VECTOR_PREPROCESS_NO_COUNT(kNegateI)
1482 case ByteCodeInstruction::kNotB: break;
1483 case ByteCodeInstruction::kOrB: break;
1484 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kPop)
1485 case ByteCodeInstruction::kPushImmediate: READ32(); break;
1486
1487 case ByteCodeInstruction::kReadExternal:
1488 case ByteCodeInstruction::kReadExternal2:
1489 case ByteCodeInstruction::kReadExternal3:
1490 case ByteCodeInstruction::kReadExternal4: READ16(); break;
1491
1492 VECTOR_PREPROCESS(kRemainderF)
1493 VECTOR_PREPROCESS(kRemainderS)
1494 VECTOR_PREPROCESS(kRemainderU)
1495 case ByteCodeInstruction::kReserve: READ8(); break;
1496 case ByteCodeInstruction::kReturn: READ8(); break;
1497 case ByteCodeInstruction::kScalarToMatrix: READ8(); READ8(); break;
Brian Osman4c2146f2019-09-24 09:39:38 -04001498 case ByteCodeInstruction::kShiftLeft: READ8(); break;
1499 case ByteCodeInstruction::kShiftRightS: READ8(); break;
1500 case ByteCodeInstruction::kShiftRightU: READ8(); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001501 VECTOR_PREPROCESS(kSin)
1502 VECTOR_PREPROCESS_NO_COUNT(kSqrt)
1503
1504 case ByteCodeInstruction::kStore:
1505 case ByteCodeInstruction::kStore2:
1506 case ByteCodeInstruction::kStore3:
1507 case ByteCodeInstruction::kStore4:
1508 case ByteCodeInstruction::kStoreGlobal:
1509 case ByteCodeInstruction::kStoreGlobal2:
1510 case ByteCodeInstruction::kStoreGlobal3:
1511 case ByteCodeInstruction::kStoreGlobal4: READ8(); break;
1512
1513 case ByteCodeInstruction::kStoreSwizzle:
1514 case ByteCodeInstruction::kStoreSwizzleGlobal: {
1515 READ8();
1516 int count = READ8();
1517 ip += count;
1518 break;
1519 }
1520
1521 case ByteCodeInstruction::kStoreSwizzleIndirect:
1522 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
1523 int count = READ8();
1524 ip += count;
1525 break;
1526 }
1527
1528 case ByteCodeInstruction::kStoreExtended: READ8(); break;
1529 case ByteCodeInstruction::kStoreExtendedGlobal: READ8(); break;
1530
1531 VECTOR_MATRIX_PREPROCESS(kSubtractF)
1532 VECTOR_PREPROCESS(kSubtractI)
1533
1534 case ByteCodeInstruction::kSwizzle: {
1535 READ8();
1536 int count = READ8();
1537 ip += count;
1538 break;
1539 }
1540 VECTOR_PREPROCESS(kTan)
1541 case ByteCodeInstruction::kWriteExternal:
1542 case ByteCodeInstruction::kWriteExternal2:
1543 case ByteCodeInstruction::kWriteExternal3:
1544 case ByteCodeInstruction::kWriteExternal4: READ16(); break;
1545
1546 case ByteCodeInstruction::kXorB: break;
1547 case ByteCodeInstruction::kMaskPush: break;
1548 case ByteCodeInstruction::kMaskPop: break;
1549 case ByteCodeInstruction::kMaskNegate: break;
1550 case ByteCodeInstruction::kMaskBlend: READ8(); break;
1551 case ByteCodeInstruction::kBranchIfAllFalse: READ16(); break;
1552 case ByteCodeInstruction::kLoopBegin: break;
1553 case ByteCodeInstruction::kLoopNext: break;
1554 case ByteCodeInstruction::kLoopMask: break;
1555 case ByteCodeInstruction::kLoopEnd: break;
1556 case ByteCodeInstruction::kLoopContinue: break;
1557 case ByteCodeInstruction::kLoopBreak: break;
1558 default:
1559 ip -= 2;
1560 printf("unknown(%d)\n", READ16());
1561 SkASSERT(false);
1562 }
1563 }
1564#endif
1565}
1566
Brian Osmanb23d66e2019-09-27 10:25:57 -04001567bool ByteCode::run(const ByteCodeFunction* f,
1568 float* args, int argCount,
1569 float* outReturn, int returnCount,
Brian Osman08a84962019-06-14 10:17:16 -04001570 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001571#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman4b202a32019-06-21 09:50:29 -04001572 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001573 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1574 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001575 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001576 }
Brian Osmanef787f72019-06-13 13:07:12 -04001577
Brian Osmanb23d66e2019-09-27 10:25:57 -04001578 if (argCount != f->fParameterCount ||
1579 returnCount != f->fReturnCount ||
Brian Osman9b8b4552019-09-30 13:23:14 -04001580 uniformCount != (int)fUniformSlots.size()) {
Brian Osman869a3e82019-07-18 17:00:34 -04001581 return false;
1582 }
1583
Brian Osman08a84962019-06-14 10:17:16 -04001584 Interpreter::VValue globals[32];
Brian Osman869a3e82019-07-18 17:00:34 -04001585 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1586 return false;
1587 }
Brian Osman9b8b4552019-09-30 13:23:14 -04001588 for (uint8_t slot : fUniformSlots) {
Brian Osman08a84962019-06-14 10:17:16 -04001589 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001590 }
1591
Brian Osmanb23d66e2019-09-27 10:25:57 -04001592 // Transpose args into stack
1593 {
1594 float* src = args;
1595 float* dst = (float*)stack;
1596 for (int i = 0; i < argCount; ++i) {
1597 *dst = *src++;
Brian Osman9b8b4552019-09-30 13:23:14 -04001598 dst += VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001599 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001600 }
Brian Osmanb23d66e2019-09-27 10:25:57 -04001601
1602 bool stripedOutput = false;
1603 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman9b8b4552019-09-30 13:23:14 -04001604 if (!Interpreter::InnerRun(this, f, stack, outArray, globals, stripedOutput, 1, 0)) {
Brian Osmanb23d66e2019-09-27 10:25:57 -04001605 return false;
1606 }
1607
1608 // Transpose out parameters back
1609 {
1610 float* dst = args;
1611 float* src = (float*)stack;
1612 for (const auto& p : f->fParameters) {
1613 if (p.fIsOutParameter) {
1614 for (int i = p.fSlotCount; i > 0; --i) {
1615 *dst++ = *src;
Brian Osman9b8b4552019-09-30 13:23:14 -04001616 src += VecWidth;
Brian Osmanb23d66e2019-09-27 10:25:57 -04001617 }
1618 } else {
1619 dst += p.fSlotCount;
Brian Osman9b8b4552019-09-30 13:23:14 -04001620 src += p.fSlotCount * VecWidth;
Brian Osmanb23d66e2019-09-27 10:25:57 -04001621 }
1622 }
1623 }
1624
Brian Osman869a3e82019-07-18 17:00:34 -04001625 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001626#else
1627 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001628 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001629#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001630}
1631
Brian Osmanb23d66e2019-09-27 10:25:57 -04001632bool ByteCode::runStriped(const ByteCodeFunction* f, int N,
1633 float* args[], int argCount,
1634 float* outReturn[], int returnCount,
1635 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001636#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001637 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001638 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1639 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001640 return false;
1641 }
1642
Brian Osmanb23d66e2019-09-27 10:25:57 -04001643 if (argCount != f->fParameterCount ||
1644 returnCount != f->fReturnCount ||
Brian Osman9b8b4552019-09-30 13:23:14 -04001645 uniformCount != (int)fUniformSlots.size()) {
Brian Osman869a3e82019-07-18 17:00:34 -04001646 return false;
1647 }
1648
1649 Interpreter::VValue globals[32];
1650 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1651 return false;
1652 }
Brian Osman9b8b4552019-09-30 13:23:14 -04001653 for (uint8_t slot : fUniformSlots) {
Brian Osman869a3e82019-07-18 17:00:34 -04001654 globals[slot].fFloat = *uniforms++;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001655 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001656
Mike Reed3fd3cc92019-06-20 12:40:30 -04001657 // innerRun just takes outArgs, so clear it if the count is zero
Brian Osmanb23d66e2019-09-27 10:25:57 -04001658 if (returnCount == 0) {
1659 outReturn = nullptr;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001660 }
1661
Brian Osman1a79f0b2019-06-24 16:32:14 -04001662 int baseIndex = 0;
1663
Brian Osman2b1a5442019-06-19 11:40:33 -04001664 while (N) {
Brian Osman9b8b4552019-09-30 13:23:14 -04001665 int w = std::min(N, VecWidth);
Brian Osman2b1a5442019-06-19 11:40:33 -04001666
1667 // Copy args into stack
Brian Osmanb23d66e2019-09-27 10:25:57 -04001668 for (int i = 0; i < argCount; ++i) {
Brian Osman2b1a5442019-06-19 11:40:33 -04001669 memcpy(stack + i, args[i], w * sizeof(float));
1670 }
1671
Mike Reed3fd3cc92019-06-20 12:40:30 -04001672 bool stripedOutput = true;
Brian Osman9b8b4552019-09-30 13:23:14 -04001673 if (!Interpreter::InnerRun(this, f, stack, outReturn, globals, stripedOutput, w,
1674 baseIndex)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001675 return false;
1676 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001677
1678 // Copy out parameters back
1679 int slot = 0;
1680 for (const auto& p : f->fParameters) {
1681 if (p.fIsOutParameter) {
1682 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1683 memcpy(args[i], stack + i, w * sizeof(float));
1684 }
1685 }
1686 slot += p.fSlotCount;
1687 }
1688
1689 // Step each argument pointer ahead
Brian Osmanb23d66e2019-09-27 10:25:57 -04001690 for (int i = 0; i < argCount; ++i) {
Brian Osman2b1a5442019-06-19 11:40:33 -04001691 args[i] += w;
1692 }
1693 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001694 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001695 }
Brian Osman869a3e82019-07-18 17:00:34 -04001696
1697 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001698#else
1699 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001700 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001701#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001702}
1703
Brian Osman80164412019-06-07 13:00:23 -04001704} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001705
1706#endif