From: Jason Ekstrand Date: Fri, 17 Jan 2020 23:46:31 +0000 (-0600) Subject: anv: Canonicalize buffer formats for image/buffer copies X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dd92179a72e5263b9db730d92a883e2536aa4474;p=mesa.git anv: Canonicalize buffer formats for image/buffer copies Some formats, in particular YCbCr formats and ASTC have additional restrictions. We already whack ASTC formats to RGBA32_UINT because the hardware doesn't allow LINEAR with ASTC. However, we need to fix YCbCr formats as well because they come with alignment restrictions that we can't guarantee are satisfied. We're using blorp_copy to do the copies so we may as well just stomp formats for everything. Fixes: b24b93d5843 "anv: enable VK_KHR_sampler_ycbcr_conversion" Reviewed-by: Lionel Landwerlin Tested-by: Marge Bot Part-of: --- diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 5649b00f29f..71690eab037 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -410,6 +410,24 @@ void anv_CmdCopyImage( blorp_batch_finish(&batch); } +static enum isl_format +isl_format_for_size(unsigned size_B) +{ + /* Prefer 32-bit per component formats for CmdFillBuffer */ + switch (size_B) { + case 1: return ISL_FORMAT_R8_UINT; + case 2: return ISL_FORMAT_R16_UINT; + case 3: return ISL_FORMAT_R8G8B8_UINT; + case 4: return ISL_FORMAT_R32_UINT; + case 6: return ISL_FORMAT_R16G16B16_UINT; + case 8: return ISL_FORMAT_R32G32_UINT; + case 12: return ISL_FORMAT_R32G32B32_UINT; + case 16: return ISL_FORMAT_R32G32B32A32_UINT; + default: + unreachable("Unknown format size"); + } +} + static void copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer, struct anv_buffer *anv_buffer, @@ -457,12 +475,11 @@ copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer, anv_get_layerCount(anv_image, &pRegions[r].imageSubresource); } - const enum isl_format buffer_format = + const enum isl_format linear_format = anv_get_isl_format(&cmd_buffer->device->info, anv_image->vk_format, aspect, VK_IMAGE_TILING_LINEAR); - - const struct isl_format_layout *buffer_fmtl = - isl_format_get_layout(buffer_format); + const struct isl_format_layout *linear_fmtl = + isl_format_get_layout(linear_format); const uint32_t buffer_row_length = pRegions[r].bufferRowLength ? @@ -473,17 +490,34 @@ copy_buffer_to_image(struct anv_cmd_buffer *cmd_buffer, pRegions[r].bufferImageHeight : extent.height; const uint32_t buffer_row_pitch = - DIV_ROUND_UP(buffer_row_length, buffer_fmtl->bw) * - (buffer_fmtl->bpb / 8); + DIV_ROUND_UP(buffer_row_length, linear_fmtl->bw) * + (linear_fmtl->bpb / 8); const uint32_t buffer_layer_stride = - DIV_ROUND_UP(buffer_image_height, buffer_fmtl->bh) * + DIV_ROUND_UP(buffer_image_height, linear_fmtl->bh) * buffer_row_pitch; + /* Some formats have additional restrictions which may cause ISL to + * fail to create a surface for us. Some examples include: + * + * 1. ASTC formats are not allowed to be LINEAR and must be tiled + * 2. YCbCr formats have to have 2-pixel aligned strides + * + * To avoid these issues, we always bind the buffer as if it's a + * "normal" format like RGBA32_UINT. Since we're using blorp_copy, + * the format doesn't matter as long as it has the right bpb. + */ + const VkExtent2D buffer_extent = { + .width = DIV_ROUND_UP(extent.width, linear_fmtl->bw), + .height = DIV_ROUND_UP(extent.height, linear_fmtl->bh), + }; + const enum isl_format buffer_format = + isl_format_for_size(linear_fmtl->bpb / 8); + struct isl_surf buffer_isl_surf; get_blorp_surf_for_anv_buffer(cmd_buffer->device, anv_buffer, pRegions[r].bufferOffset, - extent.width, extent.height, + buffer_extent.width, buffer_extent.height, buffer_row_pitch, buffer_format, &buffer.surf, &buffer_isl_surf); @@ -699,18 +733,6 @@ void anv_CmdBlitImage( blorp_batch_finish(&batch); } -static enum isl_format -isl_format_for_size(unsigned size_B) -{ - switch (size_B) { - case 4: return ISL_FORMAT_R32_UINT; - case 8: return ISL_FORMAT_R32G32_UINT; - case 16: return ISL_FORMAT_R32G32B32A32_UINT; - default: - unreachable("Not a power-of-two format size"); - } -} - /** * Returns the greatest common divisor of a and b that is a power of two. */