[PATCH 01/10] wined3d: Make the adapter responsible for buffer creation and destruction.

Henri Verbeet hverbeet at codeweavers.com
Sun Aug 11 04:35:08 CDT 2019


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/adapter_gl.c      |  63 ++++++++++++++++++++
 dlls/wined3d/adapter_vk.c      |  48 +++++++++++++++
 dlls/wined3d/buffer.c          | 129 +++++++++++++++++++++++++++--------------
 dlls/wined3d/directx.c         |  47 +++++++++++++++
 dlls/wined3d/wined3d_private.h |  29 +++++++++
 5 files changed, 274 insertions(+), 42 deletions(-)

diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index e60437d2812..471eb42e862 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4680,6 +4680,67 @@ static void adapter_gl_destroy_swapchain(struct wined3d_swapchain *swapchain)
     heap_free(swapchain);
 }
 
+static HRESULT adapter_gl_create_buffer(struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+{
+    struct wined3d_buffer_gl *buffer_gl;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
+            device, desc, data, parent, parent_ops, buffer);
+
+    if (!(buffer_gl = heap_alloc_zero(sizeof(*buffer_gl))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_buffer_gl_init(buffer_gl, device, desc, data, parent, parent_ops)))
+    {
+        WARN("Failed to initialise buffer, hr %#x.\n", hr);
+        heap_free(buffer_gl);
+        return hr;
+    }
+
+    TRACE("Created buffer %p.\n", buffer_gl);
+    *buffer = &buffer_gl->b;
+
+    return hr;
+}
+
+static void wined3d_buffer_gl_destroy_object(void *object)
+{
+    struct wined3d_buffer_gl *buffer_gl = object;
+    struct wined3d_context *context;
+
+    if (buffer_gl->buffer_object)
+    {
+        context = context_acquire(buffer_gl->b.resource.device, NULL, 0);
+        wined3d_buffer_gl_destroy_buffer_object(buffer_gl, wined3d_context_gl(context));
+        context_release(context);
+    }
+
+    heap_free(buffer_gl);
+}
+
+static void adapter_gl_destroy_buffer(struct wined3d_buffer *buffer)
+{
+    struct wined3d_buffer_gl *buffer_gl = wined3d_buffer_gl(buffer);
+    struct wined3d_device *device = buffer_gl->b.resource.device;
+    unsigned int swapchain_count = device->swapchain_count;
+
+    TRACE("buffer_gl %p.\n", buffer_gl);
+
+    /* Take a reference to the device, in case releasing the buffer would
+     * cause the device to be destroyed. However, swapchain resources don't
+     * take a reference to the device, and we wouldn't want to increment the
+     * refcount on a device that's in the process of being destroyed. */
+    if (swapchain_count)
+        wined3d_device_incref(device);
+    wined3d_buffer_cleanup(&buffer_gl->b);
+    wined3d_cs_destroy_object(device->cs, wined3d_buffer_gl_destroy_object, buffer_gl);
+    if (swapchain_count)
+        wined3d_device_decref(device);
+}
+
 static const struct wined3d_adapter_ops wined3d_adapter_gl_ops =
 {
     adapter_gl_destroy,
@@ -4693,6 +4754,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops =
     adapter_gl_uninit_3d,
     adapter_gl_create_swapchain,
     adapter_gl_destroy_swapchain,
+    adapter_gl_create_buffer,
+    adapter_gl_destroy_buffer,
 };
 
 static BOOL wined3d_adapter_gl_init(struct wined3d_adapter_gl *adapter_gl,
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index cdb5c977f5d..73a16177f41 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -494,6 +494,52 @@ static void adapter_vk_destroy_swapchain(struct wined3d_swapchain *swapchain)
     heap_free(swapchain);
 }
 
