Repository navigation
feat: common.attachAutoResizer #2534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9e9e390
c1a095b
5e96dee
0521ebe
bbb1f08
c0c25e0
0f574a1
e1ac34a
d150189
3883aa2
a87aad1
0a967c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| <canvas data-fit-to-container></canvas> | ||
| <canvas class="w-full h-full"></canvas> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -399,8 +399,6 @@ function createRenderTargets() { | |
| .$usage('render'); | ||
|
|
||
| return { | ||
| width: canvas.width, | ||
| height: canvas.height, | ||
| normal, | ||
| depth, | ||
| colorAttachments: [ | ||
|
|
@@ -452,14 +450,6 @@ function frame(timestamp: number) { | |
| const dt = Math.min((timestamp - (lastTimestamp ?? timestamp)) * 0.001, 1 / 30); | ||
| lastTimestamp = timestamp; | ||
|
|
||
| if (canvas.width === 0 || canvas.height === 0) { | ||
| return; | ||
| } | ||
| if (canvas.width !== targets.width || canvas.height !== targets.height) { | ||
| targets.destroy(); | ||
| targets = createRenderTargets(); | ||
| } | ||
|
|
||
| controls.update(dt); | ||
| outsideOpacity.target = controls.focus.z > 0.5 ? 1 : 0; | ||
| outsideOpacity.step(dt); | ||
|
|
@@ -469,6 +459,14 @@ function frame(timestamp: number) { | |
| outsideOpacityUniform.write(std.saturate(outsideOpacity.value)); | ||
| fadeInUniform.write(std.saturate(controls.in3dTransition * 2 - 1)); | ||
|
|
||
| render(); | ||
| } | ||
|
|
||
| function render() { | ||
| if (canvas.width === 0 || canvas.height === 0) { | ||
| return; | ||
| } | ||
|
|
||
| const encoder = root['~unstable'].createCommandEncoder(); | ||
| const pass = encoder.beginRenderPass({ | ||
| colorAttachments: targets.colorAttachments, | ||
|
|
@@ -506,8 +504,19 @@ function frame(timestamp: number) { | |
|
|
||
| frameId = requestAnimationFrame(frame); | ||
|
|
||
| const autoResizer = common.attachAutoResizer({ | ||
| root, | ||
| canvas, | ||
| onResize() { | ||
| targets.destroy(); | ||
| targets = createRenderTargets(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new Technical details# `mipLevelCount: 2` exceeds the mip limit for a clamped 1x1 canvas
## Affected sites
- `apps/typegpu-docs/src/examples/advanced/appjs-venue/index.ts:512` — newly calls `createRenderTargets()` from `onResize`.
- `apps/typegpu-docs/src/examples/advanced/appjs-venue/index.ts:392` — `normal` created with `mipLevelCount: 2`.
- `apps/typegpu-docs/src/examples/advanced/appjs-venue/index.ts:393` — `depth` created with `mipLevelCount: 2`.
- `packages/typegpu/src/common/attachAutoResizer.ts:84` — clamps the canvas to `Math.max(1, ...)`.
## Required outcome
- Recreating render targets when the canvas collapses to 1x1 must not request more mip levels than the texture size supports (`floor(log2(max(width, height))) + 1`).
## Suggested approach (optional)
- Derive the mip count from the target size, e.g. `Math.min(2, Math.floor(Math.log2(Math.max(width, height))) + 1)`, or skip target recreation while the reported size is below 2x2. |
||
| render(); | ||
| }, | ||
| }); | ||
|
|
||
| export function onCleanup() { | ||
| abortController.abort(); | ||
| cancelAnimationFrame(frameId); | ||
| autoResizer.detach(); | ||
| root.destroy(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| <canvas data-fit-to-container></canvas> | ||
| <canvas class="w-full h-full"></canvas> |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -34,7 +34,9 @@ let resolutionScale = 0.5; | |||||||
| let [width, height] = [0, 0]; | ||||||||
|
|
||||||||
| function updateDimensions() { | ||||||||
| [width, height] = [canvas.width, canvas.height].map((v) => Math.floor(v * resolutionScale)); | ||||||||
| [width, height] = [canvas.width, canvas.height].map((v) => | ||||||||
| Math.max(1, Math.floor(v * resolutionScale)), | ||||||||
| ); | ||||||||
| } | ||||||||
| updateDimensions(); | ||||||||
|
|
||||||||
|
|
@@ -342,8 +344,6 @@ function recreateResources() { | |||||||
| sourceIdx = 0; | ||||||||
| } | ||||||||
|
|
||||||||
| clearCanvas(); | ||||||||
|
|
||||||||
| function getTouchPosition(rect: DOMRect, touches: TouchList) { | ||||||||
| if (touches.length === 2) { | ||||||||
| return { | ||||||||
|
|
@@ -357,17 +357,17 @@ function getTouchPosition(rect: DOMRect, touches: TouchList) { | |||||||
| }; | ||||||||
| } | ||||||||
|
|
||||||||
| // #region Example controls & Cleanup | ||||||||
|
|
||||||||
| let resizeTimeout: ReturnType<typeof setTimeout>; | ||||||||
| const resizeObserver = new ResizeObserver(() => { | ||||||||
| clearTimeout(resizeTimeout); | ||||||||
| resizeTimeout = setTimeout(() => { | ||||||||
| const autoResizer = common.attachAutoResizer({ | ||||||||
| root, | ||||||||
| canvas, | ||||||||
| onResize() { | ||||||||
|
iwoplaza marked this conversation as resolved.
|
||||||||
| recreateResources(); | ||||||||
| clearCanvas(); | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| }, 100); | ||||||||
| updateBrushSize(); | ||||||||
| }, | ||||||||
| }); | ||||||||
| resizeObserver.observe(canvas); | ||||||||
|
|
||||||||
| // #region Example controls & Cleanup | ||||||||
|
|
||||||||
| const onMouseDown = (e: MouseEvent) => { | ||||||||
| if (e.button !== 0 && e.button !== 2) { | ||||||||
|
|
@@ -475,8 +475,7 @@ export const controls = defineControls({ | |||||||
| }); | ||||||||
|
|
||||||||
| export function onCleanup() { | ||||||||
| clearTimeout(resizeTimeout); | ||||||||
| resizeObserver.disconnect(); | ||||||||
| autoResizer.detach(); | ||||||||
| root.destroy(); | ||||||||
| } | ||||||||
|
|
||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| <canvas data-fit-to-container></canvas> | ||
| <canvas class="w-full h-full"></canvas> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stackblitz examples are now 300x150
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's because
common.attachAutoResizerisn't published yet, and Stackblitz uses the pinned published version of typegpu