1

In WebGPU you can create a render pass by defining its descriptor:

const renderPassDesc: GPURenderPassDescriptor = {
  colorAttachments: [
    {
      view: context.getCurrentTexture().createView(),
      loadValue: [0.2, 0.3, 0.5, 1],
      storeOp: "store"
    }
  ]
};

And then run it through the command encoder and start recording.

const commandEncoder = device.createCommandEncoder();
const renderPass = commandEncoder.beginRenderPass(renderPassDesc);

So, essentially, it appears that you need the current texture to start recording (i.e. without calling context.getCurrentTexture().createView() you can't create the descriptor and without it you can't start the recording). But the API seems to suggest that the texture can change every frame (note that this used to be the case even months ago, when the API was different and you would be retrieving the texture from the swap chain). So, basically, it appears that you can't reuse render passes across different frames (unless of course you don't render to the swap chain, and target an offscreen texture instead).

So, the question is. In WebGPU, can you reuse the same render pass in multiple frames?

Comparison with Vulkan

My question stems from the (little) exposure I had to Vulkan. In Vulkan, you can reuse recorded resources because there is a way to know upfront how many VKImage objects are in the swap chain; they are going to have 0-based indices such as 0, 1 and 2. I can't remember the exact syntax, but I remember that basically you can record 3 separate command buffers, one per VKImage and reuse them across frames. All you have to do is query in the render loop the index of the current VKImage and retrieve the corresponding recorded command buffer.

damix911
  • 4,165
  • 1
  • 29
  • 44
  • 1
    As answered below, a render pass (or more specifically: a GPURenderPassEncoder) cannot be reused. However, if your goal is to execute the same render commands repeatedly without re-encoding them each time you'll want to look at WebGPU's Render Bundles API. It allows you to record most render commands into a resuable object that can be executed as part of a full render pass. – Toji May 09 '23 at 06:28

1 Answers1

1

By seeing the specification about the getCurrentTexture it seems that there is no control over the number of "swap" textures, at this time.

The texture is created (if it is null or it is destroyed) in the "allocate a new context texture" step, as the note there states that:

If a previously presented texture from context matches the required criteria, its GPU memory may be re-used.

Each time on the "update the rendering [of the] Document" step, if the current texture is not null and its not destroyed then it will be presented, destroyed, and set to null.

Another note from the specs:

Developers can expect that the same GPUTexture object will be returned by every call to getCurrentTexture() made within the same frame (i.e. between invocations of Update the rendering) unless configure() is called.

All of this seems to point that you have to get the current texture for each frame and create all related other objects as well.

Nikolay Handzhiyski
  • 1,360
  • 1
  • 6
  • 20
  • Makes sense, thank you. It looks like, under the hood, WebGPU is going to do much more than I anticipated; after reading some Vulkan tutorials I was like "oh wow, that's a lot of bookkeeping that the dev will need to do" and I started to understand why it had to be that way for maximum performance, so I was expecting WebGPU to fully mimic that. But maybe it would be overkill. – damix911 Dec 29 '21 at 22:48
  • 1
    You are welcome. In the previous stages the "swap" textures were defined to be from 1 to 3 (see in https://gpuweb.github.io/gpuweb/explainer/#canvas-output-swap-chains), but that has changed (and so the explainer is not up to date it seems). – Nikolay Handzhiyski Dec 30 '21 at 08:01