+static HRESULT adapter_vk_create_buffer(struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+{
+    struct wined3d_buffer_vk *buffer_vk;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
+            device, desc, data, parent, parent_ops, buffer);
+
+    if (!(buffer_vk = heap_alloc_zero(sizeof(*buffer_vk))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_buffer_vk_init(buffer_vk, device, desc, data, parent, parent_ops)))
+    {
+        WARN("Failed to initialise buffer, hr %#x.\n", hr);
+        heap_free(buffer_vk);
+        return hr;
+    }
+
+    TRACE("Created buffer %p.\n", buffer_vk);
+    *buffer = &buffer_vk->b;
+
+    return hr;
+}
+
+static void adapter_vk_destroy_buffer(struct wined3d_buffer *buffer)
+{
+    struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
+    struct wined3d_device *device = buffer_vk->b.resource.device;
+    unsigned int swapchain_count = device->swapchain_count;
+
+    TRACE("buffer_vk %p.\n", buffer_vk);
+
+    /* Take a reference to the device, in case releasing the buffer would
+     * cause the device to be destroyed. However, swapchain resources don't
+     * take a reference to the device, and we wouldn't want to increment the
+     * refcount on a device that's in the process of being destroyed. */
+    if (swapchain_count)
+        wined3d_device_incref(device);
+    wined3d_buffer_cleanup(&buffer_vk->b);
+    wined3d_cs_destroy_object(device->cs, heap_free, buffer_vk);
+    if (swapchain_count)
+        wined3d_device_decref(device);
+}
+
 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
 {
     adapter_vk_destroy,
@@ -507,6 +553,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops =
     adapter_vk_uninit_3d,
     adapter_vk_create_swapchain,
     adapter_vk_destroy_swapchain,
+    adapter_vk_create_buffer,
+    adapter_vk_destroy_buffer,
 };
 
 static unsigned int wined3d_get_wine_vk_version(void)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 65eff2171e1..b5f44c56ec3 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -139,7 +139,7 @@ static void wined3d_buffer_gl_bind(struct wined3d_buffer_gl *buffer_gl, struct w
 }
 
 /* Context activation is done by the caller. */
-static void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *buffer_gl,
+void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *buffer_gl,
         struct wined3d_context_gl *context_gl)
 {
     const struct wined3d_gl_info *gl_info = context_gl->gl_info;
@@ -757,22 +757,18 @@ static void wined3d_buffer_drop_bo(struct wined3d_buffer *buffer)
     buffer_unload(&buffer->resource);
 }
 
-static void wined3d_buffer_gl_destroy_object(void *object)
+static void wined3d_buffer_destroy_object(void *object)
 {
-    struct wined3d_buffer_gl *buffer_gl = object;
-    struct wined3d_context *context;
+    struct wined3d_buffer *buffer = object;
 
-    if (buffer_gl->buffer_object)
-    {
-        context = context_acquire(buffer_gl->b.resource.device, NULL, 0);
-        wined3d_buffer_gl_destroy_buffer_object(buffer_gl, wined3d_context_gl(context));
-        context_release(context);
-
-        heap_free(buffer_gl->b.conversion_map);
-    }
+    heap_free(buffer->conversion_map);
+    heap_free(buffer->maps);
+}
 
-    heap_free(buffer_gl->b.maps);
-    heap_free(buffer_gl);
+void wined3d_buffer_cleanup(struct wined3d_buffer *buffer)
+{
+    resource_cleanup(&buffer->resource);
+    wined3d_cs_destroy_object(buffer->resource.device->cs, wined3d_buffer_destroy_object, buffer);
 }
 
 ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
@@ -784,9 +780,7 @@ ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer)
     if (!refcount)
     {
         buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent);
-        resource_cleanup(&buffer->resource);
-        wined3d_cs_destroy_object(buffer->resource.device->cs,
-                wined3d_buffer_gl_destroy_object, wined3d_buffer_gl(buffer));
+        buffer->resource.device->adapter->adapter_ops->adapter_destroy_buffer(buffer);
     }
 
     return refcount;
