v3dv: ignore stencil load operation if attachment format doesn't have stencil

This gets vkQuake to render correctly, which creates render passes with
stencil load operations even when the depth/stencil attachment format
doesn't have a stencil aspect. While this is a bit weird, it seems to
be allowed by the spec:

   "If the format has depth and/or stencil components, loadOp and storeOp
    apply only to the depth data, while stencilLoadOp and stencilStoreOp
    define how the stencil data is handled."

In our case we were not ignoring it and this was causing that we emitted a
Z buffer load that seemed to clobber the Z clear, preventing all draw calls
from passing the depth test.

While we are at it, also change the depth/stencil store operation (which
was already handling this scenario correctly) to use the format of the
render pass attachment description rather than the underlying image
format.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Iago Toral Quiroga 2020-07-10 09:50:57 +02:00 committed by Marge Bot
parent 1e1903fc1b
commit add8778638
2 changed files with 35 additions and 11 deletions

View File

@ -1460,14 +1460,22 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer,
&state->pass->attachments[ds_attachment_idx];
assert(state->job->first_subpass >= ds_attachment->first_subpass);
bool needs_load =
const bool might_need_load =
state->job->first_subpass > ds_attachment->first_subpass ||
state->job->is_subpass_continue ||
ds_attachment->desc.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
ds_attachment->desc.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
!state->tile_aligned_render_area;
if (needs_load) {
const bool needs_depth_load =
vk_format_has_depth(ds_attachment->desc.format) &&
(ds_attachment->desc.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
might_need_load);
const bool needs_stencil_load =
vk_format_has_stencil(ds_attachment->desc.format) &&
(ds_attachment->desc.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
might_need_load);
if (needs_depth_load || needs_stencil_load) {
struct v3dv_image_view *iview =
framebuffer->attachments[ds_attachment_idx];
/* From the Vulkan spec:
@ -1475,9 +1483,13 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer,
* "When an image view of a depth/stencil image is used as a
* depth/stencil framebuffer attachment, the aspectMask is ignored
* and both depth and stencil image subresources are used."
*
* So we ignore the aspects from the subresource range of the image
* view for the depth/stencil attachment, but we still need to restrict
* the to aspects compatible with the render pass and the image.
*/
const uint32_t zs_buffer =
v3dv_zs_buffer_from_vk_format(iview->image->vk_format);
v3dv_zs_buffer(needs_depth_load, needs_stencil_load);
cmd_buffer_render_pass_emit_load(cmd_buffer, cl,
iview, layer, zs_buffer);
}
@ -1554,9 +1566,9 @@ cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,
* depth/stencil framebuffer attachment, the aspectMask is ignored
* and both depth and stencil image subresources are used."
*
* So we ignore the aspects from the subresource range of the image view
* for the depth/stencil attachment, but we still need to restrict this
* to aspects that actually exist in the image.
* So we ignore the aspects from the subresource range of the image
* view for the depth/stencil attachment, but we still need to restrict
* the to aspects compatible with the render pass and the image.
*/
const VkImageAspectFlags aspects =
vk_format_aspects(ds_attachment->desc.format);
@ -1606,9 +1618,9 @@ cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,
* correctly.
*/
use_per_buffer_clear = !needs_stencil_clear && !needs_depth_clear;
bool needs_ds_store = needs_stencil_store || needs_depth_store;
if (needs_ds_store) {
uint32_t zs_buffer = v3dv_zs_buffer_from_aspect_bits(aspects);
if (needs_depth_store || needs_stencil_store) {
const uint32_t zs_buffer =
v3dv_zs_buffer(needs_depth_store, needs_stencil_store);
cmd_buffer_render_pass_emit_store(cmd_buffer, cl,
ds_attachment_idx, layer,
zs_buffer, false);

View File

@ -1593,6 +1593,18 @@ v3dv_zs_buffer_from_vk_format(VkFormat format)
}
}
static inline uint32_t
v3dv_zs_buffer(bool depth, bool stencil)
{
if (depth && stencil)
return ZSTENCIL;
else if (depth)
return Z;
else if (stencil)
return STENCIL;
return NONE;
}
uint32_t v3dv_physical_device_api_version(struct v3dv_physical_device *dev);
int v3dv_get_instance_entrypoint_index(const char *name);