-- v3: 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.
From: Conor McCarthy cmccarthy@codeweavers.com
Based on code by Jan Sikorski. --- libs/vkd3d/resource.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 213b2dbbb..b381350cc 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -776,9 +776,11 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_format_compatibility_list *compat_list; const bool sparse_resource = !heap_properties; + VkSparseImageFormatProperties properties[2]; VkImageFormatListCreateInfoKHR format_list; const struct vkd3d_format *format; VkImageCreateInfo image_info; + uint32_t count; VkResult vr;
if (resource) @@ -914,6 +916,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 = ARRAY_SIZE(properties); + VK_CALL(vkGetPhysicalDeviceSparseImageFormatProperties(device->vk_physical_device, image_info.format, + image_info.imageType, image_info.samples, image_info.usage, image_info.tiling, &count, properties)); + + 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 b381350cc..cfc7aff21 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -944,6 +944,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); @@ -956,8 +957,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 | 9 +++++++++ libs/vkd3d/vkd3d_private.h | 4 +++- 3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 4263dcf41..007a6f651 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_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 cfc7aff21..a1b2e6548 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1680,6 +1680,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 b01507544..dde82414f 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_residency_3d; + VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
unsigned int shader_extension_count;
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 a1b2e6548..0444db7ff 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1687,6 +1687,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 | 114 ++++++++++++++++++++++++++++++++++++- libs/vkd3d/resource.c | 9 +++ libs/vkd3d/vkd3d_private.h | 25 ++++++++ 3 files changed, 146 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index c5bd687bd..f7cec81ec 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,115 @@ static struct vkd3d_cs_op_data *d3d12_command_queue_op_array_require_space(struc return &array->ops[array->count++]; }
+static bool clone_tile_mapping_parameter(void **dst, const void *src, size_t elem_size, unsigned int count) +{ + void *buffer; + + *dst = NULL; + if (src) + { + if (!(buffer = vkd3d_malloc(count * elem_size))) + return false; + memcpy(buffer, src, count * elem_size); + *dst = buffer; + } + return true; +} + 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_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; + } + + 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 done; + } + + op->opcode = VKD3D_CS_OP_UPDATE_MAPPINGS; + memset(&op->u.update_mappings, 0, sizeof(op->u.update_mappings)); + op->u.update_mappings.resource = resource_impl; + op->u.update_mappings.heap = heap_impl; + if (!clone_tile_mapping_parameter((void **)&op->u.update_mappings.region_start_coordinates, + region_start_coordinates, sizeof(*region_start_coordinates), region_count)) + { + ERR("Failed to allocate region start coordinates.\n"); + goto done; + } + if (!clone_tile_mapping_parameter((void **)&op->u.update_mappings.region_sizes, + region_sizes, sizeof(*region_sizes), region_count)) + { + ERR("Failed to allocate region sizes.\n"); + goto done; + } + if (!clone_tile_mapping_parameter((void **)&op->u.update_mappings.range_flags, + range_flags, sizeof(*range_flags), range_count)) + { + ERR("Failed to allocate range flags.\n"); + goto done; + } + if (!clone_tile_mapping_parameter((void **)&op->u.update_mappings.heap_range_offsets, + heap_range_offsets, sizeof(*heap_range_offsets), range_count)) + { + ERR("Failed to allocate heap range offsets.\n"); + goto done; + } + if (!clone_tile_mapping_parameter((void **)&op->u.update_mappings.range_tile_counts, + range_tile_counts, sizeof(*range_tile_counts), range_count)) + { + ERR("Failed to allocate range tile counts.\n"); + goto done; + } + op->u.update_mappings.region_count = region_count; + op->u.update_mappings.range_count = range_count; + op->u.update_mappings.flags = flags; + + d3d12_command_queue_submit_locked(command_queue); + +done: + vkd3d_mutex_unlock(&command_queue->op_mutex); }
static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12CommandQueue *iface, @@ -6934,6 +7033,15 @@ 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"); + vkd3d_free(op->u.update_mappings.region_start_coordinates); + vkd3d_free(op->u.update_mappings.region_sizes); + vkd3d_free(op->u.update_mappings.range_flags); + vkd3d_free(op->u.update_mappings.heap_range_offsets); + vkd3d_free(op->u.update_mappings.range_tile_counts); + break; + default: vkd3d_unreachable(); } @@ -7000,6 +7108,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 0444db7ff..f4bbdfe03 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1058,6 +1058,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) { @@ -1821,6 +1826,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); @@ -2006,6 +2013,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 dde82414f..b4a544828 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -672,6 +672,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 { @@ -700,6 +705,8 @@ struct d3d12_resource
struct d3d12_device *device;
+ struct d3d12_resource_tile_info tiles; + struct vkd3d_private_store private_store; };
@@ -1456,6 +1463,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 @@ -1476,6 +1484,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; @@ -1484,6 +1506,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; };
@@ -1521,6 +1544,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 f7cec81ec..39c0f4cd3 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -6282,10 +6282,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, @@ -7042,6 +7066,10 @@ static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue * vkd3d_free(op->u.update_mappings.range_tile_counts); 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 f4bbdfe03..dbecd0098 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1064,11 +1064,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 b4a544828..48d66ad4a 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -710,6 +710,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; @@ -1464,6 +1469,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 @@ -1498,6 +1504,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; @@ -1507,6 +1523,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; };
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/resource.c:
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_format_compatibility_list *compat_list; const bool sparse_resource = !heap_properties;
- VkSparseImageFormatProperties properties[2];
Are you going to use this array? So far it doesn't look like, in which case you can just pass `NULL` to `vkGetPhysicalDeviceSparseImageFormatProperties()`.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/resource.c:
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)))
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.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/resource.c:
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)
Shouldn't an equivalent check be made for both 2D and 3D resources, testing for `sparseBinding`? Or is it already done? I couldn't find it.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/command.c:
return &array->ops[array->count++];
}
+static bool clone_tile_mapping_parameter(void **dst, const void *src, size_t elem_size, unsigned int count) +{
- void *buffer;
- *dst = NULL;
- if (src)
- {
if (!(buffer = vkd3d_malloc(count * elem_size)))
I would suggest `vkd3d_calloc()`, so that overflow is detected.
As an aside, the method is not really specific for tile mappings, so it could get a more generic name. Like `clone_array()`.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/command.c:
- struct d3d12_heap *heap_impl = unsafe_impl_from_ID3D12Heap(heap);
- 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);
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.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/command.c:
- if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue)))
- {
ERR("Failed to add op.\n");
goto done;
- }
- op->opcode = VKD3D_CS_OP_UPDATE_MAPPINGS;
- memset(&op->u.update_mappings, 0, sizeof(op->u.update_mappings));
- op->u.update_mappings.resource = resource_impl;
- op->u.update_mappings.heap = heap_impl;
- if (!clone_tile_mapping_parameter((void **)&op->u.update_mappings.region_start_coordinates,
region_start_coordinates, sizeof(*region_start_coordinates), region_count))
- {
ERR("Failed to allocate region start coordinates.\n");
goto done;
All this `goto`'s do not properly release allocated memory, and leave the half-filled op structure in the array, even if they don't submit for flushing.
Also, maybe all the clone operations could be done before taking the `op_mutex` lock, so there is as little contention as possible. I am never sure on this kind of micro-optimizations, but I always feel some excitement for critical sections that only set a few bytes and are done.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/command.c:
WARN("Range tile counts must not be NULL when range count is > 1.\n");
return;
- }
- 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 done;
- }
- op->opcode = VKD3D_CS_OP_UPDATE_MAPPINGS;
- memset(&op->u.update_mappings, 0, sizeof(op->u.update_mappings));
- op->u.update_mappings.resource = resource_impl;
- op->u.update_mappings.heap = heap_impl;
It seems `AddRef()` should be called here.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d/command.c:
- 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;
These probably need an `AddRef()` too.