blob: 0181f038b3433dc25f309b3b773d80e0619f4f6a [file] [log] [blame]
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_STANDALONE
9
Ethan Nicholasae9633b2019-05-24 12:46:34 -040010#include "include/core/SkPoint3.h"
Brian Osman569f12f2019-06-13 11:23:57 -040011#include "include/private/SkVx.h"
Mike Klein7a177b42019-06-17 17:17:47 -050012#include "src/core/SkUtils.h" // sk_unaligned_load
Brian Osman80164412019-06-07 13:00:23 -040013#include "src/sksl/SkSLByteCode.h"
Brian Osman07c117b2019-05-23 12:51:06 -070014#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040015#include "src/sksl/SkSLExternalValue.h"
Brian Osman80164412019-06-07 13:00:23 -040016
17#include <vector>
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040018
19namespace SkSL {
Brian Osman489cf882019-07-09 10:48:28 -040020
21#if defined(SK_ENABLE_SKSL_INTERPRETER)
22
Brian Osman80164412019-06-07 13:00:23 -040023namespace Interpreter {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040024
Mike Reed3fd3cc92019-06-20 12:40:30 -040025constexpr int VecWidth = ByteCode::kVecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -040026
27using F32 = skvx::Vec<VecWidth, float>;
28using I32 = skvx::Vec<VecWidth, int32_t>;
29using U32 = skvx::Vec<VecWidth, uint32_t>;
30
Mike Kleine7007382019-05-21 08:36:32 -050031#define READ8() (*(ip++))
Mike Klein7a177b42019-06-17 17:17:47 -050032#define READ16() (ip += 2, sk_unaligned_load<uint16_t>(ip - 2))
33#define READ32() (ip += 4, sk_unaligned_load<uint32_t>(ip - 4))
Ethan 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 Osman3e833e12019-05-23 13:23:24 -070057static const uint8_t* disassemble_instruction(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 Osman3e833e12019-05-23 13:23:24 -0700171 VECTOR_DISASSEMBLE(kSin, "sin")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400172 VECTOR_DISASSEMBLE_NO_COUNT(kSqrt, "sqrt")
Brian Osman3e833e12019-05-23 13:23:24 -0700173 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
174 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
175 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
176 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
177 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
178 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
179 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
180 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
181 case ByteCodeInstruction::kStoreSwizzle: {
182 int target = READ8();
183 int count = READ8();
184 printf("storeswizzle %d %d", target, count);
185 for (int i = 0; i < count; ++i) {
186 printf(", %d", READ8());
187 }
188 break;
189 }
190 case ByteCodeInstruction::kStoreSwizzleGlobal: {
191 int target = READ8();
192 int count = READ8();
193 printf("storeswizzleglobal %d %d", target, count);
194 for (int i = 0; i < count; ++i) {
195 printf(", %d", READ8());
196 }
197 break;
198 }
199 case ByteCodeInstruction::kStoreSwizzleIndirect: {
200 int count = READ8();
201 printf("storeswizzleindirect %d", count);
202 for (int i = 0; i < count; ++i) {
203 printf(", %d", READ8());
204 }
205 break;
206 }
207 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
208 int count = READ8();
209 printf("storeswizzleindirectglobal %d", count);
210 for (int i = 0; i < count; ++i) {
211 printf(", %d", READ8());
212 }
213 break;
214 }
215 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
216 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
217 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400218 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700219 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
220 case ByteCodeInstruction::kSwizzle: {
221 printf("swizzle %d, ", READ8());
222 int count = READ8();
223 printf("%d", count);
224 for (int i = 0; i < count; ++i) {
225 printf(", %d", READ8());
226 }
227 break;
228 }
229 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400230 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ16() >> 8); break;
231 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ16() >> 8); break;
232 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ16() >> 8); break;
233 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ16() >> 8); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400234 case ByteCodeInstruction::kXorB: printf("xorb"); break;
235 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
236 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
237 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
238 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
239 case ByteCodeInstruction::kBranchIfAllFalse:
240 printf("branchifallfalse %d", READ16());
241 break;
242 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
243 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
244 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
245 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
246 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
247 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400248 default:
249 ip -= sizeof(instruction);
250 printf("unknown(%d)\n", (int) (intptr_t) READ_INST());
251 SkASSERT(false);
Brian Osman3e833e12019-05-23 13:23:24 -0700252 }
253 return ip;
254}
255
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400256#ifdef SKSLC_THREADED_CODE
257 #define LABEL(name) name:
258 #ifdef TRACE
259 #define NEXT() goto next
260 #else
261 #define NEXT() goto *READ_INST()
262 #endif
263#else
264 #define LABEL(name) case ByteCodeInstruction::name:
265 #define NEXT() continue
266#endif
267
268#define VECTOR_BINARY_OP(base, field, op) \
269 LABEL(base ## 4) \
270 sp[-4] = sp[-4].field op sp[0].field; \
271 POP(); \
272 /* fall through */ \
273 LABEL(base ## 3) { \
274 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
275 POP(); \
276 } /* fall through */ \
277 LABEL(base ## 2) { \
278 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
279 POP(); \
280 } /* fall through */ \
281 LABEL(base) { \
282 sp[-ip[0]] = sp[-ip[0]].field op sp[0].field; \
283 POP(); \
284 ++ip; \
285 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500286 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400287
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400288#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
289 VECTOR_BINARY_OP(base, field, op) \
290 LABEL(base ## N) { \
291 int count = READ8(); \
292 for (int i = count; i > 0; --i) { \
293 sp[-count] = sp[-count].field op sp[0].field; \
294 POP(); \
295 } \
296 NEXT(); \
Brian Osman1e855b22019-05-29 15:21:52 -0400297 }
298
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400299#define VECTOR_BINARY_FN(base, field, fn) \
300 LABEL(base ## 4) \
301 sp[-4] = fn(sp[-4].field, sp[0].field); \
302 POP(); \
303 /* fall through */ \
304 LABEL(base ## 3) { \
305 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
306 POP(); \
307 } /* fall through */ \
308 LABEL(base ## 2) { \
309 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
310 POP(); \
311 } /* fall through */ \
312 LABEL(base) { \
313 sp[-ip[0]] = fn(sp[-ip[0]].field, sp[0].field); \
314 POP(); \
315 ++ip; \
316 NEXT(); \
Mike Kleine7007382019-05-21 08:36:32 -0500317 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400318
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400319#define VECTOR_UNARY_FN(base, fn, field) \
320 LABEL(base ## 4) sp[-3] = fn(sp[-3].field); \
321 LABEL(base ## 3) sp[-2] = fn(sp[-2].field); \
322 LABEL(base ## 2) sp[-1] = fn(sp[-1].field); \
323 LABEL(base) sp[ 0] = fn(sp[ 0].field); \
324 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400325
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400326#define VECTOR_UNARY_FN_VEC(base, fn) \
327 LABEL(base ## 4) \
328 LABEL(base ## 3) \
329 LABEL(base ## 2) \
330 LABEL(base) { \
331 int count = READ8(); \
332 float* v = (float*)sp - count + 1; \
333 for (int i = VecWidth * count; i > 0; --i, ++v) { \
334 *v = fn(*v); \
335 } \
336 NEXT(); \
Brian Osman569f12f2019-06-13 11:23:57 -0400337 }
338
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400339#define VECTOR_LABELS(base) \
340 &&base ## 4, \
341 &&base ## 3, \
342 &&base ## 2, \
343 &&base
344
345#define VECTOR_MATRIX_LABELS(base) \
346 VECTOR_LABELS(base), \
347 &&base ## N
348
349// If you trip this assert, it means that the order of the opcodes listed in ByteCodeInstruction
350// does not match the order of the opcodes listed in the 'labels' array in innerRun().
351#define CHECK_LABEL(name) \
352 SkASSERT(labels[(int) ByteCodeInstruction::name] == &&name)
353
354#define CHECK_VECTOR_LABELS(name) \
355 CHECK_LABEL(name ## 4); \
356 CHECK_LABEL(name ## 3); \
357 CHECK_LABEL(name ## 2); \
358 CHECK_LABEL(name)
359
360#define CHECK_VECTOR_MATRIX_LABELS(name) \
361 CHECK_VECTOR_LABELS(name); \
362 CHECK_LABEL(name ## N)
363
Brian Osman569f12f2019-06-13 11:23:57 -0400364union VValue {
365 VValue() {}
366
367 VValue(F32 f)
368 : fFloat(f) {
369 }
370
371 VValue(I32 s)
372 : fSigned(s) {
373 }
374
375 VValue(U32 u)
376 : fUnsigned(u) {
377 }
378
379 F32 fFloat;
380 I32 fSigned;
381 U32 fUnsigned;
382};
383
Brian Osman226668a2019-05-14 16:47:30 -0400384struct StackFrame {
385 const uint8_t* fCode;
386 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400387 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400388 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400389};
390
Brian Osman569f12f2019-06-13 11:23:57 -0400391// TODO: trunc on integers?
392template <typename T>
393static T vec_mod(T a, T b) {
394 return a - skvx::trunc(a / b) * b;
395}
Mike Kleine7007382019-05-21 08:36:32 -0500396
Mike Reed634c9412019-07-18 13:20:04 -0400397#define spf(index) sp[index].fFloat
398
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400399static void call_external(const ByteCode* byteCode, const uint8_t*& ip, VValue*& sp,
400 int baseIndex, I32 mask) {
401 int argumentCount = READ8();
402 int returnCount = READ8();
403 int target = READ8();
404 ExternalValue* v = byteCode->fExternalValues[target];
405 sp -= argumentCount - 1;
406
407 float tmpArgs[4];
408 float tmpReturn[4];
409 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
410 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
411
412 for (int i = 0; i < VecWidth; ++i) {
413 if (mask[i]) {
414 for (int j = 0; j < argumentCount; ++j) {
415 tmpArgs[j] = sp[j].fFloat[i];
416 }
417 v->call(baseIndex + i, tmpArgs, tmpReturn);
418 for (int j = 0; j < returnCount; ++j) {
419 sp[j].fFloat[i] = tmpReturn[j];
420 }
421 }
422 }
423 sp += returnCount - 1;
424}
425
426static void inverse2x2(VValue* sp) {
427 F32 a = sp[-3].fFloat,
428 b = sp[-2].fFloat,
429 c = sp[-1].fFloat,
430 d = sp[ 0].fFloat;
431 F32 idet = F32(1) / (a*d - b*c);
432 sp[-3].fFloat = d * idet;
433 sp[-2].fFloat = -b * idet;
434 sp[-1].fFloat = -c * idet;
435 sp[ 0].fFloat = a * idet;
436}
437
438static void inverse3x3(VValue* sp) {
439 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
440 a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
441 a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
442 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
443 a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
444 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
445 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
446 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
447 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
448 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
449 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
450 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
451 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
452 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
453}
454
455static void inverse4x4(VValue* sp) {
456 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
457 a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
458 a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
459 a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf( 0);
460
461 F32 b00 = a00 * a11 - a01 * a10,
462 b01 = a00 * a12 - a02 * a10,
463 b02 = a00 * a13 - a03 * a10,
464 b03 = a01 * a12 - a02 * a11,
465 b04 = a01 * a13 - a03 * a11,
466 b05 = a02 * a13 - a03 * a12,
467 b06 = a20 * a31 - a21 * a30,
468 b07 = a20 * a32 - a22 * a30,
469 b08 = a20 * a33 - a23 * a30,
470 b09 = a21 * a32 - a22 * a31,
471 b10 = a21 * a33 - a23 * a31,
472 b11 = a22 * a33 - a23 * a32;
473
474 F32 idet = F32(1) /
475 (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
476
477 b00 *= idet;
478 b01 *= idet;
479 b02 *= idet;
480 b03 *= idet;
481 b04 *= idet;
482 b05 *= idet;
483 b06 *= idet;
484 b07 *= idet;
485 b08 *= idet;
486 b09 *= idet;
487 b10 *= idet;
488 b11 *= idet;
489
490 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
491 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
492 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
493 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
494 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
495 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
496 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
497 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
498 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
499 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
500 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
501 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
502 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
503 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
504 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
505 spf( 0) = a20 * b03 - a21 * b01 + a22 * b00;
506}
507
Brian Osman869a3e82019-07-18 17:00:34 -0400508static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400509 float* outReturn[], VValue globals[], bool stripedOutput, int N,
510 int baseIndex) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400511#ifdef SKSLC_THREADED_CODE
512 static const void* labels[] = {
513 // If you aren't familiar with it, the &&label syntax is the GCC / Clang "labels as values"
514 // extension. If you add anything to this array, be sure to add the corresponding
515 // CHECK_LABEL() or CHECK_*_LABELS() assert below.
516 VECTOR_MATRIX_LABELS(kAddF),
517 VECTOR_LABELS(kAddI),
518 &&kAndB,
519 &&kBranch,
520 &&kCall,
521 &&kCallExternal,
522 &&kClampIndex,
523 VECTOR_LABELS(kCompareIEQ),
524 VECTOR_LABELS(kCompareINEQ),
525 VECTOR_MATRIX_LABELS(kCompareFEQ),
526 VECTOR_MATRIX_LABELS(kCompareFNEQ),
527 VECTOR_LABELS(kCompareFGT),
528 VECTOR_LABELS(kCompareFGTEQ),
529 VECTOR_LABELS(kCompareFLT),
530 VECTOR_LABELS(kCompareFLTEQ),
531 VECTOR_LABELS(kCompareSGT),
532 VECTOR_LABELS(kCompareSGTEQ),
533 VECTOR_LABELS(kCompareSLT),
534 VECTOR_LABELS(kCompareSLTEQ),
535 VECTOR_LABELS(kCompareUGT),
536 VECTOR_LABELS(kCompareUGTEQ),
537 VECTOR_LABELS(kCompareULT),
538 VECTOR_LABELS(kCompareULTEQ),
539 VECTOR_LABELS(kConvertFtoI),
540 VECTOR_LABELS(kConvertStoF),
541 VECTOR_LABELS(kConvertUtoF),
542 VECTOR_LABELS(kCos),
543 VECTOR_MATRIX_LABELS(kDivideF),
544 VECTOR_LABELS(kDivideS),
545 VECTOR_LABELS(kDivideU),
546 VECTOR_MATRIX_LABELS(kDup),
547 &&kInverse2x2,
548 &&kInverse3x3,
549 &&kInverse4x4,
550 VECTOR_LABELS(kLoad),
551 VECTOR_LABELS(kLoadGlobal),
552 &&kLoadSwizzle,
553 &&kLoadSwizzleGlobal,
554 &&kLoadExtended,
555 &&kLoadExtendedGlobal,
556 &&kMatrixToMatrix,
557 &&kMatrixMultiply,
558 VECTOR_MATRIX_LABELS(kNegateF),
559 VECTOR_LABELS(kNegateI),
560 VECTOR_MATRIX_LABELS(kMultiplyF),
561 VECTOR_LABELS(kMultiplyI),
562 &&kNotB,
563 &&kOrB,
564 VECTOR_MATRIX_LABELS(kPop),
565 &&kPushImmediate,
566 VECTOR_LABELS(kReadExternal),
567 VECTOR_LABELS(kRemainderF),
568 VECTOR_LABELS(kRemainderS),
569 VECTOR_LABELS(kRemainderU),
570 &&kReserve,
571 &&kReturn,
572 &&kScalarToMatrix,
573 VECTOR_LABELS(kSin),
574 VECTOR_LABELS(kSqrt),
575 VECTOR_LABELS(kStore),
576 VECTOR_LABELS(kStoreGlobal),
577 &&kStoreExtended,
578 &&kStoreExtendedGlobal,
579 &&kStoreSwizzle,
580 &&kStoreSwizzleGlobal,
581 &&kStoreSwizzleIndirect,
582 &&kStoreSwizzleIndirectGlobal,
583 &&kSwizzle,
584 VECTOR_MATRIX_LABELS(kSubtractF),
585 VECTOR_LABELS(kSubtractI),
586 VECTOR_LABELS(kTan),
587 VECTOR_LABELS(kWriteExternal),
588 &&kXorB,
589
590 &&kMaskPush,
591 &&kMaskPop,
592 &&kMaskNegate,
593 &&kMaskBlend,
594 &&kBranchIfAllFalse,
595
596 &&kLoopBegin,
597 &&kLoopNext,
598 &&kLoopMask,
599 &&kLoopEnd,
600 &&kLoopBreak,
601 &&kLoopContinue,
602 };
603 // Verify that the order of the labels array matches the order of the ByteCodeInstruction enum.
604 CHECK_VECTOR_MATRIX_LABELS(kAddF);
605 CHECK_VECTOR_LABELS(kAddI);
606 CHECK_LABEL(kAndB);
607 CHECK_LABEL(kBranch);
608 CHECK_LABEL(kCall);
609 CHECK_LABEL(kCallExternal);
610 CHECK_LABEL(kClampIndex);
611 CHECK_VECTOR_LABELS(kCompareIEQ);
612 CHECK_VECTOR_LABELS(kCompareINEQ);
613 CHECK_VECTOR_MATRIX_LABELS(kCompareFEQ);
614 CHECK_VECTOR_MATRIX_LABELS(kCompareFNEQ);
615 CHECK_VECTOR_LABELS(kCompareFGT);
616 CHECK_VECTOR_LABELS(kCompareFGTEQ);
617 CHECK_VECTOR_LABELS(kCompareFLT);
618 CHECK_VECTOR_LABELS(kCompareFLTEQ);
619 CHECK_VECTOR_LABELS(kCompareSGT);
620 CHECK_VECTOR_LABELS(kCompareSGTEQ);
621 CHECK_VECTOR_LABELS(kCompareSLT);
622 CHECK_VECTOR_LABELS(kCompareSLTEQ);
623 CHECK_VECTOR_LABELS(kCompareUGT);
624 CHECK_VECTOR_LABELS(kCompareUGTEQ);
625 CHECK_VECTOR_LABELS(kCompareULT);
626 CHECK_VECTOR_LABELS(kCompareULTEQ);
627 CHECK_VECTOR_LABELS(kConvertFtoI);
628 CHECK_VECTOR_LABELS(kConvertStoF);
629 CHECK_VECTOR_LABELS(kConvertUtoF);
630 CHECK_VECTOR_LABELS(kCos);
631 CHECK_VECTOR_MATRIX_LABELS(kDivideF);
632 CHECK_VECTOR_LABELS(kDivideS);
633 CHECK_VECTOR_LABELS(kDivideU);
634 CHECK_VECTOR_MATRIX_LABELS(kDup);
635 CHECK_LABEL(kInverse2x2);
636 CHECK_LABEL(kInverse3x3);
637 CHECK_LABEL(kInverse4x4);
638 CHECK_VECTOR_LABELS(kLoad);
639 CHECK_VECTOR_LABELS(kLoadGlobal);
640 CHECK_LABEL(kLoadSwizzle);
641 CHECK_LABEL(kLoadSwizzleGlobal);
642 CHECK_LABEL(kLoadExtended);
643 CHECK_LABEL(kLoadExtendedGlobal);
644 CHECK_LABEL(kMatrixToMatrix);
645 CHECK_LABEL(kMatrixMultiply);
646 CHECK_VECTOR_MATRIX_LABELS(kNegateF);
647 CHECK_VECTOR_LABELS(kNegateI);
648 CHECK_VECTOR_MATRIX_LABELS(kMultiplyF);
649 CHECK_VECTOR_LABELS(kMultiplyI);
650 CHECK_LABEL(kNotB);
651 CHECK_LABEL(kOrB);
652 CHECK_VECTOR_MATRIX_LABELS(kPop);
653 CHECK_LABEL(kPushImmediate);
654 CHECK_VECTOR_LABELS(kReadExternal);
655 CHECK_VECTOR_LABELS(kRemainderF);
656 CHECK_VECTOR_LABELS(kRemainderS);
657 CHECK_VECTOR_LABELS(kRemainderU);
658 CHECK_LABEL(kReserve);
659 CHECK_LABEL(kReturn);
660 CHECK_LABEL(kScalarToMatrix);
661 CHECK_VECTOR_LABELS(kSin);
662 CHECK_VECTOR_LABELS(kSqrt);
663 CHECK_VECTOR_LABELS(kStore);
664 CHECK_VECTOR_LABELS(kStoreGlobal);
665 CHECK_LABEL(kStoreExtended);
666 CHECK_LABEL(kStoreExtendedGlobal);
667 CHECK_LABEL(kStoreSwizzle);
668 CHECK_LABEL(kStoreSwizzleGlobal);
669 CHECK_LABEL(kStoreSwizzleIndirect);
670 CHECK_LABEL(kStoreSwizzleIndirectGlobal);
671 CHECK_LABEL(kSwizzle);
672 CHECK_VECTOR_MATRIX_LABELS(kSubtractF);
673 CHECK_VECTOR_LABELS(kSubtractI);
674 CHECK_VECTOR_LABELS(kTan);
675 CHECK_VECTOR_LABELS(kWriteExternal);
676 CHECK_LABEL(kXorB);
677 CHECK_LABEL(kMaskPush);
678 CHECK_LABEL(kMaskPop);
679 CHECK_LABEL(kMaskNegate);
680 CHECK_LABEL(kMaskBlend);
681 CHECK_LABEL(kBranchIfAllFalse);
682 CHECK_LABEL(kLoopBegin);
683 CHECK_LABEL(kLoopNext);
684 CHECK_LABEL(kLoopMask);
685 CHECK_LABEL(kLoopEnd);
686 CHECK_LABEL(kLoopBreak);
687 CHECK_LABEL(kLoopContinue);
Brian Osman11b877e2019-09-17 10:21:06 -0400688 f->fPreprocessOnce([f] { ((ByteCodeFunction*)f)->preprocess(labels); });
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400689#endif
690
Brian Osman4b202a32019-06-21 09:50:29 -0400691 // Needs to be the first N non-negative integers, at least as large as VecWidth
692 static const Interpreter::I32 gLanes = {
693 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
694 };
695
Brian Osman569f12f2019-06-13 11:23:57 -0400696 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
697
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400698 #define POP() (*(sp--))
699 #define PUSH(v) (sp[1] = v, ++sp)
Mike Kleine7007382019-05-21 08:36:32 -0500700
Brian Osman80164412019-06-07 13:00:23 -0400701 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400702 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400703 std::vector<StackFrame> frames;
704
Brian Osman569f12f2019-06-13 11:23:57 -0400705 I32 condStack[16]; // Independent condition masks
706 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
707 I32 contStack[16]; // Continue flags for loops
708 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400709 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400710 contStack[0] = I32( 0);
711 loopStack[0] = I32(~0);
712 I32* condPtr = condStack;
713 I32* maskPtr = maskStack;
714 I32* contPtr = contStack;
715 I32* loopPtr = loopStack;
716
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400717 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
718 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osman869a3e82019-07-18 17:00:34 -0400719 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400720 }
721
Brian Osman569f12f2019-06-13 11:23:57 -0400722 auto mask = [&]() { return *maskPtr & *loopPtr; };
723
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400724#ifdef SKSLC_THREADED_CODE
725 // If the "labels as values" extension is available, we implement this using threaded code.
726 // Instead of opcodes, the code directly contains the addresses of the labels to jump to. Then
727 // the code for each opcode simply grabs the address of the next opcode and uses a goto to jump
728 // there.
729 NEXT();
730#else
731 // Otherwise, we have to use a switch statement and a loop to execute the right label.
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400732 for (;;) {
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400733 #ifdef TRACE
734 printf("at %3d ", (int) (ip - code));
735 disassemble_instruction(ip);
736 printf(" (stack: %d)\n", (int) (sp - stack) + 1);
737 #endif
738 switch ((ByteCodeInstruction) READ16()) {
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400739#endif
Brian Osman569f12f2019-06-13 11:23:57 -0400740
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400741 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
742 VECTOR_BINARY_OP(kAddI, fSigned, +)
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400743
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400744 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
745 LABEL(kAndB)
746 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
747 POP();
748 NEXT();
749 LABEL(kNotB)
750 sp[0] = ~sp[0].fSigned;
751 NEXT();
752 LABEL(kOrB)
753 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
754 POP();
755 NEXT();
756 LABEL(kXorB)
757 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
758 POP();
759 NEXT();
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400760
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400761 LABEL(kBranch)
762 ip = code + READ16();
763 NEXT();
764
765 LABEL(kCall) {
766 // Precursor code reserved space for the return value, and pushed all parameters to
767 // the stack. Update our bottom of stack to point at the first parameter, and our
768 // sp to point past those parameters (plus space for locals).
769 int target = READ8();
770 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
771#ifdef SKSLC_THREADED_CODE
Brian Osman11b877e2019-09-17 10:21:06 -0400772 fun->fPreprocessOnce([fun] { ((ByteCodeFunction*)fun)->preprocess(labels); });
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400773#endif
774 if (skvx::any(mask())) {
775 frames.push_back({ code, ip, stack, fun->fParameterCount });
776 ip = code = fun->fCode.data();
777 stack = sp - fun->fParameterCount + 1;
778 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
779 }
780 NEXT();
781 }
782
783 LABEL(kCallExternal) {
784 call_external(byteCode, ip, sp, baseIndex, mask());
785 NEXT();
786 }
787
788 LABEL(kClampIndex) {
789 int length = READ8();
790 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
791 return false;
792 }
793 NEXT();
794 }
795
796 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
797 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
798 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
799 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
800 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
801 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
802 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
803 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
804 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
805 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
806 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
807 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
808 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
809 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
810 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
811 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
812
813 LABEL(kConvertFtoI4) sp[-3] = skvx::cast<int>(sp[-3].fFloat);
814 LABEL(kConvertFtoI3) sp[-2] = skvx::cast<int>(sp[-2].fFloat);
815 LABEL(kConvertFtoI2) sp[-1] = skvx::cast<int>(sp[-1].fFloat);
816 LABEL(kConvertFtoI) sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
817 NEXT();
818
819 LABEL(kConvertStoF4) sp[-3] = skvx::cast<float>(sp[-3].fSigned);
820 LABEL(kConvertStoF3) sp[-2] = skvx::cast<float>(sp[-2].fSigned);
821 LABEL(kConvertStoF2) sp[-1] = skvx::cast<float>(sp[-1].fSigned);
822 LABEL(kConvertStoF) sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
823 NEXT();
824
825 LABEL(kConvertUtoF4) sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
826 LABEL(kConvertUtoF3) sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
827 LABEL(kConvertUtoF2) sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
828 LABEL(kConvertUtoF) sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
829 NEXT();
830
831 VECTOR_UNARY_FN_VEC(kCos, cosf)
832
833 VECTOR_BINARY_OP(kDivideS, fSigned, /)
834 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
835 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
836
837 LABEL(kDup4) PUSH(sp[1 - ip[0]]);
838 LABEL(kDup3) PUSH(sp[1 - ip[0]]);
839 LABEL(kDup2) PUSH(sp[1 - ip[0]]);
840 LABEL(kDup) PUSH(sp[1 - ip[0]]);
841 ++ip;
842 NEXT();
843
844 LABEL(kDupN) {
845 int count = READ8();
846 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
847 sp += count;
848 NEXT();
849 }
850
851 LABEL(kInverse2x2) {
852 inverse2x2(sp);
853 NEXT();
854 }
855 LABEL(kInverse3x3) {
856 inverse3x3(sp);
857 NEXT();
858 }
859 LABEL(kInverse4x4) {
860 inverse4x4(sp);
861 NEXT();
862 }
863
864 LABEL(kLoad4) sp[4] = stack[ip[1] + 3];
865 LABEL(kLoad3) sp[3] = stack[ip[1] + 2];
866 LABEL(kLoad2) sp[2] = stack[ip[1] + 1];
867 LABEL(kLoad) sp[1] = stack[ip[1] + 0];
868 sp += ip[0];
869 ip += 2;
870 NEXT();
871
872 LABEL(kLoadGlobal4) sp[4] = globals[ip[1] + 3];
873 LABEL(kLoadGlobal3) sp[3] = globals[ip[1] + 2];
874 LABEL(kLoadGlobal2) sp[2] = globals[ip[1] + 1];
875 LABEL(kLoadGlobal) sp[1] = globals[ip[1] + 0];
876 sp += ip[0];
877 ip += 2;
878 NEXT();
879
880 LABEL(kLoadExtended) {
881 int count = READ8();
882 I32 src = POP().fSigned;
883 I32 m = mask();
884 for (int i = 0; i < count; ++i) {
885 for (int j = 0; j < VecWidth; ++j) {
886 if (m[j]) {
887 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
Brian Osman569f12f2019-06-13 11:23:57 -0400888 }
Brian Osman226668a2019-05-14 16:47:30 -0400889 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400890 }
891 sp += count;
892 NEXT();
893 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400894
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400895 LABEL(kLoadExtendedGlobal) {
896 int count = READ8();
897 I32 src = POP().fSigned;
898 I32 m = mask();
899 for (int i = 0; i < count; ++i) {
900 for (int j = 0; j < VecWidth; ++j) {
901 if (m[j]) {
902 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
903 }
904 }
905 }
906 sp += count;
907 NEXT();
908 }
Mike Kleine7007382019-05-21 08:36:32 -0500909
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400910 LABEL(kLoadSwizzle) {
911 int src = READ8();
912 int count = READ8();
913 for (int i = 0; i < count; ++i) {
914 PUSH(stack[src + *(ip + i)]);
915 }
916 ip += count;
917 NEXT();
918 }
Brian Osman569f12f2019-06-13 11:23:57 -0400919
Ethan Nicholasc70027b2019-09-05 16:50:52 -0400920 LABEL(kLoadSwizzleGlobal) {
921 int src = READ8();
922 int count = READ8();
923 for (int i = 0; i < count; ++i) {
924 PUSH(globals[src + *(ip + i)]);
925 }
926 ip += count;
927 NEXT();
928 }
929
930 LABEL(kMatrixToMatrix) {
931 int srcCols = READ8();
932 int srcRows = READ8();
933 int dstCols = READ8();
934 int dstRows = READ8();
935 SkASSERT(srcCols >= 2 && srcCols <= 4);
936 SkASSERT(srcRows >= 2 && srcRows <= 4);
937 SkASSERT(dstCols >= 2 && dstCols <= 4);
938 SkASSERT(dstRows >= 2 && dstRows <= 4);
939 F32 tmp[16];
940 memset(tmp, 0, sizeof(tmp));
941 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
942 for (int c = srcCols - 1; c >= 0; --c) {
943 for (int r = srcRows - 1; r >= 0; --r) {
944 tmp[c*4 + r] = POP().fFloat;
945 }
946 }
947 for (int c = 0; c < dstCols; ++c) {
948 for (int r = 0; r < dstRows; ++r) {
949 PUSH(tmp[c*4 + r]);
950 }
951 }
952 NEXT();
953 }
954
955 LABEL(kMatrixMultiply) {
956 int lCols = READ8();
957 int lRows = READ8();
958 int rCols = READ8();
959 int rRows = lCols;
960 F32 tmp[16] = { 0.0f };
961 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
962 F32* A = B - (lCols * lRows);
963 for (int c = 0; c < rCols; ++c) {
964 for (int r = 0; r < lRows; ++r) {
965 for (int j = 0; j < lCols; ++j) {
966 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
967 }
968 }
969 }
970 sp -= (lCols * lRows) + (rCols * rRows);
971 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
972 sp += (rCols * lRows);
973 NEXT();
974 }
975
976 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
977 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
978
979 LABEL(kNegateF4) sp[-3] = -sp[-3].fFloat;
980 LABEL(kNegateF3) sp[-2] = -sp[-2].fFloat;
981 LABEL(kNegateF2) sp[-1] = -sp[-1].fFloat;
982 LABEL(kNegateF) sp[ 0] = -sp[ 0].fFloat;
983 NEXT();
984
985 LABEL(kNegateFN) {
986 int count = READ8();
987 for (int i = count - 1; i >= 0; --i) {
988 sp[-i] = -sp[-i].fFloat;
989 }
990 NEXT();
991 }
992
993 LABEL(kNegateI4) sp[-3] = -sp[-3].fSigned;
994 LABEL(kNegateI3) sp[-2] = -sp[-2].fSigned;
995 LABEL(kNegateI2) sp[-1] = -sp[-1].fSigned;
996 LABEL(kNegateI) sp[ 0] = -sp[ 0].fSigned;
997 NEXT();
998
999 LABEL(kPop4) POP();
1000 LABEL(kPop3) POP();
1001 LABEL(kPop2) POP();
1002 LABEL(kPop) POP();
1003 NEXT();
1004
1005 LABEL(kPopN)
1006 sp -= READ8();
1007 NEXT();
1008
1009 LABEL(kPushImmediate)
1010 PUSH(U32(READ32()));
1011 NEXT();
1012
1013 LABEL(kReadExternal)
1014 LABEL(kReadExternal2)
1015 LABEL(kReadExternal3)
1016 LABEL(kReadExternal4) {
1017 int count = READ8();
1018 int src = READ8();
1019 float tmp[4];
1020 I32 m = mask();
1021 for (int i = 0; i < VecWidth; ++i) {
1022 if (m[i]) {
1023 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
1024 for (int j = 0; j < count; ++j) {
1025 sp[j + 1].fFloat[i] = tmp[j];
1026 }
1027 }
1028 }
1029 sp += count;
1030 NEXT();
1031 }
1032
1033 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
1034 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
1035 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
1036
1037 LABEL(kReserve)
1038 sp += READ8();
1039 NEXT();
1040
1041 LABEL(kReturn) {
1042 int count = READ8();
1043 if (frames.empty()) {
1044 if (outReturn) {
1045 VValue* src = sp - count + 1;
1046 if (stripedOutput) {
1047 for (int i = 0; i < count; ++i) {
1048 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
1049 ++src;
Brian Osman569f12f2019-06-13 11:23:57 -04001050 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001051 } else {
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001052 float* outPtr = outReturn[0];
1053 for (int i = 0; i < count; ++i) {
1054 for (int j = 0; j < N; ++j) {
1055 outPtr[count * j] = src->fFloat[j];
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001056 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001057 ++outPtr;
1058 ++src;
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001059 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001060 }
1061 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001062 return true;
1063 } else {
1064 // When we were called, the caller reserved stack space for their copy of our
1065 // return value, then 'stack' was positioned after that, where our parameters
1066 // were placed. Copy our return values to their reserved area.
1067 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001068
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001069 // Now move the stack pointer to the end of the passed-in parameters. This odd
1070 // calling convention requires the caller to pop the arguments after calling,
1071 // but allows them to store any out-parameters back during that unwinding.
1072 // After that sequence finishes, the return value will be the top of the stack.
1073 const StackFrame& frame(frames.back());
1074 sp = stack + frame.fParameterCount - 1;
1075 stack = frame.fStack;
1076 code = frame.fCode;
1077 ip = frame.fIP;
1078 frames.pop_back();
1079 NEXT();
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001080 }
1081 }
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001082
1083 LABEL(kScalarToMatrix) {
1084 int cols = READ8();
1085 int rows = READ8();
1086 VValue v = POP();
1087 for (int c = 0; c < cols; ++c) {
1088 for (int r = 0; r < rows; ++r) {
1089 PUSH(c == r ? v : F32(0.0f));
1090 }
1091 }
1092 NEXT();
1093 }
1094
1095 VECTOR_UNARY_FN_VEC(kSin, sinf)
1096 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
1097
1098 LABEL(kStore4)
1099 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
1100 LABEL(kStore3)
1101 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
1102 LABEL(kStore2)
1103 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
1104 LABEL(kStore)
1105 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
1106 ++ip;
1107 NEXT();
1108
1109 LABEL(kStoreGlobal4)
1110 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
1111 LABEL(kStoreGlobal3)
1112 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
1113 LABEL(kStoreGlobal2)
1114 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
1115 LABEL(kStoreGlobal)
1116 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
1117 ++ip;
1118 NEXT();
1119
1120 LABEL(kStoreExtended) {
1121 int count = READ8();
1122 I32 target = POP().fSigned;
1123 VValue* src = sp - count + 1;
1124 I32 m = mask();
1125 for (int i = 0; i < count; ++i) {
1126 for (int j = 0; j < VecWidth; ++j) {
1127 if (m[j]) {
1128 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
1129 }
1130 }
1131 }
1132 sp -= count;
1133 NEXT();
1134 }
1135 LABEL(kStoreExtendedGlobal) {
1136 int count = READ8();
1137 I32 target = POP().fSigned;
1138 VValue* src = sp - count + 1;
1139 I32 m = mask();
1140 for (int i = 0; i < count; ++i) {
1141 for (int j = 0; j < VecWidth; ++j) {
1142 if (m[j]) {
1143 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
1144 }
1145 }
1146 }
1147 sp -= count;
1148 NEXT();
1149 }
1150
1151 LABEL(kStoreSwizzle) {
1152 int target = READ8();
1153 int count = READ8();
1154 for (int i = count - 1; i >= 0; --i) {
1155 stack[target + *(ip + i)] = skvx::if_then_else(
1156 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
1157 }
1158 ip += count;
1159 NEXT();
1160 }
1161
1162 LABEL(kStoreSwizzleGlobal) {
1163 int target = READ8();
1164 int count = READ8();
1165 for (int i = count - 1; i >= 0; --i) {
1166 globals[target + *(ip + i)] = skvx::if_then_else(
1167 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
1168 }
1169 ip += count;
1170 NEXT();
1171 }
1172
1173 LABEL(kStoreSwizzleIndirect) {
1174 int count = READ8();
1175 I32 target = POP().fSigned;
1176 I32 m = mask();
1177 for (int i = count - 1; i >= 0; --i) {
1178 I32 v = POP().fSigned;
1179 for (int j = 0; j < VecWidth; ++j) {
1180 if (m[j]) {
1181 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
1182 }
1183 }
1184 }
1185 ip += count;
1186 NEXT();
1187 }
1188
1189 LABEL(kStoreSwizzleIndirectGlobal) {
1190 int count = READ8();
1191 I32 target = POP().fSigned;
1192 I32 m = mask();
1193 for (int i = count - 1; i >= 0; --i) {
1194 I32 v = POP().fSigned;
1195 for (int j = 0; j < VecWidth; ++j) {
1196 if (m[j]) {
1197 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
1198 }
1199 }
1200 }
1201 ip += count;
1202 NEXT();
1203 }
1204
1205 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
1206 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
1207
1208 LABEL(kSwizzle) {
1209 VValue tmp[4];
1210 for (int i = READ8() - 1; i >= 0; --i) {
1211 tmp[i] = POP();
1212 }
1213 for (int i = READ8() - 1; i >= 0; --i) {
1214 PUSH(tmp[READ8()]);
1215 }
1216 NEXT();
1217 }
1218
1219 VECTOR_UNARY_FN_VEC(kTan, tanf)
1220
1221 LABEL(kWriteExternal4)
1222 LABEL(kWriteExternal3)
1223 LABEL(kWriteExternal2)
1224 LABEL(kWriteExternal) {
1225 int count = READ8();
1226 int target = READ8();
1227 float tmp[4];
1228 I32 m = mask();
1229 sp -= count;
1230 for (int i = 0; i < VecWidth; ++i) {
1231 if (m[i]) {
1232 for (int j = 0; j < count; ++j) {
1233 tmp[j] = sp[j + 1].fFloat[i];
1234 }
1235 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
1236 }
1237 }
1238 NEXT();
1239 }
1240
1241 LABEL(kMaskPush)
1242 condPtr[1] = POP().fSigned;
1243 maskPtr[1] = maskPtr[0] & condPtr[1];
1244 ++condPtr; ++maskPtr;
1245 NEXT();
1246 LABEL(kMaskPop)
1247 --condPtr; --maskPtr;
1248 NEXT();
1249 LABEL(kMaskNegate)
1250 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
1251 NEXT();
1252 LABEL(kMaskBlend) {
1253 int count = READ8();
1254 I32 m = condPtr[0];
1255 --condPtr; --maskPtr;
1256 for (int i = 0; i < count; ++i) {
1257 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1258 --sp;
1259 }
1260 NEXT();
1261 }
1262 LABEL(kBranchIfAllFalse) {
1263 int target = READ16();
1264 if (!skvx::any(mask())) {
1265 ip = code + target;
1266 }
1267 NEXT();
1268 }
1269
1270 LABEL(kLoopBegin)
1271 contPtr[1] = 0;
1272 loopPtr[1] = loopPtr[0];
1273 ++contPtr; ++loopPtr;
1274 NEXT();
1275 LABEL(kLoopNext)
1276 *loopPtr |= *contPtr;
1277 *contPtr = 0;
1278 NEXT();
1279 LABEL(kLoopMask)
1280 *loopPtr &= POP().fSigned;
1281 NEXT();
1282 LABEL(kLoopEnd)
1283 --contPtr; --loopPtr;
1284 NEXT();
1285 LABEL(kLoopBreak)
1286 *loopPtr &= ~mask();
1287 NEXT();
1288 LABEL(kLoopContinue) {
1289 I32 m = mask();
1290 *contPtr |= m;
1291 *loopPtr &= ~m;
1292 NEXT();
1293 }
1294#ifdef SKSLC_THREADED_CODE
1295 #ifdef TRACE
1296 next:
1297 printf("at %3d (stack: %d) (disable threaded code for disassembly)\n",
1298 (int) (ip - code), (int) (sp - stack) + 1);
1299 goto *READ_INST();
1300 #endif
1301#else
1302 }
1303 }
1304#endif
Brian Osman569f12f2019-06-13 11:23:57 -04001305}
1306
Brian Osman08a84962019-06-14 10:17:16 -04001307} // namespace Interpreter
1308
Brian Osman489cf882019-07-09 10:48:28 -04001309#endif // SK_ENABLE_SKSL_INTERPRETER
1310
Mike Reed634c9412019-07-18 13:20:04 -04001311#undef spf
1312
Brian Osman08a84962019-06-14 10:17:16 -04001313void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001314#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001315 const uint8_t* ip = fCode.data();
1316 while (ip < fCode.data() + fCode.size()) {
1317 printf("%d: ", (int)(ip - fCode.data()));
1318 ip = Interpreter::disassemble_instruction(ip);
1319 printf("\n");
1320 }
Brian Osman489cf882019-07-09 10:48:28 -04001321#endif
Brian Osman08a84962019-06-14 10:17:16 -04001322}
1323
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001324#define VECTOR_PREPROCESS(base) \
1325 case ByteCodeInstruction::base ## 4: \
1326 case ByteCodeInstruction::base ## 3: \
1327 case ByteCodeInstruction::base ## 2: \
1328 case ByteCodeInstruction::base: READ8(); break;
1329
1330#define VECTOR_PREPROCESS_NO_COUNT(base) \
1331 case ByteCodeInstruction::base ## 4: \
1332 case ByteCodeInstruction::base ## 3: \
1333 case ByteCodeInstruction::base ## 2: \
1334 case ByteCodeInstruction::base: break;
1335
1336#define VECTOR_MATRIX_PREPROCESS(base) \
1337 VECTOR_PREPROCESS(base) \
1338 case ByteCodeInstruction::base ## N: READ8(); break;
1339
1340#define VECTOR_MATRIX_PREPROCESS_NO_COUNT(base) \
1341 VECTOR_PREPROCESS_NO_COUNT(base) \
1342 case ByteCodeInstruction::base ## N: READ8(); break;
1343
1344void ByteCodeFunction::preprocess(const void* labels[]) {
1345#if defined(SK_ENABLE_SKSL_INTERPRETER)
1346#ifdef TRACE
1347 this->disassemble();
1348#endif
Ethan Nicholasc70027b2019-09-05 16:50:52 -04001349 uint8_t* ip = fCode.data();
1350 while (ip < fCode.data() + fCode.size()) {
1351 ByteCodeInstruction inst = (ByteCodeInstruction) (intptr_t) READ_INST();
1352 const void* label = labels[(int) inst];
1353 memcpy(ip - sizeof(instruction), &label, sizeof(label));
1354 switch (inst) {
1355 VECTOR_MATRIX_PREPROCESS(kAddF)
1356 VECTOR_PREPROCESS(kAddI)
1357 case ByteCodeInstruction::kAndB: break;
1358 case ByteCodeInstruction::kBranch: READ16(); break;
1359 case ByteCodeInstruction::kCall: READ8(); break;
1360 case ByteCodeInstruction::kCallExternal: {
1361 READ8();
1362 READ8();
1363 READ8();
1364 break;
1365 }
1366 case ByteCodeInstruction::kClampIndex: READ8(); break;
1367 VECTOR_PREPROCESS(kCompareIEQ)
1368 VECTOR_PREPROCESS(kCompareINEQ)
1369 VECTOR_MATRIX_PREPROCESS(kCompareFEQ)
1370 VECTOR_MATRIX_PREPROCESS(kCompareFNEQ)
1371 VECTOR_PREPROCESS(kCompareFGT)
1372 VECTOR_PREPROCESS(kCompareFGTEQ)
1373 VECTOR_PREPROCESS(kCompareFLT)
1374 VECTOR_PREPROCESS(kCompareFLTEQ)
1375 VECTOR_PREPROCESS(kCompareSGT)
1376 VECTOR_PREPROCESS(kCompareSGTEQ)
1377 VECTOR_PREPROCESS(kCompareSLT)
1378 VECTOR_PREPROCESS(kCompareSLTEQ)
1379 VECTOR_PREPROCESS(kCompareUGT)
1380 VECTOR_PREPROCESS(kCompareUGTEQ)
1381 VECTOR_PREPROCESS(kCompareULT)
1382 VECTOR_PREPROCESS(kCompareULTEQ)
1383 VECTOR_PREPROCESS_NO_COUNT(kConvertFtoI)
1384 VECTOR_PREPROCESS_NO_COUNT(kConvertStoF)
1385 VECTOR_PREPROCESS_NO_COUNT(kConvertUtoF)
1386 VECTOR_PREPROCESS(kCos)
1387 VECTOR_MATRIX_PREPROCESS(kDivideF)
1388 VECTOR_PREPROCESS(kDivideS)
1389 VECTOR_PREPROCESS(kDivideU)
1390 VECTOR_MATRIX_PREPROCESS(kDup)
1391
1392 case ByteCodeInstruction::kInverse2x2:
1393 case ByteCodeInstruction::kInverse3x3:
1394 case ByteCodeInstruction::kInverse4x4: break;
1395
1396 case ByteCodeInstruction::kLoad:
1397 case ByteCodeInstruction::kLoad2:
1398 case ByteCodeInstruction::kLoad3:
1399 case ByteCodeInstruction::kLoad4:
1400 case ByteCodeInstruction::kLoadGlobal:
1401 case ByteCodeInstruction::kLoadGlobal2:
1402 case ByteCodeInstruction::kLoadGlobal3:
1403 case ByteCodeInstruction::kLoadGlobal4: READ16(); break;
1404
1405 case ByteCodeInstruction::kLoadSwizzle:
1406 case ByteCodeInstruction::kLoadSwizzleGlobal: {
1407 READ8();
1408 int count = READ8();
1409 ip += count;
1410 break;
1411 }
1412
1413 case ByteCodeInstruction::kLoadExtended:
1414 case ByteCodeInstruction::kLoadExtendedGlobal:
1415 READ8();
1416 break;
1417
1418 case ByteCodeInstruction::kMatrixToMatrix: {
1419 READ8();
1420 READ8();
1421 READ8();
1422 READ8();
1423 break;
1424 }
1425 case ByteCodeInstruction::kMatrixMultiply: {
1426 READ8();
1427 READ8();
1428 READ8();
1429 break;
1430 }
1431 VECTOR_MATRIX_PREPROCESS(kMultiplyF)
1432 VECTOR_PREPROCESS(kMultiplyI)
1433 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kNegateF)
1434 VECTOR_PREPROCESS_NO_COUNT(kNegateI)
1435 case ByteCodeInstruction::kNotB: break;
1436 case ByteCodeInstruction::kOrB: break;
1437 VECTOR_MATRIX_PREPROCESS_NO_COUNT(kPop)
1438 case ByteCodeInstruction::kPushImmediate: READ32(); break;
1439
1440 case ByteCodeInstruction::kReadExternal:
1441 case ByteCodeInstruction::kReadExternal2:
1442 case ByteCodeInstruction::kReadExternal3:
1443 case ByteCodeInstruction::kReadExternal4: READ16(); break;
1444
1445 VECTOR_PREPROCESS(kRemainderF)
1446 VECTOR_PREPROCESS(kRemainderS)
1447 VECTOR_PREPROCESS(kRemainderU)
1448 case ByteCodeInstruction::kReserve: READ8(); break;
1449 case ByteCodeInstruction::kReturn: READ8(); break;
1450 case ByteCodeInstruction::kScalarToMatrix: READ8(); READ8(); break;
1451 VECTOR_PREPROCESS(kSin)
1452 VECTOR_PREPROCESS_NO_COUNT(kSqrt)
1453
1454 case ByteCodeInstruction::kStore:
1455 case ByteCodeInstruction::kStore2:
1456 case ByteCodeInstruction::kStore3:
1457 case ByteCodeInstruction::kStore4:
1458 case ByteCodeInstruction::kStoreGlobal:
1459 case ByteCodeInstruction::kStoreGlobal2:
1460 case ByteCodeInstruction::kStoreGlobal3:
1461 case ByteCodeInstruction::kStoreGlobal4: READ8(); break;
1462
1463 case ByteCodeInstruction::kStoreSwizzle:
1464 case ByteCodeInstruction::kStoreSwizzleGlobal: {
1465 READ8();
1466 int count = READ8();
1467 ip += count;
1468 break;
1469 }
1470
1471 case ByteCodeInstruction::kStoreSwizzleIndirect:
1472 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
1473 int count = READ8();
1474 ip += count;
1475 break;
1476 }
1477
1478 case ByteCodeInstruction::kStoreExtended: READ8(); break;
1479 case ByteCodeInstruction::kStoreExtendedGlobal: READ8(); break;
1480
1481 VECTOR_MATRIX_PREPROCESS(kSubtractF)
1482 VECTOR_PREPROCESS(kSubtractI)
1483
1484 case ByteCodeInstruction::kSwizzle: {
1485 READ8();
1486 int count = READ8();
1487 ip += count;
1488 break;
1489 }
1490 VECTOR_PREPROCESS(kTan)
1491 case ByteCodeInstruction::kWriteExternal:
1492 case ByteCodeInstruction::kWriteExternal2:
1493 case ByteCodeInstruction::kWriteExternal3:
1494 case ByteCodeInstruction::kWriteExternal4: READ16(); break;
1495
1496 case ByteCodeInstruction::kXorB: break;
1497 case ByteCodeInstruction::kMaskPush: break;
1498 case ByteCodeInstruction::kMaskPop: break;
1499 case ByteCodeInstruction::kMaskNegate: break;
1500 case ByteCodeInstruction::kMaskBlend: READ8(); break;
1501 case ByteCodeInstruction::kBranchIfAllFalse: READ16(); break;
1502 case ByteCodeInstruction::kLoopBegin: break;
1503 case ByteCodeInstruction::kLoopNext: break;
1504 case ByteCodeInstruction::kLoopMask: break;
1505 case ByteCodeInstruction::kLoopEnd: break;
1506 case ByteCodeInstruction::kLoopContinue: break;
1507 case ByteCodeInstruction::kLoopBreak: break;
1508 default:
1509 ip -= 2;
1510 printf("unknown(%d)\n", READ16());
1511 SkASSERT(false);
1512 }
1513 }
1514#endif
1515}
1516
Brian Osman869a3e82019-07-18 17:00:34 -04001517bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
Brian Osman08a84962019-06-14 10:17:16 -04001518 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001519#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman4b202a32019-06-21 09:50:29 -04001520 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001521 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1522 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001523 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001524 }
Brian Osmanef787f72019-06-13 13:07:12 -04001525
Brian Osman869a3e82019-07-18 17:00:34 -04001526 if (uniformCount != (int)fInputSlots.size()) {
1527 return false;
1528 }
1529
Brian Osman08a84962019-06-14 10:17:16 -04001530 Interpreter::VValue globals[32];
Brian Osman869a3e82019-07-18 17:00:34 -04001531 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1532 return false;
1533 }
Brian Osman08a84962019-06-14 10:17:16 -04001534 for (uint8_t slot : fInputSlots) {
1535 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001536 }
1537
Brian Osman1a79f0b2019-06-24 16:32:14 -04001538 int baseIndex = 0;
1539
Brian Osman569f12f2019-06-13 11:23:57 -04001540 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001541 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001542
1543 // Transpose args into stack
1544 {
Brian Osman08a84962019-06-14 10:17:16 -04001545 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001546 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001547 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001548 for (int j = f->fParameterCount; j > 0; --j) {
1549 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001550 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001551 }
1552 }
1553 }
1554
Mike Reed3fd3cc92019-06-20 12:40:30 -04001555 bool stripedOutput = false;
1556 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman869a3e82019-07-18 17:00:34 -04001557 if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
1558 return false;
1559 }
Brian Osman569f12f2019-06-13 11:23:57 -04001560
1561 // Transpose out parameters back
1562 {
Brian Osman08a84962019-06-14 10:17:16 -04001563 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001564 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001565 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001566 for (const auto& p : f->fParameters) {
1567 if (p.fIsOutParameter) {
1568 for (int j = p.fSlotCount; j > 0; --j) {
1569 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001570 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001571 }
1572 } else {
1573 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001574 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001575 }
1576 }
1577 }
1578 }
1579
1580 args += f->fParameterCount * w;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001581 if (outReturn) {
1582 outReturn += f->fReturnCount * w;
1583 }
Brian Osman4b202a32019-06-21 09:50:29 -04001584 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001585 baseIndex += w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001586 }
Brian Osman869a3e82019-07-18 17:00:34 -04001587 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001588#else
1589 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001590 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001591#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001592}
1593
Brian Osman869a3e82019-07-18 17:00:34 -04001594bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
Mike Reed3fd3cc92019-06-20 12:40:30 -04001595 const float* uniforms, int uniformCount,
1596 float* outArgs[], int outCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001597#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001598 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001599 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1600 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001601 return false;
1602 }
1603
1604 if (nargs != f->fParameterCount ||
1605 outCount != f->fReturnCount ||
1606 uniformCount != (int)fInputSlots.size()) {
1607 return false;
1608 }
1609
1610 Interpreter::VValue globals[32];
1611 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1612 return false;
1613 }
1614 for (uint8_t slot : fInputSlots) {
1615 globals[slot].fFloat = *uniforms++;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001616 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001617
Mike Reed3fd3cc92019-06-20 12:40:30 -04001618 // innerRun just takes outArgs, so clear it if the count is zero
1619 if (outCount == 0) {
1620 outArgs = nullptr;
1621 }
1622
Brian Osman1a79f0b2019-06-24 16:32:14 -04001623 int baseIndex = 0;
1624
Brian Osman2b1a5442019-06-19 11:40:33 -04001625 while (N) {
1626 int w = std::min(N, Interpreter::VecWidth);
1627
1628 // Copy args into stack
1629 for (int i = 0; i < nargs; ++i) {
1630 memcpy(stack + i, args[i], w * sizeof(float));
1631 }
1632
Mike Reed3fd3cc92019-06-20 12:40:30 -04001633 bool stripedOutput = true;
Brian Osman869a3e82019-07-18 17:00:34 -04001634 if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
1635 return false;
1636 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001637
1638 // Copy out parameters back
1639 int slot = 0;
1640 for (const auto& p : f->fParameters) {
1641 if (p.fIsOutParameter) {
1642 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1643 memcpy(args[i], stack + i, w * sizeof(float));
1644 }
1645 }
1646 slot += p.fSlotCount;
1647 }
1648
1649 // Step each argument pointer ahead
1650 for (int i = 0; i < nargs; ++i) {
1651 args[i] += w;
1652 }
1653 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001654 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001655 }
Brian Osman869a3e82019-07-18 17:00:34 -04001656
1657 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001658#else
1659 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001660 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001661#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001662}
1663
Brian Osman80164412019-06-07 13:00:23 -04001664} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001665
1666#endif