blob: 3f970ca518e228b2a305ed2d4f5f23b68a7472a3 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/sksl/ir/SkSLFunctionDeclaration.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 -040018struct ByteCode;
19class ExternalValue;
20struct FunctionDeclaration;
21
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040022#define VECTOR(name) name, name ## 2, name ## 3, name ## 4
Brian Osman1e855b22019-05-29 15:21:52 -040023#define VECTOR_MATRIX(name) name, name ## 2, name ## 3, name ## 4, name ## N
24
Mike Klein108e9352019-05-21 11:05:17 -050025enum class ByteCodeInstruction : uint16_t {
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040026 // B = bool, F = float, I = int, S = signed, U = unsigned
Brian Osman1e855b22019-05-29 15:21:52 -040027 VECTOR_MATRIX(kAddF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040028 VECTOR(kAddI),
29 VECTOR(kAndB),
30 VECTOR(kAndI),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040031 kBranch,
Brian Osman226668a2019-05-14 16:47:30 -040032 // Followed by a byte indicating the index of the function to call
33 kCall,
Ethan Nicholas9e6a3932019-05-17 16:31:21 -040034 // Followed by three bytes indicating: the number of argument slots, the number of return slots,
35 // and the index of the external value to call
36 kCallExternal,
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040037 VECTOR(kCompareIEQ),
38 VECTOR(kCompareINEQ),
Brian Osman1e855b22019-05-29 15:21:52 -040039 VECTOR_MATRIX(kCompareFEQ),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040040 VECTOR(kCompareFGT),
41 VECTOR(kCompareFGTEQ),
42 VECTOR(kCompareFLT),
43 VECTOR(kCompareFLTEQ),
Brian Osman1e855b22019-05-29 15:21:52 -040044 VECTOR_MATRIX(kCompareFNEQ),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040045 VECTOR(kCompareSGT),
46 VECTOR(kCompareSGTEQ),
47 VECTOR(kCompareSLT),
48 VECTOR(kCompareSLTEQ),
49 VECTOR(kCompareUGT),
50 VECTOR(kCompareUGTEQ),
51 VECTOR(kCompareULT),
52 VECTOR(kCompareULTEQ),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040053 // Followed by a 16 bit address
54 kConditionalBranch,
Ethan Nicholas82162ee2019-05-21 16:05:08 -040055 VECTOR(kConvertFtoI),
56 VECTOR(kConvertStoF),
57 VECTOR(kConvertUtoF),
58 VECTOR(kCos),
Ethan Nicholasae9633b2019-05-24 12:46:34 -040059 kCross,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040060 // Pops and prints the top value from the stack
61 kDebugPrint,
Brian Osman1e855b22019-05-29 15:21:52 -040062 VECTOR_MATRIX(kDivideF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040063 VECTOR(kDivideS),
64 VECTOR(kDivideU),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040065 // Duplicates the top stack value
Brian Osman1e855b22019-05-29 15:21:52 -040066 VECTOR_MATRIX(kDup),
Brian Osman07c117b2019-05-23 12:51:06 -070067 // kLoad/kLoadGlobal are followed by a byte indicating the local/global slot to load
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040068 VECTOR(kLoad),
69 VECTOR(kLoadGlobal),
Brian Osman07c117b2019-05-23 12:51:06 -070070 // 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 -040071 kLoadSwizzle,
Brian Osmanb7451292019-05-15 13:02:13 -040072 kLoadSwizzleGlobal,
Brian Osman07c117b2019-05-23 12:51:06 -070073 // kLoadExtended* are fallback load ops when we lack a specialization. They are followed by a
74 // count byte, and get the slot to load from the top of the stack.
75 kLoadExtended,
76 kLoadExtendedGlobal,
Brian Osman29e013d2019-05-28 17:16:03 -040077 // Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
78 // stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
79 // dimensions. Any overlapping values are copied, and any other values are filled in with the
80 // identity matrix.
81 kMatrixToMatrix,
Brian Osman909231c2019-05-29 15:34:36 -040082 // Followed by three bytes: leftCols (== rightRows), leftRows, rightCols
83 kMatrixMultiply,
Brian Osman1e855b22019-05-29 15:21:52 -040084 VECTOR_MATRIX(kNegateF),
Mike Klein12710912019-05-21 11:04:59 -050085 VECTOR(kNegateI),
Ethan Nicholasae9633b2019-05-24 12:46:34 -040086 VECTOR(kMix),
Brian Osman1e855b22019-05-29 15:21:52 -040087 VECTOR_MATRIX(kMultiplyF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040088 VECTOR(kMultiplyI),
89 VECTOR(kNot),
90 VECTOR(kOrB),
91 VECTOR(kOrI),
Brian Osman1e855b22019-05-29 15:21:52 -040092 VECTOR_MATRIX(kPop),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -040093 // Followed by a 32 bit value containing the value to push
94 kPushImmediate,
Ethan Nicholas91164d12019-05-15 15:29:54 -040095 // Followed by a byte indicating external value to read
Ethan Nicholas48a75aa2019-05-16 17:15:56 -040096 VECTOR(kReadExternal),
97 VECTOR(kRemainderF),
98 VECTOR(kRemainderS),
99 VECTOR(kRemainderU),
Ethan Nicholas746035a2019-04-23 13:31:09 -0400100 // Followed by a byte indicating the number of slots being returned
101 kReturn,
Brian Osman29e013d2019-05-28 17:16:03 -0400102 // Followed by two bytes indicating columns and rows of matrix (2, 3, or 4 each).
103 // Takes a single value from the top of the stack, and converts to a CxR matrix with that value
104 // replicated along the diagonal (and zero elsewhere), per the GLSL matrix construction rules.
105 kScalarToMatrix,
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400106 VECTOR(kSin),
107 VECTOR(kSqrt),
Brian Osman07c117b2019-05-23 12:51:06 -0700108 // kStore/kStoreGlobal are followed by a byte indicating the local/global slot to store
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400109 VECTOR(kStore),
110 VECTOR(kStoreGlobal),
Brian Osman07c117b2019-05-23 12:51:06 -0700111 // Fallback stores. Followed by count byte, and get the slot to store from the top of the stack
112 kStoreExtended,
113 kStoreExtendedGlobal,
114 // As kStore/kStoreGlobal, then a count byte (1-4), then one byte per swizzle component (0-3).
Brian Osman1091f022019-05-16 09:42:16 -0400115 // Expects the stack to look like: ... v1 v2 v3 v4, where the number of 'v's is equal to the
116 // number of swizzle components. After the store, all v's are popped from the stack.
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400117 kStoreSwizzle,
Brian Osman1091f022019-05-16 09:42:16 -0400118 kStoreSwizzleGlobal,
Brian Osman07c117b2019-05-23 12:51:06 -0700119 // As above, but gets the store slot from the top of the stack (before values to be stored)
120 kStoreSwizzleIndirect,
121 kStoreSwizzleIndirectGlobal,
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400122 // Followed by two count bytes (1-4), and then one byte per swizzle component (0-3). The first
123 // count byte provides the current vector size (the vector is the top n stack elements), and the
124 // second count byte provides the swizzle component count.
125 kSwizzle,
Brian Osman1e855b22019-05-29 15:21:52 -0400126 VECTOR_MATRIX(kSubtractF),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400127 VECTOR(kSubtractI),
Ethan Nicholas82162ee2019-05-21 16:05:08 -0400128 VECTOR(kTan),
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400129 VECTOR(kXorB),
130 VECTOR(kXorI),
Ethan Nicholas91164d12019-05-15 15:29:54 -0400131 // Followed by a byte indicating external value to write
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400132 VECTOR(kWriteExternal),
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400133};
Ethan Nicholas48a75aa2019-05-16 17:15:56 -0400134#undef VECTOR
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400135
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400136struct ByteCodeFunction {
Brian Osman226668a2019-05-14 16:47:30 -0400137 ByteCodeFunction(const FunctionDeclaration* declaration)
138 : fDeclaration(*declaration) {}
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400139
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400140 const FunctionDeclaration& fDeclaration;
141 int fParameterCount = 0;
142 int fLocalCount = 0;
Ethan Nicholasdfcad062019-05-07 12:53:34 -0400143 // TODO: Compute this value analytically. For now, just pick an arbitrary value that we probably
144 // won't overflow.
145 int fStackCount = 128;
146 int fReturnCount = 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400147 std::vector<uint8_t> fCode;
148};
149
150struct ByteCode {
151 int fGlobalCount = 0;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400152 // one entry per input slot, contains the global slot to which the input slot maps
153 std::vector<uint8_t> fInputSlots;
154 std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
Brian Osman226668a2019-05-14 16:47:30 -0400155
156 const ByteCodeFunction* getFunction(const char* name) const {
157 for (const auto& f : fFunctions) {
158 if (f->fDeclaration.fName == name) {
159 return f.get();
160 }
161 }
162 return nullptr;
163 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400164
165 std::vector<ExternalValue*> fExternalValues;
Ethan Nicholas0e9401d2019-03-21 11:05:37 -0400166};
167
168}
169
170#endif