Skip to content

[CI probe] SOL shader variants on GPU-less runner — do not review#3072

Closed
cptbtptpbcptdtptp wants to merge 9 commits into
dev/2.0from
test/sol-swiftshader-probe
Closed

[CI probe] SOL shader variants on GPU-less runner — do not review#3072
cptbtptpbcptdtptp wants to merge 9 commits into
dev/2.0from
test/sol-swiftshader-probe

Conversation

@cptbtptpbcptdtptp

@cptbtptpbcptdtptp cptbtptpbcptdtptp commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Throwaway probe for #3060: determines which SizeOverLifetime macro variants SwiftShader can compile on GPU-less CI runners (mesh+TwoCurves hangs the compiler; local SwiftShader behaves differently from CI's). The four probe cases have no baselines on purpose — only the 'Screenshot button visible / not visible' log lines matter. Will be closed and deleted after one CI run.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for randomized particle size-over-lifetime curves.
    • Added per-axis size-over-lifetime behavior for mesh particles, enabling distinct scaling across X, Y, and Z axes.
    • Added new particle rendering scenarios covering burst emissions, mesh rendering, and composite size curves.
  • Bug Fixes

    • Improved randomization consistency for particle size-over-lifetime effects.
    • Preserved noise-based variation when particle noise and size-over-lifetime features are used together.

cptbtptpbcptdtptp and others added 5 commits July 2, 2026 14:15
Two stacked bugs since #1682 left SOL's random-between-two-curves mode
entirely inert: an operator-precedence bug in _updateShaderData kept
RENDERER_SOL_CURVE_MODE / RENDERER_SOL_IS_RANDOM_TWO from ever being
enabled, and the per-particle random factor in instance slot 21
(a_Random0.z) was never written unless the noise module happened to be
enabled (#2953 gated the shared slot's write on noise.enabled only).

Fix the parenthesization, give SizeOverLifetimeModule its own Rand
(using the already-reserved SizeOverLifetime sub-seed), and write the
shared slot when SOL needs it; noise keeps precedence when both are on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
computeParticleSizeMesh was gated on four macros (RENDERER_SOL_CURVE,
RENDERER_SOL_RANDOM_CURVES, RENDERER_SOL_CURVE_SEPARATE,
RENDERER_SOL_RANDOM_CURVES_SEPARATE) that no TS module ever enables —
the random branch even referenced a nonexistent uniform
(u_SOLSizeGradientMax) — so the module was entirely inert for mesh-mode
particles. Rewrite it against the macro set the billboard path and
SizeOverLifetimeModule already use, extended to all three axes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The mesh-path SOL shader rewrite (3447163) had no automated guard:
unit tests only assert TS-side macro/upload/slot state, and no e2e case
combined mesh render mode with an enabled sizeOverLifetime module. This
case pins computeParticleSizeMesh end-to-end: separateAxes TwoCurves on
all three axes with a fixed seed, so per-particle random size variation
is baked into the baseline — before the fix every cuboid rendered at
constant startSize.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Vitest's coverage collection sweeps e2e/**/*.ts into the report at 0%
(they only run under Playwright, never under the unit-test runner), so
any e2e-only commit craters codecov's patch metric — this PR's baseline
commit dropped it from 97% to 35% with zero source changes. Ignore the
directory at the codecov layer; unit coverage semantics are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The RENDERER_SOL_IS_SEPARATE + RENDERER_SOL_IS_RANDOM_TWO macro combo
hangs SwiftShader's shader compiler (evaluateParticleCurve inlined at
10 call sites in one program), so the case never reached initScreenshot
on GPU-less CI runners while passing on real GPUs. Non-separate
TwoCurves keeps the mesh path and the per-particle random mix under
pixel guard; the separate combo stays covered by unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 19, 2026
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds randomized size-over-lifetime particle handling, shader and instance-data tests, three mesh-particle E2E cases, their configuration entries, and an E2E coverage exclusion.

Changes

Particle size-over-lifetime behavior

