Skip to content

[v11] Verify View: per-view scissor and render loop on WebGPU #2821

Description

@DennisSmolek

What it does

src/core/Portal/View/View.tsx:178-212 renders once per view, each into its own scissored region of the canvas:

const autoClear = prepareSkissor(renderer, targetCamera, position)
if (targetScene.background) {
  if (targetScene.background instanceof THREE.Color) renderer.setClearColor(targetScene.background, 1)
  renderer.clear(true, true)
}
renderer.render(targetScene, targetCamera)
finishSkissor(renderer, autoClear)

What to check

  • prepareSkissor / finishSkissor set scissor, viewport and autoClear around each render. Those members all exist on the WebGPU Renderer, but scissor state on WebGPU belongs to the render-pass descriptor rather than being global GL state — whether it applies to the next render() call the same way needs verifying.
  • renderer.clear(true, true) called mid-frame, between other views' renders.
  • N views means N render() calls per frame, each scheduled { after: 'render', priority: index }. Command-encoder batching on WebGPU may not preserve the ordering this depends on.

View is one of the most-used components in the library, so this deserves more care than its line count suggests.


Shared context (identical across all seven)

These components are classified agnostic — they live in core/, so they are assumed to work on both renderers. That assumption held for 104 of the 106 agnostic components when swept: 73 never touch the renderer at all, and 31 touch only members both renderers have. These seven are different: they drive their own render calls, and that is where semantics diverge even when the API surface matches. See #2818.

setRenderTarget(renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) has an identical signature on both (Renderer.js:2578 vs WebGLRenderer.js:2890), so that part is fine.

render() is where they differ — three/src/renderers/common/Renderer.js:1362:

render( scene, camera ) {
  if ( this._initialized === false ) {
    throw new Error( 'THREE.Renderer: .render() called before the backend is initialized. Use "await renderer.init();" before rendering.' );
  }
  this._renderScene( scene, camera );
}

WebGL has no such gate. A render() that happens before the backend is ready throws on WebGPU and silently works on WebGL.

This is the class of bug that produced #2809: Preload calls gl.compile(), which on WebGPU is a getter aliasing compileAsync — same name, returns an unawaited promise, so preloading never happens. Grep cannot find these; they need reading.

Acceptance

Read the component against the WebGPU Renderer implementation and either confirm it is correct or fix it and say what was wrong. A story exercising the render path on WebGPU is the evidence — note Setup sets frameloop: 'never' under test, so useFrame does not run there and a green story proves nothing about this.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    v11For v11 related taskswebgpuWebGPU Related issue

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions