playcanvas / playcanvas/engine

Improve MRT support

Open
#5,356 0 comments 0 reactions 1 assignee View on GitHub

@mvaligursky is already working on this.

Since May 30, 2023.

area: graphics enhancement
Dominant language
JavaScript
Stars
16.8k
Forks
2k
Avg merge
4h 32m
Merged PRs (30d)
222

Description

Issue for initial implementation of MRT: https://github.com/playcanvas/engine/issues/4230

Possible improvements:

  • Per-attachment clear colors and clear flags on the render pass. RenderPass#setClearColor accepts an optional attachment index, and WebGL clears the color attachments individually using clearBufferfv, applying their own clear colors and clear flags. Previously a single gl.clear applied attachment 0's clear color to all attachments, and ignored the per-attachment clear flags. Done in #9142.
  • Per-attachment blend state and color write mask. BlendState#setAttachment gives an individual color attachment its own blend state and write mask - supported natively on WebGPU, and using the OES_draw_buffers_indexed extension on WebGL2, with GraphicsDevice#supportsIndependentBlending reporting the support. Done in #9140.
  • Expand the API on the camera to specify the clear color per color attachment, and use those with MRT. CameraComponent#setClearColor(index, color) / getClearColor(index) give each color attachment of the camera's render target its own clear color, applied by the forward render pass at the pass start. Attachment 0 is clearColor, and the other attachments clear to it until given their own. Done in #9333.
  • Attachment-aware mid-render-pass clears. Renderer#clear -> GraphicsDevice#clear is the single path for a clear which happens during a render pass (a camera whose rect / scissorRect does not cover the render target, or a layer with clearColorBuffer which is not the first one rendering to the target), and it ignores the per-attachment clear colors of #9333: WebGL applies the attachment 0 color to every attachment via gl.clear (undefined for integer formats), and WebGPU fails outright - WebgpuClearRenderer draws with a single @location(0) output while every target has an all-channel write mask, which Dawn rejects (Color target has no corresponding fragment stage output but writeMask is not zero), so any mid-pass clear into an MRT target is a validation error today, independently of the new API. Plan: an additive per-attachment colors option plus an attachment enable mask on GraphicsDevice#clear (the existing color keeps meaning all attachments), filled by Renderer#clear from Camera#getClearColor(i). WebGL: lift the clearBufferfv/iv/uiv loop of startRenderPass into a helper shared with clear() - the scissor test is always enabled and clearBuffer* honours it, so the viewport-scoped semantics are preserved, and integer formats come for free. WebGPU: generate clear shader variants keyed by the attachment format classes (float / sint / uint) with a typed output at every location (Dawn requires an output wherever the write mask is non-zero, with a matching base type - a null target is not an option, as the pass still has the attachment), carry the colors as a vec4u bit-pattern array in the uniform buffer (written through the Int32 storage view) with a bitcast per output, and select the cleared attachments with a per-attachment BlendState (setAttachment NOBLEND / NOWRITE). The enable mask also lets RenderPassForward clear only the attachment 0 in the scene-textures passes, removing the debug assert which currently forbids in-pass clears there. Verification: the multi-render-targets example with the texture camera's rect set to (0.1, 0.1, 0.8, 0.8) should show each attachment's own clear color in the border on both backends, with no WebGPU errors.
  • Expand the layer clear color flag to be per color attachment. Depends on the attachment-aware mid-pass clear above, which provides the per-attachment colors and the attachment enable mask on GraphicsDevice#clear; on top of it this is the public API only: a per-attachment mask for Layer#clearColorBuffer and Camera#clearColorBuffer, composed by RenderAction#setupClears in place of the booleans on RenderAction / LayerRenderStep.
  • Clearing of integer format color attachments at the render pass start (clearBufferiv / clearBufferuiv on WebGL - WebGPU supports this natively via clearValue), which would also allow the Picker to use a uint32 format instead of encoding the id into RGBA8. Note the picker migration additionally needs uint fragment outputs for the pick shader variants. Mid-render-pass integer clears (layers) are excluded - on WebGPU the clear shader would need integer output variants, and nothing currently needs it. Done in #9143.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.