From: Jason Ekstrand Date: Thu, 31 Dec 2015 21:22:43 +0000 (-0800) Subject: meta/blit: Rework how format and aspect choices are made X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ad9ff4f2b25c0b4f6b83c9ab4dfc98ced4227fd6;p=mesa.git meta/blit: Rework how format and aspect choices are made This commit does two things. First, it introduces choose_* functions for chosing formats and aspects. Second, it changes the copy (not blit) code to use appropreately sized UINT formats for everything except depth. There are two main reasons for this: First, it means that compressed and other non-renderable texture upload should "just work" because it won't be tripping over non-renderable formats. Second, it allows us to easly copy an RGB buffer to and from an RGBX image because the formats will get switched over to their UINT variants and the shader will deal with the extra channel for us. --- diff --git a/src/vulkan/anv_meta.c b/src/vulkan/anv_meta.c index d9a5783e349..a435c26ee59 100644 --- a/src/vulkan/anv_meta.c +++ b/src/vulkan/anv_meta.c @@ -650,6 +650,10 @@ meta_finish_blit(struct anv_cmd_buffer *cmd_buffer, static VkFormat vk_format_for_size(int bs) { + /* Note: We intentionally use the 4-channel formats whenever we can. + * This is so that, when we do a RGB <-> RGBX copy, the two formats will + * line up even though one of them is 3/4 the size of the other. + */ switch (bs) { case 1: return VK_FORMAT_R8_UINT; case 2: return VK_FORMAT_R8G8_UINT; @@ -834,6 +838,50 @@ void anv_CmdCopyBuffer( meta_finish_blit(cmd_buffer, &saved_state); } +static VkFormat +choose_iview_format(struct anv_image *image, VkImageAspectFlagBits aspect) +{ + assert(__builtin_popcount(aspect) == 1); + + struct isl_surf *surf = + &anv_image_get_surface_for_aspect_mask(image, aspect)->isl; + + /* vkCmdCopyImage behaves like memcpy. Therefore we choose identical UINT + * formats for the source and destination image views. + * + * From the Vulkan spec (2015-12-30): + * + * vkCmdCopyImage performs image copies in a similar manner to a host + * memcpy. It does not perform general-purpose conversions such as + * scaling, resizing, blending, color-space conversion, or format + * conversions. Rather, it simply copies raw image data. vkCmdCopyImage + * can copy between images with different formats, provided the formats + * are compatible as defined below. + * + * [The spec later defines compatibility as having the same number of + * bytes per block]. + */ + return vk_format_for_size(isl_format_layouts[surf->format].bs); +} + +static VkFormat +choose_buffer_format(struct anv_image *image, VkImageAspectFlagBits aspect) +{ + assert(__builtin_popcount(aspect) == 1); + + /* vkCmdCopy* commands behave like memcpy. Therefore we choose + * compatable UINT formats for the source and destination image views. + * + * For the buffer, we go back to the original image format and get a + * the format as if it were linear. This way, for RGB formats, we get + * an RGB format here even if the tiled image is RGBA. XXX: This doesn't + * work if the buffer is the destination. + */ + enum isl_format linear_format = anv_get_isl_format(image->vk_format, aspect); + + return vk_format_for_size(isl_format_layouts[linear_format].bs); +} + void anv_CmdCopyImage( VkCommandBuffer commandBuffer, VkImage srcImage, @@ -852,15 +900,23 @@ void anv_CmdCopyImage( meta_prepare_blit(cmd_buffer, &saved_state); for (unsigned r = 0; r < regionCount; r++) { + assert(pRegions[r].srcSubresource.aspectMask == + pRegions[r].dstSubresource.aspectMask); + + VkImageAspectFlags aspect = pRegions[r].srcSubresource.aspectMask; + + VkFormat src_format = choose_iview_format(src_image, aspect); + VkFormat dst_format = choose_iview_format(dest_image, aspect); + struct anv_image_view src_iview; anv_image_view_init(&src_iview, cmd_buffer->device, &(VkImageViewCreateInfo) { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = srcImage, .viewType = anv_meta_get_view_type(src_image), - .format = src_image->vk_format, + .format = src_format, .subresourceRange = { - .aspectMask = pRegions[r].srcSubresource.aspectMask, + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = pRegions[r].srcSubresource.mipLevel, .levelCount = 1, .baseArrayLayer = pRegions[r].srcSubresource.baseArrayLayer, @@ -902,7 +958,7 @@ void anv_CmdCopyImage( .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = destImage, .viewType = anv_meta_get_view_type(dest_image), - .format = dest_image->vk_format, + .format = dst_format, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = pRegions[r].dstSubresource.mipLevel, @@ -1067,22 +1123,18 @@ void anv_CmdCopyBufferToImage( ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); ANV_FROM_HANDLE(anv_image, dest_image, destImage); VkDevice vk_device = anv_device_to_handle(cmd_buffer->device); - const VkFormat orig_format = dest_image->vk_format; struct anv_meta_saved_state saved_state; meta_prepare_blit(cmd_buffer, &saved_state); for (unsigned r = 0; r < regionCount; r++) { - VkFormat proxy_format = orig_format; - VkImageAspectFlags proxy_aspect = pRegions[r].imageSubresource.aspectMask; + VkImageAspectFlags aspect = pRegions[r].imageSubresource.aspectMask; - if (orig_format == VK_FORMAT_S8_UINT) { - proxy_format = VK_FORMAT_R8_UINT; - proxy_aspect = VK_IMAGE_ASPECT_COLOR_BIT; - } + VkFormat image_format = choose_iview_format(dest_image, aspect); + VkFormat buffer_format = choose_buffer_format(dest_image, aspect); struct anv_image *src_image = - make_image_for_buffer(vk_device, srcBuffer, proxy_format, + make_image_for_buffer(vk_device, srcBuffer, buffer_format, VK_IMAGE_USAGE_SAMPLED_BIT, dest_image->type, &cmd_buffer->pool->alloc, &pRegions[r]); @@ -1108,9 +1160,9 @@ void anv_CmdCopyBufferToImage( .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = anv_image_to_handle(src_image), .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = proxy_format, + .format = buffer_format, .subresourceRange = { - .aspectMask = proxy_aspect, + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, @@ -1125,7 +1177,7 @@ void anv_CmdCopyBufferToImage( .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = anv_image_to_handle(dest_image), .viewType = anv_meta_get_view_type(dest_image), - .format = proxy_format, + .format = image_format, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = pRegions[r].imageSubresource.mipLevel, @@ -1188,15 +1240,20 @@ void anv_CmdCopyImageToBuffer( meta_prepare_blit(cmd_buffer, &saved_state); for (unsigned r = 0; r < regionCount; r++) { + VkImageAspectFlags aspect = pRegions[r].imageSubresource.aspectMask; + + VkFormat image_format = choose_iview_format(src_image, aspect); + VkFormat buffer_format = choose_buffer_format(src_image, aspect); + struct anv_image_view src_iview; anv_image_view_init(&src_iview, cmd_buffer->device, &(VkImageViewCreateInfo) { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = srcImage, .viewType = anv_meta_get_view_type(src_image), - .format = src_image->vk_format, + .format = image_format, .subresourceRange = { - .aspectMask = pRegions[r].imageSubresource.aspectMask, + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = pRegions[r].imageSubresource.mipLevel, .levelCount = 1, .baseArrayLayer = pRegions[r].imageSubresource.baseArrayLayer, @@ -1205,13 +1262,8 @@ void anv_CmdCopyImageToBuffer( }, cmd_buffer); - VkFormat dest_format = src_image->vk_format; - if (dest_format == VK_FORMAT_S8_UINT) { - dest_format = VK_FORMAT_R8_UINT; - } - struct anv_image *dest_image = - make_image_for_buffer(vk_device, destBuffer, dest_format, + make_image_for_buffer(vk_device, destBuffer, buffer_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, src_image->type, &cmd_buffer->pool->alloc, &pRegions[r]); @@ -1235,7 +1287,7 @@ void anv_CmdCopyImageToBuffer( .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = anv_image_to_handle(dest_image), .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = dest_format, + .format = buffer_format, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0,