mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 13:28:06 +02:00
radv: fix multiple resolves in the same subpass
If there is multiple resolves, the driver shouldn't always select the
fragment path because it doesn't work for all images.
Fixes dEQP-VK.pipeline.monolithic.multisample.misc.*
Cc: 22.3 mesa-stable
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19986>
(cherry picked from commit 22543653d5)
This commit is contained in:
parent
b46d3d7ebb
commit
052a2a47b3
5 changed files with 110 additions and 130 deletions
|
|
@ -3010,7 +3010,7 @@
|
|||
"description": "radv: fix multiple resolves in the same subpass",
|
||||
"nominated": true,
|
||||
"nomination_type": 0,
|
||||
"resolution": 0,
|
||||
"resolution": 1,
|
||||
"main_sha": null,
|
||||
"because_sha": null
|
||||
},
|
||||
|
|
|
|||
|
|
@ -510,10 +510,14 @@ resolve_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image,
|
|||
dst_image_layout, region);
|
||||
break;
|
||||
case RESOLVE_FRAGMENT:
|
||||
radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
|
||||
|
||||
radv_meta_resolve_fragment_image(cmd_buffer, src_image, src_image_layout, dst_image,
|
||||
dst_image_layout, region);
|
||||
break;
|
||||
case RESOLVE_COMPUTE:
|
||||
radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
|
||||
|
||||
radv_meta_resolve_compute_image(cmd_buffer, src_image, src_image->vk.format, src_image_layout,
|
||||
dst_image, dst_image->vk.format, dst_image_layout, region);
|
||||
break;
|
||||
|
|
@ -732,11 +736,28 @@ radv_cmd_buffer_resolve_rendering(struct radv_cmd_buffer *cmd_buffer)
|
|||
}
|
||||
|
||||
if (has_color_resolve) {
|
||||
uint32_t layer_count = render->layer_count;
|
||||
VkRect2D resolve_area = render->area;
|
||||
struct radv_resolve_barrier barrier;
|
||||
|
||||
if (render->view_mask)
|
||||
layer_count = util_last_bit(render->view_mask);
|
||||
|
||||
/* Resolves happen before the end-of-subpass barriers get executed, so we have to make the
|
||||
* attachment shader-readable.
|
||||
*/
|
||||
barrier.src_stage_mask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
barrier.dst_stage_mask = VK_PIPELINE_STAGE_2_RESOLVE_BIT;
|
||||
barrier.src_access_mask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dst_access_mask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT;
|
||||
radv_emit_resolve_barrier(cmd_buffer, &barrier);
|
||||
|
||||
for (uint32_t i = 0; i < render->color_att_count; ++i) {
|
||||
if (render->color_att[i].resolve_iview == NULL)
|
||||
continue;
|
||||
|
||||
struct radv_image_view *src_iview = render->color_att[i].iview;
|
||||
VkImageLayout src_layout = render->color_att[i].layout;
|
||||
struct radv_image *src_img = src_iview->image;
|
||||
struct radv_image_view *dst_iview = render->color_att[i].resolve_iview;
|
||||
VkImageLayout dst_layout = render->color_att[i].resolve_layout;
|
||||
|
|
@ -745,24 +766,50 @@ radv_cmd_buffer_resolve_rendering(struct radv_cmd_buffer *cmd_buffer)
|
|||
radv_pick_resolve_method_images(cmd_buffer->device, src_img, src_iview->vk.format, dst_img,
|
||||
dst_iview->vk.base_mip_level, dst_layout,
|
||||
cmd_buffer, &resolve_method);
|
||||
VkImageResolve2 region = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2,
|
||||
.extent = {
|
||||
.width = resolve_area.extent.width,
|
||||
.height = resolve_area.extent.height,
|
||||
.depth = 1,
|
||||
},
|
||||
.srcSubresource =
|
||||
(VkImageSubresourceLayers){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = src_iview->vk.base_mip_level,
|
||||
.baseArrayLayer = src_iview->vk.base_array_layer,
|
||||
.layerCount = layer_count,
|
||||
},
|
||||
.dstSubresource =
|
||||
(VkImageSubresourceLayers){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = dst_iview->vk.base_mip_level,
|
||||
.baseArrayLayer = dst_iview->vk.base_array_layer,
|
||||
.layerCount = layer_count,
|
||||
},
|
||||
.srcOffset = { resolve_area.offset.x, resolve_area.offset.y, 0 },
|
||||
.dstOffset = { resolve_area.offset.x, resolve_area.offset.y, 0 },
|
||||
};
|
||||
|
||||
if (resolve_method == RESOLVE_FRAGMENT) {
|
||||
switch (resolve_method) {
|
||||
case RESOLVE_HW:
|
||||
radv_cmd_buffer_resolve_rendering_hw(cmd_buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case RESOLVE_COMPUTE:
|
||||
radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, ®ion);
|
||||
|
||||
switch (resolve_method) {
|
||||
case RESOLVE_HW:
|
||||
radv_cmd_buffer_resolve_rendering_hw(cmd_buffer);
|
||||
break;
|
||||
case RESOLVE_COMPUTE:
|
||||
radv_cmd_buffer_resolve_rendering_cs(cmd_buffer);
|
||||
break;
|
||||
case RESOLVE_FRAGMENT:
|
||||
radv_cmd_buffer_resolve_rendering_fs(cmd_buffer);
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid resolve method");
|
||||
radv_cmd_buffer_resolve_rendering_cs(cmd_buffer, src_iview, src_layout, dst_iview,
|
||||
dst_layout, ®ion);
|
||||
break;
|
||||
case RESOLVE_FRAGMENT:
|
||||
radv_decompress_resolve_src(cmd_buffer, src_iview->image, src_layout, ®ion);
|
||||
|
||||
radv_cmd_buffer_resolve_rendering_fs(cmd_buffer, src_iview, src_layout, dst_iview,
|
||||
dst_layout);
|
||||
break;
|
||||
default:
|
||||
unreachable("Invalid resolve method");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -671,8 +671,6 @@ radv_meta_resolve_compute_image(struct radv_cmd_buffer *cmd_buffer, struct radv_
|
|||
{
|
||||
struct radv_meta_saved_state saved_state;
|
||||
|
||||
radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
|
||||
|
||||
/* For partial resolves, DCC should be decompressed before resolving
|
||||
* because the metadata is re-initialized to the uncompressed after.
|
||||
*/
|
||||
|
|
@ -780,68 +778,16 @@ radv_meta_resolve_compute_image(struct radv_cmd_buffer *cmd_buffer, struct radv_
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit any needed resolves for the current subpass.
|
||||
*/
|
||||
void
|
||||
radv_cmd_buffer_resolve_rendering_cs(struct radv_cmd_buffer *cmd_buffer)
|
||||
radv_cmd_buffer_resolve_rendering_cs(struct radv_cmd_buffer *cmd_buffer,
|
||||
struct radv_image_view *src_iview, VkImageLayout src_layout,
|
||||
struct radv_image_view *dst_iview, VkImageLayout dst_layout,
|
||||
const VkImageResolve2 *region)
|
||||
{
|
||||
const struct radv_rendering_state *render = &cmd_buffer->state.render;
|
||||
VkRect2D resolve_area = render->area;
|
||||
struct radv_resolve_barrier barrier;
|
||||
|
||||
uint32_t layer_count = render->layer_count;
|
||||
if (render->view_mask)
|
||||
layer_count = util_last_bit(render->view_mask);
|
||||
|
||||
/* Resolves happen before the end-of-subpass barriers get executed, so
|
||||
* we have to make the attachment shader-readable.
|
||||
*/
|
||||
barrier.src_stage_mask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
barrier.dst_stage_mask = VK_PIPELINE_STAGE_2_RESOLVE_BIT;
|
||||
barrier.src_access_mask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dst_access_mask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT;
|
||||
radv_emit_resolve_barrier(cmd_buffer, &barrier);
|
||||
|
||||
for (uint32_t i = 0; i < render->color_att_count; ++i) {
|
||||
if (render->color_att[i].resolve_iview == NULL)
|
||||
continue;
|
||||
|
||||
struct radv_image_view *src_iview = render->color_att[i].iview;
|
||||
struct radv_image_view *dst_iview = render->color_att[i].resolve_iview;
|
||||
VkImageLayout src_layout = render->color_att[i].layout;
|
||||
VkImageLayout dst_layout = render->color_att[i].resolve_layout;
|
||||
|
||||
VkImageResolve2 region = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2,
|
||||
.extent = {
|
||||
.width = resolve_area.extent.width,
|
||||
.height = resolve_area.extent.height,
|
||||
.depth = 1,
|
||||
},
|
||||
.srcSubresource =
|
||||
(VkImageSubresourceLayers){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = src_iview->vk.base_mip_level,
|
||||
.baseArrayLayer = src_iview->vk.base_array_layer,
|
||||
.layerCount = layer_count,
|
||||
},
|
||||
.dstSubresource =
|
||||
(VkImageSubresourceLayers){
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = dst_iview->vk.base_mip_level,
|
||||
.baseArrayLayer = dst_iview->vk.base_array_layer,
|
||||
.layerCount = layer_count,
|
||||
},
|
||||
.srcOffset = { resolve_area.offset.x, resolve_area.offset.y, 0 },
|
||||
.dstOffset = { resolve_area.offset.x, resolve_area.offset.y, 0 },
|
||||
};
|
||||
|
||||
radv_meta_resolve_compute_image(cmd_buffer,
|
||||
src_iview->image, src_iview->vk.format, src_layout,
|
||||
dst_iview->image, dst_iview->vk.format, dst_layout,
|
||||
®ion);
|
||||
}
|
||||
radv_meta_resolve_compute_image(cmd_buffer,
|
||||
src_iview->image, src_iview->vk.format, src_layout,
|
||||
dst_iview->image, dst_iview->vk.format, dst_layout,
|
||||
region);
|
||||
|
||||
cmd_buffer->state.flush_bits |=
|
||||
RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_INV_VCACHE |
|
||||
|
|
|
|||
|
|
@ -781,8 +781,6 @@ radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, struct radv
|
|||
unsigned dst_layout = radv_meta_dst_layout_from_layout(dest_image_layout);
|
||||
VkImageLayout layout = radv_meta_dst_layout_to_layout(dst_layout);
|
||||
|
||||
radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, region);
|
||||
|
||||
radv_meta_save(
|
||||
&saved_state, cmd_buffer,
|
||||
RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS);
|
||||
|
|
@ -884,72 +882,52 @@ radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, struct radv
|
|||
radv_meta_restore(&saved_state, cmd_buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit any needed resolves for the current rendering.
|
||||
*/
|
||||
void
|
||||
radv_cmd_buffer_resolve_rendering_fs(struct radv_cmd_buffer *cmd_buffer)
|
||||
radv_cmd_buffer_resolve_rendering_fs(struct radv_cmd_buffer *cmd_buffer,
|
||||
struct radv_image_view *src_iview, VkImageLayout src_layout,
|
||||
struct radv_image_view *dst_iview, VkImageLayout dst_layout)
|
||||
{
|
||||
const struct radv_rendering_state *render = &cmd_buffer->state.render;
|
||||
struct radv_meta_saved_state saved_state;
|
||||
struct radv_resolve_barrier barrier;
|
||||
|
||||
/* Resolves happen before rendering ends, so we have to make the attachment shader-readable */
|
||||
barrier.src_stage_mask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
barrier.dst_stage_mask = VK_PIPELINE_STAGE_2_RESOLVE_BIT;
|
||||
barrier.src_access_mask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
barrier.dst_access_mask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT;
|
||||
radv_emit_resolve_barrier(cmd_buffer, &barrier);
|
||||
|
||||
radv_decompress_resolve_rendering_src(cmd_buffer);
|
||||
VkRect2D resolve_area = render->area;
|
||||
|
||||
radv_meta_save(
|
||||
&saved_state, cmd_buffer,
|
||||
RADV_META_SAVE_GRAPHICS_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS |
|
||||
RADV_META_SAVE_RENDER);
|
||||
|
||||
VkRect2D *resolve_area = &saved_state.render.area;
|
||||
|
||||
radv_CmdSetViewport(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1,
|
||||
&(VkViewport){.x = resolve_area->offset.x,
|
||||
.y = resolve_area->offset.y,
|
||||
.width = resolve_area->extent.width,
|
||||
.height = resolve_area->extent.height,
|
||||
&(VkViewport){.x = resolve_area.offset.x,
|
||||
.y = resolve_area.offset.y,
|
||||
.width = resolve_area.extent.width,
|
||||
.height = resolve_area.extent.height,
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f});
|
||||
|
||||
radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, resolve_area);
|
||||
radv_CmdSetScissor(radv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &resolve_area);
|
||||
|
||||
for (uint32_t i = 0; i < saved_state.render.color_att_count; ++i) {
|
||||
if (saved_state.render.color_att[i].resolve_iview == NULL)
|
||||
continue;
|
||||
const VkRenderingAttachmentInfo color_att = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = radv_image_view_to_handle(dst_iview),
|
||||
.imageLayout = dst_layout,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
};
|
||||
|
||||
struct radv_image_view *src_iview = saved_state.render.color_att[i].iview;
|
||||
struct radv_image_view *dst_iview = saved_state.render.color_att[i].resolve_iview;
|
||||
const VkRenderingInfo rendering_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.renderArea = saved_state.render.area,
|
||||
.layerCount = saved_state.render.layer_count,
|
||||
.viewMask = saved_state.render.view_mask,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &color_att,
|
||||
};
|
||||
|
||||
const VkRenderingAttachmentInfo color_att = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = radv_image_view_to_handle(dst_iview),
|
||||
.imageLayout = saved_state.render.color_att[i].resolve_layout,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
};
|
||||
radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
|
||||
|
||||
const VkRenderingInfo rendering_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.renderArea = saved_state.render.area,
|
||||
.layerCount = saved_state.render.layer_count,
|
||||
.viewMask = saved_state.render.view_mask,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &color_att,
|
||||
};
|
||||
emit_resolve(cmd_buffer, src_iview, dst_iview, &resolve_area.offset, &resolve_area.offset);
|
||||
|
||||
radv_CmdBeginRendering(radv_cmd_buffer_to_handle(cmd_buffer), &rendering_info);
|
||||
|
||||
emit_resolve(cmd_buffer, src_iview, dst_iview, &saved_state.render.area.offset,
|
||||
&saved_state.render.area.offset);
|
||||
|
||||
radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
|
||||
}
|
||||
radv_CmdEndRendering(radv_cmd_buffer_to_handle(cmd_buffer));
|
||||
|
||||
radv_meta_restore(&saved_state, cmd_buffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1786,11 +1786,20 @@ void radv_cmd_buffer_clear_attachment(struct radv_cmd_buffer *cmd_buffer,
|
|||
void radv_cmd_buffer_clear_rendering(struct radv_cmd_buffer *cmd_buffer,
|
||||
const VkRenderingInfo *render_info);
|
||||
void radv_cmd_buffer_resolve_rendering(struct radv_cmd_buffer *cmd_buffer);
|
||||
void radv_cmd_buffer_resolve_rendering_cs(struct radv_cmd_buffer *cmd_buffer);
|
||||
void radv_cmd_buffer_resolve_rendering_cs(struct radv_cmd_buffer *cmd_buffer,
|
||||
struct radv_image_view *src_iview,
|
||||
VkImageLayout src_layout,
|
||||
struct radv_image_view *dst_iview,
|
||||
VkImageLayout dst_layout,
|
||||
const VkImageResolve2 *region);
|
||||
void radv_depth_stencil_resolve_rendering_cs(struct radv_cmd_buffer *cmd_buffer,
|
||||
VkImageAspectFlags aspects,
|
||||
VkResolveModeFlagBits resolve_mode);
|
||||
void radv_cmd_buffer_resolve_rendering_fs(struct radv_cmd_buffer *cmd_buffer);
|
||||
void radv_cmd_buffer_resolve_rendering_fs(struct radv_cmd_buffer *cmd_buffer,
|
||||
struct radv_image_view *src_iview,
|
||||
VkImageLayout src_layout,
|
||||
struct radv_image_view *dst_iview,
|
||||
VkImageLayout dst_layout);
|
||||
void radv_depth_stencil_resolve_rendering_fs(struct radv_cmd_buffer *cmd_buffer,
|
||||
VkImageAspectFlags aspects,
|
||||
VkResolveModeFlagBits resolve_mode);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue