feat(fluids): particles drawn on WebGPU without a global sort; WebGL2 refuses them by name and the session carries on (#755) - #853
Merged
Conversation
…ve or premultiplied, soft on the scene depth, on WebGPU and WebGL2 (#755)
…y the first ever (#755)
…, and WebGL2 refuses a depth it cannot copy once (#755)
…aws; a refused WebGL2 draw finishes its frame (#755)
…e WebGL2 refusal returns for the frame to finish (#755)
…cles write the chain's untoned mask (#755)
…write the untoned mark, an earlier GL error never refuses (#755)
…rite the untoned mark, an earlier GL error never refuses; trimmed (#755)
…pool's look fields stay typed (#755)
…d group's entries in two lines (#755)
…format, stencil-packed or not, and the fake GL refuses a blit between two (#755)
…ld notice; the draw reuses matrixAtRenderOrigin and buildRenderPipeline (#755)
…rs, and a dropped visibility buffer frees the particle step (#755)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #755
What changed
Particle pools are now drawn on WebGPU without a global sort. On WebGL2 they are refused by name with a notice, and the session carries on. Each WebGPU pool is one instanced draw of eye-facing discs, placed after the transparents and before TAA. The draw reads the step's state in place; the pool stays the only store of particles.
packages/sdk-core/src/fluids/particles.ts):blend(additive|premultiplied),color,sizeandsoftness.PARTICLE_BLEND. A size or softness that is not positive is refused asPARTICLE_SIZE. A colour of other than four finite numbers is refused asPARTICLE_COLOR.packages/sdk-browser/src/particles/drawWords.ts):matrixAtRenderOrigin) and its inverse are built in double precision.particles/webgpuParticleDraw.ts, wired bydrawParticlesinparticles/webgpuParticles.tsandwebgpu/pages/render/encodeBlend.ts):Trillion3D particle draw, over the lit HDR image, mapped to thetransparentsstage.buildRenderPipeline). A pipeline that fails is heard (particles-unavailable), and the step refuses the pools and dispatches none.PARTICLES_UNSUPPORTED):particlesRefusednotice as WebGL2 (carried bybackend/types.tsandsession/backends.ts); a step made before the buffer was dropped frees its buffers.world/render/compose.ts):particlesRefused. It is modelled oneffects.refused. It is set inworld/core/worldSwitches.tsas the world noticeparticles-refused(notices.once), carried bysession/options.tsandrender/hostState.ts.particles/webglParticles.ts, feat(fluids): WebGL2 steps the particle pools in RGBA32F ping-pong targets, refused by name without them (#759) #778) is left as it is for WebGL2 draws the particle pools #844.docs/ENGINE.mdis updated. The WGSL is added to the engine shader list.Proof
pnpm run check:changed(1476 pass, 0 fail, with the Jolt submodule and the native compiler built),pnpm run test:changedandpnpm run validate --group quick: all pass.check-pr-size: 427 hand-written lines.packages/sdk-browser/src/particles/particleDraw.test.ts:packages/sdk-browser/src/world/render/compose.test.ts: "WebGL2 refuses the pools by name from the first frame, heard once, and draws on".PARTICLES_UNSUPPORTED. No particle is drawn.packages/sdk-core/src/fluids/particles.test.ts: "a pool blends, sizes and softens as told, and refuses by name what no renderer draws" (colour included).ten-thousand-bodies(0 px).Local review before push
simplify(4 agents: reuse, simplification, efficiency, altitude). Fixed:matrixAtRenderOrigininstead of a hand-rolled origin column;buildRenderPipelineinstead of a barecreateRenderPipelineAsync.particles-refusedthroughparticlesRefused, like WebGL2, instead of adiagnosticFailurepath-failure (kept for pipeline errors only); itsErroris no longer built each frame.webglParticles.ts's text).DrawState.depthtyped.particles/webglParticles.tsand its fixture/probe (parked for WebGL2 draws the particle pools #844, which needs the step); anoticeParticleRefusalfactory (notices.oncealready says it once); hoisting the render-pass descriptor (negligible); a vertex run per dead slot (needs an indirect count, out of scope).code-review --fix. Fixed: a visibility buffer dropped mid-session kept every pool's GPU buffers (the step is now freed, tested); an uncheckedcolorlength gave the previous pool's opacity or a RangeError mid-frame (PARTICLE_COLOR, tested). Not fixed, for Fluids P2: GPU particles, fire, smoke flipbooks, heat distortion, wind API #423 (one step state per engine): in a WebGL2-beside-WebGPU comparison the shared pools'refusedflag is set by the WebGL2 side each frame.Closes #755; both To-do items delivered (WebGPU draw; WebGL2 refusal that never fails the session); each changed behaviour has a test that fails when its fix is reverted; noPARTICLES_UNSUPPORTEDthrow is reachable fromcompose.tsorencodeParticles(the only throw left,webglParticles.ts, is reached by its fixture and probe alone, parked for WebGL2 draws the particle pools #844);docs/ENGINE.mdupdated;particlesRefusedis an internal measured-world option, fed by the world notice, with no public API.Lead verification
packages/sdk-browser/src/particles/webgpuParticleDraw.ts:53(additive blend, order-free), wired atwebgpu/pages/render/encodeBlend.ts:176, proved by "WebGPU: one pass, fire then the nearer smoke, each with its blend; none without particles".particles/drawWords.ts:34(drawOrder, far to near by origin, nothing allocated) andwebgpuParticleDraw.ts:57, proved by the same test (the nearer smoke drawn last).webgpuParticleDraw.ts:37(opaque depth read as a texture), proved by the same test's bindings and the measurer's image.world/render/compose.ts:130(refuseAll+particlesRefused, no throw) throughworld/core/worldSwitches.ts:39(notices.once('particles-refused')); WebGPU without the visibility buffer on the same channel (particles/webgpuParticles.ts:147), proved by "WebGL2 refuses the pools by name from the first frame, heard once, and draws on" (compose.test.ts, fails on develop's composer) and "WebGPU without the visibility buffer refuses the pools by name, heard once, and frees the step".particles-refusednotice, pools refused; 0 px vs develop on crates-under-a-spotlight, shadows-case-by-case and a-first-world, both backends, A/A 0. Draw cost per tier on Fluids S2 (spike): one GPU particle system on WebGPU and WebGL2 #420 comes with Particles hold under TAA: previous position, reactive mask, flipbooks with motion vectors #756's bench setting.Checked by the lead on the diff:
755-webgl2-draw), bench setting → Particles hold under TAA: previous position, reactive mask, flipbooks with motion vectors #756, step state per engine / records at submit /PARTICLES_ATTACH/ parallel compile + warm-up / MRT → Fluids P2: GPU particles, fire, smoke flipbooks, heat distortion, wind API #423.PARTICLES_UNSUPPORTED) and the session goes on.refuseAll,usedSlots,matrixAtRenderOrigin,buildRenderPipeline,notices.oncereused;particlesRefusedfollowseffectsRefused's plumbing and is the only particle refusal channel; new exportsdrawOrder,writeDrawWords,DISC_CORNERS,DRAW_FLOATS,createWebgpuParticleDraw,PARTICLE_DRAW_PASS,PARTICLE_DRAW_WGSLsearched (graph and grep): no twin.docs/ENGINE.md(WebGPU draw, WebGL2 refusal and its notice);particlesRefusedis an internal measured-world option, no public member changed, so no SDK.md/API reference entry.webgpuParticles.ts:152).particles/webglParticles.ts) is no longer run by the composer; WebGL2 draws the particle pools #844 wires it back and moves its throw toparticlesRefused.in reviewset,to measureat close.Not proven / left out
check-pr-size).755-webgl2-draw(head 3c08581).1b10fc595): Particles hold under TAA: previous position, reactive mask, flipbooks with motion vectors #756.PARTICLES_ATTACH,KHR_parallel_shader_compilewith warm-up, and the WebGL2 MRT step: Fluids P2: GPU particles, fire, smoke flipbooks, heat distortion, wind API #423.site/examples/.attachParticlesreaches them.particles-refusednotice is covered by the compose test (heard once through the channel) and bynotices.once. No test drives a whole world session on WebGL2; that is the measurer's proof.