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 "include/private/SkOnce.h" 12 #include "include/private/SkVx.h" 13 #include "src/sksl/SkSLString.h" 14 #include "src/sksl/ir/SkSLFunctionDeclaration.h" 15 16 #include <memory> 17 #include <vector> 18 19 namespace SkSL { 20 21 class ByteCode; 22 class ExternalValue; 23 24 class ByteCodeFunction { 25 public: 26 // all counts are of 32-bit values, so a float4 counts as 4 parameter or return slots 27 struct Parameter { 28 int fSlotCount; 29 bool fIsOutParameter; 30 }; 31 32 /** 33 * Note that this is the actual number of parameters, not the number of parameter slots. 34 */ getParameterCount()35 int getParameterCount() const { return fParameters.size(); } 36 getParameter(int idx)37 Parameter getParameter(int idx) const { return fParameters[idx]; } 38 getParameterSlotCount()39 int getParameterSlotCount() const { return fParameterSlotCount; } 40 getReturnSlotCount()41 int getReturnSlotCount() const { return fReturnSlotCount; } 42 disassemble()43 void disassemble() const { } 44 45 private: ByteCodeFunction(const FunctionDeclaration * declaration)46 ByteCodeFunction(const FunctionDeclaration* declaration) 47 : fName(declaration->fName) {} 48 49 String fName; 50 51 std::vector<Parameter> fParameters; 52 53 int fParameterSlotCount; 54 55 int fReturnSlotCount; 56 57 int fStackSlotCount; 58 59 std::vector<uint8_t> fCode; 60 61 friend class ByteCode; 62 friend class ByteCodeGenerator; 63 template<int width> 64 friend class Interpreter; 65 }; 66 67 enum class TypeCategory { 68 kBool, 69 kSigned, 70 kUnsigned, 71 kFloat, 72 }; 73 74 class SK_API ByteCode { 75 public: 76 ByteCode() = default; 77 ByteCode(ByteCode&&) = default; 78 ByteCode& operator =(ByteCode&&) = default; 79 80 template<int width> 81 union Vector { 82 skvx::Vec<width, float> fFloat; 83 skvx::Vec<width, int32_t> fInt; 84 skvx::Vec<width, uint32_t> fUInt; 85 86 Vector() = default; 87 Vector(skvx::Vec<width,float> f)88 Vector(skvx::Vec<width, float> f) 89 : fFloat(f) {} 90 Vector(skvx::Vec<width,int32_t> i)91 Vector(skvx::Vec<width, int32_t> i) 92 : fInt(i) {} 93 Vector(skvx::Vec<width,uint32_t> u)94 Vector(skvx::Vec<width, uint32_t> u) 95 : fUInt(u) {} 96 }; 97 98 // All V(I) instructions have a second (vector) instruction, that is encoded with a uint8_t count 99 // immediately following the instruction (and before any other arguments). 100 #define V(Inst) Inst, Inst ## N 101 102 enum class Instruction : uint8_t { 103 // no parameters 104 kNop, 105 // no parameters 106 kAbort, 107 // Register target, Register src1, Register src2 108 V(kAddF), 109 // Register target, Register src1, Register src2 110 V(kAddI), 111 // Register target, Register src1, Register src2 112 kAnd, 113 // Register index, int arrayLength 114 kBoundsCheck, 115 // Pointer target 116 kBranch, 117 // Pointer target 118 kBranchIfAllFalse, 119 // no parameters 120 kBreak, 121 // Register target, uint8_t functionIndex, Register parameters 122 kCall, 123 // Register target, uint8_t externalValueIndex, uint8_t targetSize, Register arguments, 124 // uint8_t argumentSize 125 kCallExternal, 126 // Register target, Register src1, Register src2 127 kCompareEQF, 128 // Register target, Register src1, Register src2 129 kCompareEQI, 130 // Register target, Register src1, Register src2 131 kCompareNEQF, 132 // Register target, Register src1, Register src2 133 kCompareNEQI, 134 // Register target, Register src1, Register src2 135 kCompareGTF, 136 // Register target, Register src1, Register src2 137 kCompareGTS, 138 // Register target, Register src1, Register src2 139 kCompareGTU, 140 // Register target, Register src1, Register src2 141 kCompareGTEQF, 142 // Register target, Register src1, Register src2 143 kCompareGTEQS, 144 // Register target, Register src1, Register src2 145 kCompareGTEQU, 146 // Register target, Register src1, Register src2 147 kCompareLTF, 148 // Register target, Register src1, Register src2 149 kCompareLTS, 150 // Register target, Register src1, Register src2 151 kCompareLTU, 152 // Register target, Register src1, Register src2 153 kCompareLTEQF, 154 // Register target, Register src1, Register src2 155 kCompareLTEQS, 156 // Register target, Register src1, Register src2 157 kCompareLTEQU, 158 // no parameters 159 kContinue, 160 // Register target, Register src 161 kCopy, 162 // Register target, Register src, 163 kCos, 164 // Register target, Register src1, Register src2 165 V(kDivideF), 166 // Register target, Register src1, Register src2 167 V(kDivideS), 168 // Register target, Register src1, Register src2 169 V(kDivideU), 170 // Register target, Register src 171 kFloatToSigned, 172 // Register target, Register src 173 kFloatToUnsigned, 174 // Load a constant into a register 175 // Register target, Immediate value 176 kImmediate, 177 // Register target, Register src 178 kInverse2x2, 179 // Register target, Register src 180 kInverse3x3, 181 // Register target, Register src 182 kInverse4x4, 183 // Load the memory cell pointed to by srcPtr into a register 184 // Register target, Register srcPtr 185 V(kLoad), 186 // Load the memory cell pointed to by src into a register 187 // Register target, Pointer src 188 V(kLoadDirect), 189 // Load the parameter slot pointed to by srcPtr into a register 190 // Register target, Register srcPtr 191 V(kLoadParameter), 192 // Load the parameter slot pointed to by src into a register 193 // Register target, Pointer src 194 V(kLoadParameterDirect), 195 // Load the stack cell pointed to by srcPtr + sp into a register 196 // Register target, Register srcPtr 197 V(kLoadStack), 198 // Load the stack cell pointed to by src + sp into a register 199 // Register target, Pointer src 200 V(kLoadStackDirect), 201 // Pushes a new loop onto the loop and continue stacks 202 // no parameters 203 kLoopBegin, 204 // Pops the loop and continue stacks 205 // no parameters 206 kLoopEnd, 207 // Register mask 208 kLoopMask, 209 // no parameters 210 kLoopNext, 211 // no parameters 212 kMaskNegate, 213 // no parameters 214 kMaskPop, 215 // Register mask 216 kMaskPush, 217 // Register target, Register left, Register right, uint8_t leftColsAndRightRows, 218 // uint8_t leftRows, uint8_t rightCols 219 kMatrixMultiply, 220 // Register target, Register src, uint8_t srcColumns, uint8_t srcRows, uint8_t dstColumns, 221 // uint8_t dstRows 222 kMatrixToMatrix, 223 // Register target, Register src1, Register src2 224 V(kMultiplyF), 225 // Register target, Register src1, Register src2 226 V(kMultiplyI), 227 // Register target, Register src 228 kNegateF, 229 // Register target, Register src 230 kNegateS, 231 // Register target, Register src 232 kNot, 233 // Register target, Register src1, Register src2 234 kOr, 235 // Register src 236 kPrint, 237 // Register target, uint8_t count, uint8_t index 238 kReadExternal, 239 // Register target, Register src1, Register src2 240 V(kRemainderF), 241 // Register target, Register src1, Register src2 242 V(kRemainderS), 243 // Register target, Register src1, Register src2 244 V(kRemainderU), 245 // no parameters 246 kReturn, 247 // Register value 248 kReturnValue, 249 // Register target, Register src, uint8_t columns, uint8_t rows 250 kScalarToMatrix, 251 // Register target, Register test, Register ifTrue, Register ifFalse 252 kSelect, 253 // Register target, Register src, uint8_t count 254 kShiftLeft, 255 // Register target, Register src, uint8_t count 256 kShiftRightS, 257 // Register target, Register src, uint8_t count 258 kShiftRightU, 259 // Register target, Register src 260 kSignedToFloat, 261 // Register target, Register src, 262 kSin, 263 // Duplicates the src to <count> targets 264 // uint8_t count, Register target, Register src 265 kSplat, 266 // Register target, Register src, 267 kSqrt, 268 // Store to the memory cell pointed to by dstPtr 269 // Register dstPtr, Register src 270 V(kStore), 271 // Store to the memory cell pointed to by dst 272 // Pointer dst, Register src 273 V(kStoreDirect), 274 // Store to the parameter slot pointed to by dstPtr 275 // Register dstPtr, Register src 276 V(kStoreParameter), 277 // Store to the parameter slot pointed to by dst 278 // Pointer dst, Register src 279 V(kStoreParameterDirect), 280 // Stores a register into the stack cell pointed to by dst + sp 281 // Register dst, Register src 282 V(kStoreStack), 283 // Stores a register into the stack cell pointed to by dstPtr + sp 284 // Pointer dst, Register src 285 V(kStoreStackDirect), 286 // Register target, Register src1, Register src2 287 V(kSubtractF), 288 // Register target, Register src1, Register src2 289 V(kSubtractI), 290 // Register target, Register src, 291 kTan, 292 // Register target, Register src, 293 kUnsignedToFloat, 294 // uint8_t index, uint8_t count, Register src 295 kWriteExternal, 296 // Register target, Register src1, Register src2 297 kXor, 298 }; 299 300 #undef V 301 302 // Compound values like vectors span multiple Registers or Pointer addresses. We always refer to 303 // them by the address of their first slot, so for instance if you add two float4's together, 304 // the resulting Register contains the first channel of the result, with the other three 305 // channels following in the next three Registers. 306 307 struct Register { 308 uint16_t fIndex; 309 310 Register operator+(uint16_t offset) const { 311 return Register{(uint16_t) (fIndex + offset)}; 312 } 313 }; 314 315 struct Pointer { 316 uint16_t fAddress; 317 318 Pointer operator+(uint16_t offset) const { 319 return Pointer{(uint16_t) (fAddress + offset)}; 320 } 321 }; 322 323 union Immediate { 324 float fFloat; 325 int32_t fInt; 326 uint32_t fUInt; 327 Immediate()328 Immediate() {} 329 Immediate(float f)330 Immediate(float f) 331 : fFloat(f) {} 332 Immediate(int32_t i)333 Immediate(int32_t i) 334 : fInt(i) {} 335 Immediate(uint32_t u)336 Immediate(uint32_t u) 337 : fUInt(u) {} 338 }; 339 340 static constexpr int kPointerMax = 65535; 341 static constexpr int kRegisterMax = 65535; 342 getFunction(const char * name)343 const ByteCodeFunction* getFunction(const char* name) const { 344 for (const auto& f : fFunctions) { 345 if (f->fName == name) { 346 return f.get(); 347 } 348 } 349 return nullptr; 350 } 351 getGlobalSlotCount()352 int getGlobalSlotCount() const { 353 return fGlobalSlotCount; 354 } 355 356 struct Uniform { 357 SkSL::String fName; 358 TypeCategory fType; 359 int fColumns; 360 int fRows; 361 int fSlot; 362 }; 363 getUniformSlotCount()364 int getUniformSlotCount() const { return fUniformSlotCount; } getUniformCount()365 int getUniformCount() const { return fUniforms.size(); } getUniformLocation(const char * name)366 int getUniformLocation(const char* name) const { 367 for (int i = 0; i < (int)fUniforms.size(); ++i) { 368 if (fUniforms[i].fName == name) { 369 return fUniforms[i].fSlot; 370 } 371 } 372 return -1; 373 } getUniform(int i)374 const Uniform& getUniform(int i) const { return fUniforms[i]; } 375 376 private: 377 ByteCode(const ByteCode&) = delete; 378 ByteCode& operator=(const ByteCode&) = delete; 379 380 std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions; 381 std::vector<ExternalValue*> fExternalValues; 382 383 int fGlobalSlotCount; 384 385 int fUniformSlotCount = 0; 386 std::vector<Uniform> fUniforms; 387 388 friend class ByteCodeGenerator; 389 template<int width> 390 friend class Interpreter; 391 }; 392 393 } // namespace 394 395 #endif 396