blob: b03e2ee328fb22d310b8471300226be9397540e3 [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 Osman1c110a02019-10-01 14:53:32 -0400107 case ByteCodeInstruction::kLoadUniform: printf("loaduniform %d", READ16() >> 8); break;
108 case ByteCodeInstruction::kLoadUniform2: printf("loaduniform2 %d", READ16() >> 8); break;
109 case ByteCodeInstruction::kLoadUniform3: printf("loaduniform3 %d", READ16() >> 8); break;
110 case ByteCodeInstruction::kLoadUniform4: printf("loaduniform4 %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 }
Brian Osman1c110a02019-10-01 14:53:32 -0400129 case ByteCodeInstruction::kLoadSwizzleUniform: {
130 int target = READ8();
131 int count = READ8();
132 printf("loadswizzleuniform %d %d", target, count);
133 for (int i = 0; i < count; ++i) {
134 printf(", %d", READ8());
135 }
136 break;
137 }
Brian Osman3e833e12019-05-23 13:23:24 -0700138 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
139 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
140 break;
Brian Osman1c110a02019-10-01 14:53:32 -0400141 case ByteCodeInstruction::kLoadExtendedUniform: printf("loadextendeduniform %d", READ8());
142 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400143 case ByteCodeInstruction::kMatrixToMatrix: {
144 int srcCols = READ8();
145 int srcRows = READ8();
146 int dstCols = READ8();
147 int dstRows = READ8();
148 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
149 break;
150 }
Brian Osman909231c2019-05-29 15:34:36 -0400151 case ByteCodeInstruction::kMatrixMultiply: {
152 int lCols = READ8();
153 int lRows = READ8();
154 int rCols = READ8();
155 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
156 break;
157 }
Brian Osman1e855b22019-05-29 15:21:52 -0400158 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700159 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400160 VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(kNegateF, "negatef")
161 VECTOR_DISASSEMBLE_NO_COUNT(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400162 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400163 case ByteCodeInstruction::kOrB: printf("orb"); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400164 VECTOR_MATRIX_DISASSEMBLE_NO_COUNT(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700165 case ByteCodeInstruction::kPushImmediate: {
166 uint32_t v = READ32();
167 union { uint32_t u; float f; } pun = { v };
168 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
169 break;
170 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400171 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ16() >> 8); break;
172 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ16() >> 8); break;
173 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ16() >> 8); break;
174 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ16() >> 8); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700175 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
176 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
177 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400178 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700179 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400180 case ByteCodeInstruction::kScalarToMatrix: {
181 int cols = READ8();
182 int rows = READ8();
183 printf("scalartomatrix %dx%d", cols, rows);
184 break;
185 }
Brian Osman4c2146f2019-09-24 09:39:38 -0400186 case ByteCodeInstruction::kShiftLeft: printf("shl %d", READ8()); break;
187 case ByteCodeInstruction::kShiftRightS: printf("shrs %d", READ8()); break;
188 case ByteCodeInstruction::kShiftRightU: printf("shru %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700189 VECTOR_DISASSEMBLE(kSin, "sin")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400190 VECTOR_DISASSEMBLE_NO_COUNT(kSqrt, "sqrt")
Brian Osman3e833e12019-05-23 13:23:24 -0700191 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
192 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
193 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
194 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
195 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
196 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
197 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
198 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
199 case ByteCodeInstruction::kStoreSwizzle: {
200 int target = READ8();
201 int count = READ8();
202 printf("storeswizzle %d %d", target, count);
203 for (int i = 0; i < count; ++i) {
204 printf(", %d", READ8());
205 }
206 break;
207 }
208 case ByteCodeInstruction::kStoreSwizzleGlobal: {
209 int target = READ8();
210 int count = READ8();
211 printf("storeswizzleglobal %d %d", target, count);
212 for (int i = 0; i < count; ++i) {
213 printf(", %d", READ8());
214 }
215 break;
216 }
217 case ByteCodeInstruction::kStoreSwizzleIndirect: {
218 int count = READ8();
219 printf("storeswizzleindirect %d", count);
220 for (int i = 0; i < count; ++i) {
221 printf(", %d", READ8());
222 }
223 break;
224 }
225 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
226 int count = READ8();
227 printf("storeswizzleindirectglobal %d", count);
228 for (int i = 0; i < count; ++i) {
229 printf(", %d", READ8());
230 }
231 break;
232 }
233 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
234 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
235 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400236 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700237 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
238 case ByteCodeInstruction::kSwizzle: {
239 printf("swizzle %d, ", READ8());
240 int count = READ8();
241 printf("%d", count);
242 for (int i = 0; i < count; ++i) {
243 printf(", %d", READ8());
244 }
245 break;
246 }
247 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400248 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ16() >> 8); break;
249 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ16() >> 8); break;
250 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ16() >> 8); break;
251 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ16() >> 8); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400252 case ByteCodeInstruction::kXorB: printf("xorb"); break;
253 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
254 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
255 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
256 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
257 case ByteCodeInstruction::kBranchIfAllFalse:
258 printf("branchifallfalse %d", READ16());
259 break;
260 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
261 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
262 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
263 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
264 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
265 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400266 default:
267 ip -= sizeof(instruction);
268 printf("unknown(%d)\n", (int) (intptr_t) READ_INST());
269 SkASSERT(false);
Brian Osman3e833e12019-05-23 13:23:24 -0700270 }
271 return ip;
272}
273
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400274#ifdef SKSLC_THREADED_CODE
275 #define LABEL(name) name:
276 #ifdef TRACE
277 #define NEXT() goto next
278 #else
279 #define NEXT() goto *READ_INST()
280 #endif
281#else
282 #define LABEL(name) case ByteCodeInstruction::name:
283 #define NEXT() continue
284#endif
285
286#define VECTOR_BINARY_OP(base, field, op) \
287 LABEL(base ## 4) \
288 sp[-4] = sp[-4].field op sp[0].field; \
289 POP(); \
290 /* fall through */ \
291 LABEL(base ## 3) { \
292 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
293 POP(); \
294 } /* fall through */ \
295 LABEL(base ## 2) { \
296 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
297 POP(); \
298 } /* fall through */ \
299 LABEL(base) { \
300 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
301 POP(); \
302 ++ip; \
303 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500304 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400305
Ethan Nicholas6f624122019-09-24 13:07:06 -0400306// A naive implementation of / or % using skvx operations will likely crash with a divide by zero
307// in inactive vector lanesm, so we need to be sure to avoid masked-off lanes.
308#define VECTOR_BINARY_MASKED_OP(base, field, op) \
309 LABEL(base ## 4) \
310 for (int i = 0; i < VecWidth; ++i) { \
311 if (mask()[i]) { \
312 sp[-4].field[i] op ## = sp[0].field[i]; \
313 } \
314 } \
315 POP(); \
316 /* fall through */ \
317 LABEL(base ## 3) { \
318 for (int i = 0; i < VecWidth; ++i) { \
319 if (mask()[i]) { \
320 sp[-ip[0]].field[i] op ## = sp[0].field[i]; \
321 } \
322 } \
323 POP(); \
324 } /* fall through */ \
325 LABEL(base ## 2) { \
326 for (int i = 0; i < VecWidth; ++i) { \
327 if (mask()[i]) { \
328 sp[-ip[0]].field[i] op ## = sp[0].field[i]; \
329 } \
330 } \
331 POP(); \
332 } /* fall through */ \
333 LABEL(base) { \
334 for (int i = 0; i < VecWidth; ++i) { \
335 if (mask()[i]) { \
336 sp[-ip[0]].field[i] op ## = sp[0].field[i]; \
337 } \
338 } \
339 POP(); \
340 ++ip; \
341 NEXT(); \
342 }
343
344
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400345#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
346 VECTOR_BINARY_OP(base, field, op) \
347 LABEL(base ## N) { \
348 int count = READ8(); \
349 for (int i = count; i > 0; --i) { \
350 sp[-count] = sp[-count].field op sp[0].field; \
351 POP(); \
352 } \
353 NEXT(); \
Brian Osman1e855b22019-05-29 15:21:52 -0400354 }
355
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400356#define VECTOR_BINARY_FN(base, field, fn) \
357 LABEL(base ## 4) \
358 sp[-4] = fn(sp[-4].field, sp[0].field); \
359 POP(); \
360 /* fall through */ \
361 LABEL(base ## 3) { \
362 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
363 POP(); \
364 } /* fall through */ \
365 LABEL(base ## 2) { \
366 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
367 POP(); \
368 } /* fall through */ \
369 LABEL(base) { \
370 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
371 POP(); \
372 ++ip; \
373 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500374 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400375
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400376#define VECTOR_UNARY_FN(base, fn, field) \
377 LABEL(base ## 4) sp[-3] = fn(sp[-3].field); \
378 LABEL(base ## 3) sp[-2] = fn(sp[-2].field); \
379 LABEL(base ## 2) sp[-1] = fn(sp[-1].field); \
380 LABEL(base) sp[ 0] = fn(sp[ 0].field); \
381 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400382
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400383#define VECTOR_UNARY_FN_VEC(base, fn) \
384 LABEL(base ## 4) \
385 LABEL(base ## 3) \
386 LABEL(base ## 2) \
387 LABEL(base) { \
388 int count = READ8(); \
389 float* v = (float*)sp - count + 1; \
390 for (int i = VecWidth * count; i > 0; --i, ++v) { \
391 *v = fn(*v); \
392 } \
393 NEXT(); \
Brian Osman569f12f2019-06-13 11:23:57 -0400394 }
395
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400396#define VECTOR_LABELS(base) \
397 &&base ## 4, \
398 &&base ## 3, \
399 &&base ## 2, \
400 &&base
401
402#define VECTOR_MATRIX_LABELS(base) \
403 VECTOR_LABELS(base), \
404 &&base ## N
405
406// If you trip this assert, it means that the order of the opcodes listed in ByteCodeInstruction
407// does not match the order of the opcodes listed in the 'labels' array in innerRun().
408#define CHECK_LABEL(name) \
409 SkASSERT(labels[(int) ByteCodeInstruction::name] == &&name)
410
411#define CHECK_VECTOR_LABELS(name) \
412 CHECK_LABEL(name ## 4); \
413 CHECK_LABEL(name ## 3); \
414 CHECK_LABEL(name ## 2); \
415 CHECK_LABEL(name)
416
417#define CHECK_VECTOR_MATRIX_LABELS(name) \
418 CHECK_VECTOR_LABELS(name); \
419 CHECK_LABEL(name ## N)
420
Brian Osman569f12f2019-06-13 11:23:57 -0400421union VValue {
422 VValue() {}
Brian Osman9b8b4552019-09-30 13:23:14 -0400423 VValue(F32 f) : fFloat(f) {}
424 VValue(I32 s) : fSigned(s) {}
425 VValue(U32 u) : fUnsigned(u) {}
Brian Osman569f12f2019-06-13 11:23:57 -0400426
427 F32 fFloat;
428 I32 fSigned;
429 U32 fUnsigned;
430};
431
Brian Osman226668a2019-05-14 16:47:30 -0400432struct StackFrame {
433 const uint8_t* fCode;
434 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400435 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400436 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400437};
438
Brian Osman9b8b4552019-09-30 13:23:14 -0400439static F32 VecMod(F32 a, F32 b) {
Brian Osman569f12f2019-06-13 11:23:57 -0400440 return a - skvx::trunc(a / b) * b;
441}
Mike Kleine7007382019-05-21 08:36:32 -0500442
Mike Reed634c9412019-07-18 13:20:04 -0400443#define spf(index) sp[index].fFloat
444
Brian Osman9b8b4552019-09-30 13:23:14 -0400445static void CallExternal(const ByteCode* byteCode, const uint8_t*& ip, VValue*& sp,
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400446 int baseIndex, I32 mask) {
447 int argumentCount = READ8();
448 int returnCount = READ8();
449 int target = READ8();
450 ExternalValue* v = byteCode->fExternalValues[target];
451 sp -= argumentCount - 1;
452
453 float tmpArgs[4];
454 float tmpReturn[4];
455 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
456 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
457
458 for (int i = 0; i < VecWidth; ++i) {
459 if (mask[i]) {
460 for (int j = 0; j < argumentCount; ++j) {
461 tmpArgs[j] = sp[j].fFloat[i];
462 }
463 v->call(baseIndex + i, tmpArgs, tmpReturn);
464 for (int j = 0; j < returnCount; ++j) {
465 sp[j].fFloat[i] = tmpReturn[j];
466 }
467 }
468 }
469 sp += returnCount - 1;
470}
471
Brian Osman9b8b4552019-09-30 13:23:14 -0400472static void Inverse2x2(VValue* sp) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400473 F32 a = sp[-3].fFloat,
474 b = sp[-2].fFloat,
475 c = sp[-1].fFloat,
476 d = sp[ 0].fFloat;
477 F32 idet = F32(1) / (a*d - b*c);
478 sp[-3].fFloat = d * idet;
479 sp[-2].fFloat = -b * idet;
480 sp[-1].fFloat = -c * idet;
481 sp[ 0].fFloat = a * idet;
482}
483
Brian Osman9b8b4552019-09-30 13:23:14 -0400484static void Inverse3x3(VValue* sp) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400485 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
486 a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
487 a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
488 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
489 a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
490 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
491 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
492 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
493 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
494 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
495 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
496 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
497 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
498 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
499}
500
Brian Osman9b8b4552019-09-30 13:23:14 -0400501static void Inverse4x4(VValue* sp) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400502 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
503 a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
504 a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
505 a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf( 0);
506
507 F32 b00 = a00 * a11 - a01 * a10,
508 b01 = a00 * a12 - a02 * a10,
509 b02 = a00 * a13 - a03 * a10,
510 b03 = a01 * a12 - a02 * a11,
511 b04 = a01 * a13 - a03 * a11,
512 b05 = a02 * a13 - a03 * a12,
513 b06 = a20 * a31 - a21 * a30,
514 b07 = a20 * a32 - a22 * a30,
515 b08 = a20 * a33 - a23 * a30,
516 b09 = a21 * a32 - a22 * a31,
517 b10 = a21 * a33 - a23 * a31,
518 b11 = a22 * a33 - a23 * a32;
519
520 F32 idet = F32(1) /
521 (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
522
523 b00 *= idet;
524 b01 *= idet;
525 b02 *= idet;
526 b03 *= idet;
527 b04 *= idet;
528 b05 *= idet;
529 b06 *= idet;
530 b07 *= idet;
531 b08 *= idet;
532 b09 *= idet;
533 b10 *= idet;
534 b11 *= idet;
535
536 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
537 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
538 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
539 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
540 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
541 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
542 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
543 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
544 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
545 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
546 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
547 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
548 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
549 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
550 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
551 spf( 0) = a20 * b03 - a21 * b01 + a22 * b00;
552}
553
Brian Osman9b8b4552019-09-30 13:23:14 -0400554static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1c110a02019-10-01 14:53:32 -0400555 float* outReturn[], VValue globals[], const float uniforms[],
556 bool stripedOutput, int N, int baseIndex) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400557#ifdef SKSLC_THREADED_CODE
558 static const void* labels[] = {
559 // If you aren't familiar with it, the &&label syntax is the GCC / Clang "labels as values"
560 // extension. If you add anything to this array, be sure to add the corresponding
561 // CHECK_LABEL() or CHECK_*_LABELS() assert below.
562 VECTOR_MATRIX_LABELS(kAddF),
563 VECTOR_LABELS(kAddI),
564 &&kAndB,
565 &&kBranch,
566 &&kCall,
567 &&kCallExternal,
568 &&kClampIndex,
569 VECTOR_LABELS(kCompareIEQ),
570 VECTOR_LABELS(kCompareINEQ),
571 VECTOR_MATRIX_LABELS(kCompareFEQ),
572 VECTOR_MATRIX_LABELS(kCompareFNEQ),
573 VECTOR_LABELS(kCompareFGT),
574 VECTOR_LABELS(kCompareFGTEQ),
575 VECTOR_LABELS(kCompareFLT),
576 VECTOR_LABELS(kCompareFLTEQ),
577 VECTOR_LABELS(kCompareSGT),
578 VECTOR_LABELS(kCompareSGTEQ),
579 VECTOR_LABELS(kCompareSLT),
580 VECTOR_LABELS(kCompareSLTEQ),
581 VECTOR_LABELS(kCompareUGT),
582 VECTOR_LABELS(kCompareUGTEQ),
583 VECTOR_LABELS(kCompareULT),
584 VECTOR_LABELS(kCompareULTEQ),
585 VECTOR_LABELS(kConvertFtoI),
586 VECTOR_LABELS(kConvertStoF),
587 VECTOR_LABELS(kConvertUtoF),
588 VECTOR_LABELS(kCos),
589 VECTOR_MATRIX_LABELS(kDivideF),
590 VECTOR_LABELS(kDivideS),
591 VECTOR_LABELS(kDivideU),
592 VECTOR_MATRIX_LABELS(kDup),
593 &&kInverse2x2,
594 &&kInverse3x3,
595 &&kInverse4x4,
596 VECTOR_LABELS(kLoad),
597 VECTOR_LABELS(kLoadGlobal),
Brian Osman1c110a02019-10-01 14:53:32 -0400598 VECTOR_LABELS(kLoadUniform),
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400599 &&kLoadSwizzle,
600 &&kLoadSwizzleGlobal,
Brian Osman1c110a02019-10-01 14:53:32 -0400601 &&kLoadSwizzleUniform,
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400602 &&kLoadExtended,
603 &&kLoadExtendedGlobal,
Brian Osman1c110a02019-10-01 14:53:32 -0400604 &&kLoadExtendedUniform,
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400605 &&kMatrixToMatrix,
606 &&kMatrixMultiply,
607 VECTOR_MATRIX_LABELS(kNegateF),
608 VECTOR_LABELS(kNegateI),
609 VECTOR_MATRIX_LABELS(kMultiplyF),
610 VECTOR_LABELS(kMultiplyI),
611 &&kNotB,
612 &&kOrB,
613 VECTOR_MATRIX_LABELS(kPop),
614 &&kPushImmediate,
615 VECTOR_LABELS(kReadExternal),
616 VECTOR_LABELS(kRemainderF),
617 VECTOR_LABELS(kRemainderS),
618 VECTOR_LABELS(kRemainderU),
619 &&kReserve,
620 &&kReturn,
621 &&kScalarToMatrix,
Brian Osman4c2146f2019-09-24 09:39:38 -0400622 &&kShiftLeft,
623 &&kShiftRightS,
624 &&kShiftRightU,
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400625 VECTOR_LABELS(kSin),
626 VECTOR_LABELS(kSqrt),
627 VECTOR_LABELS(kStore),
628 VECTOR_LABELS(kStoreGlobal),
629 &&kStoreExtended,
630 &&kStoreExtendedGlobal,
631 &&kStoreSwizzle,
632 &&kStoreSwizzleGlobal,
633 &&kStoreSwizzleIndirect,
634 &&kStoreSwizzleIndirectGlobal,
635 &&kSwizzle,
636 VECTOR_MATRIX_LABELS(kSubtractF),
637 VECTOR_LABELS(kSubtractI),
638 VECTOR_LABELS(kTan),
639 VECTOR_LABELS(kWriteExternal),
640 &&kXorB,
641
642 &&kMaskPush,
643 &&kMaskPop,
644 &&kMaskNegate,
645 &&kMaskBlend,
646 &&kBranchIfAllFalse,
647
648 &&kLoopBegin,
649 &&kLoopNext,
650 &&kLoopMask,
651 &&kLoopEnd,
652 &&kLoopBreak,
653 &&kLoopContinue,
654 };
655 // Verify that the order of the labels array matches the order of the ByteCodeInstruction enum.
656 CHECK_VECTOR_MATRIX_LABELS(kAddF);
657 CHECK_VECTOR_LABELS(kAddI);
658 CHECK_LABEL(kAndB);
659 CHECK_LABEL(kBranch);
660 CHECK_LABEL(kCall);
661 CHECK_LABEL(kCallExternal);
662 CHECK_LABEL(kClampIndex);
663 CHECK_VECTOR_LABELS(kCompareIEQ);
664 CHECK_VECTOR_LABELS(kCompareINEQ);
665 CHECK_VECTOR_MATRIX_LABELS(kCompareFEQ);
666 CHECK_VECTOR_MATRIX_LABELS(kCompareFNEQ);
667 CHECK_VECTOR_LABELS(kCompareFGT);
668 CHECK_VECTOR_LABELS(kCompareFGTEQ);
669 CHECK_VECTOR_LABELS(kCompareFLT);
670 CHECK_VECTOR_LABELS(kCompareFLTEQ);
671 CHECK_VECTOR_LABELS(kCompareSGT);
672 CHECK_VECTOR_LABELS(kCompareSGTEQ);
673 CHECK_VECTOR_LABELS(kCompareSLT);
674 CHECK_VECTOR_LABELS(kCompareSLTEQ);
675 CHECK_VECTOR_LABELS(kCompareUGT);
676 CHECK_VECTOR_LABELS(kCompareUGTEQ);
677 CHECK_VECTOR_LABELS(kCompareULT);
678 CHECK_VECTOR_LABELS(kCompareULTEQ);
679 CHECK_VECTOR_LABELS(kConvertFtoI);
680 CHECK_VECTOR_LABELS(kConvertStoF);
681 CHECK_VECTOR_LABELS(kConvertUtoF);
682 CHECK_VECTOR_LABELS(kCos);
683 CHECK_VECTOR_MATRIX_LABELS(kDivideF);
684 CHECK_VECTOR_LABELS(kDivideS);
685 CHECK_VECTOR_LABELS(kDivideU);
686 CHECK_VECTOR_MATRIX_LABELS(kDup);
687 CHECK_LABEL(kInverse2x2);
688 CHECK_LABEL(kInverse3x3);
689 CHECK_LABEL(kInverse4x4);
690 CHECK_VECTOR_LABELS(kLoad);
691 CHECK_VECTOR_LABELS(kLoadGlobal);
Brian Osman1c110a02019-10-01 14:53:32 -0400692 CHECK_VECTOR_LABELS(kLoadUniform);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400693 CHECK_LABEL(kLoadSwizzle);
694 CHECK_LABEL(kLoadSwizzleGlobal);
Brian Osman1c110a02019-10-01 14:53:32 -0400695 CHECK_LABEL(kLoadSwizzleUniform);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400696 CHECK_LABEL(kLoadExtended);
697 CHECK_LABEL(kLoadExtendedGlobal);
Brian Osman1c110a02019-10-01 14:53:32 -0400698 CHECK_LABEL(kLoadExtendedUniform);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400699 CHECK_LABEL(kMatrixToMatrix);
700 CHECK_LABEL(kMatrixMultiply);
701 CHECK_VECTOR_MATRIX_LABELS(kNegateF);
702 CHECK_VECTOR_LABELS(kNegateI);
703 CHECK_VECTOR_MATRIX_LABELS(kMultiplyF);
704 CHECK_VECTOR_LABELS(kMultiplyI);
705 CHECK_LABEL(kNotB);
706 CHECK_LABEL(kOrB);
707 CHECK_VECTOR_MATRIX_LABELS(kPop);
708 CHECK_LABEL(kPushImmediate);
709 CHECK_VECTOR_LABELS(kReadExternal);
710 CHECK_VECTOR_LABELS(kRemainderF);
711 CHECK_VECTOR_LABELS(kRemainderS);
712 CHECK_VECTOR_LABELS(kRemainderU);
713 CHECK_LABEL(kReserve);
714 CHECK_LABEL(kReturn);
715 CHECK_LABEL(kScalarToMatrix);
Brian Osman4c2146f2019-09-24 09:39:38 -0400716 CHECK_LABEL(kShiftLeft);
717 CHECK_LABEL(kShiftRightS);
718 CHECK_LABEL(kShiftRightU);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400719 CHECK_VECTOR_LABELS(kSin);
720 CHECK_VECTOR_LABELS(kSqrt);
721 CHECK_VECTOR_LABELS(kStore);
722 CHECK_VECTOR_LABELS(kStoreGlobal);
723 CHECK_LABEL(kStoreExtended);
724 CHECK_LABEL(kStoreExtendedGlobal);
725 CHECK_LABEL(kStoreSwizzle);
726 CHECK_LABEL(kStoreSwizzleGlobal);
727 CHECK_LABEL(kStoreSwizzleIndirect);
728 CHECK_LABEL(kStoreSwizzleIndirectGlobal);
729 CHECK_LABEL(kSwizzle);
730 CHECK_VECTOR_MATRIX_LABELS(kSubtractF);
731 CHECK_VECTOR_LABELS(kSubtractI);
732 CHECK_VECTOR_LABELS(kTan);
733 CHECK_VECTOR_LABELS(kWriteExternal);
734 CHECK_LABEL(kXorB);
735 CHECK_LABEL(kMaskPush);
736 CHECK_LABEL(kMaskPop);
737 CHECK_LABEL(kMaskNegate);
738 CHECK_LABEL(kMaskBlend);
739 CHECK_LABEL(kBranchIfAllFalse);
740 CHECK_LABEL(kLoopBegin);
741 CHECK_LABEL(kLoopNext);
742 CHECK_LABEL(kLoopMask);
743 CHECK_LABEL(kLoopEnd);
744 CHECK_LABEL(kLoopBreak);
745 CHECK_LABEL(kLoopContinue);
Brian Osman11b877e2019-09-17 10:21:06 -0400746 f->fPreprocessOnce([f] { ((ByteCodeFunction*)f)->preprocess(labels); });
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400747#endif
748
Brian Osman4b202a32019-06-21 09:50:29 -0400749 // Needs to be the first N non-negative integers, at least as large as VecWidth
750 static const Interpreter::I32 gLanes = {
751 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
752 };
753
Brian Osman569f12f2019-06-13 11:23:57 -0400754 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
755
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400756 #define POP() (*(sp--))
757 #define PUSH(v) (sp[1] = v, ++sp)
Mike Kleine7007382019-05-21 08:36:32 -0500758
Brian Osman80164412019-06-07 13:00:23 -0400759 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400760 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400761 std::vector<StackFrame> frames;
762
Brian Osman569f12f2019-06-13 11:23:57 -0400763 I32 condStack[16]; // Independent condition masks
764 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
765 I32 contStack[16]; // Continue flags for loops
766 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400767 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400768 contStack[0] = I32( 0);
769 loopStack[0] = I32(~0);
770 I32* condPtr = condStack;
771 I32* maskPtr = maskStack;
772 I32* contPtr = contStack;
773 I32* loopPtr = loopStack;
774
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400775 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
776 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osman869a3e82019-07-18 17:00:34 -0400777 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400778 }
779
Brian Osman569f12f2019-06-13 11:23:57 -0400780 auto mask = [&]() { return *maskPtr & *loopPtr; };
781
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400782#ifdef SKSLC_THREADED_CODE
783 // If the "labels as values" extension is available, we implement this using threaded code.
784 // Instead of opcodes, the code directly contains the addresses of the labels to jump to. Then
785 // the code for each opcode simply grabs the address of the next opcode and uses a goto to jump
786 // there.
787 NEXT();
788#else
789 // Otherwise, we have to use a switch statement and a loop to execute the right label.
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400790 for (;;) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400791 #ifdef TRACE
792 printf("at %3d ", (int) (ip - code));
793 disassemble_instruction(ip);
794 printf(" (stack: %d)\n", (int) (sp - stack) + 1);
795 #endif
796 switch ((ByteCodeInstruction) READ16()) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400797#endif
Brian Osman569f12f2019-06-13 11:23:57 -0400798
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400799 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
800 VECTOR_BINARY_OP(kAddI, fSigned, +)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400801
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400802 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
803 LABEL(kAndB)
804 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
805 POP();
806 NEXT();
807 LABEL(kNotB)
808 sp[0] = ~sp[0].fSigned;
809 NEXT();
810 LABEL(kOrB)
811 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
812 POP();
813 NEXT();
814 LABEL(kXorB)
815 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
816 POP();
817 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400818
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400819 LABEL(kBranch)
820 ip = code + READ16();
821 NEXT();
822
823 LABEL(kCall) {
824 // Precursor code reserved space for the return value, and pushed all parameters to
825 // the stack. Update our bottom of stack to point at the first parameter, and our
826 // sp to point past those parameters (plus space for locals).
827 int target = READ8();
828 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
829#ifdef SKSLC_THREADED_CODE
Brian Osman11b877e2019-09-17 10:21:06 -0400830 fun->fPreprocessOnce([fun] { ((ByteCodeFunction*)fun)->preprocess(labels); });
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400831#endif
832 if (skvx::any(mask())) {
833 frames.push_back({ code, ip, stack, fun->fParameterCount });
834 ip = code = fun->fCode.data();
835 stack = sp - fun->fParameterCount + 1;
836 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
837 }
838 NEXT();
839 }
840
841 LABEL(kCallExternal) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400842 CallExternal(byteCode, ip, sp, baseIndex, mask());
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400843 NEXT();
844 }
845
846 LABEL(kClampIndex) {
847 int length = READ8();
848 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
849 return false;
850 }
851 NEXT();
852 }
853
854 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
855 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
856 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
857 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
858 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
859 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
860 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
861 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
862 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
863 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
864 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
865 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
866 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
867 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
868 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
869 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
870
871 LABEL(kConvertFtoI4) sp[-3] = skvx::cast<int>(sp[-3].fFloat);
872 LABEL(kConvertFtoI3) sp[-2] = skvx::cast<int>(sp[-2].fFloat);
873 LABEL(kConvertFtoI2) sp[-1] = skvx::cast<int>(sp[-1].fFloat);
874 LABEL(kConvertFtoI) sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
875 NEXT();
876
877 LABEL(kConvertStoF4) sp[-3] = skvx::cast<float>(sp[-3].fSigned);
878 LABEL(kConvertStoF3) sp[-2] = skvx::cast<float>(sp[-2].fSigned);
879 LABEL(kConvertStoF2) sp[-1] = skvx::cast<float>(sp[-1].fSigned);
880 LABEL(kConvertStoF) sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
881 NEXT();
882
883 LABEL(kConvertUtoF4) sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
884 LABEL(kConvertUtoF3) sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
885 LABEL(kConvertUtoF2) sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
886 LABEL(kConvertUtoF) sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
887 NEXT();
888
889 VECTOR_UNARY_FN_VEC(kCos, cosf)
890
Ethan Nicholas6f624122019-09-24 13:07:06 -0400891 VECTOR_BINARY_MASKED_OP(kDivideS, fSigned, /)
892 VECTOR_BINARY_MASKED_OP(kDivideU, fUnsigned, /)
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400893 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
894
895 LABEL(kDup4) PUSH(sp[1 - ip[0]]);
896 LABEL(kDup3) PUSH(sp[1 - ip[0]]);
897 LABEL(kDup2) PUSH(sp[1 - ip[0]]);
898 LABEL(kDup) PUSH(sp[1 - ip[0]]);
899 ++ip;
900 NEXT();
901
902 LABEL(kDupN) {
903 int count = READ8();
904 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
905 sp += count;
906 NEXT();
907 }
908
909 LABEL(kInverse2x2) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400910 Inverse2x2(sp);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400911 NEXT();
912 }
913 LABEL(kInverse3x3) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400914 Inverse3x3(sp);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400915 NEXT();
916 }
917 LABEL(kInverse4x4) {
Brian Osman9b8b4552019-09-30 13:23:14 -0400918 Inverse4x4(sp);
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400919 NEXT();
920 }
921
922 LABEL(kLoad4) sp[4] = stack[ip[1] + 3];
923 LABEL(kLoad3) sp[3] = stack[ip[1] + 2];
924 LABEL(kLoad2) sp[2] = stack[ip[1] + 1];
925 LABEL(kLoad) sp[1] = stack[ip[1] + 0];
926 sp += ip[0];
927 ip += 2;
928 NEXT();
929
930 LABEL(kLoadGlobal4) sp[4] = globals[ip[1] + 3];
931 LABEL(kLoadGlobal3) sp[3] = globals[ip[1] + 2];
932 LABEL(kLoadGlobal2) sp[2] = globals[ip[1] + 1];
933 LABEL(kLoadGlobal) sp[1] = globals[ip[1] + 0];
934 sp += ip[0];
935 ip += 2;
936 NEXT();
937
Brian Osman1c110a02019-10-01 14:53:32 -0400938 LABEL(kLoadUniform4) sp[4].fFloat = uniforms[ip[1] + 3];
939 LABEL(kLoadUniform3) sp[3].fFloat = uniforms[ip[1] + 2];
940 LABEL(kLoadUniform2) sp[2].fFloat = uniforms[ip[1] + 1];
941 LABEL(kLoadUniform) sp[1].fFloat = uniforms[ip[1] + 0];
942 sp += ip[0];
943 ip += 2;
944 NEXT();
945
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400946 LABEL(kLoadExtended) {
947 int count = READ8();
948 I32 src = POP().fSigned;
949 I32 m = mask();
950 for (int i = 0; i < count; ++i) {
951 for (int j = 0; j < VecWidth; ++j) {
952 if (m[j]) {
953 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400954 }
Brian Osman226668a2019-05-14 16:47:30 -0400955 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400956 }
957 sp += count;
958 NEXT();
959 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400960
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400961 LABEL(kLoadExtendedGlobal) {
962 int count = READ8();
963 I32 src = POP().fSigned;
964 I32 m = mask();
965 for (int i = 0; i < count; ++i) {
966 for (int j = 0; j < VecWidth; ++j) {
967 if (m[j]) {
968 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
969 }
970 }
971 }
972 sp += count;
973 NEXT();
974 }
Mike Kleine7007382019-05-21 08:36:32 -0500975
Brian Osman1c110a02019-10-01 14:53:32 -0400976 LABEL(kLoadExtendedUniform) {
977 int count = READ8();
978 I32 src = POP().fSigned;
979 I32 m = mask();
980 for (int i = 0; i < count; ++i) {
981 for (int j = 0; j < VecWidth; ++j) {
982 if (m[j]) {
983 sp[i + 1].fFloat[j] = uniforms[src[j] + i];
984 }
985 }
986 }
987 sp += count;
988 NEXT();
989 }
990
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400991 LABEL(kLoadSwizzle) {
992 int src = READ8();
993 int count = READ8();
994 for (int i = 0; i < count; ++i) {
995 PUSH(stack[src + *(ip + i)]);
996 }
997 ip += count;
998 NEXT();
999 }
Brian Osman569f12f2019-06-13 11:23:57 -04001000
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001001 LABEL(kLoadSwizzleGlobal) {
1002 int src = READ8();
1003 int count = READ8();
1004 for (int i = 0; i < count; ++i) {
1005 PUSH(globals[src + *(ip + i)]);
1006 }
1007 ip += count;
1008 NEXT();
1009 }
1010
Brian Osman1c110a02019-10-01 14:53:32 -04001011 LABEL(kLoadSwizzleUniform) {
1012 int src = READ8();
1013 int count = READ8();
1014 for (int i = 0; i < count; ++i) {
1015 PUSH(F32(uniforms[src + *(ip + i)]));
1016 }
1017 ip += count;
1018 NEXT();
1019 }
1020
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001021 LABEL(kMatrixToMatrix) {
1022 int srcCols = READ8();
1023 int srcRows = READ8();
1024 int dstCols = READ8();
1025 int dstRows = READ8();
1026 SkASSERT(srcCols >= 2 && srcCols <= 4);
1027 SkASSERT(srcRows >= 2 && srcRows <= 4);
1028 SkASSERT(dstCols >= 2 && dstCols <= 4);
1029 SkASSERT(dstRows >= 2 && dstRows <= 4);
1030 F32 tmp[16];
1031 memset(tmp, 0, sizeof(tmp));
1032 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
1033 for (int c = srcCols - 1; c >= 0; --c) {
1034 for (int r = srcRows - 1; r >= 0; --r) {
1035 tmp[c*4 + r] = POP().fFloat;
1036 }
1037 }
1038 for (int c = 0; c < dstCols; ++c) {
1039 for (int r = 0; r < dstRows; ++r) {
1040 PUSH(tmp[c*4 + r]);
1041 }
1042 }
1043 NEXT();
1044 }
1045
1046 LABEL(kMatrixMultiply) {
1047 int lCols = READ8();
1048 int lRows = READ8();
1049 int rCols = READ8();
1050 int rRows = lCols;
1051 F32 tmp[16] = { 0.0f };
1052 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
1053 F32* A = B - (lCols * lRows);
1054 for (int c = 0; c < rCols; ++c) {
1055 for (int r = 0; r < lRows; ++r) {
1056 for (int j = 0; j < lCols; ++j) {
1057 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
1058 }
1059 }
1060 }
1061 sp -= (lCols * lRows) + (rCols * rRows);
1062 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
1063 sp += (rCols * lRows);
1064 NEXT();
1065 }
1066
1067 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
1068 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
1069
1070 LABEL(kNegateF4) sp[-3] = -sp[-3].fFloat;
1071 LABEL(kNegateF3) sp[-2] = -sp[-2].fFloat;
1072 LABEL(kNegateF2) sp[-1] = -sp[-1].fFloat;
1073 LABEL(kNegateF) sp[ 0] = -sp[ 0].fFloat;
1074 NEXT();
1075
1076 LABEL(kNegateFN) {
1077 int count = READ8();
1078 for (int i = count - 1; i >= 0; --i) {
1079 sp[-i] = -sp[-i].fFloat;
1080 }
1081 NEXT();
1082 }
1083
1084 LABEL(kNegateI4) sp[-3] = -sp[-3].fSigned;
1085 LABEL(kNegateI3) sp[-2] = -sp[-2].fSigned;
1086 LABEL(kNegateI2) sp[-1] = -sp[-1].fSigned;
1087 LABEL(kNegateI) sp[ 0] = -sp[ 0].fSigned;
1088 NEXT();
1089
1090 LABEL(kPop4) POP();
1091 LABEL(kPop3) POP();
1092 LABEL(kPop2) POP();
1093 LABEL(kPop) POP();
1094 NEXT();
1095
1096 LABEL(kPopN)
1097 sp -= READ8();
1098 NEXT();
1099
1100 LABEL(kPushImmediate)
1101 PUSH(U32(READ32()));
1102 NEXT();
1103
1104 LABEL(kReadExternal)
1105 LABEL(kReadExternal2)
1106 LABEL(kReadExternal3)
1107 LABEL(kReadExternal4) {
1108 int count = READ8();
1109 int src = READ8();
1110 float tmp[4];
1111 I32 m = mask();
1112 for (int i = 0; i < VecWidth; ++i) {
1113 if (m[i]) {
1114 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
1115 for (int j = 0; j < count; ++j) {
1116 sp[j + 1].fFloat[i] = tmp[j];
1117 }
1118 }
1119 }
1120 sp += count;
1121 NEXT();
1122 }
1123
Brian Osman9b8b4552019-09-30 13:23:14 -04001124 VECTOR_BINARY_FN(kRemainderF, fFloat, VecMod)
Ethan Nicholas6f624122019-09-24 13:07:06 -04001125 VECTOR_BINARY_MASKED_OP(kRemainderS, fSigned, %)
1126 VECTOR_BINARY_MASKED_OP(kRemainderU, fUnsigned, %)
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001127
1128 LABEL(kReserve)
1129 sp += READ8();
1130 NEXT();
1131
1132 LABEL(kReturn) {
1133 int count = READ8();
1134 if (frames.empty()) {
1135 if (outReturn) {
1136 VValue* src = sp - count + 1;
1137 if (stripedOutput) {
1138 for (int i = 0; i < count; ++i) {
1139 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
1140 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -04001141 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001142 } else {
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001143 float* outPtr = outReturn[0];
1144 for (int i = 0; i < count; ++i) {
1145 for (int j = 0; j < N; ++j) {
1146 outPtr[count * j] = src->fFloat[j];
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001147 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001148 ++outPtr;
1149 ++src;
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001150 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001151 }
1152 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001153 return true;
1154 } else {
1155 // When we were called, the caller reserved stack space for their copy of our
1156 // return value, then 'stack' was positioned after that, where our parameters
1157 // were placed. Copy our return values to their reserved area.
1158 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001159
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001160 // Now move the stack pointer to the end of the passed-in parameters. This odd
1161 // calling convention requires the caller to pop the arguments after calling,
1162 // but allows them to store any out-parameters back during that unwinding.
1163 // After that sequence finishes, the return value will be the top of the stack.
1164 const StackFrame& frame(frames.back());
1165 sp = stack + frame.fParameterCount - 1;
1166 stack = frame.fStack;
1167 code = frame.fCode;
1168 ip = frame.fIP;
1169 frames.pop_back();
1170 NEXT();
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001171 }
1172 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001173
1174 LABEL(kScalarToMatrix) {
1175 int cols = READ8();
1176 int rows = READ8();
1177 VValue v = POP();
1178 for (int c = 0; c < cols; ++c) {
1179 for (int r = 0; r < rows; ++r) {
1180 PUSH(c == r ? v : F32(0.0f));
1181 }
1182 }
1183 NEXT();
1184 }
1185
Brian Osman4c2146f2019-09-24 09:39:38 -04001186 LABEL(kShiftLeft)
1187 sp[0] = sp[0].fSigned << READ8();
1188 NEXT();
1189 LABEL(kShiftRightS)
1190 sp[0] = sp[0].fSigned >> READ8();
1191 NEXT();
1192 LABEL(kShiftRightU)
1193 sp[0] = sp[0].fUnsigned >> READ8();
1194 NEXT();
1195
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001196 VECTOR_UNARY_FN_VEC(kSin, sinf)
1197 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
1198
1199 LABEL(kStore4)
1200 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
1201 LABEL(kStore3)
1202 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
1203 LABEL(kStore2)
1204 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
1205 LABEL(kStore)
1206 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
1207 ++ip;
1208 NEXT();
1209
1210 LABEL(kStoreGlobal4)
1211 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
1212 LABEL(kStoreGlobal3)
1213 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
1214 LABEL(kStoreGlobal2)
1215 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
1216 LABEL(kStoreGlobal)
1217 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
1218 ++ip;
1219 NEXT();
1220
1221 LABEL(kStoreExtended) {
1222 int count = READ8();
1223 I32 target = POP().fSigned;
1224 VValue* src = sp - count + 1;
1225 I32 m = mask();
1226 for (int i = 0; i < count; ++i) {
1227 for (int j = 0; j < VecWidth; ++j) {
1228 if (m[j]) {
1229 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
1230 }
1231 }
1232 }
1233 sp -= count;
1234 NEXT();
1235 }
1236 LABEL(kStoreExtendedGlobal) {
1237 int count = READ8();
1238 I32 target = POP().fSigned;
1239 VValue* src = sp - count + 1;
1240 I32 m = mask();
1241 for (int i = 0; i < count; ++i) {
1242 for (int j = 0; j < VecWidth; ++j) {
1243 if (m[j]) {
1244 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
1245 }
1246 }
1247 }
1248 sp -= count;
1249 NEXT();
1250 }
1251
1252 LABEL(kStoreSwizzle) {
1253 int target = READ8();
1254 int count = READ8();
1255 for (int i = count - 1; i >= 0; --i) {
1256 stack[target + *(ip + i)] = skvx::if_then_else(
1257 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
1258 }
1259 ip += count;
1260 NEXT();
1261 }
1262
1263 LABEL(kStoreSwizzleGlobal) {
1264 int target = READ8();
1265 int count = READ8();
1266 for (int i = count - 1; i >= 0; --i) {
1267 globals[target + *(ip + i)] = skvx::if_then_else(
1268 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
1269 }
1270 ip += count;
1271 NEXT();
1272 }
1273
1274 LABEL(kStoreSwizzleIndirect) {
1275 int count = READ8();
1276 I32 target = POP().fSigned;
1277 I32 m = mask();
1278 for (int i = count - 1; i >= 0; --i) {
1279 I32 v = POP().fSigned;
1280 for (int j = 0; j < VecWidth; ++j) {
1281 if (m[j]) {
1282 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
1283 }
1284 }
1285 }
1286 ip += count;
1287 NEXT();
1288 }
1289
1290 LABEL(kStoreSwizzleIndirectGlobal) {
1291 int count = READ8();
1292 I32 target = POP().fSigned;
1293 I32 m = mask();
1294 for (int i = count - 1; i >= 0; --i) {
1295 I32 v = POP().fSigned;
1296 for (int j = 0; j < VecWidth; ++j) {
1297 if (m[j]) {
1298 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
1299 }
1300 }
1301 }
1302 ip += count;
1303 NEXT();
1304 }
1305
1306 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
1307 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
1308
1309 LABEL(kSwizzle) {
1310 VValue tmp[4];
1311 for (int i = READ8() - 1; i >= 0; --i) {
1312 tmp[i] = POP();
1313 }
1314 for (int i = READ8() - 1; i >= 0; --i) {
1315 PUSH(tmp[READ8()]);
1316 }
1317 NEXT();
1318 }
1319
1320 VECTOR_UNARY_FN_VEC(kTan, tanf)
1321
1322 LABEL(kWriteExternal4)
1323 LABEL(kWriteExternal3)
1324 LABEL(kWriteExternal2)
1325 LABEL(kWriteExternal) {
1326 int count = READ8();
1327 int target = READ8();
1328 float tmp[4];
1329 I32 m = mask();
1330 sp -= count;
1331 for (int i = 0; i < VecWidth; ++i) {
1332 if (m[i]) {
1333 for (int j = 0; j < count; ++j) {
1334 tmp[j] = sp[j + 1].fFloat[i];
1335 }
1336 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
1337 }
1338 }
1339 NEXT();
1340 }
1341
1342 LABEL(kMaskPush)
1343 condPtr[1] = POP().fSigned;
1344 maskPtr[1] = maskPtr[0] & condPtr[1];
1345 ++condPtr; ++maskPtr;
1346 NEXT();
1347 LABEL(kMaskPop)
1348 --condPtr; --maskPtr;
1349 NEXT();
1350 LABEL(kMaskNegate)
1351 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
1352 NEXT();
1353 LABEL(kMaskBlend) {
1354 int count = READ8();
1355 I32 m = condPtr[0];
1356 --condPtr; --maskPtr;
1357 for (int i = 0; i < count; ++i) {
1358 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1359 --sp;
1360 }
1361 NEXT();
1362 }
1363 LABEL(kBranchIfAllFalse) {
1364 int target = READ16();
1365 if (!skvx::any(mask())) {
1366 ip = code + target;
1367 }
1368 NEXT();
1369 }
1370
1371 LABEL(kLoopBegin)
1372 contPtr[1] = 0;
1373 loopPtr[1] = loopPtr[0];
1374 ++contPtr; ++loopPtr;
1375 NEXT();
1376 LABEL(kLoopNext)
1377 *loopPtr |= *contPtr;
1378 *contPtr = 0;
1379 NEXT();
1380 LABEL(kLoopMask)
1381 *loopPtr &= POP().fSigned;
1382 NEXT();
1383 LABEL(kLoopEnd)
1384 --contPtr; --loopPtr;
1385 NEXT();
1386 LABEL(kLoopBreak)
1387 *loopPtr &= ~mask();
1388 NEXT();
1389 LABEL(kLoopContinue) {
1390 I32 m = mask();
1391 *contPtr |= m;
1392 *loopPtr &= ~m;
1393 NEXT();
1394 }
1395#ifdef SKSLC_THREADED_CODE
1396 #ifdef TRACE
1397 next:
1398 printf("at %3d (stack: %d) (disable threaded code for disassembly)\n",
1399 (int) (ip - code), (int) (sp - stack) + 1);
1400 goto *READ_INST();
1401 #endif
1402#else
1403 }
1404 }
1405#endif
Brian Osman569f12f2019-06-13 11:23:57 -04001406}
1407
Brian Osman9b8b4552019-09-30 13:23:14 -04001408}; // class Interpreter
Brian Osman08a84962019-06-14 10:17:16 -04001409
Brian Osman489cf882019-07-09 10:48:28 -04001410#endif // SK_ENABLE_SKSL_INTERPRETER
1411
Mike Reed634c9412019-07-18 13:20:04 -04001412#undef spf
1413
Brian Osman08a84962019-06-14 10:17:16 -04001414void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001415#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001416 const uint8_t* ip = fCode.data();
1417 while (ip < fCode.data() + fCode.size()) {
1418 printf("%d: ", (int)(ip - fCode.data()));
Brian Osman9b8b4552019-09-30 13:23:14 -04001419 ip = Interpreter::DisassembleInstruction(ip);
Brian Osman08a84962019-06-14 10:17:16 -04001420 printf("\n");
1421 }
Brian Osman489cf882019-07-09 10:48:28 -04001422#endif
Brian Osman08a84962019-06-14 10:17:16 -04001423}
1424
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001425#define VECTOR_PREPROCESS(base) \
1426 case ByteCodeInstruction::base ## 4: \
1427 case ByteCodeInstruction::base ## 3: \
1428 case ByteCodeInstruction::base ## 2: \
1429 case ByteCodeInstruction::base: READ8(); break;
1430
1431#define VECTOR_PREPROCESS_NO_COUNT(base) \
1432 case ByteCodeInstruction::base ## 4: \
1433 case ByteCodeInstruction::base ## 3: \
1434 case ByteCodeInstruction::base ## 2: \
1435 case ByteCodeInstruction::base: break;
1436
1437#define VECTOR_MATRIX_PREPROCESS(base) \
1438 VECTOR_PREPROCESS(base) \
1439 case ByteCodeInstruction::base ## N: READ8(); break;
1440
1441#define VECTOR_MATRIX_PREPROCESS_NO_COUNT(base) \
1442 VECTOR_PREPROCESS_NO_COUNT(base) \
1443 case ByteCodeInstruction::base ## N: READ8(); break;
1444
1445void ByteCodeFunction::preprocess(const void* labels[]) {
1446#if defined(SK_ENABLE_SKSL_INTERPRETER)
1447#ifdef TRACE
1448 this->disassemble();
1449#endif
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001450 uint8_t* ip = fCode.data();
1451 while (ip < fCode.data() + fCode.size()) {
1452 ByteCodeInstruction inst = (ByteCodeInstruction) (intptr_t) READ_INST();
1453 const void* label = labels[(int) inst];
1454 memcpy(ip - sizeof(instruction), &label, sizeof(label));
1455 switch (inst) {
1456 VECTOR_MATRIX_PREPROCESS(kAddF)
1457 VECTOR_PREPROCESS(kAddI)
1458 case ByteCodeInstruction::kAndB: break;
1459 case ByteCodeInstruction::kBranch: READ16(); break;
1460 case ByteCodeInstruction::kCall: READ8(); break;
1461 case ByteCodeInstruction::kCallExternal: {
1462 READ8();
1463 READ8();
1464 READ8();
1465 break;
1466 }
1467 case ByteCodeInstruction::kClampIndex: READ8(); break;
1468 VECTOR_PREPROCESS(kCompareIEQ)
1469 VECTOR_PREPROCESS(kCompareINEQ)
1470 VECTOR_MATRIX_PREPROCESS(kCompareFEQ)
1471 VECTOR_MATRIX_PREPROCESS(kCompareFNEQ)
1472 VECTOR_PREPROCESS(kCompareFGT)
1473 VECTOR_PREPROCESS(kCompareFGTEQ)
1474 VECTOR_PREPROCESS(kCompareFLT)
1475 VECTOR_PREPROCESS(kCompareFLTEQ)
1476 VECTOR_PREPROCESS(kCompareSGT)
1477 VECTOR_PREPROCESS(kCompareSGTEQ)
1478 VECTOR_PREPROCESS(kCompareSLT)
1479 VECTOR_PREPROCESS(kCompareSLTEQ)
1480 VECTOR_PREPROCESS(kCompareUGT)
1481 VECTOR_PREPROCESS(kCompareUGTEQ)
1482 VECTOR_PREPROCESS(kCompareULT)
1483 VECTOR_PREPROCESS(kCompareULTEQ)
1484 VECTOR_PREPROCESS_NO_COUNT(kConvertFtoI)
1485 VECTOR_PREPROCESS_NO_COUNT(kConvertStoF)
1486 VECTOR_PREPROCESS_NO_COUNT(kConvertUtoF)
1487 VECTOR_PREPROCESS(kCos)
1488 VECTOR_MATRIX_PREPROCESS(kDivideF)
1489 VECTOR_PREPROCESS(kDivideS)
1490 VECTOR_PREPROCESS(kDivideU)
1491 VECTOR_MATRIX_PREPROCESS(kDup)
1492
1493 case ByteCodeInstruction::kInverse2x2:
1494 case ByteCodeInstruction::kInverse3x3:
1495 case ByteCodeInstruction::kInverse4x4: break;
1496
1497 case ByteCodeInstruction::kLoad:
1498 case ByteCodeInstruction::kLoad2:
1499 case ByteCodeInstruction::kLoad3:
1500 case ByteCodeInstruction::kLoad4:
1501 case ByteCodeInstruction::kLoadGlobal:
1502 case ByteCodeInstruction::kLoadGlobal2:
1503 case ByteCodeInstruction::kLoadGlobal3:
Brian Osman1c110a02019-10-01 14:53:32 -04001504 case ByteCodeInstruction::kLoadGlobal4:
1505 case ByteCodeInstruction::kLoadUniform:
1506 case ByteCodeInstruction::kLoadUniform2:
1507 case ByteCodeInstruction::kLoadUniform3:
1508 case ByteCodeInstruction::kLoadUniform4: READ16(); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001509
1510 case ByteCodeInstruction::kLoadSwizzle:
Brian Osman1c110a02019-10-01 14:53:32 -04001511 case ByteCodeInstruction::kLoadSwizzleGlobal:
1512 case ByteCodeInstruction::kLoadSwizzleUniform: {
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001513 READ8();
1514 int count = READ8();
1515 ip += count;
1516 break;
1517 }
1518
1519 case ByteCodeInstruction::kLoadExtended:
1520 case ByteCodeInstruction::kLoadExtendedGlobal:
Brian Osman1c110a02019-10-01 14:53:32 -04001521 case ByteCodeInstruction::kLoadExtendedUniform:
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001522 READ8();
1523 break;
1524
1525 case ByteCodeInstruction::kMatrixToMatrix: {
1526 READ8();
1527 READ8();
1528 READ8();
1529 READ8();
1530 break;
1531 }
1532 case ByteCodeInstruction::kMatrixMultiply: {
1533 READ8();
1534 READ8();
1535 READ8();
1536 break;
1537 }
1538 VECTOR_MATRIX_PREPROCESS(kMultiplyF)
1539 VECTOR_PREPROCESS(kMultiplyI)
1540 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kNegateF)
1541 VECTOR_PREPROCESS_NO_COUNT(kNegateI)
1542 case ByteCodeInstruction::kNotB: break;
1543 case ByteCodeInstruction::kOrB: break;
1544 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kPop)
1545 case ByteCodeInstruction::kPushImmediate: READ32(); break;
1546
1547 case ByteCodeInstruction::kReadExternal:
1548 case ByteCodeInstruction::kReadExternal2:
1549 case ByteCodeInstruction::kReadExternal3:
1550 case ByteCodeInstruction::kReadExternal4: READ16(); break;
1551
1552 VECTOR_PREPROCESS(kRemainderF)
1553 VECTOR_PREPROCESS(kRemainderS)
1554 VECTOR_PREPROCESS(kRemainderU)
1555 case ByteCodeInstruction::kReserve: READ8(); break;
1556 case ByteCodeInstruction::kReturn: READ8(); break;
1557 case ByteCodeInstruction::kScalarToMatrix: READ8(); READ8(); break;
Brian Osman4c2146f2019-09-24 09:39:38 -04001558 case ByteCodeInstruction::kShiftLeft: READ8(); break;
1559 case ByteCodeInstruction::kShiftRightS: READ8(); break;
1560 case ByteCodeInstruction::kShiftRightU: READ8(); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001561 VECTOR_PREPROCESS(kSin)
1562 VECTOR_PREPROCESS_NO_COUNT(kSqrt)
1563
1564 case ByteCodeInstruction::kStore:
1565 case ByteCodeInstruction::kStore2:
1566 case ByteCodeInstruction::kStore3:
1567 case ByteCodeInstruction::kStore4:
1568 case ByteCodeInstruction::kStoreGlobal:
1569 case ByteCodeInstruction::kStoreGlobal2:
1570 case ByteCodeInstruction::kStoreGlobal3:
1571 case ByteCodeInstruction::kStoreGlobal4: READ8(); break;
1572
1573 case ByteCodeInstruction::kStoreSwizzle:
1574 case ByteCodeInstruction::kStoreSwizzleGlobal: {
1575 READ8();
1576 int count = READ8();
1577 ip += count;
1578 break;
1579 }
1580
1581 case ByteCodeInstruction::kStoreSwizzleIndirect:
1582 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
1583 int count = READ8();
1584 ip += count;
1585 break;
1586 }
1587
1588 case ByteCodeInstruction::kStoreExtended: READ8(); break;
1589 case ByteCodeInstruction::kStoreExtendedGlobal: READ8(); break;
1590
1591 VECTOR_MATRIX_PREPROCESS(kSubtractF)
1592 VECTOR_PREPROCESS(kSubtractI)
1593
1594 case ByteCodeInstruction::kSwizzle: {
1595 READ8();
1596 int count = READ8();
1597 ip += count;
1598 break;
1599 }
1600 VECTOR_PREPROCESS(kTan)
1601 case ByteCodeInstruction::kWriteExternal:
1602 case ByteCodeInstruction::kWriteExternal2:
1603 case ByteCodeInstruction::kWriteExternal3:
1604 case ByteCodeInstruction::kWriteExternal4: READ16(); break;
1605
1606 case ByteCodeInstruction::kXorB: break;
1607 case ByteCodeInstruction::kMaskPush: break;
1608 case ByteCodeInstruction::kMaskPop: break;
1609 case ByteCodeInstruction::kMaskNegate: break;
1610 case ByteCodeInstruction::kMaskBlend: READ8(); break;
1611 case ByteCodeInstruction::kBranchIfAllFalse: READ16(); break;
1612 case ByteCodeInstruction::kLoopBegin: break;
1613 case ByteCodeInstruction::kLoopNext: break;
1614 case ByteCodeInstruction::kLoopMask: break;
1615 case ByteCodeInstruction::kLoopEnd: break;
1616 case ByteCodeInstruction::kLoopContinue: break;
1617 case ByteCodeInstruction::kLoopBreak: break;
1618 default:
1619 ip -= 2;
1620 printf("unknown(%d)\n", READ16());
1621 SkASSERT(false);
1622 }
1623 }
1624#endif
1625}
1626
Brian Osmanb23d66e2019-09-27 10:25:57 -04001627bool ByteCode::run(const ByteCodeFunction* f,
1628 float* args, int argCount,
1629 float* outReturn, int returnCount,
Brian Osman08a84962019-06-14 10:17:16 -04001630 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001631#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman4b202a32019-06-21 09:50:29 -04001632 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001633 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1634 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001635 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001636 }
Brian Osmanef787f72019-06-13 13:07:12 -04001637
Brian Osmanb23d66e2019-09-27 10:25:57 -04001638 if (argCount != f->fParameterCount ||
1639 returnCount != f->fReturnCount ||
Brian Osman1c110a02019-10-01 14:53:32 -04001640 uniformCount != fUniformSlotCount) {
Brian Osman869a3e82019-07-18 17:00:34 -04001641 return false;
1642 }
1643
Brian Osman08a84962019-06-14 10:17:16 -04001644 Interpreter::VValue globals[32];
Brian Osman1c110a02019-10-01 14:53:32 -04001645 if (fGlobalSlotCount > (int)SK_ARRAY_COUNT(globals)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001646 return false;
1647 }
Brian Osman569f12f2019-06-13 11:23:57 -04001648
Brian Osmanb23d66e2019-09-27 10:25:57 -04001649 // Transpose args into stack
1650 {
1651 float* src = args;
1652 float* dst = (float*)stack;
1653 for (int i = 0; i < argCount; ++i) {
1654 *dst = *src++;
Brian Osman9b8b4552019-09-30 13:23:14 -04001655 dst += VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001656 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001657 }
Brian Osmanb23d66e2019-09-27 10:25:57 -04001658
1659 bool stripedOutput = false;
1660 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman1c110a02019-10-01 14:53:32 -04001661 if (!Interpreter::InnerRun(this, f, stack, outArray, globals, uniforms, stripedOutput, 1, 0)) {
Brian Osmanb23d66e2019-09-27 10:25:57 -04001662 return false;
1663 }
1664
1665 // Transpose out parameters back
1666 {
1667 float* dst = args;
1668 float* src = (float*)stack;
1669 for (const auto& p : f->fParameters) {
1670 if (p.fIsOutParameter) {
1671 for (int i = p.fSlotCount; i > 0; --i) {
1672 *dst++ = *src;
Brian Osman9b8b4552019-09-30 13:23:14 -04001673 src += VecWidth;
Brian Osmanb23d66e2019-09-27 10:25:57 -04001674 }
1675 } else {
1676 dst += p.fSlotCount;
Brian Osman9b8b4552019-09-30 13:23:14 -04001677 src += p.fSlotCount * VecWidth;
Brian Osmanb23d66e2019-09-27 10:25:57 -04001678 }
1679 }
1680 }
1681
Brian Osman869a3e82019-07-18 17:00:34 -04001682 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001683#else
1684 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001685 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001686#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001687}
1688
Brian Osmanb23d66e2019-09-27 10:25:57 -04001689bool ByteCode::runStriped(const ByteCodeFunction* f, int N,
1690 float* args[], int argCount,
1691 float* outReturn[], int returnCount,
1692 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001693#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001694 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001695 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1696 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001697 return false;
1698 }
1699
Brian Osmanb23d66e2019-09-27 10:25:57 -04001700 if (argCount != f->fParameterCount ||
1701 returnCount != f->fReturnCount ||
Brian Osman1c110a02019-10-01 14:53:32 -04001702 uniformCount != fUniformSlotCount) {
Brian Osman869a3e82019-07-18 17:00:34 -04001703 return false;
1704 }
1705
1706 Interpreter::VValue globals[32];
Brian Osman1c110a02019-10-01 14:53:32 -04001707 if (fGlobalSlotCount > (int)SK_ARRAY_COUNT(globals)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001708 return false;
1709 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001710
Mike Reed3fd3cc92019-06-20 12:40:30 -04001711 // innerRun just takes outArgs, so clear it if the count is zero
Brian Osmanb23d66e2019-09-27 10:25:57 -04001712 if (returnCount == 0) {
1713 outReturn = nullptr;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001714 }
1715
Brian Osman1a79f0b2019-06-24 16:32:14 -04001716 int baseIndex = 0;
1717
Brian Osman2b1a5442019-06-19 11:40:33 -04001718 while (N) {
Brian Osman9b8b4552019-09-30 13:23:14 -04001719 int w = std::min(N, VecWidth);
Brian Osman2b1a5442019-06-19 11:40:33 -04001720
1721 // Copy args into stack
Brian Osmanb23d66e2019-09-27 10:25:57 -04001722 for (int i = 0; i < argCount; ++i) {
Brian Osman2b1a5442019-06-19 11:40:33 -04001723 memcpy(stack + i, args[i], w * sizeof(float));
1724 }
1725
Mike Reed3fd3cc92019-06-20 12:40:30 -04001726 bool stripedOutput = true;
Brian Osman1c110a02019-10-01 14:53:32 -04001727 if (!Interpreter::InnerRun(this, f, stack, outReturn, globals, uniforms, stripedOutput, w,
Brian Osman9b8b4552019-09-30 13:23:14 -04001728 baseIndex)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001729 return false;
1730 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001731
1732 // Copy out parameters back
1733 int slot = 0;
1734 for (const auto& p : f->fParameters) {
1735 if (p.fIsOutParameter) {
1736 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1737 memcpy(args[i], stack + i, w * sizeof(float));
1738 }
1739 }
1740 slot += p.fSlotCount;
1741 }
1742
1743 // Step each argument pointer ahead
Brian Osmanb23d66e2019-09-27 10:25:57 -04001744 for (int i = 0; i < argCount; ++i) {
Brian Osman2b1a5442019-06-19 11:40:33 -04001745 args[i] += w;
1746 }
1747 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001748 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001749 }
Brian Osman869a3e82019-07-18 17:00:34 -04001750
1751 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001752#else
1753 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001754 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001755#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001756}
1757
Brian Osman80164412019-06-07 13:00:23 -04001758} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001759
1760#endif