[PATCH v3 0/7] MR216: vkd3d: Prepare for tiled resource support.
-- 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. https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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); -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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)); -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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; -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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) -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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, " -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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; }; -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
From: Conor McCarthy <cmccarthy(a)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; }; -- GitLab https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216
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()`. -- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35264
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. -- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35266
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. -- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35265
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()`. -- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35267
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.
-- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35268
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. -- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35269
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.
-- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35270
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.
-- https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/216#note_35271
participants (3)
-
Conor McCarthy -
Conor McCarthy (@cmccarthy) -
Giovanni Mascellani (@giomasce)