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