Follow-up to #865, surfaced by its cross-backend regression tests (test/issues/865-cpu-control-flow.js). The cpu fixes on feature/webasm-backend exposed that the GL backends fail two of the same three shapes:
1. do-while continue skips the test. GLSL ES 1.00 has no do-while, so the backends emulate it as for (int safeI = 0; safeI < LOOP_MAX; safeI++) { body; if (!(test)) break; } — a continue in the body jumps past the trailing test check, exactly the mechanism the cpu backend had (#865). The do/while accumulator repro returns 61 on headlessgl where plain JS, cpu (fixed) and webasm give 48. The #300 loop normalization already contains the right transform (continue gains a copy of the exit check — see normalizeLoopHeader's do-while handling in src/backend/web-gl/function-node.js), but it only engages when the FXC pattern gates fire; the fix is to apply that continue rewrite to every emulated do-while, not only hoist-affected ones.
2. Assigning to a scalar argument fails to compile. Scalar arguments are GLSL uniforms; base = base + this.thread.x emits an assignment to a uniform and the shader is rejected: 'assign' : l-value required "user_base" (can't modify a uniform). Loud rather than silent, but the same legal-JavaScript shape now works on cpu and webasm (per-cell shadow binding); the GL fix is the same idea in GLSL — declare float user_base_cell = user_base; at kernel start and route references through it, exactly as the cpu backend now does with its user_X$cell shadows.
The corresponding rows in test/issues/865-cpu-control-flow.js are scoped to cpu+webasm with comments pointing here; widening them to all MODES is the acceptance test for this issue.
Follow-up to #865, surfaced by its cross-backend regression tests (test/issues/865-cpu-control-flow.js). The cpu fixes on feature/webasm-backend exposed that the GL backends fail two of the same three shapes:
1. do-while continue skips the test. GLSL ES 1.00 has no do-while, so the backends emulate it as
for (int safeI = 0; safeI < LOOP_MAX; safeI++) { body; if (!(test)) break; }— acontinuein the body jumps past the trailing test check, exactly the mechanism the cpu backend had (#865). The do/while accumulator repro returns 61 on headlessgl where plain JS, cpu (fixed) and webasm give 48. The #300 loop normalization already contains the right transform (continue gains a copy of the exit check — see normalizeLoopHeader's do-while handling in src/backend/web-gl/function-node.js), but it only engages when the FXC pattern gates fire; the fix is to apply that continue rewrite to every emulated do-while, not only hoist-affected ones.2. Assigning to a scalar argument fails to compile. Scalar arguments are GLSL uniforms;
base = base + this.thread.xemits an assignment to a uniform and the shader is rejected:'assign' : l-value required "user_base" (can't modify a uniform). Loud rather than silent, but the same legal-JavaScript shape now works on cpu and webasm (per-cell shadow binding); the GL fix is the same idea in GLSL — declarefloat user_base_cell = user_base;at kernel start and route references through it, exactly as the cpu backend now does with itsuser_X$cellshadows.The corresponding rows in test/issues/865-cpu-control-flow.js are scoped to cpu+webasm with comments pointing here; widening them to all MODES is the acceptance test for this issue.