[PATCH v2 8/8] wined3d: Accelerate texture DISCARD maps as well.

Zebediah Figura zfigura at codeweavers.com
Wed Feb 23 20:21:42 CST 2022


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
v2: Try to unmap after renaming.

 dlls/wined3d/adapter_gl.c | 76 ++++++++++++++++++++++-----------------
 dlls/wined3d/adapter_vk.c | 54 ++++++++++++++++------------
 dlls/wined3d/cs.c         |  9 ++---
 dlls/wined3d/texture.c    | 33 +++++++++++++++++
 4 files changed, 113 insertions(+), 59 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;
+        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;
+    }
 
-        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 = heap_alloc(sizeof(*bo_gl))))
+        return false;
 
-        if (bo_gl->memory)
-        {
-            struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk);
+    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;
+    }
 
-            wined3d_allocator_chunk_gl_lock(chunk);
+    if (bo_gl->memory)
+    {
+        struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk);
 
-            if ((bo_gl->b.map_ptr = chunk->c.map_ptr))
-                ++chunk->c.map_count;
+        wined3d_allocator_chunk_gl_lock(chunk);
 
-            wined3d_allocator_chunk_gl_unlock(chunk);
-        }
+        if ((bo_gl->b.map_ptr = chunk->c.map_ptr))
+            ++chunk->c.map_count;
 
-        addr->buffer_object = &bo_gl->b;
-        addr->addr = NULL;
+        wined3d_allocator_chunk_gl_unlock(chunk);
+    }
 
-        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);
-        }
+    addr->buffer_object = &bo_gl->b;
+    addr->addr = NULL;
 
-        return true;
+    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 false;
+    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;
+        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;
+    }
 
-        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 = heap_alloc(sizeof(*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_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 (!wined3d_bo_vk_map(bo_vk, context_vk))
-                ERR("Failed to map bo.\n");
-        }
+    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);
 
-        addr->buffer_object = &bo_vk->b;
-        addr->addr = NULL;
-        return true;
+        if (!wined3d_bo_vk_map(bo_vk, context_vk))
+            ERR("Failed to map bo.\n");
     }
 
-    return false;
+    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 c65379fe46d..f0328f82794 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -3093,9 +3093,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;
@@ -3126,7 +3124,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)
-- 
2.35.1




More information about the wine-devel mailing list