blob: 518e16f9163536cc6465c60a8774dce7f438e316 [file] [log] [blame]
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001/*
2 * Copyright 2019 Google LLC
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_BYTECODE
9#define SKSL_BYTECODE
10
Brian Osman80164412019-06-07 13:00:23 -040011#include "src/sksl/SkSLString.h"
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040012
Ethan Nicholas91164d12019-05-15 15:29:54 -040013#include <memory>
14#include <vector>
15
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040016namespace SkSL {
17
Ethan Nicholas91164d12019-05-15 15:29:54 -040018class ExternalValue;
19struct FunctionDeclaration;
20
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040021#define VECTOR(name) name, name ## 2, name ## 3, name ## 4
Brian Osman1e855b22019-05-29 15:21:52 -040022#define VECTOR_MATRIX(name) name, name ## 2, name ## 3, name ## 4, name ## N
23
Mike Klein108e9352019-05-21 11:05:17 -050024enum class ByteCodeInstruction : uint16_t {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040025 // B = bool, F = float, I = int, S = signed, U = unsigned
Brian Osman1e855b22019-05-29 15:21:52 -040026 VECTOR_MATRIX(kAddF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040027 VECTOR(kAddI),
Brian Osman32c526b2019-06-03 16:13:52 -040028 kAndB,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040029 kBranch,
Brian Osman226668a2019-05-14 16:47:30 -040030 // Followed by a byte indicating the index of the function to call
31 kCall,
Ethan Nicholas9e6a3932019-05-17 16:31:21 -040032 // Followed by three bytes indicating: the number of argument slots, the number of return slots,
33 // and the index of the external value to call
34 kCallExternal,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040035 VECTOR(kCompareIEQ),
36 VECTOR(kCompareINEQ),
Brian Osman1e855b22019-05-29 15:21:52 -040037 VECTOR_MATRIX(kCompareFEQ),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040038 VECTOR(kCompareFGT),
39 VECTOR(kCompareFGTEQ),
40 VECTOR(kCompareFLT),
41 VECTOR(kCompareFLTEQ),
Brian Osman1e855b22019-05-29 15:21:52 -040042 VECTOR_MATRIX(kCompareFNEQ),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040043 VECTOR(kCompareSGT),
44 VECTOR(kCompareSGTEQ),
45 VECTOR(kCompareSLT),
46 VECTOR(kCompareSLTEQ),
47 VECTOR(kCompareUGT),
48 VECTOR(kCompareUGTEQ),
49 VECTOR(kCompareULT),
50 VECTOR(kCompareULTEQ),
Ethan Nicholas82162ee2019-05-21 16:05:08 -040051 VECTOR(kConvertFtoI),
52 VECTOR(kConvertStoF),
53 VECTOR(kConvertUtoF),
54 VECTOR(kCos),
Ethan Nicholasae9633b2019-05-24 12:46:34 -040055 kCross,
Brian Osman1e855b22019-05-29 15:21:52 -040056 VECTOR_MATRIX(kDivideF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040057 VECTOR(kDivideS),
58 VECTOR(kDivideU),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040059 // Duplicates the top stack value
Brian Osman1e855b22019-05-29 15:21:52 -040060 VECTOR_MATRIX(kDup),
Brian Osman07c117b2019-05-23 12:51:06 -070061 // kLoad/kLoadGlobal are followed by a byte indicating the local/global slot to load
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040062 VECTOR(kLoad),
63 VECTOR(kLoadGlobal),
Brian Osman07c117b2019-05-23 12:51:06 -070064 // As kLoad/kLoadGlobal, then a count byte (1-4), and then one byte per swizzle component (0-3).
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040065 kLoadSwizzle,
Brian Osmanb7451292019-05-15 13:02:13 -040066 kLoadSwizzleGlobal,
Brian Osman07c117b2019-05-23 12:51:06 -070067 // kLoadExtended* are fallback load ops when we lack a specialization. They are followed by a
68 // count byte, and get the slot to load from the top of the stack.
69 kLoadExtended,
70 kLoadExtendedGlobal,
Brian Osman29e013d2019-05-28 17:16:03 -040071 // Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
72 // stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
73 // dimensions. Any overlapping values are copied, and any other values are filled in with the
74 // identity matrix.
75 kMatrixToMatrix,
Brian Osman909231c2019-05-29 15:34:36 -040076 // Followed by three bytes: leftCols (== rightRows), leftRows, rightCols
77 kMatrixMultiply,
Brian Osman1e855b22019-05-29 15:21:52 -040078 VECTOR_MATRIX(kNegateF),
Mike Klein12710912019-05-21 11:04:59 -050079 VECTOR(kNegateI),
Ethan Nicholasae9633b2019-05-24 12:46:34 -040080 VECTOR(kMix),
Brian Osman1e855b22019-05-29 15:21:52 -040081 VECTOR_MATRIX(kMultiplyF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040082 VECTOR(kMultiplyI),
Brian Osman569f12f2019-06-13 11:23:57 -040083 kNotB,
Brian Osman32c526b2019-06-03 16:13:52 -040084 kOrB,
Brian Osman1e855b22019-05-29 15:21:52 -040085 VECTOR_MATRIX(kPop),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040086 // Followed by a 32 bit value containing the value to push
87 kPushImmediate,
Ethan Nicholas91164d12019-05-15 15:29:54 -040088 // Followed by a byte indicating external value to read
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040089 VECTOR(kReadExternal),
90 VECTOR(kRemainderF),
91 VECTOR(kRemainderS),
92 VECTOR(kRemainderU),
Ethan Nicholas746035a2019-04-23 13:31:09 -040093 // Followed by a byte indicating the number of slots being returned
94 kReturn,
Brian Osman29e013d2019-05-28 17:16:03 -040095 // Followed by two bytes indicating columns and rows of matrix (2, 3, or 4 each).
96 // Takes a single value from the top of the stack, and converts to a CxR matrix with that value
97 // replicated along the diagonal (and zero elsewhere), per the GLSL matrix construction rules.
98 kScalarToMatrix,
Ethan Nicholas82162ee2019-05-21 16:05:08 -040099 VECTOR(kSin),
100 VECTOR(kSqrt),
Brian Osman07c117b2019-05-23 12:51:06 -0700101 // kStore/kStoreGlobal are followed by a byte indicating the local/global slot to store
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400102 VECTOR(kStore),
103 VECTOR(kStoreGlobal),
Brian Osman07c117b2019-05-23 12:51:06 -0700104 // Fallback stores. Followed by count byte, and get the slot to store from the top of the stack
105 kStoreExtended,
106 kStoreExtendedGlobal,
107 // As kStore/kStoreGlobal, then a count byte (1-4), then one byte per swizzle component (0-3).
Brian Osman1091f022019-05-16 09:42:16 -0400108 // Expects the stack to look like: ... v1 v2 v3 v4, where the number of 'v's is equal to the
109 // number of swizzle components. After the store, all v's are popped from the stack.
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400110 kStoreSwizzle,
Brian Osman1091f022019-05-16 09:42:16 -0400111 kStoreSwizzleGlobal,
Brian Osman07c117b2019-05-23 12:51:06 -0700112 // As above, but gets the store slot from the top of the stack (before values to be stored)
113 kStoreSwizzleIndirect,
114 kStoreSwizzleIndirectGlobal,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400115 // Followed by two count bytes (1-4), and then one byte per swizzle component (0-3). The first
116 // count byte provides the current vector size (the vector is the top n stack elements), and the
117 // second count byte provides the swizzle component count.
118 kSwizzle,
Brian Osman1e855b22019-05-29 15:21:52 -0400119 VECTOR_MATRIX(kSubtractF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400120 VECTOR(kSubtractI),
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400121 VECTOR(kTan),
Ethan Nicholas91164d12019-05-15 15:29:54 -0400122 // Followed by a byte indicating external value to write
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400123 VECTOR(kWriteExternal),
Brian Osman569f12f2019-06-13 11:23:57 -0400124 kXorB,
125
126 kMaskPush,
127 kMaskPop,
128 kMaskNegate,
129 // Followed by count byte
130 kMaskBlend,
131 // Followed by address
132 kBranchIfAllFalse,
133
134 kLoopBegin,
135 kLoopNext,
136 kLoopMask,
137 kLoopEnd,
138 kLoopBreak,
139 kLoopContinue,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140};
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400141#undef VECTOR
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400142
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400143struct ByteCodeFunction {
Brian Osman80164412019-06-07 13:00:23 -0400144 ByteCodeFunction(const FunctionDeclaration* declaration);
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400145
Brian Osman80164412019-06-07 13:00:23 -0400146 struct Parameter {
147 int fSlotCount;
148 bool fIsOutParameter;
149 };
150
151 SkSL::String fName;
152 std::vector<Parameter> fParameters;
153 int fParameterCount;
154
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400155 int fLocalCount = 0;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400156 // TODO: Compute this value analytically. For now, just pick an arbitrary value that we probably
157 // won't overflow.
158 int fStackCount = 128;
159 int fReturnCount = 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400160 std::vector<uint8_t> fCode;
Brian Osman08a84962019-06-14 10:17:16 -0400161
162 /**
163 * Print bytecode disassembly to stdout.
164 */
165 void disassemble() const;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166};
167
168struct ByteCode {
169 int fGlobalCount = 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400170 // one entry per input slot, contains the global slot to which the input slot maps
171 std::vector<uint8_t> fInputSlots;
172 std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
Brian Osman08a84962019-06-14 10:17:16 -0400173 std::vector<ExternalValue*> fExternalValues;
Brian Osman226668a2019-05-14 16:47:30 -0400174
175 const ByteCodeFunction* getFunction(const char* name) const {
176 for (const auto& f : fFunctions) {
Brian Osman80164412019-06-07 13:00:23 -0400177 if (f->fName == name) {
Brian Osman226668a2019-05-14 16:47:30 -0400178 return f.get();
179 }
180 }
181 return nullptr;
182 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400183
Brian Osman08a84962019-06-14 10:17:16 -0400184 /**
185 * Invokes the specified function with the given arguments, 'N' times.
186 * 'args', 'outReturn', and 'uniforms' are collections of 32-bit values (typically floats,
187 * but possibly int32_t or uint32_t, depending on the types used in the SkSL).
188 * Any 'out' or 'inout' parameters will result in the 'args' array being modified.
189 * The return value is stored in 'outReturn' (may be null, to discard the return value).
190 * 'uniforms' are mapped to 'uniform' globals, in order.
191 */
192 void run(const ByteCodeFunction*, float* args, float* outReturn, int N,
193 const float* uniforms, int uniformCount) const;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400194};
195
196}
197
198#endif