Mesa (master): radv: Allow mixed src/dst aspects in copies.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 25 20:08:16 UTC 2019


Module: Mesa
Branch: master
Commit: dc917c80736715ac271471289f04654f1d578158
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dc917c80736715ac271471289f04654f1d578158

Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date:   Sun Apr  7 22:40:30 2019 +0200

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 at gmail.com>

---

 src/amd/vulkan/radv_meta_copy.c | 220 +++++++++++++++++++++-------------------
 1 file changed, 116 insertions(+), 104 deletions(-)

diff --git a/src/amd/vulkan/radv_meta_copy.c b/src/amd/vulkan/radv_meta_copy.c
index 1736f0543b3..8081057d9df 100644
--- a/src/amd/vulkan/radv_meta_copy.c
+++ b/src/amd/vulkan/radv_meta_copy.c
@@ -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);
-
-		/* Create blit surfaces */
-		struct radv_meta_blit2d_surf b_src =
-			blit_surf_for_image_level_layer(src_image,
-							src_image_layout,
-							&pRegions[r].srcSubresource);
-
-		struct radv_meta_blit2d_surf b_dst =
-			blit_surf_for_image_level_layer(dest_image,
-							dest_image_layout,
-							&pRegions[r].dstSubresource);
-
-		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;
+		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;
+
+		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,
+								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);
+
+			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 = 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;
+			}
 
-		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) {
+			/**
+			 * 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);
 
-			/* 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;
+			/* Start creating blit rect */
+			struct radv_meta_blit2d_rect rect = {
+				.width = img_extent_el.width,
+				.height = img_extent_el.height,
+			};
 
-			/* 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);
-			}
+			if (src_image->type == VK_IMAGE_TYPE_3D)
+				b_src.layer = src_offset_el.z;
 
-			b_src.layer++;
-			b_dst.layer++;
 			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++;
+			}
 		}
 	}
 




More information about the mesa-commit mailing list