From 1b1b03055db8bf03c6783d4fcb19abf670d53338 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Thu, 17 Feb 2022 23:01:37 -0600 Subject: [PATCH] wined3d: Try to allocate new OpenGL BOs from the client thread for DISCARD maps. Signed-off-by: Zebediah Figura Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/adapter_gl.c | 43 ++++++++++++++++++++++++++++++++++ dlls/wined3d/buffer.c | 2 +- dlls/wined3d/cs.c | 36 ++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 4 ++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index bc54f46222f..cb0c34823aa 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4616,6 +4616,49 @@ static void adapter_gl_flush_bo_address(struct wined3d_context *context, static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_bo_address *addr) { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_device_gl *device_gl = wined3d_device_gl(device); + + wined3d_not_from_cs(device->cs); + assert(device->context_count); + + if (resource->type == WINED3D_RTYPE_BUFFER) + { + GLenum usage = GL_STATIC_DRAW; + struct wined3d_bo_gl *bo_gl; + bool coherent = true; + + if (resource->usage & WINED3DUSAGE_DYNAMIC) + { + usage = GL_STREAM_DRAW_ARB; + coherent = false; + } + + if (!(bo_gl = heap_alloc(sizeof(*bo_gl)))) + return false; + + if (!(wined3d_device_gl_create_bo(device_gl, NULL, resource->size, + wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags), + usage, coherent, wined3d_resource_gl_storage_flags(resource), bo_gl))) + { + WARN("Failed to create OpenGL buffer.\n"); + heap_free(bo_gl); + return false; + } + + addr->buffer_object = &bo_gl->b; + addr->addr = NULL; + + if (!bo_gl->b.map_ptr) + { + WARN_(d3d_perf)("BO %p (chunk %p) is not persistently mapped.\n", + bo_gl, bo_gl->memory ? bo_gl->memory->chunk : NULL); + wined3d_cs_map_bo_address(device->cs, addr, resource->size, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD); + } + + return true; + } + return false; } diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 3ecaa9017d0..16308a098e3 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -136,7 +136,7 @@ void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD loc wined3d_buffer_invalidate_range(buffer, location, 0, 0); } -static GLenum wined3d_buffer_gl_binding_from_bind_flags(const struct wined3d_gl_info *gl_info, uint32_t bind_flags) +GLenum wined3d_buffer_gl_binding_from_bind_flags(const struct wined3d_gl_info *gl_info, uint32_t bind_flags) { if (!bind_flags) return GL_PIXEL_UNPACK_BUFFER; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 027a6786717..4a3b805c0bd 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -118,6 +118,7 @@ enum wined3d_cs_op WINED3D_CS_OP_UNLOAD_RESOURCE, WINED3D_CS_OP_MAP, WINED3D_CS_OP_UNMAP, + WINED3D_CS_OP_MAP_BO_ADDRESS, WINED3D_CS_OP_BLT_SUB_RESOURCE, WINED3D_CS_OP_UPDATE_SUB_RESOURCE, WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION, @@ -452,6 +453,14 @@ struct wined3d_cs_unmap HRESULT *hr; }; +struct wined3d_cs_map_bo_address +{ + enum wined3d_cs_op opcode; + struct wined3d_bo_address addr; + size_t size; + uint32_t flags; +}; + struct wined3d_cs_blt_sub_resource { enum wined3d_cs_op opcode; @@ -592,6 +601,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op) WINED3D_TO_STR(WINED3D_CS_OP_UNLOAD_RESOURCE); WINED3D_TO_STR(WINED3D_CS_OP_MAP); WINED3D_TO_STR(WINED3D_CS_OP_UNMAP); + WINED3D_TO_STR(WINED3D_CS_OP_MAP_BO_ADDRESS); WINED3D_TO_STR(WINED3D_CS_OP_BLT_SUB_RESOURCE); WINED3D_TO_STR(WINED3D_CS_OP_UPDATE_SUB_RESOURCE); WINED3D_TO_STR(WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION); @@ -2548,6 +2558,31 @@ HRESULT wined3d_device_context_emit_unmap(struct wined3d_device_context *context return hr; } +static void wined3d_cs_exec_map_bo_address(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_map_bo_address *op = data; + struct wined3d_context *context; + + context = context_acquire(cs->c.device, NULL, 0); + wined3d_context_map_bo_address(context, &op->addr, op->size, op->flags); + context_release(context); +} + +void wined3d_cs_map_bo_address(struct wined3d_cs *cs, + struct wined3d_bo_address *addr, size_t size, unsigned int flags) +{ + struct wined3d_device_context *context = &cs->c; + struct wined3d_cs_map_bo_address *op; + + op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_MAP); + op->opcode = WINED3D_CS_OP_MAP_BO_ADDRESS; + op->addr = *addr; + op->size = size; + op->flags = flags; + wined3d_device_context_submit(context, WINED3D_CS_QUEUE_MAP); + wined3d_device_context_finish(context, WINED3D_CS_QUEUE_MAP); +} + static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_blt_sub_resource *op = data; @@ -2966,6 +3001,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_UNLOAD_RESOURCE */ wined3d_cs_exec_unload_resource, /* WINED3D_CS_OP_MAP */ wined3d_cs_exec_map, /* WINED3D_CS_OP_UNMAP */ wined3d_cs_exec_unmap, + /* WINED3D_CS_OP_MAP_BO_ADDRESS */ wined3d_cs_exec_map_bo_address, /* WINED3D_CS_OP_BLT_SUB_RESOURCE */ wined3d_cs_exec_blt_sub_resource, /* WINED3D_CS_OP_UPDATE_SUB_RESOURCE */ wined3d_cs_exec_update_sub_resource, /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e190fc4285e..eff42be3aa6 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -5034,6 +5034,8 @@ 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_bo_address(struct wined3d_cs *cs, + struct wined3d_bo_address *addr, size_t size, unsigned int flags) DECLSPEC_HIDDEN; static inline void wined3d_cs_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id) { @@ -5217,6 +5219,8 @@ static inline const struct wined3d_buffer_gl *wined3d_buffer_gl_const(const stru return CONTAINING_RECORD(buffer, struct wined3d_buffer_gl, b); } +GLenum wined3d_buffer_gl_binding_from_bind_flags(const struct wined3d_gl_info *gl_info, + uint32_t bind_flags) 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;