Interpreter: Simplify interface quite a bit.
Slightly sharper, but far easier to hold:
- Remove Value union from interface, everything is a 32-bit
value type, or a collection thereof.
- Collapse to one version of Run (that takes count), and make
it a member on ByteCode.
- Similarly, move disassemble to ByteCodeFunction.
Change-Id: I07c85e65991178b3f52e20e815c25f36bc9c4257
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/220753
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/bench/SkSLInterpreterBench.cpp b/bench/SkSLInterpreterBench.cpp
index c3a34cc..646d59f 100644
--- a/bench/SkSLInterpreterBench.cpp
+++ b/bench/SkSLInterpreterBench.cpp
@@ -6,8 +6,8 @@
*/
#include "bench/Benchmark.h"
#include "include/utils/SkRandom.h"
+#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLCompiler.h"
-#include "src/sksl/SkSLInterpreter.h"
// Benchmarks the interpreter with a function that has a color-filter style signature
class SkSLInterpreterCFBench : public Benchmark {
@@ -36,17 +36,15 @@
fMain = fByteCode->getFunction("main");
SkRandom rnd;
- fPixels.resize(fCount);
- for (int i = 0; i < fCount; ++i) {
- fPixels[i] = SkColor4f::FromColor(rnd.nextU());
+ fPixels.resize(fCount * 4);
+ for (float& c : fPixels) {
+ c = rnd.nextF();
}
}
void onDraw(int loops, SkCanvas*) override {
for (int i = 0; i < loops; i++) {
- SkSL::Interpreter::VecRun(fByteCode.get(), fMain,
- (SkSL::Interpreter::Value*)fPixels.data(), nullptr, fCount,
- nullptr, 0);
+ fByteCode->run(fMain, fPixels.data(), nullptr, fCount, nullptr, 0);
}
}
@@ -57,7 +55,7 @@
const SkSL::ByteCodeFunction* fMain;
int fCount;
- std::vector<SkColor4f> fPixels;
+ std::vector<float> fPixels;
typedef Benchmark INHERITED;
};
@@ -164,16 +162,12 @@
fDst.resize(fGroups * fValues);
SkRandom rnd;
- for (auto& x : fSrc) {
- x = rnd.nextS();
+ for (float& x : fSrc) {
+ x = rnd.nextF();
}
// Trigger one run now to check correctness
- SkSL::Interpreter::VecRun(fByteCode.get(), fMain,
- (SkSL::Interpreter::Value*)fSrc.data(),
- (SkSL::Interpreter::Value*)fDst.data(),
- fGroups,
- nullptr, 0);
+ fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0);
for (int i = 0; i < fGroups; ++i) {
for (int j = 1; j < fValues; ++j) {
SkASSERT(fDst[i * fValues + j] >= fDst[i * fValues + j - 1]);
@@ -183,11 +177,7 @@
void onDraw(int loops, SkCanvas*) override {
for (int i = 0; i < loops; i++) {
- SkSL::Interpreter::VecRun(fByteCode.get(), fMain,
- (SkSL::Interpreter::Value*)fSrc.data(),
- (SkSL::Interpreter::Value*)fDst.data(),
- fGroups,
- nullptr, 0);
+ fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0);
}
}
@@ -199,8 +189,8 @@
int fGroups;
int fValues;
- std::vector<int32_t> fSrc;
- std::vector<int32_t> fDst;
+ std::vector<float> fSrc;
+ std::vector<float> fDst;
typedef Benchmark INHERITED;
};
@@ -209,10 +199,10 @@
// bounds checking.
#if 0
DEF_BENCH(return new SkSLInterpreterSortBench(1024, 32, R"(
- int[32] main(int v[32]) {
+ float[32] main(float v[32]) {
for (int i = 1; i < 32; ++i) {
for (int j = i; j > 0 && v[j-1] > v[j]; --j) {
- int t = v[j];
+ float t = v[j];
v[j] = v[j-1];
v[j-1] = t;
}
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 3c12321..de369ef 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -8,6 +8,7 @@
skia_sksl_sources = [
"$_src/sksl/SkSLASTNode.cpp",
+ "$_src/sksl/SkSLByteCode.cpp",
"$_src/sksl/SkSLByteCodeGenerator.cpp",
"$_src/sksl/SkSLCFGGenerator.cpp",
"$_src/sksl/SkSLCompiler.cpp",
@@ -15,7 +16,6 @@
"$_src/sksl/SkSLCPPUniformCTypes.cpp",
"$_src/sksl/SkSLGLSLCodeGenerator.cpp",
"$_src/sksl/SkSLHCodeGenerator.cpp",
- "$_src/sksl/SkSLInterpreter.cpp",
"$_src/sksl/SkSLIRGenerator.cpp",
"$_src/sksl/SkSLJIT.cpp",
"$_src/sksl/SkSLLexer.cpp",
diff --git a/modules/particles/src/SkParticleAffector.cpp b/modules/particles/src/SkParticleAffector.cpp
index ab22088..0ed3ad1 100644
--- a/modules/particles/src/SkParticleAffector.cpp
+++ b/modules/particles/src/SkParticleAffector.cpp
@@ -17,9 +17,9 @@
#include "src/core/SkMakeUnique.h"
#if SK_SUPPORT_GPU
+#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLExternalValue.h"
-#include "src/sksl/SkSLInterpreter.h"
#endif
void SkParticleAffector::apply(const SkParticleUpdateParams& params,
@@ -481,8 +481,7 @@
void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
for (int i = 0; i < count; ++i) {
fRandomValue->setRandom(&ps[i].fRandom);
- SkSL::Interpreter::Run(fByteCode.get(), fMain, (SkSL::Interpreter::Value*)&ps[i].fAge,
- nullptr, (SkSL::Interpreter::Value*)¶ms, 2);
+ fByteCode->run(fMain, &ps[i].fAge, nullptr, 1, ¶ms.fDeltaTime, 2);
}
}
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index fa6cede..4a1bd13 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -366,7 +366,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/sksl/SkSLByteCode.h"
-#include "src/sksl/SkSLInterpreter.h"
class SkRuntimeColorFilter : public SkColorFilter {
public:
@@ -425,10 +424,8 @@
ctx->main = ctx->byteCode->fFunctions[0].get();
ctx->fn = [](SkRasterPipeline_CallbackCtx* arg, int active_pixels) {
auto ctx = (InterpreterCtx*)arg;
- SkSL::Interpreter::VecRun(ctx->byteCode.get(), ctx->main,
- (SkSL::Interpreter::Value*)ctx->rgba,
- nullptr, active_pixels,
- (SkSL::Interpreter::Value*)ctx->inputs, ctx->ninputs);
+ ctx->byteCode->run(ctx->main, ctx->rgba, nullptr, active_pixels,
+ (float*)ctx->inputs, ctx->ninputs);
};
rec.fPipeline->append(SkRasterPipeline::callback, ctx);
}
diff --git a/src/sksl/SkSLInterpreter.cpp b/src/sksl/SkSLByteCode.cpp
similarity index 95%
rename from src/sksl/SkSLInterpreter.cpp
rename to src/sksl/SkSLByteCode.cpp
index 14a8206..739eed4 100644
--- a/src/sksl/SkSLInterpreter.cpp
+++ b/src/sksl/SkSLByteCode.cpp
@@ -12,7 +12,6 @@
#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLByteCodeGenerator.h"
#include "src/sksl/SkSLExternalValue.h"
-#include "src/sksl/SkSLInterpreter.h"
#include <vector>
@@ -241,15 +240,6 @@
return ip;
}
-void Disassemble(const ByteCodeFunction* f) {
- const uint8_t* ip = f->fCode.data();
- while (ip < f->fCode.data() + f->fCode.size()) {
- printf("%d: ", (int) (ip - f->fCode.data()));
- ip = disassemble_instruction(ip);
- printf("\n");
- }
-}
-
#define VECTOR_BINARY_OP(base, field, op) \
case ByteCodeInstruction::base ## 4: \
sp[-4] = sp[-4].field op sp[0].field; \
@@ -361,8 +351,8 @@
return a - skvx::trunc(a / b) * b;
}
-void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack, Value* outReturn,
- I32 initMask, VValue globals[], int globalCount) {
+void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
+ float* outReturn, I32 initMask, VValue globals[]) {
VValue* sp = stack + f->fParameterCount + f->fLocalCount - 1;
auto POP = [&] { SkASSERT(sp >= stack); return *(sp--); };
@@ -443,8 +433,8 @@
ExternalValue* v = byteCode->fExternalValues[target];
sp -= argumentCount - 1;
- Value tmpArgs[4];
- Value tmpReturn[4];
+ int32_t tmpArgs[4];
+ int32_t tmpReturn[4];
SkASSERT(argumentCount <= (int)SK_ARRAY_COUNT(tmpArgs));
SkASSERT(returnCount <= (int)SK_ARRAY_COUNT(tmpReturn));
@@ -452,11 +442,11 @@
for (int i = 0; i < VecWidth; ++i) {
if (m[i]) {
for (int j = 0; j < argumentCount; ++j) {
- tmpArgs[j].fSigned = sp[j].fSigned[i];
+ tmpArgs[j] = sp[j].fSigned[i];
}
v->call(tmpArgs, tmpReturn);
for (int j = 0; j < returnCount; ++j) {
- sp[j].fSigned[i] = tmpReturn[j].fSigned;
+ sp[j].fSigned[i] = tmpReturn[j];
}
}
}
@@ -592,7 +582,6 @@
int src = READ8();
int count = READ8();
for (int i = 0; i < count; ++i) {
- SkASSERT(src + *(ip + i) < globalCount);
PUSH(globals[src + *(ip + i)]);
}
ip += count;
@@ -741,7 +730,7 @@
for (int i = 0; i < count; ++i) {
for (int j = 0; j < VecWidth; ++j) {
if (m[j]) {
- outReturn[count * j].fSigned = src->fSigned[j];
+ outReturn[count * j] = src->fFloat[j];
}
}
++outReturn;
@@ -983,59 +972,71 @@
}
}
-void VecRun(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
- int N, Value uniforms[], int uniformCount) {
+} // namespace Interpreter
+
+void ByteCodeFunction::disassemble() const {
+ const uint8_t* ip = fCode.data();
+ while (ip < fCode.data() + fCode.size()) {
+ printf("%d: ", (int)(ip - fCode.data()));
+ ip = Interpreter::disassemble_instruction(ip);
+ printf("\n");
+ }
+}
+
+void ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
+ const float* uniforms, int uniformCount) const {
#ifdef TRACE
- disassemble(f);
+ f->disassemble();
#endif
- VValue smallStack[128];
+ Interpreter::VValue smallStack[128];
// Needs to be the first N non-negative integers, at least as large as VecWidth
- static const I32 gLanes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ static const Interpreter::I32 gLanes = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ };
- SkASSERT(uniformCount == (int)byteCode->fInputSlots.size());
- VValue smallGlobals[32];
- VValue* globals = smallGlobals;
- SkASSERT((int)SK_ARRAY_COUNT(smallGlobals) >= byteCode->fGlobalCount);
- for (uint8_t slot : byteCode->fInputSlots) {
- globals[slot].fUnsigned = (uniforms++)->fUnsigned;
+ SkASSERT(uniformCount == (int)fInputSlots.size());
+ Interpreter::VValue globals[32];
+ SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
+ for (uint8_t slot : fInputSlots) {
+ globals[slot].fFloat = *uniforms++;
}
while (N) {
- VValue* stack = smallStack;
+ Interpreter::VValue* stack = smallStack;
- int w = std::min(N, VecWidth);
+ int w = std::min(N, Interpreter::VecWidth);
N -= w;
// Transpose args into stack
{
- uint32_t* src = (uint32_t*)args;
+ float* src = args;
for (int i = 0; i < w; ++i) {
- uint32_t* dst = (uint32_t*)stack + i;
+ float* dst = (float*)stack + i;
for (int j = f->fParameterCount; j > 0; --j) {
*dst = *src++;
- dst += VecWidth;
+ dst += Interpreter::VecWidth;
}
}
}
auto mask = w > gLanes;
- innerRun(byteCode, f, stack, outReturn, mask, globals, byteCode->fGlobalCount);
+ innerRun(this, f, stack, outReturn, mask, globals);
// Transpose out parameters back
{
- uint32_t* dst = (uint32_t*)args;
+ float* dst = args;
for (int i = 0; i < w; ++i) {
- uint32_t* src = (uint32_t*)stack + i;
+ float* src = (float*)stack + i;
for (const auto& p : f->fParameters) {
if (p.fIsOutParameter) {
for (int j = p.fSlotCount; j > 0; --j) {
*dst++ = *src;
- src += VecWidth;
+ src += Interpreter::VecWidth;
}
} else {
dst += p.fSlotCount;
- src += p.fSlotCount * VecWidth;
+ src += p.fSlotCount * Interpreter::VecWidth;
}
}
}
@@ -1046,12 +1047,6 @@
}
}
-void Run(const ByteCode* byteCode, const ByteCodeFunction* f, Value args[], Value* outReturn,
- Value uniforms[], int uniformCount) {
- VecRun(byteCode, f, args, outReturn, 1, uniforms, uniformCount);
-}
-
-} // namespace Interpreter
} // namespace SkSL
#endif
diff --git a/src/sksl/SkSLByteCode.h b/src/sksl/SkSLByteCode.h
index 1a02152..518e16f 100644
--- a/src/sksl/SkSLByteCode.h
+++ b/src/sksl/SkSLByteCode.h
@@ -15,7 +15,6 @@
namespace SkSL {
-struct ByteCode;
class ExternalValue;
struct FunctionDeclaration;
@@ -159,6 +158,11 @@
int fStackCount = 128;
int fReturnCount = 0;
std::vector<uint8_t> fCode;
+
+ /**
+ * Print bytecode disassembly to stdout.
+ */
+ void disassemble() const;
};
struct ByteCode {
@@ -166,6 +170,7 @@
// 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) {
@@ -176,7 +181,16 @@
return nullptr;
}
- std::vector<ExternalValue*> fExternalValues;
+ /**
+ * 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.
+ */
+ void run(const ByteCodeFunction*, float* args, float* outReturn, int N,
+ const float* uniforms, int uniformCount) const;
};
}
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 13ffc9e..9d779f2 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
+#include "include/private/SkFloatBits.h"
#include "src/sksl/SkSLByteCodeGenerator.h"
-#include "src/sksl/SkSLInterpreter.h"
#include <algorithm>
@@ -591,7 +591,7 @@
void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
this->write(ByteCodeInstruction::kPushImmediate);
- this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
+ this->write32(SkFloat2Bits(f.fValue));
}
void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
@@ -659,8 +659,7 @@
std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
lvalue->load();
this->write(ByteCodeInstruction::kPushImmediate);
- this->write32(type_category(p.fType) == TypeCategory::kFloat
- ? Interpreter::Value(1.0f).fUnsigned : 1);
+ this->write32(type_category(p.fType) == TypeCategory::kFloat ? SkFloat2Bits(1.0f) : 1);
if (p.fOperator == Token::Kind::PLUSPLUS) {
this->writeTypedInstruction(p.fType,
ByteCodeInstruction::kAddI,
@@ -704,8 +703,7 @@
this->write(ByteCodeInstruction::kDup);
}
this->write(ByteCodeInstruction::kPushImmediate);
- this->write32(type_category(p.fType) == TypeCategory::kFloat
- ? Interpreter::Value(1.0f).fUnsigned : 1);
+ this->write32(type_category(p.fType) == TypeCategory::kFloat ? SkFloat2Bits(1.0f) : 1);
if (p.fOperator == Token::Kind::PLUSPLUS) {
this->writeTypedInstruction(p.fType,
ByteCodeInstruction::kAddI,
diff --git a/src/sksl/SkSLExternalValue.h b/src/sksl/SkSLExternalValue.h
index 0cd4f19..08d57f9 100644
--- a/src/sksl/SkSLExternalValue.h
+++ b/src/sksl/SkSLExternalValue.h
@@ -8,7 +8,6 @@
#ifndef SKSL_EXTERNALVALUE
#define SKSL_EXTERNALVALUE
-#include "src/sksl/SkSLInterpreter.h"
#include "src/sksl/ir/SkSLSymbol.h"
namespace SkSL {
@@ -83,7 +82,7 @@
* outResult must be a pointer to a region of sufficient size to hold the function's return
* value.
*/
- virtual void call(Interpreter::Value* arguments, Interpreter::Value* outResult) {
+ virtual void call(void* arguments, void* outResult) {
SkASSERT(false);
}
diff --git a/src/sksl/SkSLInterpreter.h b/src/sksl/SkSLInterpreter.h
deleted file mode 100644
index b9f0327..0000000
--- a/src/sksl/SkSLInterpreter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_INTERPRETER
-#define SKSL_INTERPRETER
-
-#include "src/sksl/SkSLDefines.h"
-
-namespace SkSL {
-
-struct ByteCode;
-struct ByteCodeFunction;
-
-namespace Interpreter {
-
- union Value {
- Value() {}
-
- Value(float f)
- : fFloat(f) {}
-
- Value(int32_t s)
- : fSigned(s) {}
-
- Value(uint32_t u)
- : fUnsigned(u) {}
-
- Value(bool b)
- : fBool(b) {}
-
- float fFloat;
- int32_t fSigned;
- uint32_t fUnsigned;
- bool fBool;
- };
-
- /**
- * Invokes the specified function with the given arguments. 'out' and 'inout' parameters will
- * result in the 'args' array being modified. The return value is stored in 'outReturn' (may be
- * null, in which case the return value is discarded).
- */
- void Run(const ByteCode*, const ByteCodeFunction*, Value args[], Value* outReturn,
- Value uniforms[], int uniformCount);
-
- void VecRun(const ByteCode*, const ByteCodeFunction*, Value args[], Value* outReturn,
- int N, Value uniforms[], int uniformCount);
-
- /**
- * Print bytecode disassembly to stdout.
- */
- void Disassemble(const ByteCodeFunction*);
-
-} // namespace Interpreter
-} // namespace SkSL
-
-#endif
diff --git a/tests/SkSLInterpreterTest.cpp b/tests/SkSLInterpreterTest.cpp
index d425ea8..4b67d09 100644
--- a/tests/SkSLInterpreterTest.cpp
+++ b/tests/SkSLInterpreterTest.cpp
@@ -6,15 +6,14 @@
*/
#include "include/core/SkPoint3.h"
+#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLExternalValue.h"
-#include "src/sksl/SkSLInterpreter.h"
#include "src/utils/SkJSON.h"
#include "tests/Test.h"
-void test(skiatest::Reporter* r, const char* src, SkSL::Interpreter::Value* in, int expectedCount,
- SkSL::Interpreter::Value* expected) {
+void test(skiatest::Reporter* r, const char* src, float* in, int expectedCount, float* expected) {
SkSL::Compiler compiler;
SkSL::Program::Settings settings;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
@@ -30,26 +29,25 @@
return;
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
- std::unique_ptr<SkSL::Interpreter::Value[]> out =
- std::unique_ptr<SkSL::Interpreter::Value[]>(new SkSL::Interpreter::Value[expectedCount]);
- SkSL::Interpreter::Run(byteCode.get(), main, in, out.get(), nullptr, 0);
- bool valid = !memcmp(out.get(), expected, sizeof(SkSL::Interpreter::Value) * expectedCount);
+ std::unique_ptr<float[]> out = std::unique_ptr<float[]>(new float[expectedCount]);
+ byteCode->run(main, in, out.get(), 1, nullptr, 0);
+ bool valid = !memcmp(out.get(), expected, sizeof(float) * expectedCount);
if (!valid) {
printf("for program: %s\n", src);
printf(" expected (");
const char* separator = "";
for (int i = 0; i < expectedCount; ++i) {
- printf("%s%f", separator, expected[i].fFloat);
+ printf("%s%f", separator, expected[i]);
separator = ", ";
}
printf("), but received (");
separator = "";
for (int i = 0; i < expectedCount; ++i) {
- printf("%s%f", separator, out.get()[i].fFloat);
+ printf("%s%f", separator, out.get()[i]);
separator = ", ";
}
printf(")\n");
- SkSL::Interpreter::Disassemble(main);
+ main->disassemble();
}
REPORTER_ASSERT(r, valid);
} else {
@@ -64,56 +62,48 @@
7, 5, 8, 6,
6, 8, 5, 7 };
+ SkSL::Compiler compiler;
+ std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
+ SkSL::Program::kGeneric_Kind, SkSL::String(src), SkSL::Program::Settings());
+ if (!program) {
+ REPORT_FAILURE(r, "!program", SkString(compiler.errorText().c_str()));
+ return;
+ }
+
+ std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
+ if (compiler.errorCount() > 0) {
+ REPORT_FAILURE(r, "!toByteCode", SkString(compiler.errorText().c_str()));
+ return;
+ }
+
+ const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
+
float out_s[16], out_v[16];
memcpy(out_s, input, sizeof(out_s));
memcpy(out_v, input, sizeof(out_v));
- for (int pass = 0; pass < 2; ++pass) {
- SkSL::Compiler compiler;
- std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
- SkSL::Program::kGeneric_Kind, SkSL::String(src), SkSL::Program::Settings());
- if (!program) {
- REPORT_FAILURE(r, "!program", SkString(compiler.errorText().c_str()));
- return;
- }
+ // First run in scalar mode to determine the expected output
+ for (int i = 0; i < 4; ++i) {
+ byteCode->run(main, out_s + i * 4, nullptr, 1, nullptr, 0);
+ }
- std::unique_ptr<SkSL::ByteCode> byteCode = compiler.toByteCode(*program);
- if (compiler.errorCount() > 0) {
- REPORT_FAILURE(r, "!toByteCode", SkString(compiler.errorText().c_str()));
- return;
+ // Now run in parallel and compare results
+ byteCode->run(main, out_v, nullptr, 4, nullptr, 0);
+ if (memcmp(out_s, out_v, sizeof(out_s)) != 0) {
+ printf("for program: %s\n", src);
+ for (int i = 0; i < 4; ++i) {
+ printf("(%g %g %g %g) -> (%g %g %g %g), expected (%g %g %g %g)\n",
+ input[4*i + 0], input[4*i + 1], input[4*i + 2], input[4*i + 3],
+ out_v[4*i + 0], out_v[4*i + 1], out_v[4*i + 2], out_v[4*i + 3],
+ out_s[4*i + 0], out_s[4*i + 1], out_s[4*i + 2], out_s[4*i + 3]);
}
-
- const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
-
- if (pass == 0) {
- // First pass - run in scalar mode to determine the expected output
- for (int i = 0; i < 4; ++i) {
- SkSL::Interpreter::Run(byteCode.get(), main,
- (SkSL::Interpreter::Value*)(out_s + i * 4), nullptr,
- nullptr, 0);
- }
- } else {
- // Second pass - run the vectorized interpreter and compare results
- SkSL::Interpreter::VecRun(byteCode.get(), main,
- (SkSL::Interpreter::Value*)out_v, nullptr, 4,
- nullptr, 0);
- if (memcmp(out_s, out_v, sizeof(out_s)) != 0) {
- printf("for program: %s\n", src);
- for (int i = 0; i < 4; ++i) {
- printf("(%g %g %g %g) -> (%g %g %g %g), expected (%g %g %g %g)\n",
- input[4*i + 0], input[4*i + 1], input[4*i + 2], input[4*i + 3],
- out_v[4*i + 0], out_v[4*i + 1], out_v[4*i + 2], out_v[4*i + 3],
- out_s[4*i + 0], out_s[4*i + 1], out_s[4*i + 2], out_s[4*i + 3]);
- }
- SkSL::Interpreter::Disassemble(main);
- REPORT_FAILURE(r, "VecInterpreter mismatch", SkString());
- }
- }
+ main->disassemble();
+ REPORT_FAILURE(r, "VecInterpreter mismatch", SkString());
}
}
void test(skiatest::Reporter* r, const char* src, float inR, float inG, float inB, float inA,
- float expectedR, float expectedG, float expectedB, float expectedA) {
+ float expectedR, float expectedG, float expectedB, float expectedA) {
SkSL::Compiler compiler;
SkSL::Program::Settings settings;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
@@ -130,15 +120,14 @@
}
const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
float inoutColor[4] = { inR, inG, inB, inA };
- SkSL::Interpreter::Run(byteCode.get(), main, (SkSL::Interpreter::Value*) inoutColor,
- nullptr, nullptr, 0);
+ byteCode->run(main, inoutColor, nullptr, 1, nullptr, 0);
if (inoutColor[0] != expectedR || inoutColor[1] != expectedG ||
inoutColor[2] != expectedB || inoutColor[3] != expectedA) {
printf("for program: %s\n", src);
printf(" expected (%f, %f, %f, %f), but received (%f, %f, %f, %f)\n", expectedR,
expectedG, expectedB, expectedA, inoutColor[0], inoutColor[1], inoutColor[2],
inoutColor[3]);
- SkSL::Interpreter::Disassemble(main);
+ main->disassemble();
}
REPORTER_ASSERT(r, inoutColor[0] == expectedR);
REPORTER_ASSERT(r, inoutColor[1] == expectedG);
@@ -210,8 +199,8 @@
}
DEF_TEST(SkSLInterpreterMatrix, r) {
- SkSL::Interpreter::Value in[16];
- SkSL::Interpreter::Value expected[16];
+ float in[16];
+ float expected[16];
// Constructing matrix from scalar produces a diagonal matrix
in[0] = 1.0f;
@@ -291,7 +280,7 @@
// M*M
{
SkMatrix44 m;
- m.setColMajorf(&in[0].fFloat);
+ m.setColMajorf(in);
SkMatrix44 m2;
for (int i = 0; i < 16; ++i) {
m2.set(i % 4, i / 4, (i + 4) % 16);
@@ -299,7 +288,7 @@
m.setConcat(m, m2);
// Rearrange the columns on the RHS so we detect left-hand/right-hand errors
test(r, "float4x4 main(float4x4 m) { return m * float4x4(m[1], m[2], m[3], m[0]); }",
- in, 16, (SkSL::Interpreter::Value*)&m);
+ in, 16, (float*)&m);
}
}
@@ -314,34 +303,40 @@
}
DEF_TEST(SkSLInterpreterCast, r) {
- SkSL::Interpreter::Value input[2];
- SkSL::Interpreter::Value expected[2];
+ union Val {
+ float f;
+ uint32_t u;
+ int32_t s;
+ };
- input[0].fSigned = 3;
- input[1].fSigned = -5;
- expected[0].fFloat = 3.0f;
- expected[1].fFloat = -5.0f;
- test(r, "float main(int x) { return float (x); }", input, 1, expected);
- test(r, "float2 main(int2 x) { return float2(x); }", input, 2, expected);
+ Val input[2];
+ Val expected[2];
- input[0].fUnsigned = 3;
- input[1].fUnsigned = 5;
- expected[0].fFloat = 3.0f;
- expected[1].fFloat = 5.0f;
- test(r, "float main(uint x) { return float (x); }", input, 1, expected);
- test(r, "float2 main(uint2 x) { return float2(x); }", input, 2, expected);
+ input[0].s = 3;
+ input[1].s = -5;
+ expected[0].f = 3.0f;
+ expected[1].f = -5.0f;
+ test(r, "float main(int x) { return float (x); }", (float*)input, 1, (float*)expected);
+ test(r, "float2 main(int2 x) { return float2(x); }", (float*)input, 2, (float*)expected);
- input[0].fFloat = 3.0f;
- input[1].fFloat = -5.0f;
- expected[0].fSigned = 3;
- expected[1].fSigned = -5;
- test(r, "int main(float x) { return int (x); }", input, 1, expected);
- test(r, "int2 main(float2 x) { return int2(x); }", input, 2, expected);
+ input[0].u = 3;
+ input[1].u = 5;
+ expected[0].f = 3.0f;
+ expected[1].f = 5.0f;
+ test(r, "float main(uint x) { return float (x); }", (float*)input, 1, (float*)expected);
+ test(r, "float2 main(uint2 x) { return float2(x); }", (float*)input, 2, (float*)expected);
- input[0].fSigned = 3;
- expected[0].fFloat = 3.0f;
- expected[1].fFloat = 3.0f;
- test(r, "float2 main(int x) { return float2(x); }", input, 2, expected);
+ input[0].f = 3.0f;
+ input[1].f = -5.0f;
+ expected[0].s = 3;
+ expected[1].s = -5;
+ test(r, "int main(float x) { return int (x); }", (float*)input, 1, (float*)expected);
+ test(r, "int2 main(float2 x) { return int2(x); }", (float*)input, 2, (float*)expected);
+
+ input[0].s = 3;
+ expected[0].f = 3.0f;
+ expected[1].f = 3.0f;
+ test(r, "float2 main(int x) { return float2(x); }", (float*)input, 2, (float*)expected);
}
DEF_TEST(SkSLInterpreterIf, r) {
@@ -469,13 +464,10 @@
DEF_TEST(SkSLInterpreterGeneric, r) {
float value1 = 5;
float expected1 = 25;
- test(r, "float main(float x) { return x * x; }", (SkSL::Interpreter::Value*) &value1, 1,
- (SkSL::Interpreter::Value*) &expected1);
+ test(r, "float main(float x) { return x * x; }", &value1, 1, &expected1);
float value2[2] = { 5, 25 };
float expected2[2] = { 25, 625 };
- test(r, "float2 main(float x, float y) { return float2(x * x, y * y); }",
- (SkSL::Interpreter::Value*) &value2, 2,
- (SkSL::Interpreter::Value*) expected2);
+ test(r, "float2 main(float x, float y) { return float2(x * x, y * y); }", value2, 2, expected2);
}
DEF_TEST(SkSLInterpreterCompound, r) {
@@ -548,20 +540,14 @@
{
SkIRect in = SkIRect::MakeXYWH(10, 10, 20, 30);
int out = 0;
- SkSL::Interpreter::Run(byteCode.get(), rect_height,
- (SkSL::Interpreter::Value*)&in,
- (SkSL::Interpreter::Value*)&out,
- (SkSL::Interpreter::Value*)gRects, 16);
+ byteCode->run(rect_height, (float*)&in, (float*)&out, 1, (float*)gRects, 16);
REPORTER_ASSERT(r, out == 30);
}
{
int in[2] = { 15, 25 };
RectAndColor out;
- SkSL::Interpreter::Run(byteCode.get(), make_blue_rect,
- (SkSL::Interpreter::Value*)in,
- (SkSL::Interpreter::Value*)&out,
- (SkSL::Interpreter::Value*)gRects, 16);
+ byteCode->run(make_blue_rect, (float*)in, (float*)&out, 1, (float*)gRects, 16);
REPORTER_ASSERT(r, out.fRect.width() == 15);
REPORTER_ASSERT(r, out.fRect.height() == 25);
SkColor4f blue = { 0.0f, 1.0f, 0.0f, 1.0f };
@@ -571,20 +557,14 @@
{
int in[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
int out = 0;
- SkSL::Interpreter::Run(byteCode.get(), median,
- (SkSL::Interpreter::Value*)in,
- (SkSL::Interpreter::Value*)&out,
- (SkSL::Interpreter::Value*)gRects, 16);
+ byteCode->run(median, (float*)in, (float*)&out, 1, (float*)gRects, 16);
REPORTER_ASSERT(r, out == 8);
}
{
float in[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
float out[8] = { 0 };
- SkSL::Interpreter::Run(byteCode.get(), sums,
- (SkSL::Interpreter::Value*)in,
- (SkSL::Interpreter::Value*)out,
- (SkSL::Interpreter::Value*)gRects, 16);
+ byteCode->run(sums, in, out, 1, (float*)gRects, 16);
for (int i = 0; i < 8; ++i) {
REPORTER_ASSERT(r, out[i] == static_cast<float>((i + 1) * (i + 2) / 2));
}
@@ -593,10 +573,7 @@
{
int in = 2;
SkIRect out = SkIRect::MakeEmpty();
- SkSL::Interpreter::Run(byteCode.get(), get_rect,
- (SkSL::Interpreter::Value*)&in,
- (SkSL::Interpreter::Value*)&out,
- (SkSL::Interpreter::Value*)gRects, 16);
+ byteCode->run(get_rect, (float*)&in, (float*)&out, 1, (float*)gRects, 16);
REPORTER_ASSERT(r, out == gRects[2]);
}
@@ -604,10 +581,7 @@
ManyRects in;
memset(&in, 0, sizeof(in));
in.fNumRects = 2;
- SkSL::Interpreter::Run(byteCode.get(), fill_rects,
- (SkSL::Interpreter::Value*)&in,
- nullptr,
- (SkSL::Interpreter::Value*)gRects, 16);
+ byteCode->run(fill_rects, (float*)&in, nullptr, 1, (float*)gRects, 16);
ManyRects expected;
memset(&expected, 0, sizeof(expected));
expected.fNumRects = 2;
@@ -663,27 +637,23 @@
float out = 0.0f;
float in = 3.0f;
- SkSL::Interpreter::Run(byteCode.get(), main, (SkSL::Interpreter::Value*)&in,
- (SkSL::Interpreter::Value*)&out, nullptr, 0);
+ byteCode->run(main, &in, &out, 1, nullptr, 0);
REPORTER_ASSERT(r, out = 6.0f);
- SkSL::Interpreter::Run(byteCode.get(), dot3, (SkSL::Interpreter::Value*)&in,
- (SkSL::Interpreter::Value*)&out, nullptr, 0);
+ byteCode->run(dot3, &in, &out, 1, nullptr, 0);
REPORTER_ASSERT(r, out = 9.0f);
- SkSL::Interpreter::Run(byteCode.get(), dot2, (SkSL::Interpreter::Value*)&in,
- (SkSL::Interpreter::Value*)&out, nullptr, 0);
+ byteCode->run(dot2, &in, &out, 1, nullptr, 0);
REPORTER_ASSERT(r, out = -1.0f);
int fibIn = 6;
int fibOut = 0;
- SkSL::Interpreter::Run(byteCode.get(), fib, (SkSL::Interpreter::Value*)&fibIn,
- (SkSL::Interpreter::Value*)&fibOut, nullptr, 0);
+ byteCode->run(fib, (float*)&fibIn, (float*)&fibOut, 1, nullptr, 0);
REPORTER_ASSERT(r, fibOut == 13);
}
DEF_TEST(SkSLInterpreterMathFunctions, r) {
- SkSL::Interpreter::Value value, expected;
+ float value, expected;
value = 0.0f; expected = 0.0f;
test(r, "float main(float x) { return sin(x); }", &value, 1, &expected);
@@ -697,7 +667,7 @@
}
DEF_TEST(SkSLInterpreterMix, r) {
- SkSL::Interpreter::Value value, expected;
+ float value, expected;
value = 0.5f; expected = 0.0f;
test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
@@ -706,39 +676,35 @@
value = 2.0f; expected = 30.0f;
test(r, "float main(float x) { return mix(-10, 10, x); }", &value, 1, &expected);
- SkSL::Interpreter::Value valueVectors[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f },
- expectedVector[] = { 3.0f, 4.0f, 5.0f, 6.0f };
+ float valueVectors[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f },
+ expectedVector[] = { 3.0f, 4.0f, 5.0f, 6.0f };
test(r, "float4 main(float4 x, float4 y) { return mix(x, y, 0.5); }", valueVectors, 4,
expectedVector);
}
DEF_TEST(SkSLInterpreterCross, r) {
- SkSL::Interpreter::Value args[] = { 1.0f, 4.0f, -6.0f, -2.0f, 7.0f, -3.0f };
- SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(args[0].fFloat,
- args[1].fFloat,
- args[2].fFloat),
- SkPoint3::Make(args[3].fFloat,
- args[4].fFloat,
- args[5].fFloat));
- SkSL::Interpreter::Value expected[] = { cross.fX, cross.fY, cross.fZ };
+ float args[] = { 1.0f, 4.0f, -6.0f, -2.0f, 7.0f, -3.0f };
+ SkPoint3 cross = SkPoint3::CrossProduct(SkPoint3::Make(args[0], args[1], args[2]),
+ SkPoint3::Make(args[3], args[4], args[5]));
+ float expected[] = { cross.fX, cross.fY, cross.fZ };
test(r, "float3 main(float3 x, float3 y) { return cross(x, y); }", args, 3, expected);
}
DEF_TEST(SkSLInterpreterDot, r) {
- SkSL::Interpreter::Value args[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
- SkSL::Interpreter::Value expected = args[0].fFloat * args[2].fFloat +
- args[1].fFloat * args[3].fFloat;
+ float args[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
+ float expected = args[0] * args[2] +
+ args[1] * args[3];
test(r, "float main(float2 x, float2 y) { return dot(x, y); }", args, 1, &expected);
- expected = args[0].fFloat * args[3].fFloat +
- args[1].fFloat * args[4].fFloat +
- args[2].fFloat * args[5].fFloat;
+ expected = args[0] * args[3] +
+ args[1] * args[4] +
+ args[2] * args[5];
test(r, "float main(float3 x, float3 y) { return dot(x, y); }", args, 1, &expected);
- expected = args[0].fFloat * args[4].fFloat +
- args[1].fFloat * args[5].fFloat +
- args[2].fFloat * args[6].fFloat +
- args[3].fFloat * args[7].fFloat;
+ expected = args[0] * args[4] +
+ args[1] * args[5] +
+ args[2] * args[6] +
+ args[3] * args[7];
test(r, "float main(float4 x, float4 y) { return dot(x, y); }", args, 1, &expected);
}
@@ -859,9 +825,9 @@
return;
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
- SkSL::Interpreter::Value out;
- SkSL::Interpreter::Run(byteCode.get(), main, nullptr, &out, nullptr, 0);
- REPORTER_ASSERT(r, out.fFloat == 66.0);
+ float out;
+ byteCode->run(main, nullptr, &out, 1, nullptr, 0);
+ REPORTER_ASSERT(r, out == 66.0);
REPORTER_ASSERT(r, outValue == 152);
} else {
printf("%s\n%s", src, compiler.errorText().c_str());
@@ -892,8 +858,7 @@
return;
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
- SkSL::Interpreter::Value out;
- SkSL::Interpreter::Run(byteCode.get(), main, nullptr, &out, nullptr, 0);
+ byteCode->run(main, nullptr, nullptr, 1, nullptr, 0);
REPORTER_ASSERT(r, value[0] == 2);
REPORTER_ASSERT(r, value[1] == 4);
REPORTER_ASSERT(r, value[2] == 6);
@@ -922,8 +887,8 @@
outTypes[0] = fCompiler.context().fFloat_Type.get();
}
- void call(SkSL::Interpreter::Value* arguments, SkSL::Interpreter::Value* outReturn) override {
- outReturn[0].fFloat = fFunction(arguments[0].fFloat);
+ void call(void* arguments, void* outReturn) override {
+ ((float*)outReturn)[0] = fFunction(((float*)arguments)[0]);
}
private:
@@ -958,9 +923,9 @@
return;
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
- SkSL::Interpreter::Value out;
- SkSL::Interpreter::Run(byteCode.get(), main, nullptr, &out, nullptr, 0);
- REPORTER_ASSERT(r, out.fFloat == 5.0);
+ float out;
+ byteCode->run(main, nullptr, &out, 1, nullptr, 0);
+ REPORTER_ASSERT(r, out == 5.0);
} else {
printf("%s\n%s", src, compiler.errorText().c_str());
}
@@ -986,7 +951,7 @@
outTypes[0] = fCompiler.context().fFloat4_Type.get();
}
- void call(SkSL::Interpreter::Value* arguments, SkSL::Interpreter::Value* outReturn) override {
+ void call(void* arguments, void* outReturn) override {
fFunction((float*) arguments, (float*) outReturn);
}
@@ -1026,12 +991,12 @@
return;
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
- SkSL::Interpreter::Value out[4];
- SkSL::Interpreter::Run(byteCode.get(), main, nullptr, out, nullptr, 0);
- REPORTER_ASSERT(r, out[0].fFloat == 1.0);
- REPORTER_ASSERT(r, out[1].fFloat == 2.0);
- REPORTER_ASSERT(r, out[2].fFloat == 3.0);
- REPORTER_ASSERT(r, out[3].fFloat == 4.0);
+ float out[4];
+ byteCode->run(main, nullptr, out, 1, nullptr, 0);
+ REPORTER_ASSERT(r, out[0] == 1.0);
+ REPORTER_ASSERT(r, out[1] == 2.0);
+ REPORTER_ASSERT(r, out[2] == 3.0);
+ REPORTER_ASSERT(r, out[3] == 4.0);
} else {
printf("%s\n%s", src, compiler.errorText().c_str());
}