Hash :
c55cd6b4
Author :
Date :
2020-10-14T23:06:27
Vulkan: Remove dead path in clear If the clear is not mid render pass, clearWithLoadOp was used to either: - modify the current render pass loadOps, assuming no rendering has been done, or - defer the clears by staging them in the attachment images. The former path however is dead code. It's impossible to start the render pass without recording any commands. In other words, if the render pass has already started, the clear must be mid RP. Bug: angleproject:4836 Change-Id: Idb1cb37b8a0e56b897ac69cf435f9a52be4bd2f4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2473764 Reviewed-by: Charlie Lao <cclao@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Take the following scenario:
Steps 2 and 3 each require a render pass for rendering. The clear in step 1 can potentially be done
through loadOp of the render pass for step 3, assuming step 2 doesn’t use the attachments of FBO1.
This optimization is achieved in ANGLE by deferring clears.
When a clear is issued, one of the following happens:
vkCmdClearAttachments)
Deferring a clear is done by staging a Clear update in the vk::ImageHelper corresponding to the
attachment being cleared.
There are two possibilities at this point:
vk::ImageHelper is used in any way other than as a framebuffer attachment (for example it’s
sampled from), or
In scenario 1, the staged updates in the vk::ImageHelper are flushed. That includes the Clear
updates which will be done with an out-of-render-pass vkCmdClear*Image call.
In scenario 2, FramebufferVk::syncState is responsible for extracting the staged Clear updates,
assuming there are no subsequent updates to that subresource of the image, and keep them as
deferred clears. The FramebufferVk call that immediately follows must handle these clears one
way or another. In most cases, this implies starting a new render pass and using loadOps to
perform the clear before the actual operation in that function is performed. This also implies that
the front-end must always follow a syncState call with another call (and for example cannot decide
to no-op the call in between).
If the subsequent call itself is a clear operation, there could be further optimizations. In particular, the previously deferred clears and can be overridden by and/or re-deferred along with the new clears.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
# Deferred Clears
Take the following scenario:
1. Application binds and clears FBO1
2. Application binds FBO2 and renders to it
3. Application binds FBO1 again and renders to it
Steps 2 and 3 each require a render pass for rendering. The clear in step 1 can potentially be done
through `loadOp` of the render pass for step 3, assuming step 2 doesn't use the attachments of FBO1.
This optimization is achieved in ANGLE by deferring clears.
When a clear is issued, one of the following happens:
- If a render pass is already open, the framebuffer is cleared inline (using
`vkCmdClearAttachments`)
- If the clear is not to the whole attachment (i.e. is scissored, or masked), a draw call is used to
perform the clear.
- Otherwise the clear is deferred.
Deferring a clear is done by staging a `Clear` update in the `vk::ImageHelper` corresponding to the
attachment being cleared.
There are two possibilities at this point:
1. The `vk::ImageHelper` is used in any way other than as a framebuffer attachment (for example it's
sampled from), or
2. It's used as a framebuffer attachment and rendering is done.
In scenario 1, the staged updates in the `vk::ImageHelper` are flushed. That includes the `Clear`
updates which will be done with an out-of-render-pass `vkCmdClear*Image` call.
In scenario 2, `FramebufferVk::syncState` is responsible for extracting the staged `Clear` updates,
assuming there are no subsequent updates to that subresource of the image, and keep them as
_deferred clears_. The `FramebufferVk` call that immediately follows must handle these clears one
way or another. In most cases, this implies starting a new render pass and using `loadOp`s to
perform the clear before the actual operation in that function is performed. This also implies that
the front-end must always follow a `syncState` call with another call (and for example cannot decide
to no-op the call in between).
If the subsequent call itself is a clear operation, there could be further optimizations. In
particular, the previously deferred clears and can be overridden by and/or re-deferred along with
the new clears.