[PATCH] wined3d: Reuse deferred uploads heaps.

Jan Sikorski jsikorski at codeweavers.com
Fri Mar 25 03:49:45 CDT 2022


Avoids needing to fault-in the memory on each recording.

Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
---
The HeapFree loop over uploads in a command list is still a little
concerning. If it turns out to be an issue, we could allocate larger
buffers based on previous usage and fit multiple uploads in it.
---
 dlls/wined3d/cs.c | 55 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 63d6ed4c123..87d7b60bc15 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -49,13 +49,15 @@ struct wined3d_command_list
     SIZE_T data_size;
     void *data;
 
-    HANDLE upload_heap;
     SIZE_T resource_count;
     struct wined3d_resource **resources;
 
     SIZE_T upload_count;
     struct wined3d_deferred_upload *uploads;
 
+    HANDLE upload_heap;
+    LONG *upload_heap_refcount;
+
     /* List of command lists queued for execution on this command list. We might
      * be the only thing holding a pointer to another command list, so we need
      * to hold a reference here (and in wined3d_deferred_context) as well. */
@@ -3960,7 +3962,6 @@ static void wined3d_cs_packet_incref_objects(struct wined3d_cs_packet *packet)
 struct wined3d_deferred_context
 {
     struct wined3d_device_context c;
-    HANDLE upload_heap;
 
     SIZE_T data_size, data_capacity;
     void *data;
@@ -3971,6 +3972,9 @@ struct wined3d_deferred_context
     SIZE_T upload_count, uploads_capacity;
     struct wined3d_deferred_upload *uploads;
 
+    HANDLE upload_heap;
+    LONG *upload_heap_refcount;
+
     /* List of command lists queued for execution on this context. A command
      * list can be the only thing holding a pointer to another command list, so
      * we need to hold a reference here and in wined3d_command_list as well. */
@@ -4090,12 +4094,22 @@ static bool wined3d_deferred_context_map_upload_bo(struct wined3d_device_context
             deferred->upload_count + 1, sizeof(*deferred->uploads)))
         return false;
 
-    if (!deferred->upload_heap)
-        deferred->upload_heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
     if (!deferred->upload_heap)
     {
-        ERR("Failed to create upload heap.\n");
-        return false;
+        if (!(deferred->upload_heap = HeapCreate(0, 0, 0)))
+        {
+            ERR("Failed to create upload heap.\n");
+            return false;
+        }
+
+        if (!(deferred->upload_heap_refcount = heap_alloc(sizeof(deferred->upload_heap_refcount))))
+        {
+            HeapDestroy(deferred->upload_heap);
+            deferred->upload_heap = 0;
+            return false;
+        }
+
+        *deferred->upload_heap_refcount = 1;
     }
 
     if (!(sysmem = HeapAlloc(deferred->upload_heap, 0, size + RESOURCE_ALIGNMENT - 1)))
@@ -4243,9 +4257,20 @@ void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *conte
     heap_free(deferred->resources);
 
     for (i = 0; i < deferred->upload_count; ++i)
+    {
         wined3d_resource_decref(deferred->uploads[i].resource);
+        HeapFree(deferred->upload_heap, 0, deferred->uploads[i].resource);
+    }
+
     if (deferred->upload_heap)
-        HeapDestroy(deferred->upload_heap);
+    {
+        if (!InterlockedDecrement(deferred->upload_heap_refcount))
+        {
+            HeapDestroy(deferred->upload_heap);
+            heap_free(deferred->upload_heap_refcount);
+        }
+    }
+
     heap_free(deferred->uploads);
 
     for (i = 0; i < deferred->command_list_count; ++i)
@@ -4331,7 +4356,8 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
     deferred->query_count = 0;
 
     object->upload_heap = deferred->upload_heap;
-    deferred->upload_heap = 0;
+    if ((object->upload_heap_refcount = deferred->upload_heap_refcount))
+        InterlockedIncrement(object->upload_heap_refcount);
 
     /* This is in fact recorded into a subsequent command list. */
     if (restore)
@@ -4349,11 +4375,22 @@ HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device
 static void wined3d_command_list_destroy_object(void *object)
 {
     struct wined3d_command_list *list = object;
+    unsigned int i;
 
     TRACE("list %p.\n", list);
 
+    for (i = 0; i < list->upload_count; ++i)
+        HeapFree(list->upload_heap, 0, list->uploads[i].sysmem);
+
     if (list->upload_heap)
-        HeapDestroy(list->upload_heap);
+    {
+        if (!InterlockedDecrement(list->upload_heap_refcount))
+        {
+            HeapDestroy(list->upload_heap);
+            heap_free(list->upload_heap_refcount);
+        }
+    }
+
     heap_free(list);
 }
 
-- 
2.32.0




More information about the wine-devel mailing list