v3dv: add paths to handle partial copies of linear images

v2:
   * Removed unneeded copy_image_linear_buffer
   * Add tiling/image-type check on copy_image_blit

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19950>
This commit is contained in:
Iago Toral Quiroga
2022-09-06 09:34:46 +02:00
committed by Marge Bot
parent b39958a3a1
commit 36ec3d6fe3
3 changed files with 132 additions and 7 deletions

View File

@@ -2697,8 +2697,8 @@ v3dv_BindImageMemory2(VkDevice _device,
return VK_SUCCESS;
}
static void
buffer_init(struct v3dv_device *device,
void
v3dv_buffer_init(struct v3dv_device *device,
const VkBufferCreateInfo *pCreateInfo,
struct v3dv_buffer *buffer)
{
@@ -2751,12 +2751,12 @@ v3dv_GetDeviceBufferMemoryRequirementsKHR(
V3DV_FROM_HANDLE(v3dv_device, device, _device);
struct v3dv_buffer buffer = { 0 };
buffer_init(device, pInfo->pCreateInfo, &buffer);
v3dv_buffer_init(device, pInfo->pCreateInfo, &buffer);
get_buffer_memory_requirements(&buffer, pMemoryRequirements);
}
static void
bind_buffer_memory(const VkBindBufferMemoryInfo *info)
void
v3dv_buffer_bind_memory(const VkBindBufferMemoryInfo *info)
{
V3DV_FROM_HANDLE(v3dv_buffer, buffer, info->buffer);
V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory);
@@ -2781,7 +2781,7 @@ v3dv_BindBufferMemory2(VkDevice device,
const VkBindBufferMemoryInfo *pBindInfos)
{
for (uint32_t i = 0; i < bindInfoCount; i++)
bind_buffer_memory(&pBindInfos[i]);
v3dv_buffer_bind_memory(&pBindInfos[i]);
return VK_SUCCESS;
}
@@ -2806,7 +2806,7 @@ v3dv_CreateBuffer(VkDevice _device,
if (buffer == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
buffer_init(device, pCreateInfo, buffer);
v3dv_buffer_init(device, pCreateInfo, buffer);
/* Limit allocations to 32-bit */
const VkDeviceSize aligned_size = align64(buffer->size, buffer->alignment);

View File

@@ -40,6 +40,19 @@ meta_blit_key_compare(const void *key1, const void *key2)
return memcmp(key1, key2, V3DV_META_BLIT_CACHE_KEY_SIZE) == 0;
}
static bool
texel_buffer_shader_copy(struct v3dv_cmd_buffer *cmd_buffer,
VkImageAspectFlags aspect,
struct v3dv_image *image,
VkFormat dst_format,
VkFormat src_format,
struct v3dv_buffer *buffer,
uint32_t buffer_bpp,
VkColorComponentFlags cmask,
VkComponentMapping *cswizzle,
uint32_t region_count,
const VkBufferImageCopy2 *regions);
static bool
create_blit_pipeline_layout(struct v3dv_device *device,
VkDescriptorSetLayout *descriptor_set_layout,
@@ -1027,6 +1040,10 @@ copy_image_blit(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_image *src,
const VkImageCopy2 *region)
{
if (src->vk.tiling == VK_IMAGE_TILING_LINEAR &&
src->vk.image_type != VK_IMAGE_TYPE_1D)
return false;
const uint32_t src_block_w = vk_format_get_blockwidth(src->vk.format);
const uint32_t src_block_h = vk_format_get_blockheight(src->vk.format);
const uint32_t dst_block_w = vk_format_get_blockwidth(dst->vk.format);
@@ -1163,6 +1180,104 @@ copy_image_blit(struct v3dv_cmd_buffer *cmd_buffer,
return handled;
}
static bool
copy_image_linear_texel_buffer(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_image *dst,
struct v3dv_image *src,
const VkImageCopy2 *region)
{
if (src->vk.tiling != VK_IMAGE_TILING_LINEAR)
return false;
/* Implementations are allowed to restrict linear images like this */
assert(region->srcOffset.z == 0);
assert(region->dstOffset.z == 0);
assert(region->srcSubresource.mipLevel == 0);
assert(region->srcSubresource.baseArrayLayer == 0);
assert(region->srcSubresource.layerCount == 1);
assert(region->dstSubresource.mipLevel == 0);
assert(region->dstSubresource.baseArrayLayer == 0);
assert(region->dstSubresource.layerCount == 1);
const uint32_t bpp = src->cpp;
assert(src->cpp == dst->cpp);
VkFormat format;
switch (bpp) {
case 16:
format = VK_FORMAT_R32G32B32A32_UINT;
break;
case 8:
format = VK_FORMAT_R16G16B16A16_UINT;
break;
case 4:
format = VK_FORMAT_R8G8B8A8_UINT;
break;
case 2:
format = VK_FORMAT_R16_UINT;
break;
case 1:
format = VK_FORMAT_R8_UINT;
break;
default:
unreachable("unsupported bit-size");
return false;
}
VkComponentMapping ident_swizzle = {
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
};
const uint32_t buf_stride = src->slices[0].stride;
const VkDeviceSize buf_offset =
v3dv_layer_offset(src, 0, 0) +
region->srcOffset.y * buf_stride + region->srcOffset.x * bpp;
struct v3dv_buffer src_buffer;
vk_object_base_init(&cmd_buffer->device->vk, &src_buffer.base,
VK_OBJECT_TYPE_BUFFER);
const struct VkBufferCreateInfo buf_create_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = src->size,
.usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
v3dv_buffer_init(cmd_buffer->device, &buf_create_info, &src_buffer);
const VkBindBufferMemoryInfo buf_bind_info = {
.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
.buffer = v3dv_buffer_to_handle(&src_buffer),
.memory = v3dv_device_memory_to_handle(src->mem),
.memoryOffset = src->mem_offset,
};
v3dv_buffer_bind_memory(&buf_bind_info);
const VkBufferImageCopy2 copy_region = {
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.pNext = NULL,
.bufferOffset = buf_offset,
.bufferRowLength = buf_stride / bpp,
.bufferImageHeight = src->vk.extent.height,
.imageSubresource = region->dstSubresource,
.imageOffset = region->dstOffset,
.imageExtent = region->extent,
};
return texel_buffer_shader_copy(cmd_buffer,
VK_IMAGE_ASPECT_COLOR_BIT,
dst,
format,
format,
&src_buffer,
src->cpp,
0 /* color mask: full */, &ident_swizzle,
1, &copy_region);
}
VKAPI_ATTR void VKAPI_CALL
v3dv_CmdCopyImage2KHR(VkCommandBuffer commandBuffer,
const VkCopyImageInfo2 *info)
@@ -1183,6 +1298,8 @@ v3dv_CmdCopyImage2KHR(VkCommandBuffer commandBuffer,
continue;
if (copy_image_blit(cmd_buffer, dst, src, &info->pRegions[i]))
continue;
if (copy_image_linear_texel_buffer(cmd_buffer, dst, src, &info->pRegions[i]))
continue;
unreachable("Image copy not supported");
}

View File

@@ -733,6 +733,14 @@ struct v3dv_buffer {
VkDeviceSize mem_offset;
};
void
v3dv_buffer_init(struct v3dv_device *device,
const VkBufferCreateInfo *pCreateInfo,
struct v3dv_buffer *buffer);
void
v3dv_buffer_bind_memory(const VkBindBufferMemoryInfo *info);
struct v3dv_buffer_view {
struct vk_object_base base;