Prototype interpreter particle affector
Change-Id: Ib440570ecbd46b5bc98d346592cbbb72f58ae85a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/212500
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/modules/particles/src/SkParticleAffector.cpp b/modules/particles/src/SkParticleAffector.cpp
index e34306f..17ca75b 100644
--- a/modules/particles/src/SkParticleAffector.cpp
+++ b/modules/particles/src/SkParticleAffector.cpp
@@ -14,6 +14,8 @@
#include "include/utils/SkTextUtils.h"
#include "modules/particles/include/SkCurve.h"
#include "modules/particles/include/SkParticleData.h"
+#include "src/sksl/SkSLCompiler.h"
+#include "src/sksl/SkSLInterpreter.h"
void SkParticleAffector::apply(const SkParticleUpdateParams& params,
@@ -433,6 +435,78 @@
SkColorCurve fCurve;
};
+static const char* kDefaultCode =
+ "layout(ctype=float) in uniform float dt;\n"
+ "layout(ctype=float) in uniform float effectAge;\n"
+ "\n"
+ "void main(in float age,\n"
+ " in float invLifetime,\n"
+ " inout float2 pos,\n"
+ " inout float2 dir,\n"
+ " inout float scale,\n"
+ " inout float2 vel,\n"
+ " inout float spin,\n"
+ " inout float4 color,\n"
+ " in float t) {\n"
+ "}\n";
+
+class SkInterpreterAffector : public SkParticleAffector {
+public:
+ SkInterpreterAffector() : fCode(kDefaultCode) {
+ this->rebuild();
+ }
+
+ REFLECTED(SkInterpreterAffector, SkParticleAffector)
+
+ void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ fInterpreter->setInputs((SkSL::Interpreter::Value*)¶ms);
+ for (int i = 0; i < count; ++i) {
+ fInterpreter->run(*fMain, (SkSL::Interpreter::Value*)&ps[i].fAge, nullptr);
+ }
+ }
+
+ void visitFields(SkFieldVisitor* v) override {
+ SkString oldCode = fCode;
+
+ SkParticleAffector::visitFields(v);
+ v->visit("Code", fCode);
+
+ if (fCode != oldCode) {
+ this->rebuild();
+ }
+ }
+
+private:
+ SkString fCode;
+
+ // Cached
+ std::unique_ptr<SkSL::Interpreter> fInterpreter;
+ SkSL::ByteCodeFunction* fMain;
+
+ void rebuild() {
+ SkSL::Compiler compiler;
+ SkSL::Program::Settings settings;
+ auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
+ SkSL::String(fCode.c_str()), settings);
+ if (!program) {
+ SkDebugf("%s\n", compiler.errorText().c_str());
+ return;
+ }
+
+ auto byteCode = compiler.toByteCode(*program);
+ if (compiler.errorCount()) {
+ SkDebugf("%s\n", compiler.errorText().c_str());
+ return;
+ }
+
+ // These will be replaced with the real inputs in onApply, before running
+ SkParticleUpdateParams defaultInputs = { 0.0f, 0.0f, 0 };
+ fMain = byteCode->fFunctions[0].get();
+ fInterpreter.reset(new SkSL::Interpreter(std::move(program), std::move(byteCode),
+ (SkSL::Interpreter::Value*)&defaultInputs));
+ }
+};
+
void SkParticleAffector::RegisterAffectorTypes() {
REGISTER_REFLECTED(SkParticleAffector);
REGISTER_REFLECTED(SkLinearVelocityAffector);
@@ -445,6 +519,7 @@
REGISTER_REFLECTED(SkSizeAffector);
REGISTER_REFLECTED(SkFrameAffector);
REGISTER_REFLECTED(SkColorAffector);
+ REGISTER_REFLECTED(SkInterpreterAffector);
}
sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,