Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 7 ++++ dlls/wined3d/adapter_vk.c | 57 +++++++++++++++++++++++++++++++++ dlls/wined3d/buffer.c | 58 +++++++++++++++++++++++++++++++++- dlls/wined3d/cs.c | 32 +++++++++++++++---- dlls/wined3d/directx.c | 7 ++++ dlls/wined3d/wined3d_private.h | 19 +++++++++++ 6 files changed, 173 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index f1cdbffe718..37f055662ea 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4604,6 +4604,12 @@ static void adapter_gl_flush_bo_address(struct wined3d_context *context, wined3d_context_gl_flush_bo_address(wined3d_context_gl(context), data, size); }
+static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr) +{ + return false; +} + static HRESULT adapter_gl_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain) @@ -5057,6 +5063,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = .adapter_unmap_bo_address = adapter_gl_unmap_bo_address, .adapter_copy_bo_address = adapter_gl_copy_bo_address, .adapter_flush_bo_address = adapter_gl_flush_bo_address, + .adapter_alloc_bo = adapter_gl_alloc_bo, .adapter_create_swapchain = adapter_gl_create_swapchain, .adapter_destroy_swapchain = adapter_gl_destroy_swapchain, .adapter_create_buffer = adapter_gl_create_buffer, diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 19763b49267..002d9e07a00 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -23,6 +23,7 @@ #include "wine/vulkan_driver.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
static const struct wined3d_state_entry_template misc_state_template_vk[] = { @@ -1205,6 +1206,61 @@ static void adapter_vk_flush_bo_address(struct wined3d_context *context, flush_bo_range(context_vk, bo, (uintptr_t)data->addr, size); }
+struct wined3d_client_bo_vk_map_ctx +{ + struct wined3d_device *device; + struct wined3d_client_bo_vk *client_bo; +}; + +static void wined3d_client_bo_vk_map_cs(void *object) +{ + const struct wined3d_client_bo_vk_map_ctx *ctx = object; + struct wined3d_context_vk *context_vk; + + context_vk = wined3d_context_vk(context_acquire(ctx->device, NULL, 0)); + if (!wined3d_bo_vk_map(&ctx->client_bo->bo, context_vk)) + ERR("Failed to map bo.\n"); + context_release(&context_vk->c); +} + +static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr) +{ + wined3d_not_from_cs(device->cs); + + if (resource->type == WINED3D_RTYPE_BUFFER) + { + struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); + struct wined3d_client_bo_vk *client_bo; + + if (!(client_bo = heap_alloc(sizeof(*client_bo)))) + return false; + + if (!wined3d_buffer_vk_create_buffer_object(buffer_vk, NULL, &client_bo->bo)) + { + heap_free(client_bo); + return false; + } + + if (!client_bo->bo.b.map_ptr) + { + struct wined3d_client_bo_vk_map_ctx ctx = {.device = device, .client_bo = client_bo}; + + WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n", &client_bo->bo, + client_bo->bo.memory ? client_bo->bo.memory->chunk : NULL, client_bo->bo.slab); + + wined3d_cs_map_object(device->cs, wined3d_client_bo_vk_map_cs, &ctx); + wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_MAP); + } + + addr->buffer_object = (uintptr_t)&client_bo->bo; + addr->addr = NULL; + return true; + } + + return false; +} + static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain) @@ -1858,6 +1914,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = .adapter_unmap_bo_address = adapter_vk_unmap_bo_address, .adapter_copy_bo_address = adapter_vk_copy_bo_address, .adapter_flush_bo_address = adapter_vk_flush_bo_address, + .adapter_alloc_bo = adapter_vk_alloc_bo, .adapter_create_swapchain = adapter_vk_create_swapchain, .adapter_destroy_swapchain = adapter_vk_destroy_swapchain, .adapter_create_buffer = adapter_vk_create_buffer, diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 99a8683df48..fe7debfd92d 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1061,6 +1061,16 @@ static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resou return WINED3D_OK; }
+void wined3d_buffer_rename(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo) +{ + TRACE("buffer %p, context %p, bo %p.\n", buffer, context, bo); + + buffer->buffer_ops->buffer_rename_bo(buffer, context, bo); + buffer->buffer_object = (uintptr_t)bo; + wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER); + wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER); +} + void wined3d_buffer_copy_bo_address(struct wined3d_buffer *dst_buffer, struct wined3d_context *context, unsigned int dst_offset, const struct wined3d_const_bo_address *src_addr, unsigned int size) { @@ -1256,12 +1266,19 @@ static void wined3d_buffer_no3d_download_ranges(struct wined3d_buffer *buffer, s FIXME("Not implemented.\n"); }
+static void wined3d_buffer_no3d_rename_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) +{ + FIXME("Not implemented.\n"); +} + static const struct wined3d_buffer_ops wined3d_buffer_no3d_ops = { wined3d_buffer_no3d_prepare_location, wined3d_buffer_no3d_unload_location, wined3d_buffer_no3d_upload_ranges, wined3d_buffer_no3d_download_ranges, + wined3d_buffer_no3d_rename_bo, };
HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device, @@ -1366,12 +1383,19 @@ static void wined3d_buffer_gl_download_ranges(struct wined3d_buffer *buffer, str checkGLcall("buffer download"); }
+static void wined3d_buffer_gl_rename_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) +{ + FIXME("Not implemented.\n"); +} + static const struct wined3d_buffer_ops wined3d_buffer_gl_ops = { wined3d_buffer_gl_prepare_location, wined3d_buffer_gl_unload_location, wined3d_buffer_gl_upload_ranges, wined3d_buffer_gl_download_ranges, + wined3d_buffer_gl_rename_bo, };
HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined3d_device *device, @@ -1399,7 +1423,7 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined return wined3d_buffer_init(&buffer_gl->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops); }
-static BOOL wined3d_buffer_vk_create_buffer_object(const struct wined3d_buffer_vk *buffer_vk, +BOOL wined3d_buffer_vk_create_buffer_object(const struct wined3d_buffer_vk *buffer_vk, struct wined3d_context_vk *context_vk, struct wined3d_bo_vk *bo) { const struct wined3d_resource *resource = &buffer_vk->b.resource; @@ -1568,12 +1592,44 @@ static void wined3d_buffer_vk_download_ranges(struct wined3d_buffer *buffer, str FIXME("Not implemented.\n"); }
+static void wined3d_buffer_vk_rename_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) +{ + struct wined3d_bo_vk *prev_bo = (struct wined3d_bo_vk *)buffer->buffer_object; + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer); + struct wined3d_bo_vk *bo_vk = wined3d_bo_vk(bo); + + if (prev_bo) + { + struct wined3d_bo_user *bo_user; + + LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->b.users, struct wined3d_bo_user, entry) + bo_user->valid = false; + assert(list_empty(&bo_vk->b.users)); + list_move_head(&bo_vk->b.users, &prev_bo->b.users); + + if (prev_bo != &buffer_vk->bo) + { + struct wined3d_client_bo_vk *client_bo = CONTAINING_RECORD(prev_bo, struct wined3d_client_bo_vk, bo); + + wined3d_context_vk_destroy_bo(context_vk, &client_bo->bo); + heap_free(client_bo); + } + } + else + { + list_add_head(&bo_vk->b.users, &buffer_vk->b.bo_user.entry); + } +} + static const struct wined3d_buffer_ops wined3d_buffer_vk_ops = { wined3d_buffer_vk_prepare_location, wined3d_buffer_vk_unload_location, wined3d_buffer_vk_upload_ranges, wined3d_buffer_vk_download_ranges, + wined3d_buffer_vk_rename_bo, };
HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device, diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index e6ff448b028..6978e6bf3cb 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2304,26 +2304,32 @@ static void wined3d_cs_exec_callback(struct wined3d_cs *cs, const void *data) op->callback(op->object); }
-static void wined3d_cs_emit_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) +static void wined3d_cs_emit_callback(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id, + void (*callback)(void *object), void *object) { struct wined3d_cs_callback *op;
- op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op = wined3d_device_context_require_space(&cs->c, sizeof(*op), queue_id); op->opcode = WINED3D_CS_OP_CALLBACK; op->callback = callback; op->object = object;
- wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_DEFAULT); + wined3d_device_context_submit(&cs->c, queue_id); }
void wined3d_cs_destroy_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) { - wined3d_cs_emit_callback(cs, callback, object); + wined3d_cs_emit_callback(cs, WINED3D_CS_QUEUE_DEFAULT, callback, object); }
void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) { - wined3d_cs_emit_callback(cs, callback, object); + wined3d_cs_emit_callback(cs, WINED3D_CS_QUEUE_DEFAULT, callback, object); +} + +void wined3d_cs_map_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) +{ + wined3d_cs_emit_callback(cs, WINED3D_CS_QUEUE_MAP, callback, object); }
static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) @@ -2747,6 +2753,9 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi struct wined3d_buffer *buffer = buffer_from_resource(resource); size_t size = box->right - box->left;
+ if (op->bo.flags & UPLOAD_BO_RENAME_ON_UNMAP) + wined3d_buffer_rename(buffer, context, (struct wined3d_bo *)op->bo.addr.buffer_object); + if (op->bo.addr.buffer_object && op->bo.addr.buffer_object == buffer->buffer_object) wined3d_context_flush_bo_address(context, &op->bo.addr, size); else @@ -3121,12 +3130,20 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str { /* Limit NOOVERWRITE maps to buffers for now; there are too many ways that * a texture can be invalidated to even count. */ - if (wined3d_map_persistent() && resource->type == WINED3D_RTYPE_BUFFER && (flags & WINED3D_MAP_NOOVERWRITE)) + if (wined3d_map_persistent() && resource->type == WINED3D_RTYPE_BUFFER + && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) { struct wined3d_client_resource *client = &resource->client; + struct wined3d_device *device = context->device; const struct wined3d_bo *bo; uint8_t *map_ptr;
+ if (flags & WINED3D_MAP_DISCARD) + { + if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &client->addr)) + return NULL; + } + bo = (const struct wined3d_bo *)client->addr.buffer_object; map_ptr = bo ? bo->map_ptr : NULL; map_ptr += (uintptr_t)client->addr.addr; @@ -3150,6 +3167,9 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str } map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box);
+ if (flags & WINED3D_MAP_DISCARD) + client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP | UPLOAD_BO_RENAME_ON_UNMAP; + client->mapped_box = *box;
TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client->mapped_upload.addr), diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index c265bdc8c95..f14f57fd3f4 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2805,6 +2805,12 @@ static void adapter_no3d_flush_bo_address(struct wined3d_context *context, { }
+static bool adapter_no3d_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr) +{ + return false; +} + static HRESULT adapter_no3d_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain) @@ -3075,6 +3081,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops = .adapter_unmap_bo_address = adapter_no3d_unmap_bo_address, .adapter_copy_bo_address = adapter_no3d_copy_bo_address, .adapter_flush_bo_address = adapter_no3d_flush_bo_address, + .adapter_alloc_bo = adapter_no3d_alloc_bo, .adapter_create_swapchain = adapter_no3d_create_swapchain, .adapter_destroy_swapchain = adapter_no3d_destroy_swapchain, .adapter_create_buffer = adapter_no3d_create_buffer, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index fab1c755a81..568eebb5ace 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1639,6 +1639,16 @@ struct wined3d_bo_vk bool host_synced; };
+static inline struct wined3d_bo_vk *wined3d_bo_vk(struct wined3d_bo *bo) +{ + return CONTAINING_RECORD(bo, struct wined3d_bo_vk, b); +} + +struct wined3d_client_bo_vk +{ + struct wined3d_bo_vk bo; +}; + struct wined3d_bo_slab_vk_key { VkMemoryPropertyFlags memory_type; @@ -3335,6 +3345,7 @@ bool wined3d_driver_info_init(struct wined3d_driver_info *driver_info, UINT64 vram_bytes, UINT64 sysmem_bytes) DECLSPEC_HIDDEN;
#define UPLOAD_BO_UPLOAD_ON_UNMAP 0x1 +#define UPLOAD_BO_RENAME_ON_UNMAP 0x2
struct upload_bo { @@ -3367,6 +3378,8 @@ struct wined3d_adapter_ops const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size); void (*adapter_flush_bo_address)(struct wined3d_context *context, const struct wined3d_const_bo_address *data, size_t size); + bool (*adapter_alloc_bo)(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr); HRESULT (*adapter_create_swapchain)(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, @@ -4874,6 +4887,7 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; +void wined3d_cs_map_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN;
static inline void wined3d_cs_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id) { @@ -5002,6 +5016,7 @@ struct wined3d_buffer_ops unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges); void (*buffer_download_ranges)(struct wined3d_buffer *buffer, struct wined3d_context *context, void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges); + void (*buffer_rename_bo)(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo); };
struct wined3d_buffer @@ -5047,6 +5062,8 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN; BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, struct wined3d_context *context, unsigned int location) DECLSPEC_HIDDEN; +void wined3d_buffer_rename(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) 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, @@ -5089,6 +5106,8 @@ static inline struct wined3d_buffer_vk *wined3d_buffer_vk(struct wined3d_buffer
void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk, struct wined3d_context_vk *context_vk, uint32_t bind_mask) DECLSPEC_HIDDEN; +BOOL wined3d_buffer_vk_create_buffer_object(const struct wined3d_buffer_vk *buffer_vk, + struct wined3d_context_vk *context_vk, struct wined3d_bo_vk *bo) DECLSPEC_HIDDEN; const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_buffer_vk *buffer_vk) DECLSPEC_HIDDEN; 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,