=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: libs/vkd3d: Implement internal reference counting for resources.

Alexandre Julliard julliard at winehq.org
Wed Jan 24 15:41:58 CST 2018


Module: vkd3d
Branch: master
Commit: 9075722128021f29f4cd317924d1c330de35b778
URL:    https://source.winehq.org/git/vkd3d.git/?a=commit;h=9075722128021f29f4cd317924d1c330de35b778

Author: Józef Kucia <jkucia at codeweavers.com>
Date:   Wed Jan 24 14:33:37 2018 +0100

libs/vkd3d: Implement internal reference counting for resources.

For swapchain back buffers.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 include/vkd3d.h            |  9 ++++--
 libs/vkd3d/resource.c      | 49 ++++++++++++++++++++++++++++--
 libs/vkd3d/vkd3d.map       |  2 ++
 libs/vkd3d/vkd3d_private.h |  1 +
 tests/vkd3d_api.c          | 76 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 132 insertions(+), 5 deletions(-)

diff --git a/include/vkd3d.h b/include/vkd3d.h
index de75ee3..8f2c9b5 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -83,9 +83,7 @@ VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance);
 ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
 
 HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
-        REFIID riid, void **device);
-HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc,
-        VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource);
+        REFIID iid, void **device);
 VkDevice vkd3d_get_vk_device(ID3D12Device *device);
 VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device);
 struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device);
@@ -94,6 +92,11 @@ uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue);
 VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue);
 void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
 
+HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc,
+        VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource);
+ULONG vkd3d_resource_decref(ID3D12Resource *resource);
+ULONG vkd3d_resource_incref(ID3D12Resource *resource);
+
 HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *root_signature_desc,
         D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
 
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 264578b..712ff9c 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -332,6 +332,30 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12
         VK_CALL(vkFreeMemory(device->vk_device, resource->vk_memory, NULL));
 }
 
+static ULONG d3d12_resource_incref(struct d3d12_resource *resource)
+{
+    ULONG refcount = InterlockedIncrement(&resource->internal_refcount);
+
+    TRACE("%p increasing refcount to %u.\n", resource, refcount);
+
+    return refcount;
+}
+
+static ULONG d3d12_resource_decref(struct d3d12_resource *resource)
+{
+    ULONG refcount = InterlockedDecrement(&resource->internal_refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", resource, refcount);
+
+    if (!refcount)
+    {
+        d3d12_resource_destroy(resource, resource->device);
+        vkd3d_free(resource);
+    }
+
+    return refcount;
+}
+
 /* ID3D12Resource */
 static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface)
 {
@@ -367,6 +391,14 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource *iface)
 
     TRACE("%p increasing refcount to %u.\n", resource, refcount);
 
+    if (refcount == 1)
+    {
+        struct d3d12_device *device = resource->device;
+
+        ID3D12Device_AddRef(&device->ID3D12Device_iface);
+        d3d12_resource_incref(resource);
+    }
+
     return refcount;
 }
 
@@ -381,8 +413,7 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource *iface)
     {
         struct d3d12_device *device = resource->device;
 
-        d3d12_resource_destroy(resource, device);
-        vkd3d_free(resource);
+        d3d12_resource_decref(resource);
 
         ID3D12Device_Release(&device->ID3D12Device_iface);
     }
@@ -641,6 +672,7 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st
 
     resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
     resource->refcount = 1;
+    resource->internal_refcount = 1;
 
     resource->desc = *desc;
 
@@ -773,6 +805,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_D
 
     object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
     object->refcount = 1;
+    object->internal_refcount = 1;
     object->desc = *desc;
     object->u.vk_image = vk_image;
     object->vk_memory = VK_NULL_HANDLE;
@@ -793,6 +826,18 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_D
     return S_OK;
 }
 