Layer / File(s) Summary
Random state and shader modes
packages/core/src/particle/ParticleGenerator.ts, packages/core/src/particle/modules/SizeOverLifetimeModule.ts
Adds dedicated size-over-lifetime RNG handling, seed propagation, random curve-mode detection, and shared random-slot precedence with noise.
Renderer validation
tests/src/core/particle/SizeOverLifetime.test.ts
Tests shader macros, curve uploads, per-particle random values, noise precedence, and separate-axis mesh rendering.
E2E scenarios and registration
e2e/case/*size-over-lifetime.ts, e2e/case/probe4-final-*.ts, e2e/config.ts, codecov.yml
Adds mesh-particle screenshots for separate-axis, non-separate-axis, and emission scenarios, registers them, and excludes E2E files from coverage.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: shader, particle

Poem

I’m a rabbit with curves in my flight,
Random seeds make my particles bright.
Meshes burst from a spherical show,
Axes stretch as the lifetimes flow.
Tests watch each spark and sprite—
Hop, hop, rendered right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the PR’s CI probe for SizeOverLifetime shader variants on a GPU-less runner.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/sol-swiftshader-probe

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cptbtptpbcptdtptp
cptbtptpbcptdtptp marked this pull request as ready for review July 19, 2026 14:25
@cptbtptpbcptdtptp
cptbtptpbcptdtptp force-pushed the test/sol-swiftshader-probe branch from d03fd22 to 8d27be3 Compare July 19, 2026 14:29
@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.14286% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 85.20%. Comparing base (721b42a) to head (2066c7d).
⚠️ Report is 6 commits behind head on dev/2.0.

Files with missing lines Patch % Lines
packages/core/src/particle/ParticleGenerator.ts 83.33% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           dev/2.0    #3072      +/-   ##
===========================================
+ Coverage    79.37%   85.20%   +5.82%     
===========================================
  Files          903      810      -93     
  Lines       100632    94671    -5961     
  Branches     11260    11337      +77     
===========================================
+ Hits         79879    80663     +784     
+ Misses       20569    13918    -6651     
+ Partials       184       90      -94     
Flag Coverage Δ
unittests 85.20% <97.14%> (+5.82%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/src/core/particle/SizeOverLifetime.test.ts`:
- Around line 32-38: Restore the original performance.now implementation after
the mocked timing loop in the test. Capture the original method before
overriding it, then restore it after the engine.update calls in the relevant
test flow, including when the test exits unexpectedly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2054c6a5-d2f1-45f8-97d4-5d24710e2817

📥 Commits

Reviewing files that changed from the base of the PR and between 9fe48c6 and 8d27be3.

⛔ Files ignored due to path filters (2)
  • e2e/fixtures/originImage/Particle_particleRenderer-emit-mesh-size-over-lifetime.jpg is excluded by !**/*.jpg
  • packages/shader/src/ShaderLibrary/Particle/Module/SizeOverLifetime.glsl is excluded by !**/*.glsl
📒 Files selected for processing (10)
  • codecov.yml
  • e2e/case/particleRenderer-emit-mesh-size-over-lifetime.ts
  • e2e/case/probe-billboard-sol-separate-two-curves.ts
  • e2e/case/probe-billboard-sol-two-curves.ts
  • e2e/case/probe-mesh-sol-separate-single-curve.ts
  • e2e/case/probe-mesh-sol-single-curve.ts
  • e2e/config.ts
  • packages/core/src/particle/ParticleGenerator.ts
  • packages/core/src/particle/modules/SizeOverLifetimeModule.ts
  • tests/src/core/particle/SizeOverLifetime.test.ts

Comment on lines +32 to +38
performance.now = function () {
times++;
return times * deltaTime;
};
for (let i = 0; i < frames; i++) {
engine.update();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Restore performance.now after mocking to avoid test pollution.

Overwriting the global performance.now without restoring it can leak this mocked state into other test files running in the same environment, potentially causing unrelated time-dependent tests to flake or fail.

🛠️ Proposed fix
+ const originalNow = performance.now;
  performance.now = function () {
    times++;
    return times * deltaTime;
  };
  for (let i = 0; i < frames; i++) {
    engine.update();
  }
+ performance.now = originalNow;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
performance.now = function () {
times++;
return times * deltaTime;
};
for (let i = 0; i < frames; i++) {
engine.update();
}
const originalNow = performance.now;
performance.now = function () {
times++;
return times * deltaTime;
};
for (let i = 0; i < frames; i++) {
engine.update();
}
performance.now = originalNow;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/src/core/particle/SizeOverLifetime.test.ts` around lines 32 - 38,
Restore the original performance.now implementation after the mocked timing loop
in the test. Capture the original method before overriding it, then restore it
after the engine.update calls in the relevant test flow, including when the test
exits unexpectedly.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/config.ts`:
- Around line 422-426: Update the E2E_CONFIG entry for
Probe3ConebaseInstrumented so it bypasses screenshotWithThreshold and does not
perform baseline image comparison. Route it through a probe-specific test path
or enable the existing explicit skip-comparison behavior while preserving the
probe’s button-visibility validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d0191a22-7359-4982-bfec-93e8ddf302b8

📥 Commits

Reviewing files that changed from the base of the PR and between 4e4c6b8 and 7e488a0.

📒 Files selected for processing (2)
  • e2e/case/probe3-conebase-instrumented.ts
  • e2e/config.ts

Comment thread e2e/config.ts Outdated
Comment on lines +422 to +426
Probe3ConebaseInstrumented: {
category: "Particle",
caseFileName: "probe3-conebase-instrumented",
threshold: 0,
diffPercentage: 0.005

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the baseline-free probe out of screenshot comparison.

E2E_CONFIG routes this case through screenshotWithThreshold, which compares against an origin image after the screenshot button is clicked. Since this probe has no baseline and only button visibility is relevant, it will fail later on missing/invalid comparison data and obscure the compiler result. Run it through a probe-specific test path or add an explicit skip-comparison mode.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/config.ts` around lines 422 - 426, Update the E2E_CONFIG entry for
Probe3ConebaseInstrumented so it bypasses screenshotWithThreshold and does not
perform baseline image comparison. Route it through a probe-specific test path
or enable the existing explicit skip-comparison behavior while preserving the
probe’s button-visibility validation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/config.ts`:
- Around line 422-433: Update the E2E_CONFIG entries Probe4FinalSeparate and
Probe4FinalNonseparate so they bypass screenshotWithThreshold and do not require
baseline comparison data. Route them through an existing probe-specific path or
enable an explicit skip-comparison mode while preserving the button-visibility
validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 495b8fec-c227-4337-b5a2-1e369c617dd5

📥 Commits

Reviewing files that changed from the base of the PR and between 7e488a0 and 2066c7d.

📒 Files selected for processing (3)
  • e2e/case/probe4-final-nonseparate.ts
  • e2e/case/probe4-final-separate.ts
  • e2e/config.ts

Comment thread e2e/config.ts
Comment on lines +422 to +433
Probe4FinalSeparate: {
category: "Particle",
caseFileName: "probe4-final-separate",
threshold: 0,
diffPercentage: 0.005
},
Probe4FinalNonseparate: {
category: "Particle",
caseFileName: "probe4-final-nonseparate",
threshold: 0,
diffPercentage: 0.005
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the baseline-free probes out of screenshot comparison.

E2E_CONFIG routes these cases through screenshotWithThreshold, which compares against an origin image after the screenshot button is clicked. Since these probes have no baseline and only button visibility is relevant, they will fail later on missing comparison data and obscure the compiler result. Run them through a probe-specific test path or add an explicit skip-comparison mode.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/config.ts` around lines 422 - 433, Update the E2E_CONFIG entries
Probe4FinalSeparate and Probe4FinalNonseparate so they bypass
screenshotWithThreshold and do not require baseline comparison data. Route them
through an existing probe-specific path or enable an explicit skip-comparison
mode while preserving the button-visibility validation.

@cptbtptpbcptdtptp

Copy link
Copy Markdown
Collaborator Author

Probe complete. Root cause of every hang: this branch's new e2e cases called engine.canvas.resizeByClientSize, which #3037 removed on dev/2.0 (PR CI builds the merge, so old cases — updated by #3037 — passed while newly added ones died in a silent unhandled rejection). Nothing to do with shader variants or SwiftShader. Fix landed on #3060 as 88bc982.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant