[PATCH vkd3d 4/5] vkd3d: Create private heap objects for committed resources.

Józef Kucia joseph.kucia at gmail.com
Thu Jun 20 14:08:08 CDT 2019


From: Józef Kucia <jkucia at codeweavers.com>

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
 libs/vkd3d/device.c        |   2 +-
 libs/vkd3d/resource.c      | 201 +++++++++++++++++++------------------
 libs/vkd3d/vkd3d_private.h |  12 +--
 3 files changed, 113 insertions(+), 102 deletions(-)

diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 7522c413278a..f67713594ea5 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2758,7 +2758,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device *iface,
     TRACE("iface %p, desc %p, iid %s, heap %p.\n",
             iface, desc, debugstr_guid(iid), heap);
 
-    if (FAILED(hr = d3d12_heap_create(device, desc, &object)))
+    if (FAILED(hr = d3d12_heap_create(device, desc, NULL, &object)))
     {
         *heap = NULL;
         return hr;
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index f1cbff11d1ea..0e13cc53e018 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -21,8 +21,6 @@
 #define VKD3D_NULL_BUFFER_SIZE 16
 #define VKD3D_NULL_VIEW_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM
 
-#define VKD3D_HEAP_TYPE_INVALID ((D3D12_HEAP_TYPE)~0u)
-
 static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *properties)
 {
     if (properties->Type == D3D12_HEAP_TYPE_DEFAULT)
@@ -288,31 +286,42 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface)
 
     TRACE("%p increasing refcount to %u.\n", heap, refcount);
 
+    assert(!heap->is_private);
+
     return refcount;
 }
 
-static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
+static void d3d12_heap_destroy(struct d3d12_heap *heap)
 {
-    struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
-    ULONG refcount = InterlockedDecrement(&heap->refcount);
+    struct d3d12_device *device = heap->device;
+    const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
 
-    TRACE("%p decreasing refcount to %u.\n", heap, refcount);
+    TRACE("Destroying heap %p.\n", heap);
 
-    if (!refcount)
-    {
-        struct d3d12_device *device = heap->device;
-        const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+    vkd3d_private_store_destroy(&heap->private_store);
 
-        vkd3d_private_store_destroy(&heap->private_store);
+    VK_CALL(vkFreeMemory(device->vk_device, heap->vk_memory, NULL));
 
-        VK_CALL(vkFreeMemory(device->vk_device, heap->vk_memory, NULL));
+    pthread_mutex_destroy(&heap->mutex);
 
-        pthread_mutex_destroy(&heap->mutex);
+    if (heap->is_private)
+        device = NULL;
 
-        vkd3d_free(heap);
+    vkd3d_free(heap);
 
+    if (device)
         d3d12_device_release(device);
-    }
+}
+
+static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
+{
+    struct d3d12_heap *heap = impl_from_ID3D12Heap(iface);
+    ULONG refcount = InterlockedDecrement(&heap->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", heap, refcount);
+
+    if (!refcount)
+        d3d12_heap_destroy(heap);
 
     return refcount;
 }
@@ -437,6 +446,10 @@ static HRESULT d3d12_heap_map(struct d3d12_heap *heap, uint64_t offset, void **d
         *data = (BYTE *)heap->map_ptr + offset;
         ++heap->map_count;
     }
+    else
+    {
+        *data = NULL;
+    }
 
     pthread_mutex_unlock(&heap->mutex);
 
@@ -475,9 +488,9 @@ static void d3d12_heap_unmap(struct d3d12_heap *heap)
     pthread_mutex_unlock(&heap->mutex);
 }
 
