mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-02 11:00:27 +01:00
v3dv: add a TFU path for image copies
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7809>
This commit is contained in:
parent
f9e53c6e51
commit
ece8dbe68f
1 changed files with 120 additions and 0 deletions
|
|
@ -1520,6 +1520,124 @@ emit_tfu_job(struct v3dv_cmd_buffer *cmd_buffer,
|
|||
v3dv_cmd_buffer_add_tfu_job(cmd_buffer, &tfu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the implementation supports the requested operation (even if
|
||||
* it failed to process it, for example, due to an out-of-memory error).
|
||||
*/
|
||||
static bool
|
||||
copy_image_tfu(struct v3dv_cmd_buffer *cmd_buffer,
|
||||
struct v3dv_image *dst,
|
||||
struct v3dv_image *src,
|
||||
const VkImageCopy *region)
|
||||
{
|
||||
/* Destination can't be raster format */
|
||||
if (dst->tiling == VK_IMAGE_TILING_LINEAR)
|
||||
return false;
|
||||
|
||||
/* We can only do full copies, so if the format is D24S8 both aspects need
|
||||
* to be copied. We only need to check the dst format because the spec
|
||||
* states that depth/stencil formats must match exactly.
|
||||
*/
|
||||
if (dst->vk_format == VK_FORMAT_D24_UNORM_S8_UINT) {
|
||||
const VkImageAspectFlags ds_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |
|
||||
VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if (region->dstSubresource.aspectMask != ds_aspects)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Don't handle copies between uncompressed and compressed formats for now.
|
||||
*
|
||||
* FIXME: we should be able to handle these easily but there is no coverage
|
||||
* in CTS at the moment that make such copies with full images (which we
|
||||
* require here), only partial copies. Also, in that case the code below that
|
||||
* checks for "dst image complete" requires some changes, since it is
|
||||
* checking against the region dimensions, which are in units of the source
|
||||
* image format.
|
||||
*/
|
||||
if (vk_format_is_compressed(dst->vk_format) !=
|
||||
vk_format_is_compressed(src->vk_format)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Source region must start at (0,0) */
|
||||
if (region->srcOffset.x != 0 || region->srcOffset.y != 0)
|
||||
return false;
|
||||
|
||||
/* Destination image must be complete */
|
||||
if (region->dstOffset.x != 0 || region->dstOffset.y != 0)
|
||||
return false;
|
||||
|
||||
const uint32_t dst_mip_level = region->dstSubresource.mipLevel;
|
||||
uint32_t dst_width = u_minify(dst->extent.width, dst_mip_level);
|
||||
uint32_t dst_height = u_minify(dst->extent.height, dst_mip_level);
|
||||
if (region->extent.width != dst_width || region->extent.height != dst_height)
|
||||
return false;
|
||||
|
||||
/* From vkCmdCopyImage:
|
||||
*
|
||||
* "When copying between compressed and uncompressed formats the extent
|
||||
* members represent the texel dimensions of the source image and not
|
||||
* the destination."
|
||||
*/
|
||||
const uint32_t block_w = vk_format_get_blockwidth(src->vk_format);
|
||||
const uint32_t block_h = vk_format_get_blockheight(src->vk_format);
|
||||
uint32_t width = DIV_ROUND_UP(region->extent.width, block_w);
|
||||
uint32_t height = DIV_ROUND_UP(region->extent.height, block_h);
|
||||
|
||||
/* Account for sample count */
|
||||
assert(dst->samples == src->samples);
|
||||
if (dst->samples > VK_SAMPLE_COUNT_1_BIT) {
|
||||
assert(dst->samples == VK_SAMPLE_COUNT_4_BIT);
|
||||
width *= 2;
|
||||
height *= 2;
|
||||
}
|
||||
|
||||
/* The TFU unit doesn't handle format conversions so we need the formats to
|
||||
* match. On the other hand, vkCmdCopyImage allows different color formats
|
||||
* on the source and destination images, but only if they are texel
|
||||
* compatible. For us, this means that we can effectively ignore different
|
||||
* formats and just make the copy using either of them, since we are just
|
||||
* moving raw data and not making any conversions.
|
||||
*
|
||||
* Also, the formats supported by the TFU unit are limited, but again, since
|
||||
* we are only doing raw copies here without interpreting or converting
|
||||
* the underlying pixel data according to its format, we can always choose
|
||||
* to use compatible formats that are supported with the TFU unit.
|
||||
*/
|
||||
assert(dst->cpp == src->cpp);
|
||||
VkFormat vk_format;
|
||||
switch (dst->cpp) {
|
||||
case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT; break;
|
||||
case 8: vk_format = VK_FORMAT_R16G16B16A16_SFLOAT; break;
|
||||
case 4: vk_format = VK_FORMAT_R32_SFLOAT; break;
|
||||
case 2: vk_format = VK_FORMAT_R16_SFLOAT; break;
|
||||
case 1: vk_format = VK_FORMAT_R8_UNORM; break;
|
||||
default: unreachable("unsupported format bit-size"); break;
|
||||
};
|
||||
const struct v3dv_format *format = v3dv_get_format(vk_format);
|
||||
assert(v3dv_tfu_supports_tex_format(&cmd_buffer->device->devinfo,
|
||||
format->tex_type));
|
||||
|
||||
/* Emit a TFU job for each layer to blit */
|
||||
const uint32_t layer_count = dst->type != VK_IMAGE_TYPE_3D ?
|
||||
region->dstSubresource.layerCount :
|
||||
region->extent.depth;
|
||||
const uint32_t src_mip_level = region->srcSubresource.mipLevel;
|
||||
|
||||
const uint32_t base_src_layer = src->type != VK_IMAGE_TYPE_3D ?
|
||||
region->srcSubresource.baseArrayLayer : region->srcOffset.z;
|
||||
const uint32_t base_dst_layer = dst->type != VK_IMAGE_TYPE_3D ?
|
||||
region->dstSubresource.baseArrayLayer : region->dstOffset.z;
|
||||
for (uint32_t i = 0; i < layer_count; i++) {
|
||||
emit_tfu_job(cmd_buffer,
|
||||
dst, dst_mip_level, base_dst_layer + i,
|
||||
src, src_mip_level, base_src_layer + i,
|
||||
width, height, format);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the implementation supports the requested operation (even if
|
||||
* it failed to process it, for example, due to an out-of-memory error).
|
||||
|
|
@ -1811,6 +1929,8 @@ v3dv_CmdCopyImage(VkCommandBuffer commandBuffer,
|
|||
assert(src->samples == dst->samples);
|
||||
|
||||
for (uint32_t i = 0; i < regionCount; i++) {
|
||||
if (copy_image_tfu(cmd_buffer, dst, src, &pRegions[i]))
|
||||
continue;
|
||||
if (copy_image_tlb(cmd_buffer, dst, src, &pRegions[i]))
|
||||
continue;
|
||||
if (copy_image_blit(cmd_buffer, dst, src, &pRegions[i]))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue