vkd3d: Pad reserved resources to 64k alignment.

Fix GPU crashes when attempting to bind non-aligned reserved resource.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-10-15 16:51:14 +02:00
parent c3a92a0dad
commit dda02faf89
2 changed files with 14 additions and 2 deletions

View File

@ -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);

View File

@ -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
{