From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/command.c | 107 +++++++++++++++++++++++++++++++++++++++---- tests/d3d12.c | 1 - 2 files changed, 97 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index ec306cd04..d61ee7177 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -6522,6 +6522,39 @@ static void d3d12_resource_update_buffer_tile_mappings(struct d3d12_resource *re vkd3d_mutex_unlock(&resource->tiles.mutex); }
+/* Never called for mip tails. */ +static void d3d12_resource_update_image_tile_mappings(struct d3d12_resource *resource, unsigned int subresource, + const VkSparseImageMemoryBind *image_memory_bind) +{ + struct vkd3d_subresource_tile_mapping *layer, *column, *row; + VkDeviceSize offset = image_memory_bind->memoryOffset; + const struct vkd3d_tiled_region_extent *extent; + unsigned int x, y, z, layer_stride; + + extent = &resource->tiles.subresources[subresource].extent; + + vkd3d_mutex_lock(&resource->tiles.mutex); + + layer_stride = extent->width * extent->height; + layer = &resource->tiles.subresources[subresource].mappings[image_memory_bind->offset.z * layer_stride]; + for (z = 0; z < image_memory_bind->extent.depth; ++z, layer += layer_stride) + { + column = layer + image_memory_bind->offset.y * extent->width; + for (y = 0; y < image_memory_bind->extent.height; ++y, column += extent->width) + { + row = column + image_memory_bind->offset.x; + for (x = 0; x < image_memory_bind->extent.width; ++x) + { + row[x].vk_memory = image_memory_bind->memory; + row[x].byte_offset = offset; + offset += D3D12_TILE_SIZE; + } + } + } + + vkd3d_mutex_unlock(&resource->tiles.mutex); +} + static void deaggregate_sparse_memory_bind(VkSparseBufferMemoryBindInfo *buffer_bind_info, const VkSparseMemoryBind *src, unsigned int tile_count, struct d3d12_resource *resource) { @@ -6647,6 +6680,8 @@ static unsigned int d3d12_command_queue_bind_sparse_block(struct d3d12_command_q image_memory_bind.memoryOffset = memory_offset * D3D12_TILE_SIZE; image_memory_bind.flags = 0;
+ d3d12_resource_update_image_tile_mappings(resource, subresource, &image_memory_bind); + /* NVIDIA bug (see above).*/ deaggregate_sparse_image_memory_bind(&image_bind_info, &image_memory_bind, resource);
@@ -6813,12 +6848,16 @@ static void vkd3d_copy_vk_tile_mapping_region(const struct d3d12_command_queue * struct vkd3d_queue *vkd3d_queue = command_queue->vkd3d_queue; const struct vkd3d_subresource_tile_mapping *src_mapping; VkSparseBufferMemoryBindInfo buffer_bind_info; + VkSparseImageMemoryBindInfo image_bind_info; + VkSparseImageMemoryBind *image_memory_bind; + unsigned int i, src_idx, subresource; VkSparseMemoryBind *memory_bind; VkBindSparseInfo sparse_info; - unsigned int i, src_idx; + bool is_end; VkResult vr;
src_mapping = src_info->mappings; + subresource = dst_loc->Subresource;
memset(&sparse_info, 0, sizeof(sparse_info)); sparse_info.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; @@ -6848,7 +6887,42 @@ static void vkd3d_copy_vk_tile_mapping_region(const struct d3d12_command_queue * } else { - vkd3d_unreachable(); + sparse_info.imageBindCount = 1; + sparse_info.pImageBinds = &image_bind_info; + image_memory_bind = dst_resource->tiles.bind_buffer; + image_bind_info.image = dst_resource->u.vk_image; + image_bind_info.bindCount = src_extent->NumTiles; + image_bind_info.pBinds = image_memory_bind; + + for (i = 0, is_end = false; i < src_extent->NumTiles && !is_end; ++i) + { + src_idx = src_loc->X + src_loc->Y * src_info->extent.width + + src_loc->Z * src_info->extent.width * src_info->extent.height; + d3d12_resource_get_vk_subresource(dst_resource, dst_loc->Subresource, &image_memory_bind[i].subresource); + image_memory_bind[i].offset.x = dst_loc->X; + image_memory_bind[i].offset.y = dst_loc->Y; + image_memory_bind[i].offset.z = dst_loc->Z; + image_memory_bind[i].extent.width = 1; + image_memory_bind[i].extent.height = 1; + image_memory_bind[i].extent.depth = 1; + image_memory_bind[i].memory = src_mapping[src_idx].vk_memory; + image_memory_bind[i].memoryOffset = src_mapping[src_idx].byte_offset; + image_memory_bind[i].flags = 0; + ++src_loc->X; + is_end = d3d12_tiled_resource_coordinate_normalise(src_base, src_extent, src_loc); + ++dst_loc->X; + is_end |= d3d12_tiled_resource_coordinate_normalise(dst_base, dst_extent, dst_loc); + } + if (i < src_extent->NumTiles && src_loc->Subresource < src_resource->tiles.subresource_count + && dst_loc->Subresource < dst_resource->tiles.subresource_count) + FIXME("Multiple sub-resource support is not implemented.\n"); + + for (i = 0; i < src_extent->NumTiles; ++i) + { + d3d12_resource_update_image_tile_mappings(dst_resource, subresource, &image_memory_bind[i]); + vk_offset_convert_tiles_to_texels(&image_memory_bind[i].offset, &dst_resource->tiles.tile_extent); + vk_extent_convert_tiles_to_texels(&image_memory_bind[i].extent, &dst_resource->tiles.tile_extent); + } }
sparse_info.pSignalSemaphores = &vkd3d_queue->tiled_binding_semaphore; @@ -6870,14 +6944,9 @@ static void d3d12_command_queue_copy_tile_mappings(struct d3d12_command_queue *c struct vkd3d_resource_tile_coordinate dst_base, src_base; D3D12_TILED_RESOURCE_COORDINATE dst_loc, src_loc; D3D12_TILE_REGION_SIZE dst_extent, src_extent; + bool dst_miptail, src_miptail; VkQueue vk_queue;
- if (d3d12_resource_is_texture(dst_resource) || d3d12_resource_is_texture(src_resource)) - { - FIXME("Not implemented for textures.\n"); - return; - } - dst_loc = *dst_region_start_coordinate; src_loc = *src_region_start_coordinate; if (!vkd3d_initialise_tile_region(&dst_base, &dst_extent, &dst_loc, region_size, dst_resource) @@ -6893,14 +6962,32 @@ static void d3d12_command_queue_copy_tile_mappings(struct d3d12_command_queue *c && dst_loc.Z == src_loc.Z && dst_loc.Subresource == src_loc.Subresource)) return;
+ dst_miptail = dst_loc.Subresource % dst_resource->desc.MipLevels >= dst_resource->tiles.standard_mip_count; + src_miptail = src_loc.Subresource % src_resource->desc.MipLevels >= src_resource->tiles.standard_mip_count; + if (dst_miptail != src_miptail) + { + /* This scenario makes little sense. */ + FIXME("Not implemented for copies between a mip tail and a standard mip.\n"); + return; + } + if (!(vk_queue = vkd3d_queue_acquire(command_queue->vkd3d_queue))) { ERR("Failed to acquire queue %p.\n", command_queue->vkd3d_queue); return; }
- vkd3d_copy_vk_tile_mapping_region(command_queue, &dst_base, &dst_loc, &dst_extent, dst_resource, - &src_base, &src_loc, &src_extent, src_resource); + if (dst_miptail) + { + /* Already bound. */ + vkd3d_queue_release(command_queue->vkd3d_queue); + return; + } + else + { + vkd3d_copy_vk_tile_mapping_region(command_queue, &dst_base, &dst_loc, &dst_extent, dst_resource, + &src_base, &src_loc, &src_extent, src_resource); + }
vkd3d_queue_release(command_queue->vkd3d_queue); } diff --git a/tests/d3d12.c b/tests/d3d12.c index b1e68fa1f..3f9f712ce 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -37367,7 +37367,6 @@ static void test_update_tile_mappings(void) for (i = 0; i < j; i++) { set_box(&box, i, 0, 0, i + 1, 1, 1); - todo_if(i == 7 || i == 11 || i == 16) check_readback_data_uint(&rb.rb, &box, texture_region_tiles[i], 0); }