+ULONG vkd3d_resource_incref(ID3D12Resource *resource)
+{
+    TRACE("resource %p.\n", resource);
+    return d3d12_resource_incref(impl_from_ID3D12Resource(resource));
+}
+
+ULONG vkd3d_resource_decref(ID3D12Resource *resource)
+{
+    TRACE("resource %p.\n", resource);
+    return d3d12_resource_decref(impl_from_ID3D12Resource(resource));
+}
+
 /* CBVs, SRVs, UAVs */
 static struct vkd3d_view *vkd3d_view_create(void)
 {
diff --git a/libs/vkd3d/vkd3d.map b/libs/vkd3d/vkd3d.map
index 9edc3aa..246275b 100644
--- a/libs/vkd3d/vkd3d.map
+++ b/libs/vkd3d/vkd3d.map
@@ -15,6 +15,8 @@ global:
     vkd3d_instance_get_vk_instance;
     vkd3d_instance_incref;
     vkd3d_release_vk_queue;
+    vkd3d_resource_decref;
+    vkd3d_resource_incref;
     vkd3d_serialize_root_signature;
 
 local: *;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index a60ee99..6913051 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -183,6 +183,7 @@ struct d3d12_resource
 {
     ID3D12Resource ID3D12Resource_iface;
     LONG refcount;
+    LONG internal_refcount;
 
     D3D12_RESOURCE_DESC desc;
 
diff --git a/tests/vkd3d_api.c b/tests/vkd3d_api.c
index 4def3b7..fc8d985 100644
--- a/tests/vkd3d_api.c
+++ b/tests/vkd3d_api.c
@@ -24,6 +24,12 @@
 #include "vkd3d_test.h"
 #include <vkd3d.h>
 
+static ULONG resource_get_internal_refcount(ID3D12Resource *resource)
+{
+    vkd3d_resource_incref(resource);
+    return vkd3d_resource_decref(resource);
+}
+
 static bool signal_event(HANDLE event)
 {
     trace("Signal event %p.\n", event);
@@ -69,6 +75,36 @@ static ID3D12CommandQueue *create_command_queue(ID3D12Device *device,
     return queue;
 }
 
+static ID3D12Resource *create_buffer(ID3D12Device *device, D3D12_HEAP_TYPE heap_type,
+        size_t size, D3D12_RESOURCE_FLAGS resource_flags, D3D12_RESOURCE_STATES initial_resource_state)
+{
+    D3D12_HEAP_PROPERTIES heap_properties;
+    D3D12_RESOURCE_DESC resource_desc;
+    ID3D12Resource *buffer;
+    HRESULT hr;
+
+    memset(&heap_properties, 0, sizeof(heap_properties));
+    heap_properties.Type = heap_type;
+
+    resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+    resource_desc.Alignment = 0;
+    resource_desc.Width = size;
+    resource_desc.Height = 1;
+    resource_desc.DepthOrArraySize = 1;
+    resource_desc.MipLevels = 1;
+    resource_desc.Format = DXGI_FORMAT_UNKNOWN;
+    resource_desc.SampleDesc.Count = 1;
+    resource_desc.SampleDesc.Quality = 0;
+    resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+    resource_desc.Flags = resource_flags;
+
+    hr = ID3D12Device_CreateCommittedResource(device, &heap_properties,
+            D3D12_HEAP_FLAG_NONE, &resource_desc, initial_resource_state,
+            NULL, &IID_ID3D12Resource, (void **)&buffer);
+    ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr);
+    return buffer;
+}
+
 static void test_create_instance(void)
 {
     struct vkd3d_instance_create_info create_info;
@@ -567,6 +603,45 @@ static void test_vkd3d_queue(void)
     ok(!refcount, "Device has %u references left.\n", refcount);
 }
 
+static void test_resource_internal_refcount(void)
+{
+    ID3D12Resource *resource;
+    ID3D12Device *device;
+    ULONG refcount;
+
+    device = create_device();
+    ok(device, "Failed to create device.\n");
+
+    resource = create_buffer(device, D3D12_HEAP_TYPE_UPLOAD, 1024,
+            D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ);
+    refcount = vkd3d_resource_incref(resource);
+    ok(refcount == 2, "Got refcount %u.\n", refcount);
+    refcount = ID3D12Resource_Release(resource);
+    ok(!refcount, "Got refcount %u.\n", refcount);
+    refcount = resource_get_internal_refcount(resource);
+    ok(refcount == 1, "Got refcount %u.\n", refcount);
+    refcount = vkd3d_resource_decref(resource);
+    ok(!refcount, "Got refcount %u.\n", refcount);
+
+    resource = create_buffer(device, D3D12_HEAP_TYPE_UPLOAD, 1024,
+            D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ);
+    refcount = vkd3d_resource_incref(resource);
+    ok(refcount == 2, "Got refcount %u.\n", refcount);
+    refcount = ID3D12Resource_Release(resource);
+    ok(!refcount, "Got refcount %u.\n", refcount);
+    refcount = resource_get_internal_refcount(resource);
+    ok(refcount == 1, "Got refcount %u.\n", refcount);
+    refcount = ID3D12Resource_AddRef(resource);
+    ok(refcount == 1, "Got refcount %u.\n", refcount);
+    refcount = vkd3d_resource_decref(resource);
+    ok(refcount == 1, "Got refcount %u.\n", refcount);
+    refcount = ID3D12Resource_Release(resource);
+    ok(!refcount, "Got refcount %u.\n", refcount);
+
+    refcount = ID3D12Device_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+}
+
 static bool have_d3d12_device(void)
 {
     ID3D12Device *device;
@@ -592,4 +667,5 @@ START_TEST(vkd3d_api)
     run_test(test_physical_device);
     run_test(test_adapter_luid);
     run_test(test_vkd3d_queue);
+    run_test(test_resource_internal_refcount);
 }




More information about the wine-cvs mailing list