From dda02faf89a7df74ea012e4039b8f1c5bffc3b82 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Fri, 15 Oct 2021 16:51:14 +0200 Subject: [PATCH] vkd3d: Pad reserved resources to 64k alignment. Fix GPU crashes when attempting to bind non-aligned reserved resource. Signed-off-by: Hans-Kristian Arntzen --- include/private/vkd3d_common.h | 5 +++++ libs/vkd3d/resource.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index f0d9c8ba..3b58ae36 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -42,6 +42,11 @@ #define MEMBER_SIZE(t, m) sizeof(((t *)0)->m) +static inline uint64_t align64(uint64_t addr, uint64_t alignment) +{ + return (addr + (alignment - 1)) & ~(alignment - 1); +} + static inline size_t align(size_t addr, size_t alignment) { return (addr + (alignment - 1)) & ~(alignment - 1); diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 13d77739..1758cd9b 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -119,6 +119,11 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device, buffer_info.flags |= VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT; + + /* If we attempt to bind sparse buffer with non-64k pages, we crash drivers. + * Specs seems a bit unclear how non-aligned VkBuffer sizes are supposed to work, + * so be safe. Pad out sparse buffers to their natural page size. */ + buffer_info.size = align64(buffer_info.size, VKD3D_TILE_SIZE); } buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT @@ -2282,13 +2287,15 @@ static HRESULT d3d12_resource_init_sparse_info(struct d3d12_resource *resource, { VkDeviceSize offset = VKD3D_TILE_SIZE * i; sparse->tiles[i].buffer.offset = offset; - sparse->tiles[i].buffer.length = min(VKD3D_TILE_SIZE, resource->desc.Width - offset); + sparse->tiles[i].buffer.length = align(min(VKD3D_TILE_SIZE, resource->desc.Width - offset), + VKD3D_TILE_SIZE); } else if (sparse->packed_mips.NumPackedMips && i >= sparse->packed_mips.StartTileIndexInOverallResource) { VkDeviceSize offset = VKD3D_TILE_SIZE * (i - sparse->packed_mips.StartTileIndexInOverallResource); sparse->tiles[i].buffer.offset = vk_memory_requirements.imageMipTailOffset + offset; - sparse->tiles[i].buffer.length = min(VKD3D_TILE_SIZE, vk_memory_requirements.imageMipTailSize - offset); + sparse->tiles[i].buffer.length = align(min(VKD3D_TILE_SIZE, vk_memory_requirements.imageMipTailSize - offset), + VKD3D_TILE_SIZE); } else {