-- v4: vkd3d: Append CopyTileMappings() commands to the command queue op array. vkd3d: Append UpdateTileMappings() commands to the command queue op array. vkd3d: Add missing const attributes to ID3D12CommandQueue::UpdateTileMappings() parameters. vkd3d: Validate plane count for tiled textures. vkd3d: Validate tiled resources tier for 3D textures. vkd3d: Validate tiled resources support during reserved resource creation. vkd3d: Always pass null heap properties to vkd3d_create_image() for sparse images. vkd3d: Check sparse image format is supported.
From: Conor McCarthy cmccarthy@codeweavers.com
Based on code by Jan Sikorski. --- libs/vkd3d/resource.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 213b2dbbb..af6e904f2 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -779,6 +779,7 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, VkImageFormatListCreateInfoKHR format_list; const struct vkd3d_format *format; VkImageCreateInfo image_info; + uint32_t count; VkResult vr;
if (resource) @@ -914,6 +915,20 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, if (resource && image_info.tiling == VK_IMAGE_TILING_LINEAR) resource->flags |= VKD3D_RESOURCE_LINEAR_TILING;
+ if (sparse_resource) + { + count = 2; + VK_CALL(vkGetPhysicalDeviceSparseImageFormatProperties(device->vk_physical_device, image_info.format, + image_info.imageType, image_info.samples, image_info.usage, image_info.tiling, &count, NULL)); + + if (!count) + { + FIXME("Sparse images are not supported with format %u, type %u, samples %u, usage %#x.\n", + image_info.format, image_info.imageType, image_info.samples, image_info.usage); + return E_INVALIDARG; + } + } + if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, vk_image))) < 0) WARN("Failed to create Vulkan image, vr %d.\n", vr);
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/resource.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index af6e904f2..3df92f357 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -943,6 +943,7 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, D3D12_RESOURCE_DESC validated_desc; VkMemoryRequirements requirements; VkImage vk_image; + bool tiled; HRESULT hr;
assert(desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER); @@ -955,8 +956,10 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, desc = &validated_desc; }
+ tiled = desc->Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; + /* XXX: We have to create an image to get its memory requirements. */ - if (SUCCEEDED(hr = vkd3d_create_image(device, &heap_properties, 0, desc, NULL, &vk_image))) + if (SUCCEEDED(hr = vkd3d_create_image(device, tiled ? NULL : &heap_properties, 0, desc, NULL, &vk_image))) { VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements)); VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL));
From: Conor McCarthy cmccarthy@codeweavers.com
Check directly for Vulkan support because the D3D12 tiled resources tier may in future be modified by a config option. --- libs/vkd3d/device.c | 1 + libs/vkd3d/resource.c | 6 ++++++ libs/vkd3d/vkd3d_private.h | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 4263dcf41..3cb43bb41 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1464,6 +1464,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
vulkan_info->device_limits = physical_device_info->properties2.properties.limits; vulkan_info->sparse_properties = physical_device_info->properties2.properties.sparseProperties; + vulkan_info->sparse_binding = features->sparseBinding; vulkan_info->rasterization_stream = physical_device_info->xfb_properties.transformFeedbackRasterizationStreamSelect; vulkan_info->transform_feedback_queries = physical_device_info->xfb_properties.transformFeedbackQueries; vulkan_info->uav_read_without_format = features->shaderStorageImageReadWithoutFormat; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 3df92f357..5bfeef3bc 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1740,6 +1740,12 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12
resource->desc = *desc;
+ if (!heap_properties && !device->vk_info.sparse_binding) + { + WARN("The device does not support tiled images.\n"); + return E_INVALIDARG; + } + if (heap_properties && !d3d12_resource_validate_heap_properties(resource, heap_properties, initial_state)) return E_INVALIDARG;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index b01507544..2acfae682 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -147,9 +147,11 @@ struct vkd3d_vulkan_info unsigned int max_vertex_attrib_divisor;
VkPhysicalDeviceLimits device_limits; - VkPhysicalDeviceSparseProperties sparse_properties; struct vkd3d_device_descriptor_limits descriptor_limits;
+ VkPhysicalDeviceSparseProperties sparse_properties; + bool sparse_binding; + VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
unsigned int shader_extension_count;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/device.c | 1 + libs/vkd3d/resource.c | 9 +++++++++ libs/vkd3d/vkd3d_private.h | 1 + 3 files changed, 11 insertions(+)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 3cb43bb41..b9a8943cc 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1465,6 +1465,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->device_limits = physical_device_info->properties2.properties.limits; vulkan_info->sparse_properties = physical_device_info->properties2.properties.sparseProperties; vulkan_info->sparse_binding = features->sparseBinding; + vulkan_info->sparse_residency_3d = features->sparseResidencyImage3D; vulkan_info->rasterization_stream = physical_device_info->xfb_properties.transformFeedbackRasterizationStreamSelect; vulkan_info->transform_feedback_queries = physical_device_info->xfb_properties.transformFeedbackQueries; vulkan_info->uav_read_without_format = features->shaderStorageImageReadWithoutFormat; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 5bfeef3bc..3886311fc 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1679,6 +1679,15 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d return E_INVALIDARG; }
+ if (desc->Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE) + { + if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D && !device->vk_info.sparse_residency_3d) + { + WARN("The device does not support tiled 3D images.\n"); + return E_INVALIDARG; + } + } + if (!d3d12_resource_validate_texture_format(desc, format) || !d3d12_resource_validate_texture_alignment(desc, format)) return E_INVALIDARG; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 2acfae682..56a518fb8 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -151,6 +151,7 @@ struct vkd3d_vulkan_info
VkPhysicalDeviceSparseProperties sparse_properties; bool sparse_binding; + bool sparse_residency_3d;
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/resource.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 3886311fc..faa3a3b92 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1686,6 +1686,12 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d WARN("The device does not support tiled 3D images.\n"); return E_INVALIDARG; } + if (format->plane_count > 1) + { + WARN("Invalid format %#x. D3D12 does not support multiplanar formats for tiled resources.\n", + format->dxgi_format); + return E_INVALIDARG; + } }
if (!d3d12_resource_validate_texture_format(desc, format)
From: Conor McCarthy cmccarthy@codeweavers.com
--- include/vkd3d_d3d12.idl | 4 ++-- libs/vkd3d/command.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl index 652ffc364..06287f5a8 100644 --- a/include/vkd3d_d3d12.idl +++ b/include/vkd3d_d3d12.idl @@ -2266,8 +2266,8 @@ interface ID3D12CommandQueue : ID3D12Pageable ID3D12Heap *heap, UINT range_count, const D3D12_TILE_RANGE_FLAGS *range_flags, - UINT *heap_range_offsets, - UINT *range_tile_counts, + const UINT *heap_range_offsets, + const UINT *range_tile_counts, D3D12_TILE_MAPPING_FLAGS flags);
void CopyTileMappings(ID3D12Resource *dst_resource, diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 32439eec7..c5bd687bd 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -6166,7 +6166,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_UpdateTileMappings(ID3D12Comma ID3D12Resource *resource, UINT region_count, const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates, const D3D12_TILE_REGION_SIZE *region_sizes, ID3D12Heap *heap, UINT range_count, const D3D12_TILE_RANGE_FLAGS *range_flags, - UINT *heap_range_offsets, UINT *range_tile_counts, D3D12_TILE_MAPPING_FLAGS flags) + const UINT *heap_range_offsets, const UINT *range_tile_counts, D3D12_TILE_MAPPING_FLAGS flags) { FIXME("iface %p, resource %p, region_count %u, region_start_coordinates %p, " "region_sizes %p, heap %p, range_count %u, range_flags %p, heap_range_offsets %p, "
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/command.c | 126 ++++++++++++++++++++++++++++++++++++- libs/vkd3d/resource.c | 9 +++ libs/vkd3d/vkd3d_private.h | 25 ++++++++ 3 files changed, 158 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index c5bd687bd..fcb61ca6c 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -26,6 +26,7 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF static void d3d12_fence_signal_timeline_semaphore(struct d3d12_fence *fence, uint64_t timeline_value); static HRESULT d3d12_command_queue_signal(struct d3d12_command_queue *command_queue, struct d3d12_fence *fence, uint64_t value); +static void d3d12_command_queue_submit_locked(struct d3d12_command_queue *queue); static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any); static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue *queue, bool *flushed_any);
@@ -6162,17 +6163,131 @@ static struct vkd3d_cs_op_data *d3d12_command_queue_op_array_require_space(struc return &array->ops[array->count++]; }
+static bool clone_array_parameter(void **dst, const void *src, size_t elem_size, unsigned int count) +{ + void *buffer; + + *dst = NULL; + if (src) + { + if (!(buffer = vkd3d_calloc(count, elem_size))) + return false; + memcpy(buffer, src, count * elem_size); + *dst = buffer; + } + return true; +} + +static void update_mappings_cleanup(struct vkd3d_cs_update_mappings *update_mappings) +{ + vkd3d_free(update_mappings->region_start_coordinates); + vkd3d_free(update_mappings->region_sizes); + vkd3d_free(update_mappings->range_flags); + vkd3d_free(update_mappings->heap_range_offsets); + vkd3d_free(update_mappings->range_tile_counts); +} + static void STDMETHODCALLTYPE d3d12_command_queue_UpdateTileMappings(ID3D12CommandQueue *iface, ID3D12Resource *resource, UINT region_count, const D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates, const D3D12_TILE_REGION_SIZE *region_sizes, ID3D12Heap *heap, UINT range_count, const D3D12_TILE_RANGE_FLAGS *range_flags, const UINT *heap_range_offsets, const UINT *range_tile_counts, D3D12_TILE_MAPPING_FLAGS flags) { - FIXME("iface %p, resource %p, region_count %u, region_start_coordinates %p, " + struct d3d12_resource *resource_impl = unsafe_impl_from_ID3D12Resource(resource); + struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface); + struct d3d12_heap *heap_impl = unsafe_impl_from_ID3D12Heap(heap); + struct vkd3d_cs_update_mappings update_mappings = {0}; + struct vkd3d_cs_op_data *op; + + TRACE("iface %p, resource %p, region_count %u, region_start_coordinates %p, " "region_sizes %p, heap %p, range_count %u, range_flags %p, heap_range_offsets %p, " - "range_tile_counts %p, flags %#x stub!\n", + "range_tile_counts %p, flags %#x.\n", iface, resource, region_count, region_start_coordinates, region_sizes, heap, range_count, range_flags, heap_range_offsets, range_tile_counts, flags); + + if (!region_count || !range_count) + return; + + if (!command_queue->supports_sparse_binding) + { + FIXME("Command queue %p does not support sparse binding.\n", command_queue); + return; + } + + if (!resource_impl->tiles.subresource_count) + { + WARN("Resource %p is not a tiled resource.\n", resource_impl); + return; + } + + if (region_count > 1 && !region_start_coordinates) + { + WARN("Region start coordinates must not be NULL when region count is > 1.\n"); + return; + } + + if (range_count > 1 && !range_tile_counts) + { + WARN("Range tile counts must not be NULL when range count is > 1.\n"); + return; + } + + update_mappings.resource = resource_impl; + update_mappings.heap = heap_impl; + if (!clone_array_parameter((void **)&update_mappings.region_start_coordinates, + region_start_coordinates, sizeof(*region_start_coordinates), region_count)) + { + ERR("Failed to allocate region start coordinates.\n"); + return; + } + if (!clone_array_parameter((void **)&update_mappings.region_sizes, + region_sizes, sizeof(*region_sizes), region_count)) + { + ERR("Failed to allocate region sizes.\n"); + goto free_clones; + } + if (!clone_array_parameter((void **)&update_mappings.range_flags, + range_flags, sizeof(*range_flags), range_count)) + { + ERR("Failed to allocate range flags.\n"); + goto free_clones; + } + if (!clone_array_parameter((void **)&update_mappings.heap_range_offsets, + heap_range_offsets, sizeof(*heap_range_offsets), range_count)) + { + ERR("Failed to allocate heap range offsets.\n"); + goto free_clones; + } + if (!clone_array_parameter((void **)&update_mappings.range_tile_counts, + range_tile_counts, sizeof(*range_tile_counts), range_count)) + { + ERR("Failed to allocate range tile counts.\n"); + goto free_clones; + } + update_mappings.region_count = region_count; + update_mappings.range_count = range_count; + update_mappings.flags = flags; + + vkd3d_mutex_lock(&command_queue->op_mutex); + + if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue))) + { + ERR("Failed to add op.\n"); + goto unlock_mutex; + } + + op->opcode = VKD3D_CS_OP_UPDATE_MAPPINGS; + op->u.update_mappings = update_mappings; + + d3d12_command_queue_submit_locked(command_queue); + + vkd3d_mutex_unlock(&command_queue->op_mutex); + return; + +unlock_mutex: + vkd3d_mutex_unlock(&command_queue->op_mutex); +free_clones: + update_mappings_cleanup(&update_mappings); }
static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12CommandQueue *iface, @@ -6934,6 +7049,11 @@ static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue * d3d12_command_queue_execute(queue, op->u.execute.buffers, op->u.execute.buffer_count); break;
+ case VKD3D_CS_OP_UPDATE_MAPPINGS: + FIXME("Tiled resource binding is not supported yet.\n"); + update_mappings_cleanup(&op->u.update_mappings); + break; + default: vkd3d_unreachable(); } @@ -7000,6 +7120,8 @@ static HRESULT d3d12_command_queue_init(struct d3d12_command_queue *queue, if (FAILED(hr = vkd3d_fence_worker_start(&queue->fence_worker, queue->vkd3d_queue, device))) goto fail_destroy_op_mutex;
+ queue->supports_sparse_binding = !!(queue->vkd3d_queue->vk_queue_flags & VK_QUEUE_SPARSE_BINDING_BIT); + d3d12_device_add_ref(queue->device = device);
return S_OK; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index faa3a3b92..609793511 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1057,6 +1057,11 @@ static void d3d12_resource_get_level_box(const struct d3d12_resource *resource, box->back = d3d12_resource_desc_get_depth(&resource->desc, level); }
+static void d3d12_resource_init_tiles(struct d3d12_resource *resource) +{ + resource->tiles.subresource_count = d3d12_resource_desc_get_sub_resource_count(&resource->desc); +} + /* ID3D12Resource */ static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface) { @@ -1826,6 +1831,8 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 resource->heap = NULL; resource->heap_offset = 0;
+ memset(&resource->tiles, 0, sizeof(resource->tiles)); + if (FAILED(hr = vkd3d_private_store_init(&resource->private_store))) { d3d12_resource_destroy(resource, device); @@ -2011,6 +2018,8 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device, desc, initial_state, optimized_clear_value, &object))) return hr;
+ d3d12_resource_init_tiles(object); + TRACE("Created reserved resource %p.\n", object);
*resource = object; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 56a518fb8..ce3f48947 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -673,6 +673,11 @@ struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface); #define VKD3D_RESOURCE_DEDICATED_HEAP 0x00000008 #define VKD3D_RESOURCE_LINEAR_TILING 0x00000010
+struct d3d12_resource_tile_info +{ + unsigned int subresource_count; +}; + /* ID3D12Resource */ struct d3d12_resource { @@ -701,6 +706,8 @@ struct d3d12_resource
struct d3d12_device *device;
+ struct d3d12_resource_tile_info tiles; + struct vkd3d_private_store private_store; };
@@ -1457,6 +1464,7 @@ enum vkd3d_cs_op VKD3D_CS_OP_WAIT, VKD3D_CS_OP_SIGNAL, VKD3D_CS_OP_EXECUTE, + VKD3D_CS_OP_UPDATE_MAPPINGS, };
struct vkd3d_cs_wait @@ -1477,6 +1485,20 @@ struct vkd3d_cs_execute unsigned int buffer_count; };
+struct vkd3d_cs_update_mappings +{ + struct d3d12_resource *resource; + struct d3d12_heap *heap; + D3D12_TILED_RESOURCE_COORDINATE *region_start_coordinates; + D3D12_TILE_REGION_SIZE *region_sizes; + D3D12_TILE_RANGE_FLAGS *range_flags; + UINT *heap_range_offsets; + UINT *range_tile_counts; + UINT region_count; + UINT range_count; + D3D12_TILE_MAPPING_FLAGS flags; +}; + struct vkd3d_cs_op_data { enum vkd3d_cs_op opcode; @@ -1485,6 +1507,7 @@ struct vkd3d_cs_op_data struct vkd3d_cs_wait wait; struct vkd3d_cs_signal signal; struct vkd3d_cs_execute execute; + struct vkd3d_cs_update_mappings update_mappings; } u; };
@@ -1522,6 +1545,8 @@ struct d3d12_command_queue * set, aux_op_queue.count must be zero. */ struct d3d12_command_queue_op_array aux_op_queue;
+ bool supports_sparse_binding; + struct vkd3d_private_store private_store; };
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/command.c | 32 ++++++++++++++++++++++++++++++-- libs/vkd3d/resource.c | 5 ----- libs/vkd3d/vkd3d_private.h | 17 +++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index fcb61ca6c..1fc6c00de 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -6298,10 +6298,34 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command const D3D12_TILE_REGION_SIZE *region_size, D3D12_TILE_MAPPING_FLAGS flags) { - FIXME("iface %p, dst_resource %p, dst_region_start_coordinate %p, " - "src_resource %p, src_region_start_coordinate %p, region_size %p, flags %#x stub!\n", + struct d3d12_resource *dst_resource_impl = impl_from_ID3D12Resource(dst_resource); + struct d3d12_resource *src_resource_impl = impl_from_ID3D12Resource(src_resource); + struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface); + struct vkd3d_cs_op_data *op; + + TRACE("iface %p, dst_resource %p, dst_region_start_coordinate %p, " + "src_resource %p, src_region_start_coordinate %p, region_size %p, flags %#x.\n", iface, dst_resource, dst_region_start_coordinate, src_resource, src_region_start_coordinate, region_size, flags); + + vkd3d_mutex_lock(&command_queue->op_mutex); + + if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue))) + { + ERR("Failed to add op.\n"); + return; + } + op->opcode = VKD3D_CS_OP_COPY_MAPPINGS; + op->u.copy_mappings.dst_resource = dst_resource_impl; + op->u.copy_mappings.src_resource = src_resource_impl; + op->u.copy_mappings.dst_region_start_coordinate = *dst_region_start_coordinate; + op->u.copy_mappings.src_region_start_coordinate = *src_region_start_coordinate; + op->u.copy_mappings.region_size = *region_size; + op->u.copy_mappings.flags = flags; + + d3d12_command_queue_submit_locked(command_queue); + + vkd3d_mutex_unlock(&command_queue->op_mutex); }
static void d3d12_command_queue_execute(struct d3d12_command_queue *command_queue, @@ -7054,6 +7078,10 @@ static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue * update_mappings_cleanup(&op->u.update_mappings); break;
+ case VKD3D_CS_OP_COPY_MAPPINGS: + FIXME("Tiled resource mapping copying is not supported yet.\n"); + break; + default: vkd3d_unreachable(); } diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 609793511..97d8935bd 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1063,11 +1063,6 @@ static void d3d12_resource_init_tiles(struct d3d12_resource *resource) }
/* ID3D12Resource */ -static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface) -{ - return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource_iface); -} - static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource *iface, REFIID riid, void **object) { diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index ce3f48947..c5259420a 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -711,6 +711,11 @@ struct d3d12_resource struct vkd3d_private_store private_store; };
+static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource_iface); +} + static inline bool d3d12_resource_is_buffer(const struct d3d12_resource *resource) { return resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER; @@ -1465,6 +1470,7 @@ enum vkd3d_cs_op VKD3D_CS_OP_SIGNAL, VKD3D_CS_OP_EXECUTE, VKD3D_CS_OP_UPDATE_MAPPINGS, + VKD3D_CS_OP_COPY_MAPPINGS, };
struct vkd3d_cs_wait @@ -1499,6 +1505,16 @@ struct vkd3d_cs_update_mappings D3D12_TILE_MAPPING_FLAGS flags; };
+struct vkd3d_cs_copy_mappings +{ + struct d3d12_resource *dst_resource; + struct d3d12_resource *src_resource; + D3D12_TILED_RESOURCE_COORDINATE dst_region_start_coordinate; + D3D12_TILED_RESOURCE_COORDINATE src_region_start_coordinate; + D3D12_TILE_REGION_SIZE region_size; + D3D12_TILE_MAPPING_FLAGS flags; +}; + struct vkd3d_cs_op_data { enum vkd3d_cs_op opcode; @@ -1508,6 +1524,7 @@ struct vkd3d_cs_op_data struct vkd3d_cs_signal signal; struct vkd3d_cs_execute execute; struct vkd3d_cs_update_mappings update_mappings; + struct vkd3d_cs_copy_mappings copy_mappings; } u; };
On Fri Jun 9 14:02:43 2023 +0000, Giovanni Mascellani wrote:
Unless I'm mistaken, this doesn't produce any behavior change, since inside `vkd3d_create_image()` parameter `heap_properties` is only used in `heap_properties && is_cpu_accessible_heap(heap_properties)`, and `is_cpu_accessible_heap(heap_properties)` is `false` anyway. So I guess you're making this change because it is needed for some upcoming patch? Though it doesn't seem that any patch in this MR has something to do with that.
It's also used to set `bool sparse_resource`
On Fri Jun 9 14:02:46 2023 +0000, Giovanni Mascellani wrote:
I guess the robust solution should be to potentially have a dedicated queue for sparse binding, and then put in place appropriate synchronization when updating mappings? In Vulkan it seems that a device could offer no queue which has both graphics and sparse binding capabilities. With D3D12 is seems that tile updating is always possible on graphics queues.
Yes the implementation patches will need to do something about this. It's already necessary to wait on a semaphore after binding, so it's just a matter of signalling in the sparse binding queue and waiting in the other.
On Mon Jun 12 14:39:02 2023 +0000, Conor McCarthy wrote:
changed this line in [version 4 of the diff](/wine/vkd3d/-/merge_requests/216/diffs?diff_id=51403&start_sha=f168489f35614a8556418200b2fd8d82743c0dfb#6ce56346069f6ab6f2e9a298a46873ae68494ff2_6236_6235)
It's invalid to free a resource while a binding operation is pending, and it is still pending for the caller even if we've delayed it in our virtual queue. I think generally we don't do "just in case" AddRef() calls and instead fix issues if/when they arise.
On Mon Jun 12 14:41:13 2023 +0000, Conor McCarthy wrote:
It's also used to set `bool sparse_resource`
Ah, indeed, my bad!
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/resource.c:
if (resource && image_info.tiling == VK_IMAGE_TILING_LINEAR) resource->flags |= VKD3D_RESOURCE_LINEAR_TILING;
- if (sparse_resource)
- {
count = 2;
Not a big deal, but I can remove this line and get no warning with GCC 12 (both native and MinGW).
This merge request was approved by Giovanni Mascellani.