X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Famd%2Fvulkan%2Fradv_meta_resolve.c;h=0a03e62f9cbd1ee334ed6123a62ed5705f8e1916;hb=HEAD;hp=7ce36b1df6e9701e5c31af000c0adb8376e2cffa;hpb=fe3f13cc5a8b70dfb27f8b26c059272e251da390;p=mesa.git diff --git a/src/amd/vulkan/radv_meta_resolve.c b/src/amd/vulkan/radv_meta_resolve.c index 7ce36b1df6e..0a03e62f9cb 100644 --- a/src/amd/vulkan/radv_meta_resolve.c +++ b/src/amd/vulkan/radv_meta_resolve.c @@ -97,7 +97,27 @@ create_pass(struct radv_device *device, VkFormat vk_format, VkRenderPass *pass) .preserveAttachmentCount = 0, .pPreserveAttachments = NULL, }, - .dependencyCount = 0, + .dependencyCount = 2, + .pDependencies = (VkSubpassDependency[]) { + { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + .srcAccessMask = 0, + .dstAccessMask = 0, + .dependencyFlags = 0 + }, + { + .srcSubpass = 0, + .dstSubpass = VK_SUBPASS_EXTERNAL, + .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + .srcAccessMask = 0, + .dstAccessMask = 0, + .dependencyFlags = 0 + } + }, }, alloc, pass); @@ -330,9 +350,12 @@ enum radv_resolve_method { RESOLVE_FRAGMENT, }; -static void radv_pick_resolve_method_images(struct radv_image *src_image, +static void radv_pick_resolve_method_images(struct radv_device *device, + struct radv_image *src_image, + VkFormat src_format, struct radv_image *dest_image, VkImageLayout dest_image_layout, + bool dest_render_loop, struct radv_cmd_buffer *cmd_buffer, enum radv_resolve_method *method) @@ -341,19 +364,29 @@ static void radv_pick_resolve_method_images(struct radv_image *src_image, cmd_buffer->queue_family_index, cmd_buffer->queue_family_index); - if (src_image->vk_format == VK_FORMAT_R16G16_UNORM || - src_image->vk_format == VK_FORMAT_R16G16_SNORM) - *method = RESOLVE_COMPUTE; - else if (vk_format_is_int(src_image->vk_format)) - *method = RESOLVE_COMPUTE; - else if (src_image->info.array_size > 1 || - dest_image->info.array_size > 1) - *method = RESOLVE_COMPUTE; + if (vk_format_is_color(src_format)) { + if (src_format == VK_FORMAT_R16G16_UNORM || + src_format == VK_FORMAT_R16G16_SNORM) + *method = RESOLVE_COMPUTE; + else if (vk_format_is_int(src_format)) + *method = RESOLVE_COMPUTE; + else if (src_image->info.array_size > 1 || + dest_image->info.array_size > 1) + *method = RESOLVE_COMPUTE; - if (radv_layout_dcc_compressed(dest_image, dest_image_layout, queue_mask)) { - *method = RESOLVE_FRAGMENT; - } else if (dest_image->surface.micro_tile_mode != src_image->surface.micro_tile_mode) { - *method = RESOLVE_COMPUTE; + if (radv_layout_dcc_compressed(device, dest_image, dest_image_layout, + dest_render_loop, queue_mask)) { + *method = RESOLVE_FRAGMENT; + } else if (dest_image->planes[0].surface.micro_tile_mode != + src_image->planes[0].surface.micro_tile_mode) { + *method = RESOLVE_COMPUTE; + } + } else { + if (src_image->info.array_size > 1 || + dest_image->info.array_size > 1) + *method = RESOLVE_COMPUTE; + else + *method = RESOLVE_FRAGMENT; } } @@ -421,8 +454,9 @@ void radv_CmdResolveImage( } else resolve_method = RESOLVE_COMPUTE; - radv_pick_resolve_method_images(src_image, dest_image, - dest_image_layout, cmd_buffer, + radv_pick_resolve_method_images(cmd_buffer->device, src_image, + src_image->vk_format, dest_image, + dest_image_layout, false, cmd_buffer, &resolve_method); if (resolve_method == RESOLVE_FRAGMENT) { @@ -438,8 +472,10 @@ void radv_CmdResolveImage( if (resolve_method == RESOLVE_COMPUTE) { radv_meta_resolve_compute_image(cmd_buffer, src_image, + src_image->vk_format, src_image_layout, dest_image, + dest_image->vk_format, dest_image_layout, region_count, regions); return; @@ -456,20 +492,9 @@ void radv_CmdResolveImage( } assert(dest_image->info.samples == 1); - if (src_image->info.samples >= 16) { - /* See commit aa3f9aaf31e9056a255f9e0472ebdfdaa60abe54 for the - * glBlitFramebuffer workaround for samples >= 16. - */ - radv_finishme("vkCmdResolveImage: need interpolation workaround when " - "samples >= 16"); - } - if (src_image->info.array_size > 1) radv_finishme("vkCmdResolveImage: multisample array images"); - if (radv_image_has_dcc(dest_image)) { - radv_initialize_dcc(cmd_buffer, dest_image, 0xffffffff); - } unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format); for (uint32_t r = 0; r < region_count; ++r) { const VkImageResolve *region = ®ions[r]; @@ -513,6 +538,17 @@ void radv_CmdResolveImage( const struct VkOffset3D dstOffset = radv_sanitize_image_offset(dest_image->type, region->dstOffset); + if (radv_dcc_enabled(dest_image, region->dstSubresource.mipLevel)) { + VkImageSubresourceRange range = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = region->dstSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = dest_base_layer, + .layerCount = region->dstSubresource.layerCount, + }; + + radv_initialize_dcc(cmd_buffer, dest_image, &range, 0xffffffff); + } for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; ++layer) { @@ -537,7 +573,7 @@ void radv_CmdResolveImage( .baseArrayLayer = src_base_layer + layer, .layerCount = 1, }, - }); + }, NULL); struct radv_image_view dest_iview; radv_image_view_init(&dest_iview, cmd_buffer->device, @@ -553,7 +589,7 @@ void radv_CmdResolveImage( .baseArrayLayer = dest_base_layer + layer, .layerCount = 1, }, - }); + }, NULL); VkFramebuffer fb_h; radv_CreateFramebuffer(device_h, @@ -573,25 +609,27 @@ void radv_CmdResolveImage( &cmd_buffer->pool->alloc, &fb_h); - radv_CmdBeginRenderPass(cmd_buffer_h, - &(VkRenderPassBeginInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = device->meta_state.resolve.pass[fs_key], - .framebuffer = fb_h, - .renderArea = { - .offset = { - dstOffset.x, - dstOffset.y, - }, - .extent = { - extent.width, - extent.height, + radv_cmd_buffer_begin_render_pass(cmd_buffer, + &(VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = device->meta_state.resolve.pass[fs_key], + .framebuffer = fb_h, + .renderArea = { + .offset = { + dstOffset.x, + dstOffset.y, + }, + .extent = { + extent.width, + extent.height, } - }, - .clearValueCount = 0, - .pClearValues = NULL, - }, - VK_SUBPASS_CONTENTS_INLINE); + }, + .clearValueCount = 0, + .pClearValues = NULL, + }); + + radv_cmd_buffer_set_subpass(cmd_buffer, + &cmd_buffer->state.pass->subpasses[0]); emit_resolve(cmd_buffer, dest_iview.vk_format, @@ -604,7 +642,7 @@ void radv_CmdResolveImage( .height = extent.height, }); - radv_CmdEndRenderPass(cmd_buffer_h); + radv_cmd_buffer_end_render_pass(cmd_buffer); radv_DestroyFramebuffer(device_h, fb_h, &cmd_buffer->pool->alloc); @@ -625,30 +663,78 @@ radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer) struct radv_meta_saved_state saved_state; enum radv_resolve_method resolve_method = RESOLVE_HW; - /* FINISHME(perf): Skip clears for resolve attachments. - * - * From the Vulkan 1.0 spec: - * - * If the first use of an attachment in a render pass is as a resolve - * attachment, then the loadOp is effectively ignored as the resolve is - * guaranteed to overwrite all pixels in the render area. - */ + if (subpass->ds_resolve_attachment) { + struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment; + struct radv_subpass_attachment dst_att = *subpass->ds_resolve_attachment; + struct radv_image_view *src_iview = + cmd_buffer->state.attachments[src_att.attachment].iview; + struct radv_image_view *dst_iview = + cmd_buffer->state.attachments[dst_att.attachment].iview; + + /* Make sure to not clear the depth/stencil attachment after resolves. */ + cmd_buffer->state.attachments[dst_att.attachment].pending_clear_aspects = 0; + + radv_pick_resolve_method_images(cmd_buffer->device, + src_iview->image, + src_iview->vk_format, + dst_iview->image, + dst_att.layout, + dst_att.in_render_loop, + cmd_buffer, + &resolve_method); + + if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) && + subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) { + if (resolve_method == RESOLVE_FRAGMENT) { + radv_depth_stencil_resolve_subpass_fs(cmd_buffer, + VK_IMAGE_ASPECT_DEPTH_BIT, + subpass->depth_resolve_mode); + } else { + assert(resolve_method == RESOLVE_COMPUTE); + radv_depth_stencil_resolve_subpass_cs(cmd_buffer, + VK_IMAGE_ASPECT_DEPTH_BIT, + subpass->depth_resolve_mode); + } + } + + if ((src_iview->aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) && + subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) { + if (resolve_method == RESOLVE_FRAGMENT) { + radv_depth_stencil_resolve_subpass_fs(cmd_buffer, + VK_IMAGE_ASPECT_STENCIL_BIT, + subpass->stencil_resolve_mode); + } else { + assert(resolve_method == RESOLVE_COMPUTE); + radv_depth_stencil_resolve_subpass_cs(cmd_buffer, + VK_IMAGE_ASPECT_STENCIL_BIT, + subpass->stencil_resolve_mode); + } + } + } - if (!subpass->has_resolve) + if (!subpass->has_color_resolve) return; for (uint32_t i = 0; i < subpass->color_count; ++i) { struct radv_subpass_attachment src_att = subpass->color_attachments[i]; struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; - if (src_att.attachment == VK_ATTACHMENT_UNUSED || - dest_att.attachment == VK_ATTACHMENT_UNUSED) + if (dest_att.attachment == VK_ATTACHMENT_UNUSED) continue; - struct radv_image *dst_img = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment->image; - struct radv_image *src_img = cmd_buffer->state.framebuffer->attachments[src_att.attachment].attachment->image; + /* Make sure to not clear color attachments after resolves. */ + cmd_buffer->state.attachments[dest_att.attachment].pending_clear_aspects = 0; + + struct radv_image *dst_img = cmd_buffer->state.attachments[dest_att.attachment].iview->image; + struct radv_image_view *src_iview= cmd_buffer->state.attachments[src_att.attachment].iview; + struct radv_image *src_img = src_iview->image; + + radv_pick_resolve_method_images(cmd_buffer->device, src_img, + src_iview->vk_format, dst_img, + dest_att.layout, + dest_att.in_render_loop, + cmd_buffer, &resolve_method); - radv_pick_resolve_method_images(src_img, dst_img, dest_att.layout, cmd_buffer, &resolve_method); if (resolve_method == RESOLVE_FRAGMENT) { break; } @@ -669,38 +755,47 @@ radv_cmd_buffer_resolve_subpass(struct radv_cmd_buffer *cmd_buffer) struct radv_subpass_attachment src_att = subpass->color_attachments[i]; struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; - if (src_att.attachment == VK_ATTACHMENT_UNUSED || - dest_att.attachment == VK_ATTACHMENT_UNUSED) + if (dest_att.attachment == VK_ATTACHMENT_UNUSED) continue; - struct radv_image *dst_img = cmd_buffer->state.framebuffer->attachments[dest_att.attachment].attachment->image; + struct radv_image_view *dest_iview = cmd_buffer->state.attachments[dest_att.attachment].iview; + struct radv_image *dst_img = dest_iview->image; - if (radv_image_has_dcc(dst_img)) { - radv_initialize_dcc(cmd_buffer, dst_img, 0xffffffff); + if (radv_dcc_enabled(dst_img, dest_iview->base_mip)) { + VkImageSubresourceRange range = { + .aspectMask = dest_iview->aspect_mask, + .baseMipLevel = dest_iview->base_mip, + .levelCount = dest_iview->level_count, + .baseArrayLayer = dest_iview->base_layer, + .layerCount = dest_iview->layer_count, + }; + + radv_initialize_dcc(cmd_buffer, dst_img, &range, 0xffffffff); cmd_buffer->state.attachments[dest_att.attachment].current_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } struct radv_subpass resolve_subpass = { .color_count = 2, .color_attachments = (struct radv_subpass_attachment[]) { src_att, dest_att }, - .depth_stencil_attachment = { .attachment = VK_ATTACHMENT_UNUSED }, + .depth_stencil_attachment = NULL, }; - radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass, false); + radv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass); - VkResult ret = build_resolve_pipeline(cmd_buffer->device, radv_format_meta_fs_key(dst_img->vk_format)); + VkResult ret = build_resolve_pipeline(cmd_buffer->device, radv_format_meta_fs_key(dest_iview->vk_format)); if (ret != VK_SUCCESS) { cmd_buffer->record_result = ret; continue; } emit_resolve(cmd_buffer, - dst_img->vk_format, + dest_iview->vk_format, &(VkOffset2D) { 0, 0 }, &(VkExtent2D) { fb->width, fb->height }); } - cmd_buffer->state.subpass = subpass; + radv_cmd_buffer_set_subpass(cmd_buffer, subpass); + radv_meta_restore(&saved_state, cmd_buffer); } @@ -713,28 +808,61 @@ radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer) { const struct radv_subpass *subpass = cmd_buffer->state.subpass; struct radv_framebuffer *fb = cmd_buffer->state.framebuffer; + uint32_t layer_count = fb->layers; + + if (subpass->view_mask) + layer_count = util_last_bit(subpass->view_mask); for (uint32_t i = 0; i < subpass->color_count; ++i) { struct radv_subpass_attachment src_att = subpass->color_attachments[i]; struct radv_subpass_attachment dest_att = subpass->resolve_attachments[i]; - if (src_att.attachment == VK_ATTACHMENT_UNUSED || - dest_att.attachment == VK_ATTACHMENT_UNUSED) + if (dest_att.attachment == VK_ATTACHMENT_UNUSED) continue; - struct radv_image *src_image = - fb->attachments[src_att.attachment].attachment->image; + struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; + struct radv_image *src_image = src_iview->image; + + VkImageResolve region = {}; + region.srcSubresource.aspectMask = src_iview->aspect_mask; + region.srcSubresource.mipLevel = 0; + region.srcSubresource.baseArrayLayer = src_iview->base_layer; + region.srcSubresource.layerCount = layer_count; + + radv_decompress_resolve_src(cmd_buffer, src_image, + src_att.layout, 1, ®ion); + } + + if (subpass->ds_resolve_attachment) { + struct radv_subpass_attachment src_att = *subpass->depth_stencil_attachment; + struct radv_image_view *src_iview = fb->attachments[src_att.attachment]; + struct radv_image *src_image = src_iview->image; VkImageResolve region = {}; - region.srcSubresource.baseArrayLayer = 0; + region.srcSubresource.aspectMask = src_iview->aspect_mask; region.srcSubresource.mipLevel = 0; - region.srcSubresource.layerCount = src_image->info.array_size; + region.srcSubresource.baseArrayLayer = src_iview->base_layer; + region.srcSubresource.layerCount = layer_count; radv_decompress_resolve_src(cmd_buffer, src_image, src_att.layout, 1, ®ion); } } +static struct radv_sample_locations_state * +radv_get_resolve_sample_locations(struct radv_cmd_buffer *cmd_buffer) +{ + struct radv_cmd_state *state = &cmd_buffer->state; + uint32_t subpass_id = radv_get_subpass_id(cmd_buffer); + + for (uint32_t i = 0; i < state->num_subpass_sample_locs; i++) { + if (state->subpass_sample_locs[i].subpass_idx == subpass_id) + return &state->subpass_sample_locs[i].sample_location; + } + + return NULL; +} + /** * Decompress CMask/FMask before resolving a multisampled source image. */ @@ -750,24 +878,40 @@ radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, const uint32_t src_base_layer = radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, ®ion->srcOffset); - VkImageSubresourceRange range; - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - range.baseMipLevel = region->srcSubresource.mipLevel; - range.levelCount = 1; - range.baseArrayLayer = src_base_layer; - range.layerCount = region->srcSubresource.layerCount; - - uint32_t queue_mask = - radv_image_queue_family_mask(src_image, - cmd_buffer->queue_family_index, - cmd_buffer->queue_family_index); - - if (radv_layout_dcc_compressed(src_image, src_image_layout, - queue_mask)) { - radv_decompress_dcc(cmd_buffer, src_image, &range); - } else { - radv_fast_clear_flush_image_inplace(cmd_buffer, - src_image, &range); + + VkImageMemoryBarrier barrier = {}; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.oldLayout = src_image_layout; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.image = radv_image_to_handle(src_image); + barrier.subresourceRange = (VkImageSubresourceRange) { + .aspectMask = region->srcSubresource.aspectMask, + .baseMipLevel = region->srcSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = src_base_layer, + .layerCount = region->srcSubresource.layerCount, + }; + + if (src_image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) { + /* If the depth/stencil image uses different sample + * locations, we need them during HTILE decompressions. + */ + struct radv_sample_locations_state *sample_locs = + radv_get_resolve_sample_locations(cmd_buffer); + + barrier.pNext = &(VkSampleLocationsInfoEXT) { + .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, + .sampleLocationsPerPixel = sample_locs->per_pixel, + .sampleLocationGridSize = sample_locs->grid_size, + .sampleLocationsCount = sample_locs->count, + .pSampleLocations = sample_locs->locations, + }; } + + radv_CmdPipelineBarrier(radv_cmd_buffer_to_handle(cmd_buffer), + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + false, 0, NULL, 0, NULL, 1, &barrier); } }