-static HRESULT validate_heap_desc(const D3D12_HEAP_DESC *desc)
+static HRESULT validate_heap_desc(const D3D12_HEAP_DESC *desc, const struct d3d12_resource *resource)
 {
-    if (!desc->SizeInBytes)
+    if (!resource && !desc->SizeInBytes)
     {
         WARN("Invalid size %"PRIu64".\n", desc->SizeInBytes);
         return E_INVALIDARG;
@@ -490,7 +503,7 @@ static HRESULT validate_heap_desc(const D3D12_HEAP_DESC *desc)
         return E_INVALIDARG;
     }
 
-    if (desc->Flags & D3D12_HEAP_FLAG_ALLOW_DISPLAY)
+    if (!resource && desc->Flags & D3D12_HEAP_FLAG_ALLOW_DISPLAY)
     {
         WARN("D3D12_HEAP_FLAG_ALLOW_DISPLAY is only for committed resources.\n");
         return E_INVALIDARG;
@@ -500,15 +513,18 @@ static HRESULT validate_heap_desc(const D3D12_HEAP_DESC *desc)
 }
 
 static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
-        struct d3d12_device *device, const D3D12_HEAP_DESC *desc)
+        struct d3d12_device *device, const D3D12_HEAP_DESC *desc, const struct d3d12_resource *resource)
 {
     VkMemoryRequirements memory_requirements;
+    VkDeviceSize vk_memory_size;
     HRESULT hr;
     int rc;
 
     heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
     heap->refcount = 1;
 
+    heap->is_private = !!resource;
+
     heap->desc = *desc;
 
     heap->map_ptr = NULL;
@@ -525,13 +541,9 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
     if (!heap->desc.Alignment)
         heap->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
 
-    if (FAILED(hr = validate_heap_desc(&heap->desc)))
+    if (FAILED(hr = validate_heap_desc(&heap->desc, resource)))
         return hr;
 
-    memory_requirements.size = heap->desc.SizeInBytes;
-    memory_requirements.alignment = heap->desc.Alignment;
-    memory_requirements.memoryTypeBits = ~(uint32_t)0;
-
     if ((rc = pthread_mutex_init(&heap->mutex, NULL)))
     {
         ERR("Failed to initialize mutex, error %d.\n", rc);
@@ -544,21 +556,49 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
         return hr;
     }
 
-    if (FAILED(hr = vkd3d_allocate_device_memory(device, &heap->desc.Properties,
-            heap->desc.Flags, &memory_requirements, NULL, &heap->vk_memory, &heap->vk_memory_type)))
+    if (resource)
+    {
+        if (d3d12_resource_is_buffer(resource))
+        {
+            hr = vkd3d_allocate_buffer_memory(device, resource->u.vk_buffer,
+                    &heap->desc.Properties, heap->desc.Flags,
+                    &heap->vk_memory, &heap->vk_memory_type, &vk_memory_size);
+        }
+        else
+        {
+            hr = vkd3d_allocate_image_memory(device, resource->u.vk_image,
+                    &heap->desc.Properties, heap->desc.Flags,
+                    &heap->vk_memory, &heap->vk_memory_type, &vk_memory_size);
+        }
+
+        heap->desc.SizeInBytes = vk_memory_size;
+    }
+    else
+    {
+        memory_requirements.size = heap->desc.SizeInBytes;
+        memory_requirements.alignment = heap->desc.Alignment;
+        memory_requirements.memoryTypeBits = ~(uint32_t)0;
+
+        hr = vkd3d_allocate_device_memory(device, &heap->desc.Properties,
+                heap->desc.Flags, &memory_requirements, NULL,
+                &heap->vk_memory, &heap->vk_memory_type);
+    }
+    if (FAILED(hr))
     {
         vkd3d_private_store_destroy(&heap->private_store);
         pthread_mutex_destroy(&heap->mutex);
         return hr;
     }
 
-    d3d12_device_add_ref(heap->device = device);
+    heap->device = device;
+    if (!heap->is_private)
+        d3d12_device_add_ref(heap->device);
 
     return S_OK;
 }
 
