From 125f5b72100d2a0f82f118b857349ff6915a661f Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Wed, 23 Feb 2022 20:21:42 -0600 Subject: [PATCH] wined3d: Accelerate texture DISCARD maps as well. Signed-off-by: Zebediah Figura Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/adapter_gl.c | 92 ++++++++++++++++++++++----------------- dlls/wined3d/adapter_vk.c | 62 +++++++++++++++----------- dlls/wined3d/cs.c | 9 ++-- dlls/wined3d/texture.c | 33 ++++++++++++++ 4 files changed, 125 insertions(+), 71 deletions(-) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 4e93e25452d..6247f60716f 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4618,60 +4618,70 @@ static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_re { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_device_gl *device_gl = wined3d_device_gl(device); + struct wined3d_bo_gl *bo_gl; + GLenum binding, usage; + bool coherent = true; + GLbitfield flags; + GLsizeiptr size; 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; - + size = resource->size; + binding = wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags); + usage = GL_STATIC_DRAW; + flags = wined3d_resource_gl_storage_flags(resource); if (resource->usage & WINED3DUSAGE_DYNAMIC) { - usage = GL_STREAM_DRAW_ARB; + usage = GL_STREAM_DRAW; coherent = false; } + } + else + { + struct wined3d_texture *texture = texture_from_resource(resource); - 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; - } - - if (bo_gl->memory) - { - struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk); - - wined3d_allocator_chunk_gl_lock(chunk); - - if ((bo_gl->b.map_ptr = chunk->c.map_ptr)) - ++chunk->c.map_count; - - wined3d_allocator_chunk_gl_unlock(chunk); - } - - 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; + size = texture->sub_resources[sub_resource_idx].size; + binding = GL_PIXEL_UNPACK_BUFFER; + usage = GL_STREAM_DRAW; + flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT; } - return false; + if (!(bo_gl = heap_alloc(sizeof(*bo_gl)))) + return false; + + if (!(wined3d_device_gl_create_bo(device_gl, NULL, size, binding, usage, coherent, flags, bo_gl))) + { + WARN("Failed to create OpenGL buffer.\n"); + heap_free(bo_gl); + return false; + } + + if (bo_gl->memory) + { + struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk); + + wined3d_allocator_chunk_gl_lock(chunk); + + if ((bo_gl->b.map_ptr = chunk->c.map_ptr)) + ++chunk->c.map_count; + + wined3d_allocator_chunk_gl_unlock(chunk); + } + + 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; } static void adapter_gl_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 9b9b399a810..72f945bddb0 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1253,41 +1253,51 @@ static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_re { struct wined3d_device_vk *device_vk = wined3d_device_vk(device); struct wined3d_context_vk *context_vk = &device_vk->context_vk; + VkMemoryPropertyFlags memory_type; + VkBufferUsageFlags buffer_usage; + struct wined3d_bo_vk *bo_vk; + VkDeviceSize size; wined3d_not_from_cs(device->cs); assert(device->context_count); if (resource->type == WINED3D_RTYPE_BUFFER) { - struct wined3d_bo_vk *bo_vk; + buffer_usage = vk_buffer_usage_from_bind_flags(resource->bind_flags); + memory_type = vk_memory_type_from_access_flags(resource->access, resource->usage); + size = resource->size; + } + else + { + struct wined3d_texture *texture = texture_from_resource(resource); - if (!(bo_vk = heap_alloc(sizeof(*bo_vk)))) - return false; - - if (!(wined3d_context_vk_create_bo(context_vk, resource->size, - vk_buffer_usage_from_bind_flags(resource->bind_flags), - vk_memory_type_from_access_flags(resource->access, resource->usage), bo_vk))) - { - WARN("Failed to create Vulkan buffer.\n"); - heap_free(bo_vk); - return false; - } - - if (!bo_vk->b.map_ptr) - { - WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not mapped.\n", - bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab); - - if (!wined3d_bo_vk_map(bo_vk, context_vk)) - ERR("Failed to map bo.\n"); - } - - addr->buffer_object = &bo_vk->b; - addr->addr = NULL; - return true; + buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + memory_type = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + size = texture->sub_resources[sub_resource_idx].size; } - return false; + if (!(bo_vk = heap_alloc(sizeof(*bo_vk)))) + return false; + + if (!(wined3d_context_vk_create_bo(context_vk, size, buffer_usage, memory_type, bo_vk))) + { + WARN("Failed to create Vulkan buffer.\n"); + heap_free(bo_vk); + return false; + } + + if (!bo_vk->b.map_ptr) + { + WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not mapped.\n", + bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab); + + if (!wined3d_bo_vk_map(bo_vk, context_vk)) + ERR("Failed to map bo.\n"); + } + + addr->buffer_object = &bo_vk->b; + addr->addr = NULL; + return true; } static void adapter_vk_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 280bd2023c9..7418c6ab4bb 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3091,9 +3091,7 @@ static void wined3d_cs_st_finish(struct wined3d_device_context *context, enum wi static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, uint32_t flags) { - /* Limit NOOVERWRITE maps to buffers for now; there are too many ways that - * a texture can be invalidated to even count. */ - if (resource->type == WINED3D_RTYPE_BUFFER && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) + if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) { const struct wined3d_d3d_info *d3d_info = &context->device->adapter->d3d_info; struct wined3d_client_resource *client = &resource->client; @@ -3124,7 +3122,10 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &addr)) return false; - client->addr = addr; + /* Limit NOOVERWRITE maps to buffers for now; there are too many + * ways that a texture can be invalidated to even count. */ + if (resource->type == WINED3D_RTYPE_BUFFER) + client->addr = addr; } else { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 75997914d77..003aca3aecb 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4570,6 +4570,30 @@ void wined3d_texture_download_from_texture(struct wined3d_texture *dst_texture, wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_location); } +static void wined3d_texture_set_bo(struct wined3d_texture *texture, + unsigned sub_resource_idx, struct wined3d_context *context, struct wined3d_bo *bo) +{ + struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx]; + struct wined3d_bo *prev_bo = sub_resource->bo; + + TRACE("texture %p, sub_resource_idx %u, context %p, bo %p.\n", texture, sub_resource_idx, context, bo); + + if (prev_bo) + { + struct wined3d_bo_user *bo_user; + + LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->users, struct wined3d_bo_user, entry) + bo_user->valid = false; + assert(list_empty(&bo->users)); + list_move_head(&bo->users, &prev_bo->users); + + wined3d_context_destroy_bo(context, prev_bo); + heap_free(prev_bo); + } + + sub_resource->bo = bo; +} + void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, const struct upload_bo *upload_bo, const struct wined3d_box *box, unsigned int row_pitch, unsigned int slice_pitch) @@ -4580,6 +4604,15 @@ void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsign unsigned int depth = wined3d_texture_get_level_depth(texture, level); struct wined3d_box src_box; + if (upload_bo->flags & UPLOAD_BO_RENAME_ON_UNMAP) + { + wined3d_texture_set_bo(texture, sub_resource_idx, context, upload_bo->addr.buffer_object); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER); + wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_BUFFER); + /* Try to free address space if we are not mapping persistently. */ + wined3d_context_unmap_bo_address(context, (const struct wined3d_bo_address *)&upload_bo->addr, 0, NULL); + } + /* Only load the sub-resource for partial updates. */ if (!box->left && !box->top && !box->front && box->right == width && box->bottom == height && box->back == depth)