123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /*
- * Copyright 2019 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SKSL_BYTECODE
- #define SKSL_BYTECODE
- #include "src/sksl/SkSLString.h"
- #include <memory>
- #include <vector>
- namespace SkSL {
- class ExternalValue;
- struct FunctionDeclaration;
- #define VECTOR(name) name, name ## 2, name ## 3, name ## 4
- #define VECTOR_MATRIX(name) name, name ## 2, name ## 3, name ## 4, name ## N
- enum class ByteCodeInstruction : uint16_t {
- // B = bool, F = float, I = int, S = signed, U = unsigned
- VECTOR_MATRIX(kAddF),
- VECTOR(kAddI),
- kAndB,
- kBranch,
- // Followed by a byte indicating the index of the function to call
- kCall,
- // Followed by three bytes indicating: the number of argument slots, the number of return slots,
- // and the index of the external value to call
- kCallExternal,
- // For dynamic array access: Followed by byte indicating length of array
- kClampIndex,
- VECTOR(kCompareIEQ),
- VECTOR(kCompareINEQ),
- VECTOR_MATRIX(kCompareFEQ),
- VECTOR(kCompareFGT),
- VECTOR(kCompareFGTEQ),
- VECTOR(kCompareFLT),
- VECTOR(kCompareFLTEQ),
- VECTOR_MATRIX(kCompareFNEQ),
- VECTOR(kCompareSGT),
- VECTOR(kCompareSGTEQ),
- VECTOR(kCompareSLT),
- VECTOR(kCompareSLTEQ),
- VECTOR(kCompareUGT),
- VECTOR(kCompareUGTEQ),
- VECTOR(kCompareULT),
- VECTOR(kCompareULTEQ),
- VECTOR(kConvertFtoI),
- VECTOR(kConvertStoF),
- VECTOR(kConvertUtoF),
- VECTOR(kCos),
- kCross,
- VECTOR_MATRIX(kDivideF),
- VECTOR(kDivideS),
- VECTOR(kDivideU),
- // Duplicates the top stack value
- VECTOR_MATRIX(kDup),
- kInverse2x2, kInverse3x3, kInverse4x4,
- // kLoad/kLoadGlobal are followed by a byte indicating the local/global slot to load
- VECTOR(kLoad),
- VECTOR(kLoadGlobal),
- // As kLoad/kLoadGlobal, then a count byte (1-4), and then one byte per swizzle component (0-3).
- kLoadSwizzle,
- kLoadSwizzleGlobal,
- // kLoadExtended* are fallback load ops when we lack a specialization. They are followed by a
- // count byte, and get the slot to load from the top of the stack.
- kLoadExtended,
- kLoadExtendedGlobal,
- // Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
- // stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
- // dimensions. Any overlapping values are copied, and any other values are filled in with the
- // identity matrix.
- kMatrixToMatrix,
- // Followed by three bytes: leftCols (== rightRows), leftRows, rightCols
- kMatrixMultiply,
- VECTOR_MATRIX(kNegateF),
- VECTOR(kNegateI),
- VECTOR(kMix),
- VECTOR_MATRIX(kMultiplyF),
- VECTOR(kMultiplyI),
- kNotB,
- kOrB,
- VECTOR_MATRIX(kPop),
- // Followed by a 32 bit value containing the value to push
- kPushImmediate,
- // Followed by a byte indicating external value to read
- VECTOR(kReadExternal),
- VECTOR(kRemainderF),
- VECTOR(kRemainderS),
- VECTOR(kRemainderU),
- // Followed by a byte indicating the number of slots to reserve on the stack (for later return)
- kReserve,
- // Followed by a byte indicating the number of slots being returned
- kReturn,
- // Followed by two bytes indicating columns and rows of matrix (2, 3, or 4 each).
- // Takes a single value from the top of the stack, and converts to a CxR matrix with that value
- // replicated along the diagonal (and zero elsewhere), per the GLSL matrix construction rules.
- kScalarToMatrix,
- VECTOR(kSin),
- VECTOR(kSqrt),
- // kStore/kStoreGlobal are followed by a byte indicating the local/global slot to store
- VECTOR(kStore),
- VECTOR(kStoreGlobal),
- // Fallback stores. Followed by count byte, and get the slot to store from the top of the stack
- kStoreExtended,
- kStoreExtendedGlobal,
- // As kStore/kStoreGlobal, then a count byte (1-4), then one byte per swizzle component (0-3).
- // Expects the stack to look like: ... v1 v2 v3 v4, where the number of 'v's is equal to the
- // number of swizzle components. After the store, all v's are popped from the stack.
- kStoreSwizzle,
- kStoreSwizzleGlobal,
- // As above, but gets the store slot from the top of the stack (before values to be stored)
- kStoreSwizzleIndirect,
- kStoreSwizzleIndirectGlobal,
- // Followed by two count bytes (1-4), and then one byte per swizzle component (0-3). The first
- // count byte provides the current vector size (the vector is the top n stack elements), and the
- // second count byte provides the swizzle component count.
- kSwizzle,
- VECTOR_MATRIX(kSubtractF),
- VECTOR(kSubtractI),
- VECTOR(kTan),
- // Followed by a byte indicating external value to write
- VECTOR(kWriteExternal),
- kXorB,
- kMaskPush,
- kMaskPop,
- kMaskNegate,
- // Followed by count byte
- kMaskBlend,
- // Followed by address
- kBranchIfAllFalse,
- kLoopBegin,
- kLoopNext,
- kLoopMask,
- kLoopEnd,
- kLoopBreak,
- kLoopContinue,
- };
- #undef VECTOR
- struct ByteCodeFunction {
- ByteCodeFunction(const FunctionDeclaration* declaration);
- struct Parameter {
- int fSlotCount;
- bool fIsOutParameter;
- };
- SkSL::String fName;
- std::vector<Parameter> fParameters;
- int fParameterCount;
- int fLocalCount = 0;
- int fStackCount = 0;
- int fConditionCount = 0;
- int fLoopCount = 0;
- int fReturnCount = 0;
- std::vector<uint8_t> fCode;
- /**
- * Print bytecode disassembly to stdout.
- */
- void disassemble() const;
- };
- struct SK_API ByteCode {
- static constexpr int kVecWidth = 16;
- ByteCode() = default;
- ByteCode(const ByteCode&) = delete;
- ByteCode& operator=(const ByteCode&) = delete;
- int fGlobalCount = 0;
- // one entry per input slot, contains the global slot to which the input slot maps
- std::vector<uint8_t> fInputSlots;
- std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
- std::vector<ExternalValue*> fExternalValues;
- const ByteCodeFunction* getFunction(const char* name) const {
- for (const auto& f : fFunctions) {
- if (f->fName == name) {
- return f.get();
- }
- }
- return nullptr;
- }
- /**
- * Invokes the specified function with the given arguments, 'N' times.
- * 'args', 'outReturn', and 'uniforms' are collections of 32-bit values (typically floats,
- * but possibly int32_t or uint32_t, depending on the types used in the SkSL).
- * Any 'out' or 'inout' parameters will result in the 'args' array being modified.
- * The return value is stored in 'outReturn' (may be null, to discard the return value).
- * 'uniforms' are mapped to 'uniform' globals, in order.
- */
- bool SKSL_WARN_UNUSED_RESULT run(const ByteCodeFunction*, float* args, float* outReturn, int N,
- const float* uniforms, int uniformCount) const;
- bool SKSL_WARN_UNUSED_RESULT runStriped(const ByteCodeFunction*,
- float* args[], int nargs, int N,
- const float* uniforms, int uniformCount,
- float* outArgs[], int outArgCount) const;
- };
- }
- #endif
|