-HRESULT d3d12_heap_create(struct d3d12_device *device,
-        const D3D12_HEAP_DESC *desc, struct d3d12_heap **heap)
+HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
+        const struct d3d12_resource *resource, struct d3d12_heap **heap)
 {
     struct d3d12_heap *object;
     HRESULT hr;
@@ -566,13 +606,13 @@ HRESULT d3d12_heap_create(struct d3d12_device *device,
     if (!(object = vkd3d_malloc(sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = d3d12_heap_init(object, device, desc)))
+    if (FAILED(hr = d3d12_heap_init(object, device, desc, resource)))
     {
         vkd3d_free(object);
         return hr;
     }
 
-    TRACE("Created heap %p.\n", object);
+    TRACE("Created %s %p.\n", object->is_private ? "private heap" : "heap", object);
 
     *heap = object;
 
@@ -883,8 +923,8 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
     else
         VK_CALL(vkDestroyImage(device->vk_device, resource->u.vk_image, NULL));
 
-    if (resource->vk_memory)
-        VK_CALL(vkFreeMemory(device->vk_device, resource->vk_memory, NULL));
+    if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
+        d3d12_heap_destroy(resource->heap);
 }
 
 static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
@@ -914,7 +954,7 @@ static ULONG d3d12_resource_decref(struct d3d12_resource *resource)
 
 bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource)
 {
-    return is_cpu_accessible_heap(&resource->heap_properties);
+    return resource->heap && is_cpu_accessible_heap(&resource->heap->desc.Properties);
 }
 
 /* ID3D12Resource */
@@ -1019,10 +1059,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource *iface, c
 
     TRACE("iface %p, name %s.\n", iface, debugstr_w(name, resource->device->wchar_size));
 
-    if (resource->vk_memory)
+    if (resource->flags & VKD3D_RESOURCE_DEDICATED_HEAP)
     {
-        if (FAILED(hr = vkd3d_set_vk_object_name(resource->device, (uint64_t)resource->vk_memory,
-                VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, name)))
+        if (FAILED(hr = d3d12_heap_SetName(&resource->heap->ID3D12Heap_iface, name)))
             return hr;
     }
 
@@ -1048,15 +1087,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT
 {
     struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
     unsigned int sub_resource_count;
-    struct d3d12_device *device;
     HRESULT hr = S_OK;
-    VkResult vr;
 
     TRACE("iface %p, sub_resource %u, read_range %p, data %p.\n",
             iface, sub_resource, read_range, data);
 
-    device = resource->device;
-
     if (!d3d12_resource_is_cpu_accessible(resource))
     {
         WARN("Resource is not CPU accessible.\n");
@@ -1077,7 +1112,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT
         return E_INVALIDARG;
     }
 
-    if (!resource->heap && !resource->vk_memory)
+    if (!resource->heap)
     {
         FIXME("Not implemented for this resource type.\n");
         return E_NOTIMPL;
@@ -1087,22 +1122,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT
 
     if (!resource->map_count)
     {
-        if (resource->heap)
-        {
-            hr = d3d12_heap_map(resource->heap, resource->heap_offset, &resource->map_ptr);
-        }
-        else
-        {
-            const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
-
-            if ((vr = VK_CALL(vkMapMemory(device->vk_device, resource->vk_memory,
-                    0, VK_WHOLE_SIZE, 0, &resource->map_ptr))) < 0)
-                WARN("Failed to map device memory, vr %d.\n", vr);
-
-            hr = hresult_from_vk_result(vr);
-        }
-
-        if (FAILED(hr))
+        if FAILED(hr = d3d12_heap_map(resource->heap, resource->heap_offset, &resource->map_ptr))
         {
             WARN("Failed to map resource, hr %#x.\n", hr);
             resource->map_ptr = NULL;
@@ -1123,7 +1143,6 @@ static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT s
 {
     struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
     unsigned int sub_resource_count;
-    struct d3d12_device *device;
 
     TRACE("iface %p, sub_resource %u, written_range %p.\n",
             iface, sub_resource, written_range);
@@ -1141,21 +1160,15 @@ static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT s
         return;
     }
 
-    device = resource->device;
-
     WARN("Ignoring written range %p.\n", written_range);
 
     --resource->map_count;
     if (!resource->map_count)
     {
-        const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
-
         resource->map_ptr = NULL;
 
-        if (resource->heap)
-            d3d12_heap_unmap(resource->heap);
-        else
-            VK_CALL(vkUnmapMemory(device->vk_device, resource->vk_memory));
+        assert(resource->heap);
+        d3d12_heap_unmap(resource->heap);
     }
 }
 
@@ -1207,20 +1220,33 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource
         D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS *flags)
 {
     struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+    struct d3d12_heap *heap;
 
     TRACE("iface %p, heap_properties %p, flags %p.\n",
             iface, heap_properties, flags);
 
-    if (resource->heap_properties.Type == VKD3D_HEAP_TYPE_INVALID)
+    if (resource->flags & VKD3D_RESOURCE_EXTERNAL)
+    {
+        if (heap_properties)
+        {
+            memset(heap_properties, 0, sizeof(*heap_properties));
+            heap_properties->Type = D3D12_HEAP_TYPE_DEFAULT;
+        }
+        if (flags)
+            *flags = D3D12_HEAP_FLAG_NONE;
+        return S_OK;
+    }
+
+    if (!(heap = resource->heap))
     {
         WARN("Cannot get heap properties for reserved resources.\n");
         return E_INVALIDARG;
     }
 
     if (heap_properties)
-        *heap_properties = resource->heap_properties;
+        *heap_properties = heap->desc.Properties;
     if (flags)
-        *flags = resource->heap_flags;
+        *flags = heap->desc.Flags;
 
     return S_OK;
 }
@@ -1382,7 +1408,6 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12
         WARN("Ignoring optimized clear value.\n");
 
     resource->gpu_address = 0;
-    resource->vk_memory = VK_NULL_HANDLE;
     resource->flags = 0;
 
     if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc)))