@@ -1353,6 +1347,11 @@ static HRESULT wined3d_buffer_init(struct wined3d_buffer *buffer, struct wined3d
     BOOL dynamic_buffer_ok;
     HRESULT hr;
 
+    TRACE("buffer %p, device %p, desc byte_width %u, usage %s, bind_flags %s, "
+            "access %s, data %p, parent %p, parent_ops %p.\n",
+            buffer, device, desc->byte_width, debug_d3dusage(desc->usage), wined3d_debug_bind_flags(desc->bind_flags),
+            wined3d_debug_resource_access(desc->access), data, parent, parent_ops);
+
     if (!desc->byte_width)
     {
         WARN("Size 0 requested, returning E_INVALIDARG.\n");
@@ -1382,9 +1381,8 @@ static HRESULT wined3d_buffer_init(struct wined3d_buffer *buffer, struct wined3d
     buffer->structure_byte_stride = desc->structure_byte_stride;
     buffer->locations = data ? WINED3D_LOCATION_DISCARDED : WINED3D_LOCATION_SYSMEM;
 
-    TRACE("buffer %p, size %#x, usage %#x, format %s, memory @ %p.\n",
-            buffer, buffer->resource.size, buffer->resource.usage,
-            debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory);
+    TRACE("buffer %p, size %#x, usage %#x, memory @ %p.\n",
+            buffer, buffer->resource.size, buffer->resource.usage, buffer->resource.heap_memory);
 
     if (device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
             || wined3d_resource_access_is_managed(desc->access))
@@ -1441,6 +1439,34 @@ static HRESULT wined3d_buffer_init(struct wined3d_buffer *buffer, struct wined3d
     return WINED3D_OK;
 }
 
+static void wined3d_buffer_no3d_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context,
+        const void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
+{
+    FIXME("Not implemented.\n");
+}
+
+static void wined3d_buffer_no3d_download_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context,
+        void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
+{
+    FIXME("Not implemented.\n");
+}
+
+static const struct wined3d_buffer_ops wined3d_buffer_no3d_ops =
+{
+    wined3d_buffer_no3d_upload_ranges,
+    wined3d_buffer_no3d_download_ranges,
+};
+
+HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    TRACE("buffer_no3d %p, device %p, desc %p, data %p, parent %p, parent_ops %p.\n",
+            buffer_no3d, device, desc, data, parent, parent_ops);
+
+    return wined3d_buffer_init(buffer_no3d, device, desc, data, parent, parent_ops, &wined3d_buffer_no3d_ops);
+}
+
 /* Context activation is done by the caller. */
 static void wined3d_buffer_gl_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context,
         const void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
@@ -1487,35 +1513,54 @@ static const struct wined3d_buffer_ops wined3d_buffer_gl_ops =
     wined3d_buffer_gl_download_ranges,
 };
 
-HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
-        const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
-        struct wined3d_buffer **buffer)
+HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    struct wined3d_buffer_gl *object;
-    HRESULT hr;
 
-    TRACE("device %p, desc byte_width %u, usage %s, bind_flags %s, access %s, data %p, parent %p, "
-            "parent_ops %p, buffer %p.\n",
-            device, desc->byte_width, debug_d3dusage(desc->usage),
-            wined3d_debug_bind_flags(desc->bind_flags), wined3d_debug_resource_access(desc->access),
-            data, parent, parent_ops, buffer);
+    TRACE("buffer_gl %p, device %p, desc %p, data %p, parent %p, parent_ops %p.\n",
+            buffer_gl, device, desc, data, parent, parent_ops);
 
-    if (!(object = heap_alloc_zero(sizeof(*object))))
-        return E_OUTOFMEMORY;
+    buffer_gl->buffer_type_hint = buffer_type_hint_from_bind_flags(gl_info, desc->bind_flags);
 
-    object->buffer_type_hint = buffer_type_hint_from_bind_flags(gl_info, desc->bind_flags);
+    return wined3d_buffer_init(&buffer_gl->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops);
+}
 
-    if (FAILED(hr = wined3d_buffer_init(&object->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops)))
-    {
-        WARN("Failed to initialize buffer, hr %#x.\n", hr);
-        heap_free(object);
-        return hr;
-    }
+static void wined3d_buffer_vk_upload_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context,
+        const void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
+{
+    FIXME("Not implemented.\n");
+}
 
-    TRACE("Created buffer %p.\n", object);
+static void wined3d_buffer_vk_download_ranges(struct wined3d_buffer *buffer, struct wined3d_context *context,
+        void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_map_range *ranges)
+{
+    FIXME("Not implemented.\n");
+}
 
-    *buffer = &object->b;
+static const struct wined3d_buffer_ops wined3d_buffer_vk_ops =
+{
+    wined3d_buffer_vk_upload_ranges,
+    wined3d_buffer_vk_download_ranges,
+};
 
-    return WINED3D_OK;
+HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+    TRACE("buffer_vk %p, device %p, desc %p, data %p, parent %p, parent_ops %p.\n",
+            buffer_vk, device, desc, data, parent, parent_ops);
+
+    return wined3d_buffer_init(&buffer_vk->b, device, desc, data, parent, parent_ops, &wined3d_buffer_vk_ops);
+}
+
+HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
+        const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_buffer **buffer)
+{
+    TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
+            device, desc, data, parent, parent_ops, buffer);
+
+    return device->adapter->adapter_ops->adapter_create_buffer(device, desc, data, parent, parent_ops, buffer);
 }
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index d175842e4c0..7cc2490390a 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2385,6 +2385,51 @@ static void adapter_no3d_destroy_swapchain(struct wined3d_swapchain *swapchain)
     heap_free(swapchain);
 }
 
