Change particle affector to work on N particles
This should severely cut down on the virtual call overhead when running
affectors. It also switches to model of "for each affector, do each
particle", rather than "for each particle, do each affector". This is
going to be an I$ improvement, and (if we ever care), make it possible
to do wide-mode threading of the affectors on disjoint blocks of
particles.
Bug: skia:
Change-Id: Ia4e8e8d461dba4e303c45766ea2b4ece1bca9196
Reviewed-on: https://skia-review.googlesource.com/c/195123
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/modules/particles/src/SkParticleAffector.cpp b/modules/particles/src/SkParticleAffector.cpp
index 74d55e9..de1a66c 100644
--- a/modules/particles/src/SkParticleAffector.cpp
+++ b/modules/particles/src/SkParticleAffector.cpp
@@ -11,9 +11,9 @@
#include "SkParticleData.h"
#include "SkRandom.h"
-void SkParticleAffector::apply(SkParticleUpdateParams& params, SkParticleState& ps) {
+void SkParticleAffector::apply(SkParticleUpdateParams& params, SkParticleState ps[], int count) {
if (fEnabled) {
- this->onApply(params, ps);
+ this->onApply(params, ps, count);
}
}
@@ -34,18 +34,20 @@
REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
- void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
- float angle = fAngle.eval(ps.fAge, ps.fStableRandom);
- SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
- SkVector heading = fLocal ? ps.fPose.fHeading : SkVector{ 0, -1 };
- SkScalar c = heading.fX * c_local - heading.fY * s_local;
- SkScalar s = heading.fX * s_local + heading.fY * c_local;
- float strength = fStrength.eval(ps.fAge, ps.fStableRandom);
- SkVector force = { c * strength, s * strength };
- if (fForce) {
- ps.fVelocity.fLinear += force * params.fDeltaTime;
- } else {
- ps.fVelocity.fLinear = force;
+ void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ for (int i = 0; i < count; ++i) {
+ float angle = fAngle.eval(ps[i].fAge, ps[i].fStableRandom);
+ SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
+ SkVector heading = fLocal ? ps[i].fPose.fHeading : SkVector{ 0, -1 };
+ SkScalar c = heading.fX * c_local - heading.fY * s_local;
+ SkScalar s = heading.fX * s_local + heading.fY * c_local;
+ float strength = fStrength.eval(ps[i].fAge, ps[i].fStableRandom);
+ SkVector force = { c * strength, s * strength };
+ if (fForce) {
+ ps[i].fVelocity.fLinear += force * params.fDeltaTime;
+ } else {
+ ps[i].fVelocity.fLinear = force;
+ }
}
}
@@ -72,11 +74,14 @@
REFLECTED(SkPointForceAffector, SkParticleAffector)
- void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
- SkVector toPoint = fPoint - ps.fPose.fPosition;
- SkScalar lenSquare = toPoint.dot(toPoint);
- toPoint.normalize();
- ps.fVelocity.fLinear += toPoint * (fConstant + (fInvSquare/lenSquare)) * params.fDeltaTime;
+ void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ for (int i = 0; i < count; ++i) {
+ SkVector toPoint = fPoint - ps[i].fPose.fPosition;
+ SkScalar lenSquare = toPoint.dot(toPoint);
+ toPoint.normalize();
+ ps[i].fVelocity.fLinear +=
+ toPoint * (fConstant + (fInvSquare / lenSquare)) * params.fDeltaTime;
+ }
}
void visitFields(SkFieldVisitor* v) override {
@@ -98,12 +103,14 @@
REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
- void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
- SkVector heading = ps.fVelocity.fLinear;
- if (!heading.normalize()) {
- heading.set(0, -1);
+ void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ for (int i = 0; i < count; ++i) {
+ SkVector heading = ps[i].fVelocity.fLinear;
+ if (!heading.normalize()) {
+ heading.set(0, -1);
+ }
+ ps[i].fPose.fHeading = heading;
}
- ps.fPose.fHeading = heading;
}
void visitFields(SkFieldVisitor *v) override {
@@ -117,8 +124,10 @@
REFLECTED(SkSizeAffector, SkParticleAffector)
- void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
- ps.fPose.fScale = fCurve.eval(ps.fAge, ps.fStableRandom);
+ void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ for (int i = 0; i < count; ++i) {
+ ps[i].fPose.fScale = fCurve.eval(ps[i].fAge, ps[i].fStableRandom);
+ }
}
void visitFields(SkFieldVisitor* v) override {
@@ -136,8 +145,10 @@
REFLECTED(SkFrameAffector, SkParticleAffector)
- void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
- ps.fFrame = fCurve.eval(ps.fAge, ps.fStableRandom);
+ void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ for (int i = 0; i < count; ++i) {
+ ps[i].fFrame = fCurve.eval(ps[i].fAge, ps[i].fStableRandom);
+ }
}
void visitFields(SkFieldVisitor* v) override {
@@ -156,8 +167,10 @@
REFLECTED(SkColorAffector, SkParticleAffector)
- void onApply(SkParticleUpdateParams& params, SkParticleState& ps) override {
- ps.fColor = fCurve.eval(ps.fAge, ps.fStableRandom);
+ void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
+ for (int i = 0; i < count; ++i) {
+ ps[i].fColor = fCurve.eval(ps[i].fAge, ps[i].fStableRandom);
+ }
}
void visitFields(SkFieldVisitor* v) override {