@@ -1422,18 +1447,6 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12
     resource->map_count = 0;
     resource->map_ptr = NULL;
 
-    if (heap_properties)
-    {
-        resource->heap_properties = *heap_properties;
-        resource->heap_flags = heap_flags;
-    }
-    else
-    {
-        memset(&resource->heap_properties, 0, sizeof(resource->heap_properties));
-        resource->heap_properties.Type = VKD3D_HEAP_TYPE_INVALID;
-        resource->heap_flags = 0;
-    }
-
     resource->initial_state = initial_state;
 
     resource->heap = NULL;
@@ -1477,16 +1490,16 @@ static HRESULT vkd3d_allocate_resource_memory(
         struct d3d12_device *device, struct d3d12_resource *resource,
         const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
 {
-    if (d3d12_resource_is_buffer(resource))
-    {
-        return vkd3d_allocate_buffer_memory(device, resource->u.vk_buffer,
-                heap_properties, heap_flags, &resource->vk_memory, NULL, NULL);
-    }
-    else
-    {
-        return vkd3d_allocate_image_memory(device, resource->u.vk_image,
-                heap_properties, heap_flags, &resource->vk_memory, NULL, NULL);
-    }
+    D3D12_HEAP_DESC heap_desc;
+    HRESULT hr;
+
+    heap_desc.SizeInBytes = 0;
+    heap_desc.Properties = *heap_properties;
+    heap_desc.Alignment = 0;
+    heap_desc.Flags = heap_flags;
+    if (SUCCEEDED(hr = d3d12_heap_create(device, &heap_desc, resource, &resource->heap)))
+        resource->flags |= VKD3D_RESOURCE_DEDICATED_HEAP;
+    return hr;
 }
 
 HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
@@ -1642,8 +1655,6 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device,
     object->u.vk_image = create_info->vk_image;
     object->flags = VKD3D_RESOURCE_EXTERNAL;
     object->flags |= create_info->flags & VKD3D_RESOURCE_PUBLIC_FLAGS;
-    memset(&object->heap_properties, 0, sizeof(object->heap_properties));
-    object->heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
     object->initial_state = D3D12_RESOURCE_STATE_COMMON;
     if (create_info->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
         object->present_state = create_info->present_state;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index caaaa2427af7..34df976fe647 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -54,6 +54,7 @@
 
 struct d3d12_command_list;
 struct d3d12_device;
+struct d3d12_resource;
 
 struct vkd3d_vk_global_procs
 {
@@ -348,6 +349,7 @@ struct d3d12_heap
     ID3D12Heap ID3D12Heap_iface;
     LONG refcount;
 
+    bool is_private;
     D3D12_HEAP_DESC desc;
 
     pthread_mutex_t mutex;
@@ -362,13 +364,14 @@ struct d3d12_heap
     struct vkd3d_private_store private_store;
 };
 
-HRESULT d3d12_heap_create(struct d3d12_device *device,
-        const D3D12_HEAP_DESC *desc, struct d3d12_heap **heap) DECLSPEC_HIDDEN;
+HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
+        const struct d3d12_resource *resource, struct d3d12_heap **heap) DECLSPEC_HIDDEN;
 struct d3d12_heap *unsafe_impl_from_ID3D12Heap(ID3D12Heap *iface) DECLSPEC_HIDDEN;
 
 #define VKD3D_RESOURCE_PUBLIC_FLAGS \
         (VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION)
-#define VKD3D_RESOURCE_EXTERNAL 0x00000004
+#define VKD3D_RESOURCE_EXTERNAL       0x00000004
+#define VKD3D_RESOURCE_DEDICATED_HEAP 0x00000008
 
 /* ID3D12Resource */
 struct d3d12_resource
@@ -385,7 +388,6 @@ struct d3d12_resource
         VkBuffer vk_buffer;
         VkImage vk_image;
     } u;
-    VkDeviceMemory vk_memory;
     unsigned int flags;
 
     unsigned int map_count;
@@ -394,8 +396,6 @@ struct d3d12_resource
     struct d3d12_heap *heap;
     uint64_t heap_offset;
 
-    D3D12_HEAP_PROPERTIES heap_properties;
-    D3D12_HEAP_FLAGS heap_flags;
     D3D12_RESOURCE_STATES initial_state;
     D3D12_RESOURCE_STATES present_state;
 
-- 
2.21.0




More information about the wine-devel mailing list