+static HRESULT adapter_no3d_create_buffer(struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
+{
+    struct wined3d_buffer *buffer_no3d;
+    HRESULT hr;
+
+    TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
+            device, desc, data, parent, parent_ops, buffer);
+
+    if (!(buffer_no3d = heap_alloc_zero(sizeof(*buffer_no3d))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = wined3d_buffer_no3d_init(buffer_no3d, device, desc, data, parent, parent_ops)))
+    {
+        WARN("Failed to initialise buffer, hr %#x.\n", hr);
+        heap_free(buffer_no3d);
+        return hr;
+    }
+
+    TRACE("Created buffer %p.\n", buffer_no3d);
+    *buffer = buffer_no3d;
+
+    return hr;
+}
+
+static void adapter_no3d_destroy_buffer(struct wined3d_buffer *buffer)
+{
+    struct wined3d_device *device = buffer->resource.device;
+    unsigned int swapchain_count = device->swapchain_count;
+
+    TRACE("buffer %p.\n", buffer);
+
+    /* Take a reference to the device, in case releasing the buffer would
+     * cause the device to be destroyed. However, swapchain resources don't
+     * take a reference to the device, and we wouldn't want to increment the
+     * refcount on a device that's in the process of being destroyed. */
+    if (swapchain_count)
+        wined3d_device_incref(device);
+    wined3d_buffer_cleanup(buffer);
+    wined3d_cs_destroy_object(device->cs, heap_free, buffer);
+    if (swapchain_count)
+        wined3d_device_decref(device);
+}
+
 static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops =
 {
     adapter_no3d_destroy,
@@ -2398,6 +2443,8 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops =
     adapter_no3d_uninit_3d,
     adapter_no3d_create_swapchain,
     adapter_no3d_destroy_swapchain,
+    adapter_no3d_create_buffer,
+    adapter_no3d_destroy_buffer,
 };
 
 static void wined3d_adapter_no3d_init_d3d_info(struct wined3d_adapter *adapter, unsigned int wined3d_creation_flags)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 173f1691c86..18fed2eda19 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2784,6 +2784,10 @@ struct wined3d_adapter_ops
     HRESULT (*adapter_create_swapchain)(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
             void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain);
     void (*adapter_destroy_swapchain)(struct wined3d_swapchain *swapchain);
+    HRESULT (*adapter_create_buffer)(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
+            const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
+            struct wined3d_buffer **buffer);
+    void (*adapter_destroy_buffer)(struct wined3d_buffer *buffer);
 };
 
 /* The adapter structure */
@@ -4078,6 +4082,7 @@ static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resourc
     return CONTAINING_RECORD(resource, struct wined3d_buffer, resource);
 }
 
+void wined3d_buffer_cleanup(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN;
 DWORD wined3d_buffer_get_memory(struct wined3d_buffer *buffer,
         struct wined3d_bo_address *data, DWORD locations) DECLSPEC_HIDDEN;
 void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD location) DECLSPEC_HIDDEN;
@@ -4091,6 +4096,10 @@ void wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_off
 void wined3d_buffer_upload_data(struct wined3d_buffer *buffer, struct wined3d_context *context,
         const struct wined3d_box *box, const void *data) DECLSPEC_HIDDEN;
 
+HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+
 struct wined3d_buffer_gl
 {
     struct wined3d_buffer b;
@@ -4105,6 +4114,26 @@ static inline struct wined3d_buffer_gl *wined3d_buffer_gl(struct wined3d_buffer
     return CONTAINING_RECORD(buffer, struct wined3d_buffer_gl, b);
 }
 
+void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *buffer_gl,
+        struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN;
+HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+
+struct wined3d_buffer_vk
+{
+    struct wined3d_buffer b;
+};
+
+static inline struct wined3d_buffer_vk *wined3d_buffer_vk(struct wined3d_buffer *buffer)
+{
+    return CONTAINING_RECORD(buffer, struct wined3d_buffer_vk, b);
+}
+
+HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device,
+        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+        void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+
 struct wined3d_rendertarget_view
 {
     LONG refcount;
-- 
2.11.0




More information about the wine-devel mailing list