• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
11 #include "src/sksl/SkSLString.h"
12 
13 #include <memory>
14 #include <vector>
15 
16 namespace SkSL {
17 
18 class  ExternalValue;
19 struct FunctionDeclaration;
20 
21 #define VECTOR(name) name, name ## 2, name ## 3, name ## 4
22 #define VECTOR_MATRIX(name) name, name ## 2, name ## 3, name ## 4, name ## N
23 
24 enum class ByteCodeInstruction : uint16_t {
25     // B = bool, F = float, I = int, S = signed, U = unsigned
26     VECTOR_MATRIX(kAddF),
27     VECTOR(kAddI),
28     kAndB,
29     kBranch,
30     // Followed by a byte indicating the index of the function to call
31     kCall,
32     // 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,
35     // For dynamic array access: Followed by byte indicating length of array
36     kClampIndex,
37     VECTOR(kCompareIEQ),
38     VECTOR(kCompareINEQ),
39     VECTOR_MATRIX(kCompareFEQ),
40     VECTOR(kCompareFGT),
41     VECTOR(kCompareFGTEQ),
42     VECTOR(kCompareFLT),
43     VECTOR(kCompareFLTEQ),
44     VECTOR_MATRIX(kCompareFNEQ),
45     VECTOR(kCompareSGT),
46     VECTOR(kCompareSGTEQ),
47     VECTOR(kCompareSLT),
48     VECTOR(kCompareSLTEQ),
49     VECTOR(kCompareUGT),
50     VECTOR(kCompareUGTEQ),
51     VECTOR(kCompareULT),
52     VECTOR(kCompareULTEQ),
53     VECTOR(kConvertFtoI),
54     VECTOR(kConvertStoF),
55     VECTOR(kConvertUtoF),
56     VECTOR(kCos),
57     VECTOR_MATRIX(kDivideF),
58     VECTOR(kDivideS),
59     VECTOR(kDivideU),
60     // Duplicates the top stack value
61     VECTOR_MATRIX(kDup),
62     kInverse2x2, kInverse3x3, kInverse4x4,
63     // kLoad/kLoadGlobal are followed by a byte indicating the local/global slot to load
64     VECTOR(kLoad),
65     VECTOR(kLoadGlobal),
66     // As kLoad/kLoadGlobal, then a count byte (1-4), and then one byte per swizzle component (0-3).
67     kLoadSwizzle,
68     kLoadSwizzleGlobal,
69     // kLoadExtended* are fallback load ops when we lack a specialization. They are followed by a
70     // count byte, and get the slot to load from the top of the stack.
71     kLoadExtended,
72     kLoadExtendedGlobal,
73     // Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
74     // stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
75     // dimensions. Any overlapping values are copied, and any other values are filled in with the
76     // identity matrix.
77     kMatrixToMatrix,
78     // Followed by three bytes: leftCols (== rightRows), leftRows, rightCols
79     kMatrixMultiply,
80     VECTOR_MATRIX(kNegateF),
81     VECTOR(kNegateI),
82     VECTOR_MATRIX(kMultiplyF),
83     VECTOR(kMultiplyI),
84     kNotB,
85     kOrB,
86     VECTOR_MATRIX(kPop),
87     // Followed by a 32 bit value containing the value to push
88     kPushImmediate,
89     // Followed by a byte indicating external value to read
90     VECTOR(kReadExternal),
91     VECTOR(kRemainderF),
92     VECTOR(kRemainderS),
93     VECTOR(kRemainderU),
94     // Followed by a byte indicating the number of slots to reserve on the stack (for later return)
95     kReserve,
96     // Followed by a byte indicating the number of slots being returned
97     kReturn,
98     // Followed by two bytes indicating columns and rows of matrix (2, 3, or 4 each).
99     // Takes a single value from the top of the stack, and converts to a CxR matrix with that value
100     // replicated along the diagonal (and zero elsewhere), per the GLSL matrix construction rules.
101     kScalarToMatrix,
102     VECTOR(kSin),
103     VECTOR(kSqrt),
104     // kStore/kStoreGlobal are followed by a byte indicating the local/global slot to store
105     VECTOR(kStore),
106     VECTOR(kStoreGlobal),
107     // Fallback stores. Followed by count byte, and get the slot to store from the top of the stack
108     kStoreExtended,
109     kStoreExtendedGlobal,
110     // As kStore/kStoreGlobal, then a count byte (1-4), then one byte per swizzle component (0-3).
111     // Expects the stack to look like: ... v1 v2 v3 v4, where the number of 'v's is equal to the
112     // number of swizzle components. After the store, all v's are popped from the stack.
113     kStoreSwizzle,
114     kStoreSwizzleGlobal,
115     // As above, but gets the store slot from the top of the stack (before values to be stored)
116     kStoreSwizzleIndirect,
117     kStoreSwizzleIndirectGlobal,
118     // Followed by two count bytes (1-4), and then one byte per swizzle component (0-3). The first
119     // count byte provides the current vector size (the vector is the top n stack elements), and the
120     // second count byte provides the swizzle component count.
121     kSwizzle,
122     VECTOR_MATRIX(kSubtractF),
123     VECTOR(kSubtractI),
124     VECTOR(kTan),
125     // Followed by a byte indicating external value to write
126     VECTOR(kWriteExternal),
127     kXorB,
128 
129     kMaskPush,
130     kMaskPop,
131     kMaskNegate,
132     // Followed by count byte
133     kMaskBlend,
134     // Followed by address
135     kBranchIfAllFalse,
136 
137     kLoopBegin,
138     kLoopNext,
139     kLoopMask,
140     kLoopEnd,
141     kLoopBreak,
142     kLoopContinue,
143 };
144 #undef VECTOR
145 
146 struct ByteCodeFunction {
147     ByteCodeFunction(const FunctionDeclaration* declaration);
148 
149     struct Parameter {
150         int fSlotCount;
151         bool fIsOutParameter;
152     };
153 
154     SkSL::String fName;
155     std::vector<Parameter> fParameters;
156     int fParameterCount;
157 
158     int fLocalCount = 0;
159     int fStackCount = 0;
160     int fConditionCount = 0;
161     int fLoopCount = 0;
162     int fReturnCount = 0;
163     std::vector<uint8_t> fCode;
164 
165     /**
166      * Print bytecode disassembly to stdout.
167      */
168     void disassemble() const;
169 };
170 
171 struct SK_API ByteCode {
172     static constexpr int kVecWidth = 16;
173 
174     ByteCode() = default;
175     ByteCode(const ByteCode&) = delete;
176     ByteCode& operator=(const ByteCode&) = delete;
177 
178     int fGlobalCount = 0;
179     // one entry per input slot, contains the global slot to which the input slot maps
180     std::vector<uint8_t> fInputSlots;
181     std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
182     std::vector<ExternalValue*> fExternalValues;
183 
getFunctionByteCode184     const ByteCodeFunction* getFunction(const char* name) const {
185         for (const auto& f : fFunctions) {
186             if (f->fName == name) {
187                 return f.get();
188             }
189         }
190         return nullptr;
191     }
192 
193     /**
194      * Invokes the specified function with the given arguments, 'N' times.
195      * 'args', 'outReturn', and 'uniforms' are collections of 32-bit values (typically floats,
196      * but possibly int32_t or uint32_t, depending on the types used in the SkSL).
197      * Any 'out' or 'inout' parameters will result in the 'args' array being modified.
198      * The return value is stored in 'outReturn' (may be null, to discard the return value).
199      * 'uniforms' are mapped to 'uniform' globals, in order.
200      */
201     bool SKSL_WARN_UNUSED_RESULT run(const ByteCodeFunction*, float* args, float* outReturn, int N,
202                                      const float* uniforms, int uniformCount) const;
203 
204     bool SKSL_WARN_UNUSED_RESULT runStriped(const ByteCodeFunction*,
205                                             float* args[], int nargs, int N,
206                                             const float* uniforms, int uniformCount,
207                                             float* outArgs[], int outArgCount) const;
208 };
209 
210 }
211 
212 #endif
213