perf(shaders): move RoundedWithBorder border math from varyings to CPU uniforms#89
Closed
chiefcll wants to merge 1 commit into
Closed
perf(shaders): move RoundedWithBorder border math from varyings to CPU uniforms#89chiefcll wants to merge 1 commit into
chiefcll wants to merge 1 commit into
Conversation
…U uniforms
All nine border varyings (inner/outer size, border UVs, inner/outer radii,
half dimensions) were derived purely from uniforms, so they were constant
across the quad yet interpolated per fragment. Compute them once on the CPU
in update() (cached by the shader value-key, so they only recompute when
border props or node dimensions change) and upload them as uniforms.
The fragment shader now carries the same 3 varyings as the plain Rounded
shader, and with a zero-width border its per-pixel cost is identical to
Rounded - the common TV-app pattern of border: {w: 0} until focus no longer
pays the full border pipeline on every unfocused card.
borderZero is also precomputed on the CPU and uploaded as a uniform instead
of being re-derived per fragment, and the vertex shader's branch is replaced
with arithmetic on that flag. GLSL output is unchanged by construction; the
CPU math mirrors the previous vertex shader expressions exactly and is unit
tested against hand-computed cases.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
Rewrites the WebGL
RoundedWithBordershader so all border geometry is computed once on the CPU and uploaded as uniforms, instead of being recomputed in the vertex shader and shipped to the fragment stage through varyings.Why
All nine border varyings (
v_innerSize,v_outerSize,v_outerBorderUv,v_innerBorderUv,v_innerBorderRadius,v_outerBorderRadius,v_halfDimensions— 18 interpolated floats) were derived purely from uniforms, so they were constant across the quad yet paid per-fragment interpolation cost on every pixel. On the embedded GPUs this engine targets, interpolator pressure is real fragment-pipeline cost.This matters most for the common TV-app pattern of
border: {w: 0}on every card until focus: with a zero-width border, the fragment shader now carries the same 3 varyings as the plainRoundedshader, making the per-pixel cost of an unfocused card identical toRounded. The full border path only runs its math when border props or node dimensions actually change (cached by the existing shader value-key cache), i.e. once per focus change rather than per frame.How
calcBorderShaderValues()mirrors the previous vertex-shader expressions exactly (adjusted widths, gap handling, inner/outer sizes, UV offsets, inner/outer radii, edge offset) and writes into a reused scratch buffer.borderZerois precomputed and uploaded as a uniform instead of re-derived per fragment viadot/step.edge+ edge offset) is preserved.update()skips computing/uploading the border uniforms entirely (both shader stages early-out before reading them).GLSL output is unchanged by construction. No prop/API changes; the Canvas2D backend is untouched.
Testing
pnpm buildpasses.RoundedWithBorder.test.ts) verify the CPU math against hand-computed cases: uniform/asymmetric borders, gap, align inside/center/outside, sub-pixel width collapse, and negative inner-radius clamping.?test=shader-borderin the examples app: shaders compile and render with no GL errors.🤖 Generated with Claude Code