blob: 9f5d3e85873b28f66783a85a018e59b6723a4bdd [file] [log] [blame]
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_STANDALONE
9
Ethan Nicholasae9633b2019-05-24 12:46:34 -040010#include "include/core/SkPoint3.h"
Brian Osman569f12f2019-06-13 11:23:57 -040011#include "include/private/SkVx.h"
Mike Klein7a177b42019-06-17 17:17:47 -050012#include "src/core/SkUtils.h" // sk_unaligned_load
Brian Osman80164412019-06-07 13:00:23 -040013#include "src/sksl/SkSLByteCode.h"
Brian Osman07c117b2019-05-23 12:51:06 -070014#include "src/sksl/SkSLByteCodeGenerator.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040015#include "src/sksl/SkSLExternalValue.h"
Brian Osman80164412019-06-07 13:00:23 -040016
17#include <vector>
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040018
19namespace SkSL {
Brian Osman489cf882019-07-09 10:48:28 -040020
21#if defined(SK_ENABLE_SKSL_INTERPRETER)
22
Brian Osman80164412019-06-07 13:00:23 -040023namespace Interpreter {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040024
Mike Reed3fd3cc92019-06-20 12:40:30 -040025constexpr int VecWidth = ByteCode::kVecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -040026
27using F32 = skvx::Vec<VecWidth, float>;
28using I32 = skvx::Vec<VecWidth, int32_t>;
29using U32 = skvx::Vec<VecWidth, uint32_t>;
30
Mike Kleine7007382019-05-21 08:36:32 -050031#define READ8() (*(ip++))
Mike Klein7a177b42019-06-17 17:17:47 -050032#define READ16() (ip += 2, sk_unaligned_load<uint16_t>(ip - 2))
33#define READ32() (ip += 4, sk_unaligned_load<uint32_t>(ip - 4))
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040034
Ethan Nicholascbdc8292019-09-05 18:06:38 +000035#define VECTOR_DISASSEMBLE(op, text) \
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040036 case ByteCodeInstruction::op: printf(text); break; \
37 case ByteCodeInstruction::op##2: printf(text "2"); break; \
38 case ByteCodeInstruction::op##3: printf(text "3"); break; \
39 case ByteCodeInstruction::op##4: printf(text "4"); break;
40
Ethan Nicholascbdc8292019-09-05 18:06:38 +000041#define VECTOR_MATRIX_DISASSEMBLE(op, text) \
42 case ByteCodeInstruction::op: printf(text); break; \
43 case ByteCodeInstruction::op##2: printf(text "2"); break; \
44 case ByteCodeInstruction::op##3: printf(text "3"); break; \
45 case ByteCodeInstruction::op##4: printf(text "4"); break; \
Brian Osman1e855b22019-05-29 15:21:52 -040046 case ByteCodeInstruction::op##N: printf(text "N %d", READ8()); break;
47
Brian Osman3e833e12019-05-23 13:23:24 -070048static const uint8_t* disassemble_instruction(const uint8_t* ip) {
49 switch ((ByteCodeInstruction) READ16()) {
Brian Osman1e855b22019-05-29 15:21:52 -040050 VECTOR_MATRIX_DISASSEMBLE(kAddF, "addf")
Brian Osman3e833e12019-05-23 13:23:24 -070051 VECTOR_DISASSEMBLE(kAddI, "addi")
Brian Osman32c526b2019-06-03 16:13:52 -040052 case ByteCodeInstruction::kAndB: printf("andb"); break;
Brian Osman3e833e12019-05-23 13:23:24 -070053 case ByteCodeInstruction::kBranch: printf("branch %d", READ16()); break;
54 case ByteCodeInstruction::kCall: printf("call %d", READ8()); break;
55 case ByteCodeInstruction::kCallExternal: {
56 int argumentCount = READ8();
57 int returnCount = READ8();
58 int externalValue = READ8();
59 printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
60 break;
61 }
Brian Osman869a3e82019-07-18 17:00:34 -040062 case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -070063 VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
64 VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
Brian Osman1e855b22019-05-29 15:21:52 -040065 VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
66 VECTOR_MATRIX_DISASSEMBLE(kCompareFNEQ, "comparefneq")
Brian Osman3e833e12019-05-23 13:23:24 -070067 VECTOR_DISASSEMBLE(kCompareFGT, "comparefgt")
68 VECTOR_DISASSEMBLE(kCompareFGTEQ, "comparefgteq")
69 VECTOR_DISASSEMBLE(kCompareFLT, "compareflt")
70 VECTOR_DISASSEMBLE(kCompareFLTEQ, "compareflteq")
71 VECTOR_DISASSEMBLE(kCompareSGT, "comparesgt")
72 VECTOR_DISASSEMBLE(kCompareSGTEQ, "comparesgteq")
73 VECTOR_DISASSEMBLE(kCompareSLT, "compareslt")
74 VECTOR_DISASSEMBLE(kCompareSLTEQ, "compareslteq")
75 VECTOR_DISASSEMBLE(kCompareUGT, "compareugt")
76 VECTOR_DISASSEMBLE(kCompareUGTEQ, "compareugteq")
77 VECTOR_DISASSEMBLE(kCompareULT, "compareult")
78 VECTOR_DISASSEMBLE(kCompareULTEQ, "compareulteq")
Ethan Nicholascbdc8292019-09-05 18:06:38 +000079 VECTOR_DISASSEMBLE(kConvertFtoI, "convertftoi")
80 VECTOR_DISASSEMBLE(kConvertStoF, "convertstof")
81 VECTOR_DISASSEMBLE(kConvertUtoF, "convertutof")
Brian Osman3e833e12019-05-23 13:23:24 -070082 VECTOR_DISASSEMBLE(kCos, "cos")
Brian Osman1e855b22019-05-29 15:21:52 -040083 VECTOR_MATRIX_DISASSEMBLE(kDivideF, "dividef")
Brian Osman3e833e12019-05-23 13:23:24 -070084 VECTOR_DISASSEMBLE(kDivideS, "divideS")
85 VECTOR_DISASSEMBLE(kDivideU, "divideu")
Brian Osman1e855b22019-05-29 15:21:52 -040086 VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
Mike Reed634c9412019-07-18 13:20:04 -040087 case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
88 case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
89 case ByteCodeInstruction::kInverse4x4: printf("inverse4x4"); break;
Ethan Nicholascbdc8292019-09-05 18:06:38 +000090 case ByteCodeInstruction::kLoad: printf("load %d", READ8()); break;
91 case ByteCodeInstruction::kLoad2: printf("load2 %d", READ8()); break;
92 case ByteCodeInstruction::kLoad3: printf("load3 %d", READ8()); break;
93 case ByteCodeInstruction::kLoad4: printf("load4 %d", READ8()); break;
94 case ByteCodeInstruction::kLoadGlobal: printf("loadglobal %d", READ8()); break;
95 case ByteCodeInstruction::kLoadGlobal2: printf("loadglobal2 %d", READ8()); break;
96 case ByteCodeInstruction::kLoadGlobal3: printf("loadglobal3 %d", READ8()); break;
97 case ByteCodeInstruction::kLoadGlobal4: printf("loadglobal4 %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -070098 case ByteCodeInstruction::kLoadSwizzle: {
99 int target = READ8();
100 int count = READ8();
101 printf("loadswizzle %d %d", target, count);
102 for (int i = 0; i < count; ++i) {
103 printf(", %d", READ8());
104 }
105 break;
106 }
107 case ByteCodeInstruction::kLoadSwizzleGlobal: {
108 int target = READ8();
109 int count = READ8();
110 printf("loadswizzleglobal %d %d", target, count);
111 for (int i = 0; i < count; ++i) {
112 printf(", %d", READ8());
113 }
114 break;
115 }
116 case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
117 case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
118 break;
Brian Osman29e013d2019-05-28 17:16:03 -0400119 case ByteCodeInstruction::kMatrixToMatrix: {
120 int srcCols = READ8();
121 int srcRows = READ8();
122 int dstCols = READ8();
123 int dstRows = READ8();
124 printf("matrixtomatrix %dx%d %dx%d", srcCols, srcRows, dstCols, dstRows);
125 break;
126 }
Brian Osman909231c2019-05-29 15:34:36 -0400127 case ByteCodeInstruction::kMatrixMultiply: {
128 int lCols = READ8();
129 int lRows = READ8();
130 int rCols = READ8();
131 printf("matrixmultiply %dx%d %dx%d", lCols, lRows, rCols, lCols);
132 break;
133 }
Brian Osman1e855b22019-05-29 15:21:52 -0400134 VECTOR_MATRIX_DISASSEMBLE(kMultiplyF, "multiplyf")
Brian Osman3e833e12019-05-23 13:23:24 -0700135 VECTOR_DISASSEMBLE(kMultiplyI, "multiplyi")
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000136 VECTOR_MATRIX_DISASSEMBLE(kNegateF, "negatef")
137 VECTOR_DISASSEMBLE(kNegateI, "negatei")
Brian Osman569f12f2019-06-13 11:23:57 -0400138 case ByteCodeInstruction::kNotB: printf("notb"); break;
Brian Osman32c526b2019-06-03 16:13:52 -0400139 case ByteCodeInstruction::kOrB: printf("orb"); break;
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000140 VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
Brian Osman3e833e12019-05-23 13:23:24 -0700141 case ByteCodeInstruction::kPushImmediate: {
142 uint32_t v = READ32();
143 union { uint32_t u; float f; } pun = { v };
144 printf("pushimmediate %s", (to_string(v) + "(" + to_string(pun.f) + ")").c_str());
145 break;
146 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000147 case ByteCodeInstruction::kReadExternal: printf("readexternal %d", READ8()); break;
148 case ByteCodeInstruction::kReadExternal2: printf("readexternal2 %d", READ8()); break;
149 case ByteCodeInstruction::kReadExternal3: printf("readexternal3 %d", READ8()); break;
150 case ByteCodeInstruction::kReadExternal4: printf("readexternal4 %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700151 VECTOR_DISASSEMBLE(kRemainderF, "remainderf")
152 VECTOR_DISASSEMBLE(kRemainderS, "remainders")
153 VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
Brian Osmand3494ed2019-06-20 15:41:34 -0400154 case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
Brian Osman3e833e12019-05-23 13:23:24 -0700155 case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
Brian Osman29e013d2019-05-28 17:16:03 -0400156 case ByteCodeInstruction::kScalarToMatrix: {
157 int cols = READ8();
158 int rows = READ8();
159 printf("scalartomatrix %dx%d", cols, rows);
160 break;
161 }
Brian Osman3e833e12019-05-23 13:23:24 -0700162 VECTOR_DISASSEMBLE(kSin, "sin")
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000163 VECTOR_DISASSEMBLE(kSqrt, "sqrt")
Brian Osman3e833e12019-05-23 13:23:24 -0700164 case ByteCodeInstruction::kStore: printf("store %d", READ8()); break;
165 case ByteCodeInstruction::kStore2: printf("store2 %d", READ8()); break;
166 case ByteCodeInstruction::kStore3: printf("store3 %d", READ8()); break;
167 case ByteCodeInstruction::kStore4: printf("store4 %d", READ8()); break;
168 case ByteCodeInstruction::kStoreGlobal: printf("storeglobal %d", READ8()); break;
169 case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
170 case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
171 case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
172 case ByteCodeInstruction::kStoreSwizzle: {
173 int target = READ8();
174 int count = READ8();
175 printf("storeswizzle %d %d", target, count);
176 for (int i = 0; i < count; ++i) {
177 printf(", %d", READ8());
178 }
179 break;
180 }
181 case ByteCodeInstruction::kStoreSwizzleGlobal: {
182 int target = READ8();
183 int count = READ8();
184 printf("storeswizzleglobal %d %d", target, count);
185 for (int i = 0; i < count; ++i) {
186 printf(", %d", READ8());
187 }
188 break;
189 }
190 case ByteCodeInstruction::kStoreSwizzleIndirect: {
191 int count = READ8();
192 printf("storeswizzleindirect %d", count);
193 for (int i = 0; i < count; ++i) {
194 printf(", %d", READ8());
195 }
196 break;
197 }
198 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
199 int count = READ8();
200 printf("storeswizzleindirectglobal %d", count);
201 for (int i = 0; i < count; ++i) {
202 printf(", %d", READ8());
203 }
204 break;
205 }
206 case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
207 case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
208 break;
Brian Osman1e855b22019-05-29 15:21:52 -0400209 VECTOR_MATRIX_DISASSEMBLE(kSubtractF, "subtractf")
Brian Osman3e833e12019-05-23 13:23:24 -0700210 VECTOR_DISASSEMBLE(kSubtractI, "subtracti")
211 case ByteCodeInstruction::kSwizzle: {
212 printf("swizzle %d, ", READ8());
213 int count = READ8();
214 printf("%d", count);
215 for (int i = 0; i < count; ++i) {
216 printf(", %d", READ8());
217 }
218 break;
219 }
220 VECTOR_DISASSEMBLE(kTan, "tan")
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000221 case ByteCodeInstruction::kWriteExternal: printf("writeexternal %d", READ8()); break;
222 case ByteCodeInstruction::kWriteExternal2: printf("writeexternal2 %d", READ8()); break;
223 case ByteCodeInstruction::kWriteExternal3: printf("writeexternal3 %d", READ8()); break;
224 case ByteCodeInstruction::kWriteExternal4: printf("writeexternal4 %d", READ8()); break;
Brian Osman569f12f2019-06-13 11:23:57 -0400225 case ByteCodeInstruction::kXorB: printf("xorb"); break;
226 case ByteCodeInstruction::kMaskPush: printf("maskpush"); break;
227 case ByteCodeInstruction::kMaskPop: printf("maskpop"); break;
228 case ByteCodeInstruction::kMaskNegate: printf("masknegate"); break;
229 case ByteCodeInstruction::kMaskBlend: printf("maskblend %d", READ8()); break;
230 case ByteCodeInstruction::kBranchIfAllFalse:
231 printf("branchifallfalse %d", READ16());
232 break;
233 case ByteCodeInstruction::kLoopBegin: printf("loopbegin"); break;
234 case ByteCodeInstruction::kLoopNext: printf("loopnext"); break;
235 case ByteCodeInstruction::kLoopMask: printf("loopmask"); break;
236 case ByteCodeInstruction::kLoopEnd: printf("loopend"); break;
237 case ByteCodeInstruction::kLoopContinue: printf("loopcontinue"); break;
238 case ByteCodeInstruction::kLoopBreak: printf("loopbreak"); break;
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000239 default: printf("unknown(%d)\n", *(ip - 1)); SkASSERT(false);
Brian Osman3e833e12019-05-23 13:23:24 -0700240 }
241 return ip;
242}
243
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000244#define VECTOR_BINARY_OP(base, field, op) \
245 case ByteCodeInstruction::base ## 4: \
246 sp[-4] = sp[-4].field op sp[0].field; \
247 POP(); \
248 /* fall through */ \
249 case ByteCodeInstruction::base ## 3: { \
250 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
251 sp[count] = sp[count].field op sp[0].field; \
252 POP(); \
253 } /* fall through */ \
254 case ByteCodeInstruction::base ## 2: { \
255 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
256 sp[count] = sp[count].field op sp[0].field; \
257 POP(); \
258 } /* fall through */ \
259 case ByteCodeInstruction::base: { \
260 int count = (int) ByteCodeInstruction::base - (int) inst - 1; \
261 sp[count] = sp[count].field op sp[0].field; \
262 POP(); \
263 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500264 }
Ethan Nicholasaeb71ce2019-05-20 09:55:44 -0400265
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000266#define VECTOR_MATRIX_BINARY_OP(base, field, op) \
267 VECTOR_BINARY_OP(base, field, op) \
268 case ByteCodeInstruction::base ## N: { \
269 int count = READ8(); \
270 for (int i = count; i > 0; --i) { \
271 sp[-count] = sp[-count].field op sp[0].field; \
272 POP(); \
273 } \
274 break; \
Brian Osman1e855b22019-05-29 15:21:52 -0400275 }
276
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000277#define VECTOR_BINARY_FN(base, field, fn) \
278 case ByteCodeInstruction::base ## 4: \
279 sp[-4] = fn(sp[-4].field, sp[0].field); \
280 POP(); \
281 /* fall through */ \
282 case ByteCodeInstruction::base ## 3: { \
283 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
284 sp[target] = fn(sp[target].field, sp[0].field); \
285 POP(); \
286 } /* fall through */ \
287 case ByteCodeInstruction::base ## 2: { \
288 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
289 sp[target] = fn(sp[target].field, sp[0].field); \
290 POP(); \
291 } /* fall through */ \
292 case ByteCodeInstruction::base: { \
293 int target = (int) ByteCodeInstruction::base - (int) inst - 1; \
294 sp[target] = fn(sp[target].field, sp[0].field); \
295 POP(); \
296 break; \
Mike Kleine7007382019-05-21 08:36:32 -0500297 }
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400298
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000299#define VECTOR_UNARY_FN(base, fn, field) \
300 case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
301 case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
302 case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
303 case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
304 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400305
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000306#define VECTOR_UNARY_FN_VEC(base, fn) \
307 case ByteCodeInstruction::base ## 4: \
308 case ByteCodeInstruction::base ## 3: \
309 case ByteCodeInstruction::base ## 2: \
310 case ByteCodeInstruction::base : { \
311 int count = (int)inst - (int)ByteCodeInstruction::base + 1; \
312 float* v = (float*)sp - count + 1; \
313 for (int i = VecWidth * count; i > 0; --i, ++v) { \
314 *v = fn(*v); \
315 } \
316 break; \
Brian Osman569f12f2019-06-13 11:23:57 -0400317 }
318
319union VValue {
320 VValue() {}
321
322 VValue(F32 f)
323 : fFloat(f) {
324 }
325
326 VValue(I32 s)
327 : fSigned(s) {
328 }
329
330 VValue(U32 u)
331 : fUnsigned(u) {
332 }
333
334 F32 fFloat;
335 I32 fSigned;
336 U32 fUnsigned;
337};
338
Brian Osman226668a2019-05-14 16:47:30 -0400339struct StackFrame {
340 const uint8_t* fCode;
341 const uint8_t* fIP;
Brian Osman569f12f2019-06-13 11:23:57 -0400342 VValue* fStack;
Brian Osmand3494ed2019-06-20 15:41:34 -0400343 int fParameterCount;
Brian Osman226668a2019-05-14 16:47:30 -0400344};
345
Brian Osman569f12f2019-06-13 11:23:57 -0400346// TODO: trunc on integers?
347template <typename T>
348static T vec_mod(T a, T b) {
349 return a - skvx::trunc(a / b) * b;
350}
Mike Kleine7007382019-05-21 08:36:32 -0500351
Mike Reed634c9412019-07-18 13:20:04 -0400352#define spf(index) sp[index].fFloat
353
Brian Osman869a3e82019-07-18 17:00:34 -0400354static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
Brian Osman1a79f0b2019-06-24 16:32:14 -0400355 float* outReturn[], VValue globals[], bool stripedOutput, int N,
356 int baseIndex) {
Brian Osman4b202a32019-06-21 09:50:29 -0400357 // Needs to be the first N non-negative integers, at least as large as VecWidth
358 static const Interpreter::I32 gLanes = {
359 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
360 };
361
Brian Osman569f12f2019-06-13 11:23:57 -0400362 VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
363
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000364 auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
365 auto PUSH = [&](VValue v) { SkASSERT(sp + 1 >= stack); *(++sp) = v; };
Mike Kleine7007382019-05-21 08:36:32 -0500366
Brian Osman80164412019-06-07 13:00:23 -0400367 const uint8_t* code = f->fCode.data();
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400368 const uint8_t* ip = code;
Brian Osman226668a2019-05-14 16:47:30 -0400369 std::vector<StackFrame> frames;
370
Brian Osman569f12f2019-06-13 11:23:57 -0400371 I32 condStack[16]; // Independent condition masks
372 I32 maskStack[16]; // Combined masks (eg maskStack[0] & maskStack[1] & ...)
373 I32 contStack[16]; // Continue flags for loops
374 I32 loopStack[16]; // Loop execution masks
Brian Osman4b202a32019-06-21 09:50:29 -0400375 condStack[0] = maskStack[0] = (gLanes < N);
Brian Osman569f12f2019-06-13 11:23:57 -0400376 contStack[0] = I32( 0);
377 loopStack[0] = I32(~0);
378 I32* condPtr = condStack;
379 I32* maskPtr = maskStack;
380 I32* contPtr = contStack;
381 I32* loopPtr = loopStack;
382
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400383 if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
384 f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
Brian Osman869a3e82019-07-18 17:00:34 -0400385 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -0400386 }
387
Brian Osman569f12f2019-06-13 11:23:57 -0400388 auto mask = [&]() { return *maskPtr & *loopPtr; };
389
Ethan Nicholas7e603db2019-05-03 12:57:47 -0400390 for (;;) {
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000391#ifdef TRACE
392 printf("at %3d ", (int) (ip - code));
393 disassemble_instruction(ip);
394 printf("\n");
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400395#endif
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000396 ByteCodeInstruction inst = (ByteCodeInstruction) READ16();
397 switch (inst) {
398 VECTOR_BINARY_OP(kAddI, fSigned, +)
399 VECTOR_MATRIX_BINARY_OP(kAddF, fFloat, +)
Brian Osman569f12f2019-06-13 11:23:57 -0400400
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000401 // Booleans are integer masks: 0/~0 for false/true. So bitwise ops do what we want:
402 case ByteCodeInstruction::kAndB:
403 sp[-1] = sp[-1].fSigned & sp[0].fSigned;
404 POP();
405 break;
406 case ByteCodeInstruction::kNotB:
407 sp[0] = ~sp[0].fSigned;
408 break;
409 case ByteCodeInstruction::kOrB:
410 sp[-1] = sp[-1].fSigned | sp[0].fSigned;
411 POP();
412 break;
413 case ByteCodeInstruction::kXorB:
414 sp[-1] = sp[-1].fSigned ^ sp[0].fSigned;
415 POP();
416 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400417
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000418 case ByteCodeInstruction::kBranch:
419 ip = code + READ16();
420 break;
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400421
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000422 case ByteCodeInstruction::kCall: {
423 // Precursor code reserved space for the return value, and pushed all parameters to
424 // the stack. Update our bottom of stack to point at the first parameter, and our
425 // sp to point past those parameters (plus space for locals).
426 int target = READ8();
427 const ByteCodeFunction* fun = byteCode->fFunctions[target].get();
428 if (skvx::any(mask())) {
429 frames.push_back({ code, ip, stack, fun->fParameterCount });
430 ip = code = fun->fCode.data();
431 stack = sp - fun->fParameterCount + 1;
432 sp = stack + fun->fParameterCount + fun->fLocalCount - 1;
Brian Osman569f12f2019-06-13 11:23:57 -0400433 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000434 break;
Brian Osman226668a2019-05-14 16:47:30 -0400435 }
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400436
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000437 case ByteCodeInstruction::kCallExternal: {
438 int argumentCount = READ8();
439 int returnCount = READ8();
440 int target = READ8();
441 ExternalValue* v = byteCode->fExternalValues[target];
442 sp -= argumentCount - 1;
Mike Kleine7007382019-05-21 08:36:32 -0500443
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000444 float tmpArgs[4];
445 float tmpReturn[4];
446 SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
447 SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
Brian Osman569f12f2019-06-13 11:23:57 -0400448
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000449 I32 m = mask();
450 for (int i = 0; i < VecWidth; ++i) {
451 if (m[i]) {
452 for (int j = 0; j < argumentCount; ++j) {
453 tmpArgs[j] = sp[j].fFloat[i];
Brian Osman569f12f2019-06-13 11:23:57 -0400454 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000455 v->call(baseIndex + i, tmpArgs, tmpReturn);
456 for (int j = 0; j < returnCount; ++j) {
457 sp[j].fFloat[i] = tmpReturn[j];
458 }
Brian Osman569f12f2019-06-13 11:23:57 -0400459 }
460 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000461 sp += returnCount - 1;
462 break;
Brian Osman07c117b2019-05-23 12:51:06 -0700463 }
Brian Osman07c117b2019-05-23 12:51:06 -0700464
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000465 case ByteCodeInstruction::kClampIndex: {
466 int length = READ8();
467 if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
468 return false;
469 }
470 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400471 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400472
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000473 VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
474 VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
475 VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
476 VECTOR_MATRIX_BINARY_OP(kCompareFNEQ, fFloat, !=)
477 VECTOR_BINARY_OP(kCompareSGT, fSigned, >)
478 VECTOR_BINARY_OP(kCompareUGT, fUnsigned, >)
479 VECTOR_BINARY_OP(kCompareFGT, fFloat, >)
480 VECTOR_BINARY_OP(kCompareSGTEQ, fSigned, >=)
481 VECTOR_BINARY_OP(kCompareUGTEQ, fUnsigned, >=)
482 VECTOR_BINARY_OP(kCompareFGTEQ, fFloat, >=)
483 VECTOR_BINARY_OP(kCompareSLT, fSigned, <)
484 VECTOR_BINARY_OP(kCompareULT, fUnsigned, <)
485 VECTOR_BINARY_OP(kCompareFLT, fFloat, <)
486 VECTOR_BINARY_OP(kCompareSLTEQ, fSigned, <=)
487 VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
488 VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400489
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000490 case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
491 case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
492 case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
493 case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
494 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400495
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000496 case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
497 case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
498 case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
499 case ByteCodeInstruction::kConvertStoF : sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
500 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400501
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000502 case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
503 case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
504 case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
505 case ByteCodeInstruction::kConvertUtoF : sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
506 break;
507
508 VECTOR_UNARY_FN_VEC(kCos, cosf)
509
510 VECTOR_BINARY_OP(kDivideS, fSigned, /)
511 VECTOR_BINARY_OP(kDivideU, fUnsigned, /)
512 VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
513
514 case ByteCodeInstruction::kDup4: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
515 case ByteCodeInstruction::kDup3: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
516 case ByteCodeInstruction::kDup2: PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
517 case ByteCodeInstruction::kDup : PUSH(sp[(int)ByteCodeInstruction::kDup - (int)inst]);
518 break;
519
520 case ByteCodeInstruction::kDupN: {
521 int count = READ8();
522 memcpy(sp + 1, sp - count + 1, count * sizeof(VValue));
523 sp += count;
524 break;
525 }
526
527 case ByteCodeInstruction::kInverse2x2: {
528 F32 a = sp[-3].fFloat,
529 b = sp[-2].fFloat,
530 c = sp[-1].fFloat,
531 d = sp[ 0].fFloat;
532 F32 idet = F32(1) / (a*d - b*c);
533 sp[-3].fFloat = d * idet;
534 sp[-2].fFloat = -b * idet;
535 sp[-1].fFloat = -c * idet;
536 sp[ 0].fFloat = a * idet;
537 break;
538 }
539 case ByteCodeInstruction::kInverse3x3: {
540 F32 a11 = sp[-8].fFloat, a12 = sp[-5].fFloat, a13 = sp[-2].fFloat,
541 a21 = sp[-7].fFloat, a22 = sp[-4].fFloat, a23 = sp[-1].fFloat,
542 a31 = sp[-6].fFloat, a32 = sp[-3].fFloat, a33 = sp[ 0].fFloat;
543 F32 idet = F32(1) / (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 -
544 a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31);
545 sp[-8].fFloat = (a22 * a33 - a23 * a32) * idet;
546 sp[-7].fFloat = (a23 * a31 - a21 * a33) * idet;
547 sp[-6].fFloat = (a21 * a32 - a22 * a31) * idet;
548 sp[-5].fFloat = (a13 * a32 - a12 * a33) * idet;
549 sp[-4].fFloat = (a11 * a33 - a13 * a31) * idet;
550 sp[-3].fFloat = (a12 * a31 - a11 * a32) * idet;
551 sp[-2].fFloat = (a12 * a23 - a13 * a22) * idet;
552 sp[-1].fFloat = (a13 * a21 - a11 * a23) * idet;
553 sp[ 0].fFloat = (a11 * a22 - a12 * a21) * idet;
554 break;
555 }
556 case ByteCodeInstruction::kInverse4x4: {
557 F32 a00 = spf(-15), a10 = spf(-11), a20 = spf( -7), a30 = spf( -3),
558 a01 = spf(-14), a11 = spf(-10), a21 = spf( -6), a31 = spf( -2),
559 a02 = spf(-13), a12 = spf( -9), a22 = spf( -5), a32 = spf( -1),
560 a03 = spf(-12), a13 = spf( -8), a23 = spf( -4), a33 = spf( 0);
561
562 F32 b00 = a00 * a11 - a01 * a10,
563 b01 = a00 * a12 - a02 * a10,
564 b02 = a00 * a13 - a03 * a10,
565 b03 = a01 * a12 - a02 * a11,
566 b04 = a01 * a13 - a03 * a11,
567 b05 = a02 * a13 - a03 * a12,
568 b06 = a20 * a31 - a21 * a30,
569 b07 = a20 * a32 - a22 * a30,
570 b08 = a20 * a33 - a23 * a30,
571 b09 = a21 * a32 - a22 * a31,
572 b10 = a21 * a33 - a23 * a31,
573 b11 = a22 * a33 - a23 * a32;
574
575 F32 idet = F32(1) /
576 (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
577
578 b00 *= idet;
579 b01 *= idet;
580 b02 *= idet;
581 b03 *= idet;
582 b04 *= idet;
583 b05 *= idet;
584 b06 *= idet;
585 b07 *= idet;
586 b08 *= idet;
587 b09 *= idet;
588 b10 *= idet;
589 b11 *= idet;
590
591 spf(-15) = a11 * b11 - a12 * b10 + a13 * b09;
592 spf(-14) = a02 * b10 - a01 * b11 - a03 * b09;
593 spf(-13) = a31 * b05 - a32 * b04 + a33 * b03;
594 spf(-12) = a22 * b04 - a21 * b05 - a23 * b03;
595 spf(-11) = a12 * b08 - a10 * b11 - a13 * b07;
596 spf(-10) = a00 * b11 - a02 * b08 + a03 * b07;
597 spf( -9) = a32 * b02 - a30 * b05 - a33 * b01;
598 spf( -8) = a20 * b05 - a22 * b02 + a23 * b01;
599 spf( -7) = a10 * b10 - a11 * b08 + a13 * b06;
600 spf( -6) = a01 * b08 - a00 * b10 - a03 * b06;
601 spf( -5) = a30 * b04 - a31 * b02 + a33 * b00;
602 spf( -4) = a21 * b02 - a20 * b04 - a23 * b00;
603 spf( -3) = a11 * b07 - a10 * b09 - a12 * b06;
604 spf( -2) = a00 * b09 - a01 * b07 + a02 * b06;
605 spf( -1) = a31 * b01 - a30 * b03 - a32 * b00;
606 spf( 0) = a20 * b03 - a21 * b01 + a22 * b00;
607 break;
608 }
609
610 case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
611 case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
612 case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
613 case ByteCodeInstruction::kLoad : sp[1] = stack[*ip + 0];
614 ++ip;
615 sp += (int)inst - (int)ByteCodeInstruction::kLoad + 1;
616 break;
617
618 case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
619 case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
620 case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
621 case ByteCodeInstruction::kLoadGlobal : sp[1] = globals[*ip + 0];
622 ++ip;
623 sp += (int)inst -
624 (int)ByteCodeInstruction::kLoadGlobal + 1;
625 break;
626
627 case ByteCodeInstruction::kLoadExtended: {
628 int count = READ8();
629 I32 src = POP().fSigned;
630 I32 m = mask();
631 for (int i = 0; i < count; ++i) {
632 for (int j = 0; j < VecWidth; ++j) {
633 if (m[j]) {
634 sp[i + 1].fSigned[j] = stack[src[j] + i].fSigned[j];
635 }
636 }
637 }
638 sp += count;
639 break;
640 }
641
642 case ByteCodeInstruction::kLoadExtendedGlobal: {
643 int count = READ8();
644 I32 src = POP().fSigned;
645 I32 m = mask();
646 for (int i = 0; i < count; ++i) {
647 for (int j = 0; j < VecWidth; ++j) {
648 if (m[j]) {
649 sp[i + 1].fSigned[j] = globals[src[j] + i].fSigned[j];
650 }
651 }
652 }
653 sp += count;
654 break;
655 }
656
657 case ByteCodeInstruction::kLoadSwizzle: {
658 int src = READ8();
659 int count = READ8();
660 for (int i = 0; i < count; ++i) {
661 PUSH(stack[src + *(ip + i)]);
662 }
663 ip += count;
664 break;
665 }
666
667 case ByteCodeInstruction::kLoadSwizzleGlobal: {
668 int src = READ8();
669 int count = READ8();
670 for (int i = 0; i < count; ++i) {
671 PUSH(globals[src + *(ip + i)]);
672 }
673 ip += count;
674 break;
675 }
676
677 case ByteCodeInstruction::kMatrixToMatrix: {
678 int srcCols = READ8();
679 int srcRows = READ8();
680 int dstCols = READ8();
681 int dstRows = READ8();
682 SkASSERT(srcCols >= 2 && srcCols <= 4);
683 SkASSERT(srcRows >= 2 && srcRows <= 4);
684 SkASSERT(dstCols >= 2 && dstCols <= 4);
685 SkASSERT(dstRows >= 2 && dstRows <= 4);
686 F32 tmp[16];
687 memset(tmp, 0, sizeof(tmp));
688 tmp[0] = tmp[5] = tmp[10] = tmp[15] = F32(1.0f);
689 for (int c = srcCols - 1; c >= 0; --c) {
690 for (int r = srcRows - 1; r >= 0; --r) {
691 tmp[c*4 + r] = POP().fFloat;
692 }
693 }
694 for (int c = 0; c < dstCols; ++c) {
695 for (int r = 0; r < dstRows; ++r) {
696 PUSH(tmp[c*4 + r]);
697 }
698 }
699 break;
700 }
701
702 case ByteCodeInstruction::kMatrixMultiply: {
703 int lCols = READ8();
704 int lRows = READ8();
705 int rCols = READ8();
706 int rRows = lCols;
707 F32 tmp[16] = { 0.0f };
708 F32* B = &(sp - (rCols * rRows) + 1)->fFloat;
709 F32* A = B - (lCols * lRows);
710 for (int c = 0; c < rCols; ++c) {
711 for (int r = 0; r < lRows; ++r) {
712 for (int j = 0; j < lCols; ++j) {
713 tmp[c*lRows + r] += A[j*lRows + r] * B[c*rRows + j];
714 }
715 }
716 }
717 sp -= (lCols * lRows) + (rCols * rRows);
718 memcpy(sp + 1, tmp, rCols * lRows * sizeof(VValue));
719 sp += (rCols * lRows);
720 break;
721 }
722
723 VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
724 VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
725
726 case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
727 case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
728 case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
729 case ByteCodeInstruction::kNegateF : sp[ 0] = -sp[ 0].fFloat;
730 break;
731
732 case ByteCodeInstruction::kNegateFN: {
733 int count = READ8();
734 for (int i = count - 1; i >= 0; --i) {
735 sp[-i] = -sp[-i].fFloat;
736 }
737 break;
738 }
739
740 case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
741 case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
742 case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
743 case ByteCodeInstruction::kNegateI : sp[ 0] = -sp[ 0].fSigned;
744 break;
745
746 case ByteCodeInstruction::kPop4: POP();
747 case ByteCodeInstruction::kPop3: POP();
748 case ByteCodeInstruction::kPop2: POP();
749 case ByteCodeInstruction::kPop : POP();
750 break;
751
752 case ByteCodeInstruction::kPopN:
753 sp -= READ8();
754 break;
755
756 case ByteCodeInstruction::kPushImmediate:
757 PUSH(U32(READ32()));
758 break;
759
760 case ByteCodeInstruction::kReadExternal:
761 case ByteCodeInstruction::kReadExternal2:
762 case ByteCodeInstruction::kReadExternal3:
763 case ByteCodeInstruction::kReadExternal4: {
764 int count = (int)inst - (int)ByteCodeInstruction::kReadExternal + 1;
765 int src = READ8();
766 float tmp[4];
767 I32 m = mask();
768 for (int i = 0; i < VecWidth; ++i) {
769 if (m[i]) {
770 byteCode->fExternalValues[src]->read(baseIndex + i, tmp);
771 for (int j = 0; j < count; ++j) {
772 sp[j + 1].fFloat[i] = tmp[j];
773 }
774 }
775 }
776 sp += count;
777 break;
778 }
779
780 VECTOR_BINARY_FN(kRemainderF, fFloat, vec_mod<F32>)
781 VECTOR_BINARY_FN(kRemainderS, fSigned, vec_mod<I32>)
782 VECTOR_BINARY_FN(kRemainderU, fUnsigned, vec_mod<U32>)
783
784 case ByteCodeInstruction::kReserve:
785 sp += READ8();
786 break;
787
788 case ByteCodeInstruction::kReturn: {
789 int count = READ8();
790 if (frames.empty()) {
791 if (outReturn) {
792 VValue* src = sp - count + 1;
793 if (stripedOutput) {
794 for (int i = 0; i < count; ++i) {
795 memcpy(outReturn[i], &src->fFloat, N * sizeof(float));
796 ++src;
797 }
798 } else {
799 float* outPtr = outReturn[0];
800 for (int i = 0; i < count; ++i) {
801 for (int j = 0; j < N; ++j) {
802 outPtr[count * j] = src->fFloat[j];
803 }
804 ++outPtr;
805 ++src;
806 }
807 }
808 }
809 return true;
810 } else {
811 // When we were called, the caller reserved stack space for their copy of our
812 // return value, then 'stack' was positioned after that, where our parameters
813 // were placed. Copy our return values to their reserved area.
814 memcpy(stack - count, sp - count + 1, count * sizeof(VValue));
815
816 // Now move the stack pointer to the end of the passed-in parameters. This odd
817 // calling convention requires the caller to pop the arguments after calling,
818 // but allows them to store any out-parameters back during that unwinding.
819 // After that sequence finishes, the return value will be the top of the stack.
820 const StackFrame& frame(frames.back());
821 sp = stack + frame.fParameterCount - 1;
822 stack = frame.fStack;
823 code = frame.fCode;
824 ip = frame.fIP;
825 frames.pop_back();
826 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400827 }
828 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000829
830 case ByteCodeInstruction::kScalarToMatrix: {
831 int cols = READ8();
832 int rows = READ8();
833 VValue v = POP();
834 for (int c = 0; c < cols; ++c) {
835 for (int r = 0; r < rows; ++r) {
836 PUSH(c == r ? v : F32(0.0f));
837 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400838 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000839 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400840 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400841
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000842 VECTOR_UNARY_FN_VEC(kSin, sinf)
843 VECTOR_UNARY_FN(kSqrt, skvx::sqrt, fFloat)
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400844
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000845 case ByteCodeInstruction::kStore4:
846 stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
847 case ByteCodeInstruction::kStore3:
848 stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
849 case ByteCodeInstruction::kStore2:
850 stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
851 case ByteCodeInstruction::kStore :
852 stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
853 ++ip;
854 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400855
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000856 case ByteCodeInstruction::kStoreGlobal4:
857 globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
858 case ByteCodeInstruction::kStoreGlobal3:
859 globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
860 case ByteCodeInstruction::kStoreGlobal2:
861 globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
862 case ByteCodeInstruction::kStoreGlobal :
863 globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
864 ++ip;
865 break;
866
867 case ByteCodeInstruction::kStoreExtended: {
868 int count = READ8();
869 I32 target = POP().fSigned;
870 VValue* src = sp - count + 1;
871 I32 m = mask();
872 for (int i = 0; i < count; ++i) {
873 for (int j = 0; j < VecWidth; ++j) {
874 if (m[j]) {
875 stack[target[j] + i].fSigned[j] = src[i].fSigned[j];
876 }
877 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400878 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000879 sp -= count;
880 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400881 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000882 case ByteCodeInstruction::kStoreExtendedGlobal: {
883 int count = READ8();
884 I32 target = POP().fSigned;
885 VValue* src = sp - count + 1;
886 I32 m = mask();
887 for (int i = 0; i < count; ++i) {
888 for (int j = 0; j < VecWidth; ++j) {
889 if (m[j]) {
890 globals[target[j] + i].fSigned[j] = src[i].fSigned[j];
891 }
892 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400893 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000894 sp -= count;
895 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400896 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400897
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000898 case ByteCodeInstruction::kStoreSwizzle: {
899 int target = READ8();
900 int count = READ8();
901 for (int i = count - 1; i >= 0; --i) {
902 stack[target + *(ip + i)] = skvx::if_then_else(
903 mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400904 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000905 ip += count;
906 break;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400907 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400908
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000909 case ByteCodeInstruction::kStoreSwizzleGlobal: {
910 int target = READ8();
911 int count = READ8();
912 for (int i = count - 1; i >= 0; --i) {
913 globals[target + *(ip + i)] = skvx::if_then_else(
914 mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
915 }
916 ip += count;
917 break;
918 }
Ethan Nicholasadecf4b2019-09-05 12:43:34 -0400919
Ethan Nicholascbdc8292019-09-05 18:06:38 +0000920 case ByteCodeInstruction::kStoreSwizzleIndirect: {
921 int count = READ8();
922 I32 target = POP().fSigned;
923 I32 m = mask();
924 for (int i = count - 1; i >= 0; --i) {
925 I32 v = POP().fSigned;
926 for (int j = 0; j < VecWidth; ++j) {
927 if (m[j]) {
928 stack[target[j] + *(ip + i)].fSigned[j] = v[j];
929 }
930 }
931 }
932 ip += count;
933 break;
934 }
935
936 case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
937 int count = READ8();
938 I32 target = POP().fSigned;
939 I32 m = mask();
940 for (int i = count - 1; i >= 0; --i) {
941 I32 v = POP().fSigned;
942 for (int j = 0; j < VecWidth; ++j) {
943 if (m[j]) {
944 globals[target[j] + *(ip + i)].fSigned[j] = v[j];
945 }
946 }
947 }
948 ip += count;
949 break;
950 }
951
952 VECTOR_BINARY_OP(kSubtractI, fSigned, -)
953 VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
954
955 case ByteCodeInstruction::kSwizzle: {
956 VValue tmp[4];
957 for (int i = READ8() - 1; i >= 0; --i) {
958 tmp[i] = POP();
959 }
960 for (int i = READ8() - 1; i >= 0; --i) {
961 PUSH(tmp[READ8()]);
962 }
963 break;
964 }
965
966 VECTOR_UNARY_FN_VEC(kTan, tanf)
967
968 case ByteCodeInstruction::kWriteExternal:
969 case ByteCodeInstruction::kWriteExternal2:
970 case ByteCodeInstruction::kWriteExternal3:
971 case ByteCodeInstruction::kWriteExternal4: {
972 int count = (int)inst - (int)ByteCodeInstruction::kWriteExternal + 1;
973 int target = READ8();
974 float tmp[4];
975 I32 m = mask();
976 sp -= count;
977 for (int i = 0; i < VecWidth; ++i) {
978 if (m[i]) {
979 for (int j = 0; j < count; ++j) {
980 tmp[j] = sp[j + 1].fFloat[i];
981 }
982 byteCode->fExternalValues[target]->write(baseIndex + i, tmp);
983 }
984 }
985 break;
986 }
987
988 case ByteCodeInstruction::kMaskPush:
989 condPtr[1] = POP().fSigned;
990 maskPtr[1] = maskPtr[0] & condPtr[1];
991 ++condPtr; ++maskPtr;
992 break;
993 case ByteCodeInstruction::kMaskPop:
994 --condPtr; --maskPtr;
995 break;
996 case ByteCodeInstruction::kMaskNegate:
997 maskPtr[0] = maskPtr[-1] & ~condPtr[0];
998 break;
999 case ByteCodeInstruction::kMaskBlend: {
1000 int count = READ8();
1001 I32 m = condPtr[0];
1002 --condPtr; --maskPtr;
1003 for (int i = 0; i < count; ++i) {
1004 sp[-count] = skvx::if_then_else(m, sp[-count].fFloat, sp[0].fFloat);
1005 --sp;
1006 }
1007 break;
1008 }
1009 case ByteCodeInstruction::kBranchIfAllFalse: {
1010 int target = READ16();
1011 if (!skvx::any(mask())) {
1012 ip = code + target;
1013 }
1014 break;
1015 }
1016
1017 case ByteCodeInstruction::kLoopBegin:
1018 contPtr[1] = 0;
1019 loopPtr[1] = loopPtr[0];
1020 ++contPtr; ++loopPtr;
1021 break;
1022 case ByteCodeInstruction::kLoopNext:
1023 *loopPtr |= *contPtr;
1024 *contPtr = 0;
1025 break;
1026 case ByteCodeInstruction::kLoopMask:
1027 *loopPtr &= POP().fSigned;
1028 break;
1029 case ByteCodeInstruction::kLoopEnd:
1030 --contPtr; --loopPtr;
1031 break;
1032 case ByteCodeInstruction::kLoopBreak:
1033 *loopPtr &= ~mask();
1034 break;
1035 case ByteCodeInstruction::kLoopContinue: {
1036 I32 m = mask();
1037 *contPtr |= m;
1038 *loopPtr &= ~m;
1039 break;
1040 }
1041
1042 default:
1043 SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
1044 return false;
Ethan Nicholasadecf4b2019-09-05 12:43:34 -04001045 }
1046 }
Ethan Nicholascbdc8292019-09-05 18:06:38 +00001047 // Unreachable
1048 return false;
Brian Osman569f12f2019-06-13 11:23:57 -04001049}
1050
Brian Osman08a84962019-06-14 10:17:16 -04001051} // namespace Interpreter
1052
Brian Osman489cf882019-07-09 10:48:28 -04001053#endif // SK_ENABLE_SKSL_INTERPRETER
1054
Mike Reed634c9412019-07-18 13:20:04 -04001055#undef spf
1056
Brian Osman08a84962019-06-14 10:17:16 -04001057void ByteCodeFunction::disassemble() const {
Brian Osman489cf882019-07-09 10:48:28 -04001058#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman08a84962019-06-14 10:17:16 -04001059 const uint8_t* ip = fCode.data();
1060 while (ip < fCode.data() + fCode.size()) {
1061 printf("%d: ", (int)(ip - fCode.data()));
1062 ip = Interpreter::disassemble_instruction(ip);
1063 printf("\n");
1064 }
Brian Osman489cf882019-07-09 10:48:28 -04001065#endif
Brian Osman08a84962019-06-14 10:17:16 -04001066}
1067
Brian Osman869a3e82019-07-18 17:00:34 -04001068bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
Brian Osman08a84962019-06-14 10:17:16 -04001069 const float* uniforms, int uniformCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001070#if defined(SK_ENABLE_SKSL_INTERPRETER)
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001071#ifdef TRACE
Brian Osman08a84962019-06-14 10:17:16 -04001072 f->disassemble();
Ethan Nicholas9764ebd2019-05-01 14:43:54 -04001073#endif
Brian Osman4b202a32019-06-21 09:50:29 -04001074 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001075 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1076 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001077 return false;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001078 }
Brian Osmanef787f72019-06-13 13:07:12 -04001079
Brian Osman869a3e82019-07-18 17:00:34 -04001080 if (uniformCount != (int)fInputSlots.size()) {
1081 return false;
1082 }
1083
Brian Osman08a84962019-06-14 10:17:16 -04001084 Interpreter::VValue globals[32];
Brian Osman869a3e82019-07-18 17:00:34 -04001085 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1086 return false;
1087 }
Brian Osman08a84962019-06-14 10:17:16 -04001088 for (uint8_t slot : fInputSlots) {
1089 globals[slot].fFloat = *uniforms++;
Brian Osman569f12f2019-06-13 11:23:57 -04001090 }
1091
Brian Osman1a79f0b2019-06-24 16:32:14 -04001092 int baseIndex = 0;
1093
Brian Osman569f12f2019-06-13 11:23:57 -04001094 while (N) {
Brian Osman08a84962019-06-14 10:17:16 -04001095 int w = std::min(N, Interpreter::VecWidth);
Brian Osman569f12f2019-06-13 11:23:57 -04001096
1097 // Transpose args into stack
1098 {
Brian Osman08a84962019-06-14 10:17:16 -04001099 float* src = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001100 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001101 float* dst = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001102 for (int j = f->fParameterCount; j > 0; --j) {
1103 *dst = *src++;
Brian Osman08a84962019-06-14 10:17:16 -04001104 dst += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001105 }
1106 }
1107 }
1108
Mike Reed3fd3cc92019-06-20 12:40:30 -04001109 bool stripedOutput = false;
1110 float** outArray = outReturn ? &outReturn : nullptr;
Brian Osman869a3e82019-07-18 17:00:34 -04001111 if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
1112 return false;
1113 }
Brian Osman569f12f2019-06-13 11:23:57 -04001114
1115 // Transpose out parameters back
1116 {
Brian Osman08a84962019-06-14 10:17:16 -04001117 float* dst = args;
Brian Osman569f12f2019-06-13 11:23:57 -04001118 for (int i = 0; i < w; ++i) {
Brian Osman08a84962019-06-14 10:17:16 -04001119 float* src = (float*)stack + i;
Brian Osman569f12f2019-06-13 11:23:57 -04001120 for (const auto& p : f->fParameters) {
1121 if (p.fIsOutParameter) {
1122 for (int j = p.fSlotCount; j > 0; --j) {
1123 *dst++ = *src;
Brian Osman08a84962019-06-14 10:17:16 -04001124 src += Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001125 }
1126 } else {
1127 dst += p.fSlotCount;
Brian Osman08a84962019-06-14 10:17:16 -04001128 src += p.fSlotCount * Interpreter::VecWidth;
Brian Osman569f12f2019-06-13 11:23:57 -04001129 }
1130 }
1131 }
1132 }
1133
1134 args += f->fParameterCount * w;
Mike Reed3fd3cc92019-06-20 12:40:30 -04001135 if (outReturn) {
1136 outReturn += f->fReturnCount * w;
1137 }
Brian Osman4b202a32019-06-21 09:50:29 -04001138 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001139 baseIndex += w;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001140 }
Brian Osman869a3e82019-07-18 17:00:34 -04001141 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001142#else
1143 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001144 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001145#endif
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001146}
1147
Brian Osman869a3e82019-07-18 17:00:34 -04001148bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
Mike Reed3fd3cc92019-06-20 12:40:30 -04001149 const float* uniforms, int uniformCount,
1150 float* outArgs[], int outCount) const {
Brian Osman489cf882019-07-09 10:48:28 -04001151#if defined(SK_ENABLE_SKSL_INTERPRETER)
Brian Osman2b1a5442019-06-19 11:40:33 -04001152#ifdef TRACE
Brian Osmanecb3bb52019-06-20 14:59:12 -04001153 f->disassemble();
Brian Osman2b1a5442019-06-19 11:40:33 -04001154#endif
1155 Interpreter::VValue stack[128];
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001156 int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
1157 if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
Brian Osman869a3e82019-07-18 17:00:34 -04001158 return false;
1159 }
1160
1161 if (nargs != f->fParameterCount ||
1162 outCount != f->fReturnCount ||
1163 uniformCount != (int)fInputSlots.size()) {
1164 return false;
1165 }
1166
1167 Interpreter::VValue globals[32];
1168 if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
1169 return false;
1170 }
1171 for (uint8_t slot : fInputSlots) {
1172 globals[slot].fFloat = *uniforms++;
Brian Osmanaa2ca3f2019-07-15 13:24:48 -04001173 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001174
Mike Reed3fd3cc92019-06-20 12:40:30 -04001175 // innerRun just takes outArgs, so clear it if the count is zero
1176 if (outCount == 0) {
1177 outArgs = nullptr;
1178 }
1179
Brian Osman1a79f0b2019-06-24 16:32:14 -04001180 int baseIndex = 0;
1181
Brian Osman2b1a5442019-06-19 11:40:33 -04001182 while (N) {
1183 int w = std::min(N, Interpreter::VecWidth);
1184
1185 // Copy args into stack
1186 for (int i = 0; i < nargs; ++i) {
1187 memcpy(stack + i, args[i], w * sizeof(float));
1188 }
1189
Mike Reed3fd3cc92019-06-20 12:40:30 -04001190 bool stripedOutput = true;
Brian Osman869a3e82019-07-18 17:00:34 -04001191 if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
1192 return false;
1193 }
Brian Osman2b1a5442019-06-19 11:40:33 -04001194
1195 // Copy out parameters back
1196 int slot = 0;
1197 for (const auto& p : f->fParameters) {
1198 if (p.fIsOutParameter) {
1199 for (int i = slot; i < slot + p.fSlotCount; ++i) {
1200 memcpy(args[i], stack + i, w * sizeof(float));
1201 }
1202 }
1203 slot += p.fSlotCount;
1204 }
1205
1206 // Step each argument pointer ahead
1207 for (int i = 0; i < nargs; ++i) {
1208 args[i] += w;
1209 }
1210 N -= w;
Brian Osman1a79f0b2019-06-24 16:32:14 -04001211 baseIndex += w;
Brian Osman2b1a5442019-06-19 11:40:33 -04001212 }
Brian Osman869a3e82019-07-18 17:00:34 -04001213
1214 return true;
Brian Osman489cf882019-07-09 10:48:28 -04001215#else
1216 SkDEBUGFAIL("ByteCode interpreter not enabled");
Brian Osman869a3e82019-07-18 17:00:34 -04001217 return false;
Brian Osman489cf882019-07-09 10:48:28 -04001218#endif
Brian Osman2b1a5442019-06-19 11:40:33 -04001219}
1220
Brian Osman80164412019-06-07 13:00:23 -04001221} // namespace SkSL
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001222
1223#endif