Skip to content

fix(strands): preserve loop-carried variables with sequential depende… - #9383

Closed
Pcmhacker-hero wants to merge 1 commit into
processing:mainfrom
Pcmhacker-hero:fix/strands-loop-carried-vars
Closed

Pcmhacker-hero wants to merge 1 commit into
processing:mainfrom
Pcmhacker-hero:fix/strands-loop-carried-vars

Conversation

@Pcmhacker-hero

@Pcmhacker-hero Pcmhacker-hero commented Nov 8, 2026 •

Copy link
Copy Markdown

Resolves #9377

Changes:
- **`src/strands/strands_for.js`**: When updating loop-carried variables and helper states at the end of an iteration (and on `break`), detect whether any update's source expression reads a target phi variable assigned by another
update in the set.
  - If inter-dependencies exist (such as variable swaps, rotations, or Fibonacci-style recurrences), allocate temporary phi variables in the loop's `branchBlock`.
  - In the target block (e.g. `finalBodyBlock`), update the loop state in two distinct phases: first evaluate and buffer the new values into the temporaries, then assign the temporaries into their target phi nodes.
  - If no inter-dependencies exist between the loop-carried variables, preserve direct assignments to the target phi nodes without overhead.
- **Unit Tests (`test/unit/webgl/p5.Shader.js`, `test/unit/webgpu/p5.Shader.js`)**: Added regression unit tests reproducing the swap issue reported in #9377 as well as Fibonacci-style sequential updates across iterations, verifying
correct evaluation in both WebGL and WebGPU.

#### PR Checklist

- [x] `npm run lint` passes
- [ ] [Inline reference] is included / updated
- [x] [Unit tests] are included / updated

@Pcmhacker-hero

Copy link
Copy Markdown
Author

Hi @davepagurek @limzykenneth! 👋

Could you please review this PR when you have a moment?

It resolves #9377 by ensuring that loop-carried variables and helper states with inter-dependencies (e.g. variable swaps, coordinate rotations, or Fibonacci-style recurrences) are buffered through temporary phi variables before
updating target phi nodes. This prevents earlier assignments from overwriting values read later in the same iteration.

- Implemented in `src/strands/strands_for.js` with dependency detection so loops without inter-dependencies maintain direct assignments.
- Added regression tests in both WebGL (`test/unit/webgl/p5.Shader.js`) and WebGPU (`test/unit/webgpu/p5.Shader.js`).
- All 225 `p5.strands` tests pass, and `npm run lint` passes with 0 errors.

Thank you!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[p5.js 2.0+ Bug Report]: p5.strands loop-carried variables can read values overwritten earlier in the same iteration

2 participants