From 5b3f89ae8d8fd124d113918267af308f46eb54e6 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Sun, 11 Aug 2019 14:05:08 +0430 Subject: [PATCH] wined3d: Make the adapter responsible for buffer creation and destruction. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/adapter_gl.c | 63 +++++++++++++++ dlls/wined3d/adapter_vk.c | 48 ++++++++++++ dlls/wined3d/buffer.c | 137 ++++++++++++++++++++++----------- dlls/wined3d/directx.c | 47 +++++++++++ dlls/wined3d/wined3d_private.h | 29 +++++++ 5 files changed, 278 insertions(+), 46 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->conversion_map); + heap_free(buffer->maps); +} - heap_free(buffer_gl->b.conversion_map); - } - - 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 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; + + TRACE("buffer_gl %p, device %p, desc %p, data %p, parent %p, parent_ops %p.\n", + buffer_gl, device, desc, data, parent, parent_ops); + + buffer_gl->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); +} + +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"); +} + +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"); +} + +static const struct wined3d_buffer_ops wined3d_buffer_vk_ops = +{ + wined3d_buffer_vk_upload_ranges, + wined3d_buffer_vk_download_ranges, +}; + +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) { - const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; - struct wined3d_buffer_gl *object; - HRESULT hr; + TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n", + device, desc, data, parent, parent_ops, buffer); - 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); - - if (!(object = heap_alloc_zero(sizeof(*object)))) - return E_OUTOFMEMORY; - - object->buffer_type_hint = buffer_type_hint_from_bind_flags(gl_info, desc->bind_flags); - - 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; - } - - TRACE("Created buffer %p.\n", object); - - *buffer = &object->b; - - return WINED3D_OK; + 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;