radv: cleanup selecting the hardware resolve path
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6813>
This commit is contained in:

committed by
Marge Bot

parent
fe819710ad
commit
9a700af65c
@@ -420,6 +420,185 @@ fail:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer,
|
||||||
|
struct radv_image *src_image,
|
||||||
|
VkImageLayout src_image_layout,
|
||||||
|
struct radv_image *dst_image,
|
||||||
|
VkImageLayout dst_image_layout,
|
||||||
|
const VkImageResolve *region)
|
||||||
|
{
|
||||||
|
struct radv_device *device = cmd_buffer->device;
|
||||||
|
struct radv_meta_saved_state saved_state;
|
||||||
|
|
||||||
|
radv_meta_save(&saved_state, cmd_buffer,
|
||||||
|
RADV_META_SAVE_GRAPHICS_PIPELINE);
|
||||||
|
|
||||||
|
assert(src_image->info.samples > 1);
|
||||||
|
if (src_image->info.samples <= 1) {
|
||||||
|
/* this causes GPU hangs if we get past here */
|
||||||
|
fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(dst_image->info.samples == 1);
|
||||||
|
|
||||||
|
if (src_image->info.array_size > 1)
|
||||||
|
radv_finishme("vkCmdResolveImage: multisample array images");
|
||||||
|
|
||||||
|
unsigned fs_key = radv_format_meta_fs_key(dst_image->vk_format);
|
||||||
|
|
||||||
|
/* From the Vulkan 1.0 spec:
|
||||||
|
*
|
||||||
|
* - The aspectMask member of srcSubresource and dstSubresource must
|
||||||
|
* only contain VK_IMAGE_ASPECT_COLOR_BIT
|
||||||
|
*
|
||||||
|
* - The layerCount member of srcSubresource and dstSubresource must
|
||||||
|
* match
|
||||||
|
*/
|
||||||
|
assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
assert(region->srcSubresource.layerCount ==
|
||||||
|
region->dstSubresource.layerCount);
|
||||||
|
|
||||||
|
const uint32_t src_base_layer =
|
||||||
|
radv_meta_get_iview_layer(src_image, ®ion->srcSubresource,
|
||||||
|
®ion->srcOffset);
|
||||||
|
|
||||||
|
const uint32_t dst_base_layer =
|
||||||
|
radv_meta_get_iview_layer(dst_image, ®ion->dstSubresource,
|
||||||
|
®ion->dstOffset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
|
||||||
|
*
|
||||||
|
* extent is the size in texels of the source image to resolve in width,
|
||||||
|
* height and depth. 1D images use only x and width. 2D images use x, y,
|
||||||
|
* width and height. 3D images use x, y, z, width, height and depth.
|
||||||
|
*
|
||||||
|
* srcOffset and dstOffset select the initial x, y, and z offsets in
|
||||||
|
* texels of the sub-regions of the source and destination image data.
|
||||||
|
* extent is the size in texels of the source image to resolve in width,
|
||||||
|
* height and depth. 1D images use only x and width. 2D images use x, y,
|
||||||
|
* width and height. 3D images use x, y, z, width, height and depth.
|
||||||
|
*/
|
||||||
|
const struct VkExtent3D extent =
|
||||||
|
radv_sanitize_image_extent(src_image->type, region->extent);
|
||||||
|
const struct VkOffset3D dstOffset =
|
||||||
|
radv_sanitize_image_offset(dst_image->type, region->dstOffset);
|
||||||
|
|
||||||
|
if (radv_dcc_enabled(dst_image, region->dstSubresource.mipLevel)) {
|
||||||
|
VkImageSubresourceRange range = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = region->dstSubresource.mipLevel,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = dst_base_layer,
|
||||||
|
.layerCount = region->dstSubresource.layerCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
radv_initialize_dcc(cmd_buffer, dst_image, &range, 0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
|
||||||
|
++layer) {
|
||||||
|
|
||||||
|
VkResult ret = build_resolve_pipeline(device, fs_key);
|
||||||
|
if (ret != VK_SUCCESS) {
|
||||||
|
cmd_buffer->record_result = ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct radv_image_view src_iview;
|
||||||
|
radv_image_view_init(&src_iview, cmd_buffer->device,
|
||||||
|
&(VkImageViewCreateInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
|
.image = radv_image_to_handle(src_image),
|
||||||
|
.viewType = radv_meta_get_view_type(src_image),
|
||||||
|
.format = src_image->vk_format,
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = region->srcSubresource.mipLevel,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = src_base_layer + layer,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
}, NULL);
|
||||||
|
|
||||||
|
struct radv_image_view dst_iview;
|
||||||
|
radv_image_view_init(&dst_iview, cmd_buffer->device,
|
||||||
|
&(VkImageViewCreateInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
|
.image = radv_image_to_handle(dst_image),
|
||||||
|
.viewType = radv_meta_get_view_type(dst_image),
|
||||||
|
.format = dst_image->vk_format,
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = region->dstSubresource.mipLevel,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = dst_base_layer + layer,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
}, NULL);
|
||||||
|
|
||||||
|
VkFramebuffer fb_h;
|
||||||
|
radv_CreateFramebuffer(radv_device_to_handle(device),
|
||||||
|
&(VkFramebufferCreateInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
|
.attachmentCount = 2,
|
||||||
|
.pAttachments = (VkImageView[]) {
|
||||||
|
radv_image_view_to_handle(&src_iview),
|
||||||
|
radv_image_view_to_handle(&dst_iview),
|
||||||
|
},
|
||||||
|
.width = radv_minify(dst_image->info.width,
|
||||||
|
region->dstSubresource.mipLevel),
|
||||||
|
.height = radv_minify(dst_image->info.height,
|
||||||
|
region->dstSubresource.mipLevel),
|
||||||
|
.layers = 1
|
||||||
|
},
|
||||||
|
&cmd_buffer->pool->alloc,
|
||||||
|
&fb_h);
|
||||||
|
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
||||||
|
radv_cmd_buffer_set_subpass(cmd_buffer,
|
||||||
|
&cmd_buffer->state.pass->subpasses[0]);
|
||||||
|
|
||||||
|
emit_resolve(cmd_buffer,
|
||||||
|
dst_iview.vk_format,
|
||||||
|
&(VkOffset2D) {
|
||||||
|
.x = dstOffset.x,
|
||||||
|
.y = dstOffset.y,
|
||||||
|
},
|
||||||
|
&(VkExtent2D) {
|
||||||
|
.width = extent.width,
|
||||||
|
.height = extent.height,
|
||||||
|
});
|
||||||
|
|
||||||
|
radv_cmd_buffer_end_render_pass(cmd_buffer);
|
||||||
|
|
||||||
|
radv_DestroyFramebuffer(radv_device_to_handle(device),
|
||||||
|
fb_h, &cmd_buffer->pool->alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
radv_meta_restore(&saved_state, cmd_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void radv_CmdResolveImage(
|
void radv_CmdResolveImage(
|
||||||
VkCommandBuffer cmd_buffer_h,
|
VkCommandBuffer cmd_buffer_h,
|
||||||
VkImage src_image_h,
|
VkImage src_image_h,
|
||||||
@@ -432,9 +611,6 @@ void radv_CmdResolveImage(
|
|||||||
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
|
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
|
||||||
RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
|
RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
|
||||||
RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
|
RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
|
||||||
struct radv_device *device = cmd_buffer->device;
|
|
||||||
struct radv_meta_saved_state saved_state;
|
|
||||||
VkDevice device_h = radv_device_to_handle(device);
|
|
||||||
enum radv_resolve_method resolve_method = RESOLVE_HW;
|
enum radv_resolve_method resolve_method = RESOLVE_HW;
|
||||||
/* we can use the hw resolve only for single full resolves */
|
/* we can use the hw resolve only for single full resolves */
|
||||||
if (region_count == 1) {
|
if (region_count == 1) {
|
||||||
@@ -459,17 +635,25 @@ void radv_CmdResolveImage(
|
|||||||
dest_image_layout, false, cmd_buffer,
|
dest_image_layout, false, cmd_buffer,
|
||||||
&resolve_method);
|
&resolve_method);
|
||||||
|
|
||||||
if (resolve_method == RESOLVE_FRAGMENT) {
|
switch (resolve_method) {
|
||||||
|
case RESOLVE_HW:
|
||||||
|
assert(region_count == 1);
|
||||||
|
radv_meta_resolve_hardware_image(cmd_buffer,
|
||||||
|
src_image,
|
||||||
|
src_image_layout,
|
||||||
|
dest_image,
|
||||||
|
dest_image_layout,
|
||||||
|
®ions[0]);
|
||||||
|
break;
|
||||||
|
case RESOLVE_FRAGMENT:
|
||||||
radv_meta_resolve_fragment_image(cmd_buffer,
|
radv_meta_resolve_fragment_image(cmd_buffer,
|
||||||
src_image,
|
src_image,
|
||||||
src_image_layout,
|
src_image_layout,
|
||||||
dest_image,
|
dest_image,
|
||||||
dest_image_layout,
|
dest_image_layout,
|
||||||
region_count, regions);
|
region_count, regions);
|
||||||
return;
|
break;
|
||||||
}
|
case RESOLVE_COMPUTE:
|
||||||
|
|
||||||
if (resolve_method == RESOLVE_COMPUTE) {
|
|
||||||
radv_meta_resolve_compute_image(cmd_buffer,
|
radv_meta_resolve_compute_image(cmd_buffer,
|
||||||
src_image,
|
src_image,
|
||||||
src_image->vk_format,
|
src_image->vk_format,
|
||||||
@@ -478,178 +662,10 @@ void radv_CmdResolveImage(
|
|||||||
dest_image->vk_format,
|
dest_image->vk_format,
|
||||||
dest_image_layout,
|
dest_image_layout,
|
||||||
region_count, regions);
|
region_count, regions);
|
||||||
return;
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"Invalid resolve method selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
radv_meta_save(&saved_state, cmd_buffer,
|
|
||||||
RADV_META_SAVE_GRAPHICS_PIPELINE);
|
|
||||||
|
|
||||||
assert(src_image->info.samples > 1);
|
|
||||||
if (src_image->info.samples <= 1) {
|
|
||||||
/* this causes GPU hangs if we get past here */
|
|
||||||
fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert(dest_image->info.samples == 1);
|
|
||||||
|
|
||||||
if (src_image->info.array_size > 1)
|
|
||||||
radv_finishme("vkCmdResolveImage: multisample array images");
|
|
||||||
|
|
||||||
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];
|
|
||||||
|
|
||||||
/* From the Vulkan 1.0 spec:
|
|
||||||
*
|
|
||||||
* - The aspectMask member of srcSubresource and dstSubresource must
|
|
||||||
* only contain VK_IMAGE_ASPECT_COLOR_BIT
|
|
||||||
*
|
|
||||||
* - The layerCount member of srcSubresource and dstSubresource must
|
|
||||||
* match
|
|
||||||
*/
|
|
||||||
assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
|
|
||||||
assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
|
|
||||||
assert(region->srcSubresource.layerCount ==
|
|
||||||
region->dstSubresource.layerCount);
|
|
||||||
|
|
||||||
const uint32_t src_base_layer =
|
|
||||||
radv_meta_get_iview_layer(src_image, ®ion->srcSubresource,
|
|
||||||
®ion->srcOffset);
|
|
||||||
|
|
||||||
const uint32_t dest_base_layer =
|
|
||||||
radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource,
|
|
||||||
®ion->dstOffset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
|
|
||||||
*
|
|
||||||
* extent is the size in texels of the source image to resolve in width,
|
|
||||||
* height and depth. 1D images use only x and width. 2D images use x, y,
|
|
||||||
* width and height. 3D images use x, y, z, width, height and depth.
|
|
||||||
*
|
|
||||||
* srcOffset and dstOffset select the initial x, y, and z offsets in
|
|
||||||
* texels of the sub-regions of the source and destination image data.
|
|
||||||
* extent is the size in texels of the source image to resolve in width,
|
|
||||||
* height and depth. 1D images use only x and width. 2D images use x, y,
|
|
||||||
* width and height. 3D images use x, y, z, width, height and depth.
|
|
||||||
*/
|
|
||||||
const struct VkExtent3D extent =
|
|
||||||
radv_sanitize_image_extent(src_image->type, region->extent);
|
|
||||||
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) {
|
|
||||||
|
|
||||||
VkResult ret = build_resolve_pipeline(device, fs_key);
|
|
||||||
if (ret != VK_SUCCESS) {
|
|
||||||
cmd_buffer->record_result = ret;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct radv_image_view src_iview;
|
|
||||||
radv_image_view_init(&src_iview, cmd_buffer->device,
|
|
||||||
&(VkImageViewCreateInfo) {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
||||||
.image = src_image_h,
|
|
||||||
.viewType = radv_meta_get_view_type(src_image),
|
|
||||||
.format = src_image->vk_format,
|
|
||||||
.subresourceRange = {
|
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.baseMipLevel = region->srcSubresource.mipLevel,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = src_base_layer + layer,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
}, NULL);
|
|
||||||
|
|
||||||
struct radv_image_view dest_iview;
|
|
||||||
radv_image_view_init(&dest_iview, cmd_buffer->device,
|
|
||||||
&(VkImageViewCreateInfo) {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
||||||
.image = dest_image_h,
|
|
||||||
.viewType = radv_meta_get_view_type(dest_image),
|
|
||||||
.format = dest_image->vk_format,
|
|
||||||
.subresourceRange = {
|
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.baseMipLevel = region->dstSubresource.mipLevel,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = dest_base_layer + layer,
|
|
||||||
.layerCount = 1,
|
|
||||||
},
|
|
||||||
}, NULL);
|
|
||||||
|
|
||||||
VkFramebuffer fb_h;
|
|
||||||
radv_CreateFramebuffer(device_h,
|
|
||||||
&(VkFramebufferCreateInfo) {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
|
||||||
.attachmentCount = 2,
|
|
||||||
.pAttachments = (VkImageView[]) {
|
|
||||||
radv_image_view_to_handle(&src_iview),
|
|
||||||
radv_image_view_to_handle(&dest_iview),
|
|
||||||
},
|
|
||||||
.width = radv_minify(dest_image->info.width,
|
|
||||||
region->dstSubresource.mipLevel),
|
|
||||||
.height = radv_minify(dest_image->info.height,
|
|
||||||
region->dstSubresource.mipLevel),
|
|
||||||
.layers = 1
|
|
||||||
},
|
|
||||||
&cmd_buffer->pool->alloc,
|
|
||||||
&fb_h);
|
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
radv_cmd_buffer_set_subpass(cmd_buffer,
|
|
||||||
&cmd_buffer->state.pass->subpasses[0]);
|
|
||||||
|
|
||||||
emit_resolve(cmd_buffer,
|
|
||||||
dest_iview.vk_format,
|
|
||||||
&(VkOffset2D) {
|
|
||||||
.x = dstOffset.x,
|
|
||||||
.y = dstOffset.y,
|
|
||||||
},
|
|
||||||
&(VkExtent2D) {
|
|
||||||
.width = extent.width,
|
|
||||||
.height = extent.height,
|
|
||||||
});
|
|
||||||
|
|
||||||
radv_cmd_buffer_end_render_pass(cmd_buffer);
|
|
||||||
|
|
||||||
radv_DestroyFramebuffer(device_h, fb_h,
|
|
||||||
&cmd_buffer->pool->alloc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
radv_meta_restore(&saved_state, cmd_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user