Particles: Merge spawn & update into one code string with two functions
Change-Id: If57fb79db8f8c5fd185fefaa202167c8082dd846
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/229921
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/modules/particles/include/SkParticleEffect.h b/modules/particles/include/SkParticleEffect.h
index c2648cc..4f7b420 100644
--- a/modules/particles/include/SkParticleEffect.h
+++ b/modules/particles/include/SkParticleEffect.h
@@ -53,11 +53,8 @@
// Drawable (image, sprite sheet, etc.)
sk_sp<SkParticleDrawable> fDrawable;
- // Code to configure particles at spawn time
- SkString fSpawnCode;
-
- // Code to update existing particles over their lifetime
- SkString fUpdateCode;
+ // Code with spawn() and update() functions
+ SkString fCode;
SkTArray<sk_sp<SkParticleBinding>> fBindings;
@@ -67,12 +64,8 @@
friend class SkParticleEffect;
// Cached
- struct Program {
- std::unique_ptr<SkSL::ByteCode> fByteCode;
- SkTArray<std::unique_ptr<SkParticleExternalValue>> fExternalValues;
- };
- Program fSpawnProgram;
- Program fUpdateProgram;
+ std::unique_ptr<SkSL::ByteCode> fByteCode;
+ SkTArray<std::unique_ptr<SkParticleExternalValue>> fExternalValues;
void rebuild();
};
diff --git a/modules/particles/src/SkParticleEffect.cpp b/modules/particles/src/SkParticleEffect.cpp
index 056e12f..9238ce8 100644
--- a/modules/particles/src/SkParticleEffect.cpp
+++ b/modules/particles/src/SkParticleEffect.cpp
@@ -302,8 +302,7 @@
};
static const char* kDefaultCode =
-R"(
-// float rand; Every read returns a random float [0 .. 1)
+R"(// float rand; Every read returns a random float [0 .. 1)
layout(ctype=float) in uniform float dt;
layout(ctype=float) in uniform float effectAge;
@@ -319,7 +318,10 @@
float frame;
};
-void main(inout Particle p) {
+void spawn(inout Particle p) {
+}
+
+void update(inout Particle p) {
}
)";
@@ -328,14 +330,12 @@
, fEffectDuration(1.0f)
, fRate(8.0f)
, fDrawable(nullptr)
- , fSpawnCode(kDefaultCode)
- , fUpdateCode(kDefaultCode) {
+ , fCode(kDefaultCode) {
this->rebuild();
}
void SkParticleEffectParams::visitFields(SkFieldVisitor* v) {
- SkString oldSpawnCode = fSpawnCode;
- SkString oldUpdateCode = fUpdateCode;
+ SkString oldCode = fCode;
v->visit("MaxCount", fMaxCount);
v->visit("Duration", fEffectDuration);
@@ -343,55 +343,49 @@
v->visit("Drawable", fDrawable);
- v->visit("Spawn", fSpawnCode);
- v->visit("Update", fUpdateCode);
+ v->visit("Code", fCode);
v->visit("Bindings", fBindings);
// TODO: Or, if any change to binding metadata?
- if (fSpawnCode != oldSpawnCode || fUpdateCode != oldUpdateCode) {
+ if (fCode != oldCode) {
this->rebuild();
}
}
void SkParticleEffectParams::rebuild() {
- auto buildProgram = [this](Program* p, const SkString& code) {
- SkSL::Compiler compiler;
- SkSL::Program::Settings settings;
+ SkSL::Compiler compiler;
+ SkSL::Program::Settings settings;
- SkTArray<std::unique_ptr<SkParticleExternalValue>> externalValues;
+ SkTArray<std::unique_ptr<SkParticleExternalValue>> externalValues;
- auto rand = skstd::make_unique<SkRandomExternalValue>("rand", compiler);
- compiler.registerExternalValue(rand.get());
- externalValues.push_back(std::move(rand));
+ auto rand = skstd::make_unique<SkRandomExternalValue>("rand", compiler);
+ compiler.registerExternalValue(rand.get());
+ externalValues.push_back(std::move(rand));
- for (const auto& binding : fBindings) {
- if (binding) {
- auto value = binding->toValue(compiler);
- compiler.registerExternalValue(value.get());
- externalValues.push_back(std::move(value));
- }
+ for (const auto& binding : fBindings) {
+ if (binding) {
+ auto value = binding->toValue(compiler);
+ compiler.registerExternalValue(value.get());
+ externalValues.push_back(std::move(value));
}
+ }
- auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
- SkSL::String(code.c_str()), settings);
- if (!program) {
- SkDebugf("%s\n", compiler.errorText().c_str());
- return;
- }
+ 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 (!byteCode) {
- SkDebugf("%s\n", compiler.errorText().c_str());
- return;
- }
+ auto byteCode = compiler.toByteCode(*program);
+ if (!byteCode) {
+ SkDebugf("%s\n", compiler.errorText().c_str());
+ return;
+ }
- p->fByteCode = std::move(byteCode);
- p->fExternalValues.swap(externalValues);
- };
-
- buildProgram(&fSpawnProgram, fSpawnCode);
- buildProgram(&fUpdateProgram, fUpdateCode);
+ fByteCode = std::move(byteCode);
+ fExternalValues.swap(externalValues);
}
SkParticleEffect::SkParticleEffect(sk_sp<SkParticleEffectParams> params, const SkRandom& random)
@@ -448,18 +442,18 @@
}
}
- auto runProgram = [](SkParticleEffectParams::Program& program, SkParticles& particles,
- float updateParams[], int start, int count) {
- if (const auto& byteCode = program.fByteCode) {
+ auto runProgram = [](const SkParticleEffectParams* params, const char* entry,
+ SkParticles& particles, float updateParams[], int start, int count) {
+ if (const auto& byteCode = params->fByteCode) {
float* args[SkParticles::kNumChannels];
for (int i = 0; i < SkParticles::kNumChannels; ++i) {
args[i] = particles.fData[i].get() + start;
}
SkRandom* randomBase = particles.fRandom.get() + start;
- for (const auto& value : program.fExternalValues) {
+ for (const auto& value : params->fExternalValues) {
value->setRandom(randomBase);
}
- SkAssertResult(byteCode->runStriped(byteCode->getFunction("main"),
+ SkAssertResult(byteCode->runStriped(byteCode->getFunction(entry),
args, SkParticles::kNumChannels, count,
updateParams, 2, nullptr, 0));
}
@@ -496,7 +490,7 @@
}
// Run the spawn script
- runProgram(fParams->fSpawnProgram, fParticles, updateParams, spawnBase, numToSpawn);
+ runProgram(fParams.get(), "spawn", fParticles, updateParams, spawnBase, numToSpawn);
// Now stash copies of the random generators and compute inverse particle lifetimes
// (so that subsequent updates are faster)
@@ -513,7 +507,7 @@
}
// Run the update script
- runProgram(fParams->fUpdateProgram, fParticles, updateParams, 0, fCount);
+ runProgram(fParams.get(), "update", fParticles, updateParams, 0, fCount);
// Do fixed-function update work (integration of position and orientation)
for (int i = 0; i < fCount; ++i) {
diff --git a/resources/particles/default.json b/resources/particles/default.json
index ecc43a5..18b68cf 100644
--- a/resources/particles/default.json
+++ b/resources/particles/default.json
@@ -6,7 +6,7 @@
"Type": "SkCircleDrawable",
"Radius": 1
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -23,7 +23,7 @@
" float frame;",
"};",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = mix(1, 3, rand);",
" float a = radians(mix(250, 290, rand));",
" float s = mix(10, 30, rand);",
@@ -31,27 +31,8 @@
" p.vel.y = sin(a) * s;",
" p.pos = text(rand).xy;",
"}",
- ""
- ],
- "Update": [
"",
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
- "",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" float4 startColor = float4(1, 0.196, 0.078, 1);",
" float4 endColor = float4(1, 0.784, 0.078, 1);",
" p.color = mix(startColor, endColor, p.age);",
diff --git a/resources/particles/explosion.json b/resources/particles/explosion.json
index 2a2035f..791f1d7 100644
--- a/resources/particles/explosion.json
+++ b/resources/particles/explosion.json
@@ -8,7 +8,7 @@
"Columns": 4,
"Rows": 4
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -35,31 +35,13 @@
" return float2(x, y);",
"}",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 1.0 + rand * 2.0;",
" p.pos = circle() * 60;",
" p.vel = p.pos / 3;",
"}",
- ""
- ],
- "Update": [
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
"",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.frame = p.age;",
"}",
""
diff --git a/resources/particles/interp.json b/resources/particles/interp.json
index 3d82b6c..b9a5d4e 100644
--- a/resources/particles/interp.json
+++ b/resources/particles/interp.json
@@ -6,7 +6,7 @@
"Type": "SkCircleDrawable",
"Radius": 2
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -23,31 +23,13 @@
" float frame;",
"};",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 2 + (rand * 2);",
" p.vel.x = (30 * rand) + 50;",
" p.vel.y = (20 * rand) - 10;",
"}",
- ""
- ],
- "Update": [
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
"",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.color.r = p.age;",
" p.color.g = 1 - p.age;",
" float s1 = 0.5 + (1.5 * p.age);",
diff --git a/resources/particles/penguin_cannon.json b/resources/particles/penguin_cannon.json
index e4b28b6..a8e80ae 100644
--- a/resources/particles/penguin_cannon.json
+++ b/resources/particles/penguin_cannon.json
@@ -8,7 +8,7 @@
"Columns": 1,
"Rows": 1
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -25,33 +25,15 @@
" float frame;",
"};",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 20;",
" float a = radians(10 + 60 * rand);",
" float s = 140 + rand * 60;",
" p.vel.x = cos(a) * s;",
" p.vel.y = -sin(a) * s;",
"}",
- ""
- ],
- "Update": [
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
"",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.vel.y += 50 * dt;",
" p.dir = normalize(p.vel);",
"}",
diff --git a/resources/particles/snowfall.json b/resources/particles/snowfall.json
index 190454a..0b5c33d 100644
--- a/resources/particles/snowfall.json
+++ b/resources/particles/snowfall.json
@@ -6,7 +6,7 @@
"Type": "SkCircleDrawable",
"Radius": 1
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -23,32 +23,14 @@
" float frame;",
"};",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 10;",
" p.vel.y = 10 + rand * 20;",
" p.vel.x = -5 + 10 * rand;",
" p.pos.x = rand * 500;",
"}",
- ""
- ],
- "Update": [
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
"",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.scale = size(p.age);",
"}",
""
diff --git a/resources/particles/spiral.json b/resources/particles/spiral.json
index cff1533..4641c92 100644
--- a/resources/particles/spiral.json
+++ b/resources/particles/spiral.json
@@ -6,7 +6,7 @@
"Type": "SkCircleDrawable",
"Radius": 2
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -23,33 +23,15 @@
" float frame;",
"};",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 2 + rand;",
" float a = radians(effectAge * 1080);",
" float s = 50 + rand * 10;",
" p.vel.x = cos(a) * s;",
" p.vel.y = sin(a) * s;",
"}",
- ""
- ],
- "Update": [
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
"",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.scale = 0.5 + 1.5 * p.age;",
" float3 a0 = float3(0.098, 0.141, 0.784);",
" float3 a1 = float3(0.525, 0.886, 0.980);",
diff --git a/resources/particles/swirl.json b/resources/particles/swirl.json
index eb820b7..3063d49 100644
--- a/resources/particles/swirl.json
+++ b/resources/particles/swirl.json
@@ -6,7 +6,7 @@
"Type": "SkCircleDrawable",
"Radius": 2
},
- "Spawn": [
+ "Code": [
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
"layout(ctype=float) in uniform float effectAge;",
@@ -23,7 +23,7 @@
" float frame;",
"};",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 1 + 2 * rand;",
" p.pos.x = rand * 50;",
" float a = radians(-10 + 20 * rand);",
@@ -31,26 +31,8 @@
" p.vel.x = sin(a) * s;",
" p.vel.y = -cos(a) * s;",
"}",
- ""
- ],
- "Update": [
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
"",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.vel.x += wind(p.age) * dt;",
" p.scale = 3 - (1.5 * p.age);",
" p.color = color(p.age);",
diff --git a/resources/particles/warp.json b/resources/particles/warp.json
index f495d19..845814b 100644
--- a/resources/particles/warp.json
+++ b/resources/particles/warp.json
@@ -6,7 +6,7 @@
"Type": "SkCircleDrawable",
"Radius": 2
},
- "Spawn": [
+ "Code": [
"",
"// float rand; Every read returns a random float [0 .. 1)",
"layout(ctype=float) in uniform float dt;",
@@ -34,31 +34,12 @@
" return float2(x, y);",
"}",
"",
- "void main(inout Particle p) {",
+ "void spawn(inout Particle p) {",
" p.lifetime = 30;",
" p.pos = circle() * 40;",
"}",
- ""
- ],
- "Update": [
"",
- "// float rand; Every read returns a random float [0 .. 1)",
- "layout(ctype=float) in uniform float dt;",
- "layout(ctype=float) in uniform float effectAge;",
- "",
- "struct Particle {",
- " float age;",
- " float lifetime;",
- " float2 pos;",
- " float2 dir;",
- " float scale;",
- " float2 vel;",
- " float spin;",
- " float4 color;",
- " float frame;",
- "};",
- "",
- "void main(inout Particle p) {",
+ "void update(inout Particle p) {",
" p.vel += normalize(p.pos) * dt * 10;",
" p.scale = mix(0.25, 3, p.age);",
"}",