Revert "Revert "switched SkSL interpreter over to threaded code""
This reverts commit cbdc829ff1
.
Bug: skia:
Change-Id: Idb7ad413431e6556bc040369df258655c2349ef2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/239447
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
eedd08576a
commit
c70027b151
File diff suppressed because it is too large
Load Diff
@ -18,11 +18,25 @@ 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
|
||||
// GCC and Clang support the "labels as values" extension which we need to implement the interpreter
|
||||
// using threaded code. Otherwise, we fall back to using a switch statement in a for loop.
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define SKSLC_THREADED_CODE
|
||||
using instruction = void*;
|
||||
#else
|
||||
using instruction = uint16_t;
|
||||
#endif
|
||||
|
||||
#define VECTOR(name) name ## 4, name ## 3, name ## 2, name
|
||||
#define VECTOR_MATRIX(name) name ## 4, name ## 3, name ## 2, name, name ## N
|
||||
|
||||
enum class ByteCodeInstruction : uint16_t {
|
||||
// B = bool, F = float, I = int, S = signed, U = unsigned
|
||||
// All binary VECTOR instructions (kAddF, KSubtractI, kCompareIEQ, etc.) are followed by a byte
|
||||
// indicating the count, even though it is redundant due to the count appearing in the opcode.
|
||||
// This is because the original opcodes are lost after we preprocess it into threaded code, and
|
||||
// we need to still be able to access the count so as to permit the implementation to use opcode
|
||||
// fallthrough.
|
||||
VECTOR_MATRIX(kAddF),
|
||||
VECTOR(kAddI),
|
||||
kAndB,
|
||||
@ -37,11 +51,11 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
VECTOR(kCompareIEQ),
|
||||
VECTOR(kCompareINEQ),
|
||||
VECTOR_MATRIX(kCompareFEQ),
|
||||
VECTOR_MATRIX(kCompareFNEQ),
|
||||
VECTOR(kCompareFGT),
|
||||
VECTOR(kCompareFGTEQ),
|
||||
VECTOR(kCompareFLT),
|
||||
VECTOR(kCompareFLTEQ),
|
||||
VECTOR_MATRIX(kCompareFNEQ),
|
||||
VECTOR(kCompareSGT),
|
||||
VECTOR(kCompareSGTEQ),
|
||||
VECTOR(kCompareSLT),
|
||||
@ -53,14 +67,18 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
VECTOR(kConvertFtoI),
|
||||
VECTOR(kConvertStoF),
|
||||
VECTOR(kConvertUtoF),
|
||||
// Followed by a (redundant) byte indicating the count
|
||||
VECTOR(kCos),
|
||||
VECTOR_MATRIX(kDivideF),
|
||||
VECTOR(kDivideS),
|
||||
VECTOR(kDivideU),
|
||||
// Duplicates the top stack value
|
||||
// Duplicates the top stack value. Followed by a (redundant) byte indicating the count.
|
||||
VECTOR_MATRIX(kDup),
|
||||
kInverse2x2, kInverse3x3, kInverse4x4,
|
||||
// kLoad/kLoadGlobal are followed by a byte indicating the local/global slot to load
|
||||
kInverse2x2,
|
||||
kInverse3x3,
|
||||
kInverse4x4,
|
||||
// kLoad/kLoadGlobal are followed by a byte indicating the count, and 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).
|
||||
@ -99,6 +117,7 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
// 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,
|
||||
// Followed by a (redundant) byte indicating the count
|
||||
VECTOR(kSin),
|
||||
VECTOR(kSqrt),
|
||||
// kStore/kStoreGlobal are followed by a byte indicating the local/global slot to store
|
||||
@ -121,6 +140,7 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
kSwizzle,
|
||||
VECTOR_MATRIX(kSubtractF),
|
||||
VECTOR(kSubtractI),
|
||||
// Followed by a (redundant) byte indicating the count
|
||||
VECTOR(kTan),
|
||||
// Followed by a byte indicating external value to write
|
||||
VECTOR(kWriteExternal),
|
||||
@ -160,12 +180,18 @@ struct ByteCodeFunction {
|
||||
int fConditionCount = 0;
|
||||
int fLoopCount = 0;
|
||||
int fReturnCount = 0;
|
||||
bool fPreprocessed = 0;
|
||||
std::vector<uint8_t> fCode;
|
||||
|
||||
/**
|
||||
* Print bytecode disassembly to stdout.
|
||||
*/
|
||||
void disassemble() const;
|
||||
|
||||
/**
|
||||
* Replace each opcode with the corresponding entry from the labels array.
|
||||
*/
|
||||
void preprocess(const void* labels[]);
|
||||
};
|
||||
|
||||
struct SK_API ByteCode {
|
||||
|
@ -441,6 +441,7 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
||||
this->write(ByteCodeInstruction::kPushImmediate);
|
||||
this->write32(offset);
|
||||
this->write(ByteCodeInstruction::kAddI);
|
||||
this->write8(1);
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
@ -475,6 +476,7 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
||||
this->write(ByteCodeInstruction::kPushImmediate);
|
||||
this->write32(stride);
|
||||
this->write(ByteCodeInstruction::kMultiplyI);
|
||||
this->write8(1);
|
||||
}
|
||||
}
|
||||
int baseAddr = this->getLocation(*i.fBase, storage);
|
||||
@ -501,6 +503,7 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
||||
this->write32(offset);
|
||||
}
|
||||
this->write(ByteCodeInstruction::kAddI);
|
||||
this->write8(1);
|
||||
return -1;
|
||||
}
|
||||
case Expression::kSwizzle_Kind: {
|
||||
@ -513,6 +516,7 @@ int ByteCodeGenerator::getLocation(const Expression& expr, Variable::Storage* st
|
||||
this->write(ByteCodeInstruction::kPushImmediate);
|
||||
this->write32(offset);
|
||||
this->write(ByteCodeInstruction::kAddI);
|
||||
this->write8(1);
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
@ -556,19 +560,22 @@ void ByteCodeGenerator::write(ByteCodeInstruction i, int count) {
|
||||
case ByteCodeInstruction::kMaskBlend: this->exitCondition(); break;
|
||||
default: /* Do nothing */ break;
|
||||
}
|
||||
this->write16((uint16_t)i);
|
||||
instruction val = (instruction) i;
|
||||
size_t n = fCode->size();
|
||||
fCode->resize(n + sizeof(val));
|
||||
memcpy(fCode->data() + n, &val, sizeof(val));
|
||||
fStackCount += StackUsage(i, count);
|
||||
fMaxStackCount = std::max(fMaxStackCount, fStackCount);
|
||||
}
|
||||
|
||||
static ByteCodeInstruction vector_instruction(ByteCodeInstruction base, int count) {
|
||||
SkASSERT(count >= 1 && count <= 4);
|
||||
return ((ByteCodeInstruction) ((int) base + count - 1));
|
||||
return ((ByteCodeInstruction) ((int) base + 1 - count));
|
||||
}
|
||||
|
||||
void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruction s,
|
||||
ByteCodeInstruction u, ByteCodeInstruction f,
|
||||
int count) {
|
||||
int count, bool writeCount) {
|
||||
switch (type_category(type)) {
|
||||
case TypeCategory::kSigned:
|
||||
this->write(vector_instruction(s, count));
|
||||
@ -578,8 +585,7 @@ void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruct
|
||||
break;
|
||||
case TypeCategory::kFloat: {
|
||||
if (count > 4) {
|
||||
this->write((ByteCodeInstruction)((int)f + 4), count);
|
||||
this->write8(count);
|
||||
this->write((ByteCodeInstruction)((int)f + 1), count);
|
||||
} else {
|
||||
this->write(vector_instruction(f, count));
|
||||
}
|
||||
@ -588,6 +594,9 @@ void ByteCodeGenerator::writeTypedInstruction(const Type& type, ByteCodeInstruct
|
||||
default:
|
||||
SkASSERT(false);
|
||||
}
|
||||
if (writeCount) {
|
||||
this->write8(count);
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool discard) {
|
||||
@ -614,6 +623,7 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
|
||||
if (!lVecOrMtx && rVecOrMtx) {
|
||||
for (int i = SlotCount(rType); i > 1; --i) {
|
||||
this->write(ByteCodeInstruction::kDup);
|
||||
this->write8(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -621,6 +631,7 @@ bool ByteCodeGenerator::writeBinaryExpression(const BinaryExpression& b, bool di
|
||||
if (lVecOrMtx && !rVecOrMtx) {
|
||||
for (int i = SlotCount(lType); i > 1; --i) {
|
||||
this->write(ByteCodeInstruction::kDup);
|
||||
this->write8(1);
|
||||
}
|
||||
}
|
||||
// Special case for M*V, V*M, M*M (but not V*V!)
|
||||
@ -799,6 +810,7 @@ void ByteCodeGenerator::writeConstructor(const Constructor& c) {
|
||||
SkASSERT(outType.kind() == Type::kVector_Kind);
|
||||
for (; inCount != outCount; ++inCount) {
|
||||
this->write(ByteCodeInstruction::kDup);
|
||||
this->write8(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -822,8 +834,9 @@ void ByteCodeGenerator::writeExternalFunctionCall(const ExternalFunctionCall& f)
|
||||
}
|
||||
|
||||
void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
|
||||
this->write(vector_instruction(ByteCodeInstruction::kReadExternal,
|
||||
SlotCount(e.fValue->type())));
|
||||
int count = SlotCount(e.fValue->type());
|
||||
this->write(vector_instruction(ByteCodeInstruction::kReadExternal, count));
|
||||
this->write8(count);
|
||||
int index = fOutput->fExternalValues.size();
|
||||
fOutput->fExternalValues.push_back(e.fValue);
|
||||
SkASSERT(index <= 255);
|
||||
@ -848,6 +861,7 @@ void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
|
||||
this->write(vector_instruction(isGlobal ? ByteCodeInstruction::kLoadGlobal
|
||||
: ByteCodeInstruction::kLoad,
|
||||
count));
|
||||
this->write8(count);
|
||||
this->write8(location);
|
||||
}
|
||||
}
|
||||
@ -876,9 +890,11 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
case SpecialIntrinsic::kDot: {
|
||||
SkASSERT(c.fArguments.size() == 2);
|
||||
SkASSERT(count == SlotCount(c.fArguments[1]->fType));
|
||||
this->write((ByteCodeInstruction)((int)ByteCodeInstruction::kMultiplyF + count-1));
|
||||
this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
|
||||
this->write8(count);
|
||||
for (int i = count; i > 1; --i) {
|
||||
this->write(ByteCodeInstruction::kAddF);
|
||||
this->write8(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -889,11 +905,14 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
switch (found->second.fValue.fInstruction) {
|
||||
case ByteCodeInstruction::kCos:
|
||||
case ByteCodeInstruction::kSin:
|
||||
case ByteCodeInstruction::kSqrt:
|
||||
case ByteCodeInstruction::kTan:
|
||||
SkASSERT(c.fArguments.size() > 0);
|
||||
this->write((ByteCodeInstruction) ((int) found->second.fValue.fInstruction +
|
||||
count - 1));
|
||||
this->write(vector_instruction(found->second.fValue.fInstruction, count));
|
||||
this->write8(count);
|
||||
break;
|
||||
case ByteCodeInstruction::kSqrt:
|
||||
SkASSERT(c.fArguments.size() > 0);
|
||||
this->write(vector_instruction(found->second.fValue.fInstruction, count));
|
||||
break;
|
||||
case ByteCodeInstruction::kInverse2x2: {
|
||||
SkASSERT(c.fArguments.size() > 0);
|
||||
@ -1039,7 +1058,8 @@ bool ByteCodeGenerator::writePrefixExpression(const PrefixExpression& p, bool di
|
||||
ByteCodeInstruction::kNegateI,
|
||||
ByteCodeInstruction::kNegateI,
|
||||
ByteCodeInstruction::kNegateF,
|
||||
SlotCount(p.fOperand->fType));
|
||||
SlotCount(p.fOperand->fType),
|
||||
false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1058,6 +1078,7 @@ bool ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p, bool
|
||||
// If we're not supposed to discard the result, then make a copy *before* the +/-
|
||||
if (!discard) {
|
||||
this->write(ByteCodeInstruction::kDup);
|
||||
this->write8(1);
|
||||
}
|
||||
this->write(ByteCodeInstruction::kPushImmediate);
|
||||
this->write32(type_category(p.fType) == TypeCategory::kFloat ? float_to_bits(1.0f) : 1);
|
||||
@ -1202,14 +1223,17 @@ public:
|
||||
|
||||
void load() override {
|
||||
fGenerator.write(vector_instruction(ByteCodeInstruction::kReadExternal, fCount));
|
||||
fGenerator.write8(fCount);
|
||||
fGenerator.write8(fIndex);
|
||||
}
|
||||
|
||||
void store(bool discard) override {
|
||||
if (!discard) {
|
||||
fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, fCount));
|
||||
fGenerator.write8(fCount);
|
||||
}
|
||||
fGenerator.write(vector_instruction(ByteCodeInstruction::kWriteExternal, fCount));
|
||||
fGenerator.write8(fCount);
|
||||
fGenerator.write8(fIndex);
|
||||
}
|
||||
|
||||
@ -1235,6 +1259,7 @@ public:
|
||||
int count = fSwizzle.fComponents.size();
|
||||
if (!discard) {
|
||||
fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
|
||||
fGenerator.write8(count);
|
||||
}
|
||||
Variable::Storage storage = Variable::kLocal_Storage;
|
||||
int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
|
||||
@ -1279,6 +1304,7 @@ public:
|
||||
fGenerator.write8(count);
|
||||
} else {
|
||||
fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
|
||||
fGenerator.write8(count);
|
||||
}
|
||||
}
|
||||
Variable::Storage storage = Variable::kLocal_Storage;
|
||||
|
@ -94,7 +94,7 @@ public:
|
||||
* Based on 'type', writes the s (signed), u (unsigned), or f (float) instruction.
|
||||
*/
|
||||
void writeTypedInstruction(const Type& type, ByteCodeInstruction s, ByteCodeInstruction u,
|
||||
ByteCodeInstruction f, int count);
|
||||
ByteCodeInstruction f, int count, bool writeCount = true);
|
||||
|
||||
static int SlotCount(const Type& type);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user