radv: Allow mixed src/dst aspects in copies.
e.g. COLOR + PLANE_2, as well COLOR + COLOR for multiplane images. Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
This commit is contained in:
parent
b2cfa231d0
commit
dc917c8073
|
@ -82,9 +82,10 @@ vk_format_for_size(int bs)
|
|||
static struct radv_meta_blit2d_surf
|
||||
blit_surf_for_image_level_layer(struct radv_image *image,
|
||||
VkImageLayout layout,
|
||||
const VkImageSubresourceLayers *subres)
|
||||
const VkImageSubresourceLayers *subres,
|
||||
VkImageAspectFlags aspect_mask)
|
||||
{
|
||||
VkFormat format = radv_get_aspect_format(image, subres->aspectMask);
|
||||
VkFormat format = radv_get_aspect_format(image, aspect_mask);
|
||||
|
||||
if (!radv_image_has_dcc(image) &&
|
||||
!(radv_image_is_tc_compat_htile(image)))
|
||||
|
@ -98,7 +99,7 @@ blit_surf_for_image_level_layer(struct radv_image *image,
|
|||
.level = subres->mipLevel,
|
||||
.layer = subres->baseArrayLayer,
|
||||
.image = image,
|
||||
.aspect_mask = subres->aspectMask,
|
||||
.aspect_mask = aspect_mask,
|
||||
.current_layout = layout,
|
||||
};
|
||||
}
|
||||
|
@ -183,7 +184,8 @@ meta_copy_buffer_to_image(struct radv_cmd_buffer *cmd_buffer,
|
|||
struct radv_meta_blit2d_surf img_bsurf =
|
||||
blit_surf_for_image_level_layer(image,
|
||||
layout,
|
||||
&pRegions[r].imageSubresource);
|
||||
&pRegions[r].imageSubresource,
|
||||
pRegions[r].imageSubresource.aspectMask);
|
||||
|
||||
struct radv_meta_blit2d_buffer buf_bsurf = {
|
||||
.bs = img_bsurf.bs,
|
||||
|
@ -308,7 +310,8 @@ meta_copy_image_to_buffer(struct radv_cmd_buffer *cmd_buffer,
|
|||
struct radv_meta_blit2d_surf img_info =
|
||||
blit_surf_for_image_level_layer(image,
|
||||
layout,
|
||||
&pRegions[r].imageSubresource);
|
||||
&pRegions[r].imageSubresource,
|
||||
pRegions[r].imageSubresource.aspectMask);
|
||||
|
||||
struct radv_meta_blit2d_buffer buf_info = {
|
||||
.bs = img_info.bs,
|
||||
|
@ -400,111 +403,120 @@ meta_copy_image(struct radv_cmd_buffer *cmd_buffer,
|
|||
cmd_buffer->state.predicating = false;
|
||||
|
||||
for (unsigned r = 0; r < regionCount; r++) {
|
||||
assert(pRegions[r].srcSubresource.aspectMask ==
|
||||
pRegions[r].dstSubresource.aspectMask);
|
||||
VkImageAspectFlags src_aspects[3] = {VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_ASPECT_PLANE_2_BIT};
|
||||
VkImageAspectFlags dst_aspects[3] = {VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT, VK_IMAGE_ASPECT_PLANE_2_BIT};
|
||||
unsigned aspect_count = pRegions[r].srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT ? src_image->plane_count : 1;
|
||||
if (pRegions[r].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
src_aspects[0] = pRegions[r].srcSubresource.aspectMask;
|
||||
if (pRegions[r].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
dst_aspects[0] = pRegions[r].dstSubresource.aspectMask;
|
||||
|
||||
/* Create blit surfaces */
|
||||
struct radv_meta_blit2d_surf b_src =
|
||||
blit_surf_for_image_level_layer(src_image,
|
||||
src_image_layout,
|
||||
&pRegions[r].srcSubresource);
|
||||
for (unsigned a = 0; a < aspect_count; ++a) {
|
||||
/* Create blit surfaces */
|
||||
struct radv_meta_blit2d_surf b_src =
|
||||
blit_surf_for_image_level_layer(src_image,
|
||||
src_image_layout,
|
||||
&pRegions[r].srcSubresource,
|
||||
src_aspects[a]);
|
||||
|
||||
struct radv_meta_blit2d_surf b_dst =
|
||||
blit_surf_for_image_level_layer(dest_image,
|
||||
dest_image_layout,
|
||||
&pRegions[r].dstSubresource);
|
||||
struct radv_meta_blit2d_surf b_dst =
|
||||
blit_surf_for_image_level_layer(dest_image,
|
||||
dest_image_layout,
|
||||
&pRegions[r].dstSubresource,
|
||||
dst_aspects[a]);
|
||||
|
||||
uint32_t dst_queue_mask = radv_image_queue_family_mask(dest_image,
|
||||
cmd_buffer->queue_family_index,
|
||||
cmd_buffer->queue_family_index);
|
||||
bool dst_compressed = radv_layout_dcc_compressed(dest_image, dest_image_layout, dst_queue_mask);
|
||||
uint32_t src_queue_mask = radv_image_queue_family_mask(src_image,
|
||||
cmd_buffer->queue_family_index,
|
||||
cmd_buffer->queue_family_index);
|
||||
bool src_compressed = radv_layout_dcc_compressed(src_image, src_image_layout, src_queue_mask);
|
||||
uint32_t dst_queue_mask = radv_image_queue_family_mask(dest_image,
|
||||
cmd_buffer->queue_family_index,
|
||||
cmd_buffer->queue_family_index);
|
||||
bool dst_compressed = radv_layout_dcc_compressed(dest_image, dest_image_layout, dst_queue_mask);
|
||||
uint32_t src_queue_mask = radv_image_queue_family_mask(src_image,
|
||||
cmd_buffer->queue_family_index,
|
||||
cmd_buffer->queue_family_index);
|
||||
bool src_compressed = radv_layout_dcc_compressed(src_image, src_image_layout, src_queue_mask);
|
||||
|
||||
if (!src_compressed || radv_dcc_formats_compatible(b_src.format, b_dst.format)) {
|
||||
b_src.format = b_dst.format;
|
||||
} else if (!dst_compressed) {
|
||||
b_dst.format = b_src.format;
|
||||
} else {
|
||||
radv_decompress_dcc(cmd_buffer, dest_image, &(VkImageSubresourceRange) {
|
||||
.aspectMask = pRegions[r].dstSubresource.aspectMask,
|
||||
.baseMipLevel = pRegions[r].dstSubresource.mipLevel,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = pRegions[r].dstSubresource.baseArrayLayer,
|
||||
.layerCount = pRegions[r].dstSubresource.layerCount,
|
||||
});
|
||||
b_dst.format = b_src.format;
|
||||
b_dst.current_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* From the Vulkan 1.0.6 spec: 18.4 Copying Data Between Buffers and Images
|
||||
* imageExtent is the size in texels of the image to copy 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.
|
||||
*
|
||||
* Also, convert the offsets and extent from units of texels to units of
|
||||
* blocks - which is the highest resolution accessible in this command.
|
||||
*/
|
||||
const VkOffset3D dst_offset_el =
|
||||
meta_region_offset_el(dest_image, &pRegions[r].dstOffset);
|
||||
const VkOffset3D src_offset_el =
|
||||
meta_region_offset_el(src_image, &pRegions[r].srcOffset);
|
||||
|
||||
/*
|
||||
* From Vulkan 1.0.68, "Copying Data Between Images":
|
||||
* "When copying between compressed and uncompressed formats
|
||||
* the extent members represent the texel dimensions of the
|
||||
* source image and not the destination."
|
||||
* However, we must use the destination image type to avoid
|
||||
* clamping depth when copying multiple layers of a 2D image to
|
||||
* a 3D image.
|
||||
*/
|
||||
const VkExtent3D img_extent_el =
|
||||
meta_region_extent_el(src_image, dest_image->type, &pRegions[r].extent);
|
||||
|
||||
/* Start creating blit rect */
|
||||
struct radv_meta_blit2d_rect rect = {
|
||||
.width = img_extent_el.width,
|
||||
.height = img_extent_el.height,
|
||||
};
|
||||
|
||||
if (src_image->type == VK_IMAGE_TYPE_3D)
|
||||
b_src.layer = src_offset_el.z;
|
||||
|
||||
if (dest_image->type == VK_IMAGE_TYPE_3D)
|
||||
b_dst.layer = dst_offset_el.z;
|
||||
|
||||
/* Loop through each 3D or array slice */
|
||||
unsigned num_slices_3d = img_extent_el.depth;
|
||||
unsigned num_slices_array = pRegions[r].dstSubresource.layerCount;
|
||||
unsigned slice_3d = 0;
|
||||
unsigned slice_array = 0;
|
||||
while (slice_3d < num_slices_3d && slice_array < num_slices_array) {
|
||||
|
||||
/* Finish creating blit rect */
|
||||
rect.dst_x = dst_offset_el.x;
|
||||
rect.dst_y = dst_offset_el.y;
|
||||
rect.src_x = src_offset_el.x;
|
||||
rect.src_y = src_offset_el.y;
|
||||
|
||||
/* Perform Blit */
|
||||
if (cs ||
|
||||
!image_is_renderable(cmd_buffer->device, b_dst.image)) {
|
||||
radv_meta_image_to_image_cs(cmd_buffer, &b_src, &b_dst, 1, &rect);
|
||||
if (!src_compressed || radv_dcc_formats_compatible(b_src.format, b_dst.format)) {
|
||||
b_src.format = b_dst.format;
|
||||
} else if (!dst_compressed) {
|
||||
b_dst.format = b_src.format;
|
||||
} else {
|
||||
radv_meta_blit2d(cmd_buffer, &b_src, NULL, &b_dst, 1, &rect);
|
||||
radv_decompress_dcc(cmd_buffer, dest_image, &(VkImageSubresourceRange) {
|
||||
.aspectMask = dst_aspects[a],
|
||||
.baseMipLevel = pRegions[r].dstSubresource.mipLevel,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = pRegions[r].dstSubresource.baseArrayLayer,
|
||||
.layerCount = pRegions[r].dstSubresource.layerCount,
|
||||
});
|
||||
b_dst.format = b_src.format;
|
||||
b_dst.current_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
|
||||
b_src.layer++;
|
||||
b_dst.layer++;
|
||||
|
||||
/**
|
||||
* From the Vulkan 1.0.6 spec: 18.4 Copying Data Between Buffers and Images
|
||||
* imageExtent is the size in texels of the image to copy 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.
|
||||
*
|
||||
* Also, convert the offsets and extent from units of texels to units of
|
||||
* blocks - which is the highest resolution accessible in this command.
|
||||
*/
|
||||
const VkOffset3D dst_offset_el =
|
||||
meta_region_offset_el(dest_image, &pRegions[r].dstOffset);
|
||||
const VkOffset3D src_offset_el =
|
||||
meta_region_offset_el(src_image, &pRegions[r].srcOffset);
|
||||
|
||||
/*
|
||||
* From Vulkan 1.0.68, "Copying Data Between Images":
|
||||
* "When copying between compressed and uncompressed formats
|
||||
* the extent members represent the texel dimensions of the
|
||||
* source image and not the destination."
|
||||
* However, we must use the destination image type to avoid
|
||||
* clamping depth when copying multiple layers of a 2D image to
|
||||
* a 3D image.
|
||||
*/
|
||||
const VkExtent3D img_extent_el =
|
||||
meta_region_extent_el(src_image, dest_image->type, &pRegions[r].extent);
|
||||
|
||||
/* Start creating blit rect */
|
||||
struct radv_meta_blit2d_rect rect = {
|
||||
.width = img_extent_el.width,
|
||||
.height = img_extent_el.height,
|
||||
};
|
||||
|
||||
if (src_image->type == VK_IMAGE_TYPE_3D)
|
||||
b_src.layer = src_offset_el.z;
|
||||
|
||||
if (dest_image->type == VK_IMAGE_TYPE_3D)
|
||||
slice_3d++;
|
||||
else
|
||||
slice_array++;
|
||||
b_dst.layer = dst_offset_el.z;
|
||||
|
||||
/* Loop through each 3D or array slice */
|
||||
unsigned num_slices_3d = img_extent_el.depth;
|
||||
unsigned num_slices_array = pRegions[r].dstSubresource.layerCount;
|
||||
unsigned slice_3d = 0;
|
||||
unsigned slice_array = 0;
|
||||
while (slice_3d < num_slices_3d && slice_array < num_slices_array) {
|
||||
|
||||
/* Finish creating blit rect */
|
||||
rect.dst_x = dst_offset_el.x;
|
||||
rect.dst_y = dst_offset_el.y;
|
||||
rect.src_x = src_offset_el.x;
|
||||
rect.src_y = src_offset_el.y;
|
||||
|
||||
/* Perform Blit */
|
||||
if (cs ||
|
||||
!image_is_renderable(cmd_buffer->device, b_dst.image)) {
|
||||
radv_meta_image_to_image_cs(cmd_buffer, &b_src, &b_dst, 1, &rect);
|
||||
} else {
|
||||
radv_meta_blit2d(cmd_buffer, &b_src, NULL, &b_dst, 1, &rect);
|
||||
}
|
||||
|
||||
b_src.layer++;
|
||||
b_dst.layer++;
|
||||
if (dest_image->type == VK_IMAGE_TYPE_3D)
|
||||
slice_3d++;
|
||||
else
|
||||
slice_array++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue