From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d/device.c | 118 +++++++++++++++++++++---------------- libs/vkd3d/resource.c | 6 +- libs/vkd3d/vkd3d_private.h | 9 ++- tests/d3d12.c | 2 - 4 files changed, 77 insertions(+), 58 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 3d16800e3..0daf5f652 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1969,7 +1969,7 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance, * which applies to resources of a total size of 4 MiB or less. */ static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device) { - D3D12_RESOURCE_ALLOCATION_INFO info; + struct vkd3d_resource_allocation_info info; D3D12_RESOURCE_DESC resource_desc;
memset(&resource_desc, 0, sizeof(resource_desc)); @@ -1986,7 +1986,7 @@ static bool d3d12_is_64k_msaa_supported(struct d3d12_device *device) * resources, which must have 0x10000 in their description, so we might * reasonably return true here for 0x20000 or 0x40000. */ return SUCCEEDED(vkd3d_get_image_allocation_info(device, &resource_desc, &info)) - && info.Alignment <= 0x10000; + && info.alignment <= 0x10000; }
static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, @@ -3566,79 +3566,93 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device7 * 1, &src_descriptor_range_offset, &descriptor_count, descriptor_heap_type); }
-static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo( - ID3D12Device7 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, - UINT count, const D3D12_RESOURCE_DESC *resource_descs) +static void d3d12_device_get_resource_allocation_info(struct d3d12_device *device, + unsigned int count, const D3D12_RESOURCE_DESC *resource_descs, + D3D12_RESOURCE_ALLOCATION_INFO *result) { - struct d3d12_device *device = impl_from_ID3D12Device7(iface); + struct vkd3d_resource_allocation_info info; const D3D12_RESOURCE_DESC *desc; uint64_t requested_alignment; + unsigned int i;
- TRACE("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p.\n", - iface, info, visible_mask, count, resource_descs); - - debug_ignored_node_mask(visible_mask); - - info->SizeInBytes = 0; - info->Alignment = 0; - - if (count != 1) - { - FIXME("Multiple resource descriptions not supported.\n"); - return info; - } + result->Alignment = 0; + result->SizeInBytes = 0;
- desc = &resource_descs[0]; + info.offset = 0;
- if (FAILED(d3d12_resource_validate_desc(desc, device))) + for (i = 0; i < count; ++i) { - WARN("Invalid resource desc.\n"); - goto invalid; - } + desc = &resource_descs[i];
- if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - { - info->SizeInBytes = align(desc->Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); - info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - } - else - { - if (FAILED(vkd3d_get_image_allocation_info(device, desc, info))) + if (FAILED(d3d12_resource_validate_desc(desc, device))) { - WARN("Failed to get allocation info for texture.\n"); + WARN("Invalid resource desc.\n"); goto invalid; }
- requested_alignment = desc->Alignment - ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - info->Alignment = max(info->Alignment, requested_alignment); + if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + info.alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + info.offset = align(info.offset, info.alignment); + info.size_in_bytes = align(desc->Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); + } + else + { + if (FAILED(vkd3d_get_image_allocation_info(device, desc, &info))) + { + WARN("Failed to get allocation info for texture.\n"); + goto invalid; + } + + requested_alignment = desc->Alignment + ? desc->Alignment : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + info.alignment = max(info.alignment, requested_alignment); + info.size_in_bytes = align(info.size_in_bytes, info.alignment);
- info->SizeInBytes = align(info->SizeInBytes, info->Alignment); + /* Pad by the maximum heap offset increase which may be needed to align to a higher + * Vulkan requirement an offset supplied by the calling application. This allows + * us to return the standard D3D12 alignment and adjust resource placement later. */ + if (info.alignment > requested_alignment) + { + info.size_in_bytes += info.alignment - requested_alignment; + info.alignment = requested_alignment; + }
- /* Pad by the maximum heap offset increase which may be needed to align to a higher - * Vulkan requirement an offset supplied by the calling application. This allows - * us to return the standard D3D12 alignment and adjust resource placement later. */ - if (info->Alignment > requested_alignment) - { - info->SizeInBytes += info->Alignment - requested_alignment; - info->Alignment = requested_alignment; + info.offset = align(info.offset, info.alignment); } - }
- TRACE("Size %#"PRIx64", alignment %#"PRIx64".\n", info->SizeInBytes, info->Alignment); + info.offset += info.size_in_bytes;
- return info; + result->Alignment = max(result->Alignment, info.alignment); + result->SizeInBytes = info.offset; + } + + return;
invalid: - info->SizeInBytes = ~(uint64_t)0; + result->SizeInBytes = UINT64_MAX;
- /* FIXME: Should we support D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT for small MSSA resources? */ + /* FIXME: Should we support D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT for small MSAA resources? */ if (desc->SampleDesc.Count != 1) - info->Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; + result->Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; else - info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + result->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + + TRACE("Alignment %#"PRIx64".\n", result->Alignment); +} + +static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo( + ID3D12Device7 *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask, + UINT count, const D3D12_RESOURCE_DESC *resource_descs) +{ + struct d3d12_device *device = impl_from_ID3D12Device7(iface); + + TRACE("iface %p, info %p, visible_mask 0x%08x, count %u, resource_descs %p.\n", + iface, info, visible_mask, count, resource_descs); + + debug_ignored_node_mask(visible_mask);
- TRACE("Alignment %#"PRIx64".\n", info->Alignment); + d3d12_device_get_resource_allocation_info(device, count, resource_descs, info);
return info; } diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index f187c1576..373de24f9 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -940,7 +940,7 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device, }
HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, - const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info) + const D3D12_RESOURCE_DESC *desc, struct vkd3d_resource_allocation_info *allocation_info) { static const D3D12_HEAP_PROPERTIES heap_properties = {D3D12_HEAP_TYPE_DEFAULT}; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; @@ -968,8 +968,8 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements)); VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL));
- allocation_info->SizeInBytes = requirements.size; - allocation_info->Alignment = requirements.alignment; + allocation_info->size_in_bytes = requirements.size; + allocation_info->alignment = requirements.alignment; }
return hr; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 6269eb104..c551cc2f7 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -770,6 +770,13 @@ static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resour return resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER; }
+struct vkd3d_resource_allocation_info +{ + uint64_t offset; + uint64_t alignment; + uint64_t size_in_bytes; +}; + bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource); HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device); void d3d12_resource_get_tiling(struct d3d12_device *device, const struct d3d12_resource *resource, @@ -797,7 +804,7 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, const D3D12_RESOURCE_DESC *desc, VkBuffer *vk_buffer); HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, - const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_ALLOCATION_INFO *allocation_info); + const D3D12_RESOURCE_DESC *desc, struct vkd3d_resource_allocation_info *allocation_info);
enum vkd3d_view_type { diff --git a/tests/d3d12.c b/tests/d3d12.c index 9a1f35c87..4a1284053 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -32289,11 +32289,9 @@ static void test_resource_allocation_info(void) : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; } info = ID3D12Device_GetResourceAllocationInfo(device, 0, ARRAY_SIZE(desc_array), desc_array); - todo ok(info.Alignment >= D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, "Got unexpected alignment %"PRIu64".\n", info.Alignment); check_alignment(info.SizeInBytes, info.Alignment); - todo ok(info.SizeInBytes >= total, "Got unexpected size %"PRIu64".\n", info.SizeInBytes);
refcount = ID3D12Device_Release(device);