diff options
author | Lars Norberg | 2018-03-26 22:40:54 +0200 |
---|---|---|
committer | Lars Norberg | 2018-03-26 22:40:54 +0200 |
commit | 60a34983d19f8aabe667b20cf951ab4dda41d293 (patch) | |
tree | fba2b8424435d5853781e875fa78e86c7aac32a8 /0007-wined3d-Avoid-freeing-persistent-buffer-heap-element.patch | |
parent | b9ee62f46a35e7eb1a40f0c7872e48f5ec776e82 (diff) | |
download | aur-60a34983d19f8aabe667b20cf951ab4dda41d293.tar.gz |
rebased wine-pba
Diffstat (limited to '0007-wined3d-Avoid-freeing-persistent-buffer-heap-element.patch')
-rw-r--r-- | 0007-wined3d-Avoid-freeing-persistent-buffer-heap-element.patch | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/0007-wined3d-Avoid-freeing-persistent-buffer-heap-element.patch b/0007-wined3d-Avoid-freeing-persistent-buffer-heap-element.patch new file mode 100644 index 000000000000..d0872df82707 --- /dev/null +++ b/0007-wined3d-Avoid-freeing-persistent-buffer-heap-element.patch @@ -0,0 +1,351 @@ +From fc7907d5264c1606477f9287c949c3c8794859ec Mon Sep 17 00:00:00 2001 +From: Andrew Comminos <andrew@comminos.com> +Date: Thu, 8 Mar 2018 23:01:50 -0800 +Subject: [PATCH 7/9] wined3d: Avoid freeing persistent buffer heap elements + during use. + +Using HeapFree is expensive, especially when we don't have our buffers +for long. +--- + dlls/wined3d/buffer.c | 29 +++++++++++---------- + dlls/wined3d/buffer_heap.c | 57 ++++++++++++++++++------------------------ + dlls/wined3d/context.c | 4 +-- + dlls/wined3d/cs.c | 6 ++--- + dlls/wined3d/wined3d_private.h | 25 ++++++++++++------ + 5 files changed, 61 insertions(+), 60 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index c492fcc8c6..74b3ba8abd 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -276,7 +276,7 @@ static BOOL buffer_alloc_persistent_map(struct wined3d_buffer *buffer) + { + struct wined3d_device *device = buffer->resource.device; + struct wined3d_buffer_heap *heap; +- struct wined3d_map_range map_range; ++ struct wined3d_buffer_heap_element *elem; + HRESULT hr; + + if (buffer->bind_flags & WINED3D_BIND_CONSTANT_BUFFER) +@@ -292,12 +292,12 @@ static BOOL buffer_alloc_persistent_map(struct wined3d_buffer *buffer) + } + + buffer->buffer_heap = heap; +- if (FAILED(hr = wined3d_buffer_heap_alloc(heap, buffer->resource.size, &map_range))) ++ if (FAILED(hr = wined3d_buffer_heap_alloc(heap, buffer->resource.size, &elem))) + { + goto fail; + } +- buffer->cs_persistent_map = map_range; +- buffer->mt_persistent_map = map_range; ++ buffer->cs_persistent_map = elem; ++ buffer->mt_persistent_map = elem; + return TRUE; + + fail: +@@ -753,7 +753,7 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, + if (buffer->conversion_map) + FIXME("Attempting to use conversion map with persistent mapping.\n"); + memcpy(buffer->buffer_heap->map_ptr + +- buffer->cs_persistent_map.offset, ++ buffer->cs_persistent_map->range.offset, + buffer->resource.heap_memory, buffer->resource.size); + break; + +@@ -801,11 +801,11 @@ DWORD wined3d_buffer_get_memory(struct wined3d_buffer *buffer, + { + // FIXME(acomminos): should we expose a buffer object we don't wholly own here? + data->buffer_object = buffer->buffer_heap->buffer_object; +- data->addr = buffer->cs_persistent_map.offset; ++ data->addr = buffer->cs_persistent_map->range.offset; + // Note that the size of the underlying buffer allocation may be larger + // than the buffer knows about. In this case, we've rounded it up to be + // aligned (e.g. for uniform buffer offsets). +- data->length = buffer->cs_persistent_map.size; ++ data->length = buffer->cs_persistent_map->range.size; + return WINED3D_LOCATION_PERSISTENT_MAP; + } + if (locations & WINED3D_LOCATION_SYSMEM) +@@ -1122,7 +1122,7 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI + gl_info->gl_ops.gl.p_glFinish(); + + base = buffer->buffer_heap->map_ptr +- + buffer->cs_persistent_map.offset; ++ + buffer->cs_persistent_map->range.offset; + *data = base + offset; + + context_release(context); +@@ -1412,22 +1412,21 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc + if (flags & WINED3D_MAP_DISCARD) + { + HRESULT hr; +- struct wined3d_map_range map_range; +- if (FAILED(hr = wined3d_buffer_heap_alloc(buffer->buffer_heap, resource->size, &map_range))) ++ struct wined3d_buffer_heap_element *mt_elem; ++ if (FAILED(hr = wined3d_buffer_heap_alloc(buffer->buffer_heap, resource->size, &mt_elem))) + { + FIXME_(d3d_perf)("Failed to allocate new buffer, falling back to sync path.\n"); + return hr; + } +- map_desc->data = buffer->buffer_heap->map_ptr + map_range.offset + offset; ++ map_desc->data = buffer->buffer_heap->map_ptr + mt_elem->range.offset + offset; + resource->map_count++; + +- buffer->mt_persistent_map = map_range; ++ buffer->mt_persistent_map = mt_elem; + + // Discard handler on CSMT thread is responsible for returning the + // currently used buffer to the free pool, along with the fence that + // must be called before the buffer can be reused. +- wined3d_cs_emit_discard_buffer(resource->device->cs, buffer, map_range); +- ++ wined3d_cs_emit_discard_buffer(resource->device->cs, buffer, mt_elem); + return WINED3D_OK; + } + else if (flags & WINED3D_MAP_NOOVERWRITE) +@@ -1435,7 +1434,7 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc + // Allow immediate access for persistent buffers without a fence. + // Always use the latest buffer in this case in case the latest + // DISCARDed one hasn't reached the command stream yet. +- struct wined3d_map_range map_range = buffer->mt_persistent_map; ++ struct wined3d_map_range map_range = buffer->mt_persistent_map->range; + map_desc->data = buffer->buffer_heap->map_ptr + map_range.offset + offset; + resource->map_count++; + +diff --git a/dlls/wined3d/buffer_heap.c b/dlls/wined3d/buffer_heap.c +index 75f84b0088..80670c515f 100644 +--- a/dlls/wined3d/buffer_heap.c ++++ b/dlls/wined3d/buffer_heap.c +@@ -25,18 +25,6 @@ + WINE_DEFAULT_DEBUG_CHANNEL(d3d); + WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); + +-struct wined3d_buffer_heap_element +-{ +- struct wined3d_map_range range; +- +- // rbtree data +- struct wine_rb_entry entry; +- +- // Binned free list positions +- struct wined3d_buffer_heap_element *next; +- struct wined3d_buffer_heap_element *prev; +-}; +- + struct wined3d_buffer_heap_fenced_element + { + struct wined3d_buffer_heap_bin_set free_list; +@@ -82,6 +70,11 @@ static int element_bin(struct wined3d_buffer_heap_element *elem) + // Inserts an element into the appropriate free list bin. + static void element_insert_free_bin(struct wined3d_buffer_heap *heap, struct wined3d_buffer_heap_element *elem) + { ++ if (elem->prev || elem->next) ++ { ++ ERR("Element %p in already in a free list (for some reason).\n", elem); ++ } ++ + int bin = element_bin(elem); + + elem->prev = NULL; +@@ -206,7 +199,7 @@ HRESULT wined3d_buffer_heap_destroy(struct wined3d_buffer_heap *heap, struct win + return WINED3D_OK; + } + +-HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr size, struct wined3d_map_range *out_range) ++HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr size, struct wined3d_buffer_heap_element **out_elem) + { + int initial_bin; + int initial_size = size; +@@ -233,24 +226,24 @@ HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr s + remaining_range.offset = elem->range.offset + size; + remaining_range.size = elem->range.size - size; + +- out_range->offset = elem->range.offset; +- out_range->size = size; ++ // Take the element from the free list, transferring ownership to ++ // the caller. ++ element_remove_free(heap, elem); ++ // Resize the element so that we can free the remainder. ++ elem->range.size = size; + +- TRACE_(d3d_perf)("Allocated %d (requested %d) at %p from bin %d (initial %d)\n", size, initial_size, elem->range.offset, i, initial_bin); ++ *out_elem = elem; + +- // Remove the element from its current free bin to move it to the correct list. +- element_remove_free(heap, elem); ++ TRACE_(d3d_perf)("Allocated %d (requested %d) at %p from bin %d (initial %d)\n", size, initial_size, elem->range.offset, i, initial_bin); + + if (remaining_range.size > 0) + { ++ struct wined3d_buffer_heap_element *remaining_elem; ++ + TRACE_(d3d_perf)("Imperfect fit allocated, fragmenting remainder of %lld at %p.\n", remaining_range.size, remaining_range.offset); + +- elem->range = remaining_range; +- element_insert_free_bin(heap, elem); +- } +- else +- { +- HeapFree(GetProcessHeap(), 0, elem); ++ remaining_elem = element_new(remaining_range.offset, remaining_range.size); ++ element_insert_free_bin(heap, remaining_elem); + } + + LeaveCriticalSection(&heap->temp_lock); +@@ -265,7 +258,7 @@ HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr s + if (SUCCEEDED(wined3d_buffer_heap_deferred_coalesce(heap, &num_coalesced))) + { + if (num_coalesced > 0) +- return wined3d_buffer_heap_alloc(heap, size, out_range); ++ return wined3d_buffer_heap_alloc(heap, size, out_elem); + } + + FIXME_(d3d_perf)("Coalescing did not create new blocks, failing.\n"); +@@ -273,16 +266,15 @@ HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr s + return WINED3DERR_OUTOFVIDEOMEMORY; + } + +-HRESULT wined3d_buffer_heap_free(struct wined3d_buffer_heap *heap, struct wined3d_map_range range) ++HRESULT wined3d_buffer_heap_free(struct wined3d_buffer_heap *heap, struct wined3d_buffer_heap_element *elem) + { +- struct wined3d_buffer_heap_element *elem = element_new(range.offset, range.size); +- +- if (!elem) +- return E_OUTOFMEMORY; +- + EnterCriticalSection(&heap->temp_lock); + + // Only insert the element into a free bin, coalescing will occur later. ++ // ++ // Note that the reason that we pass around wined3d_buffer_heap_element ++ // instead of a range is to avoid frequent HeapAlloc/HeapFree operations ++ // when we're reusing buffers. + element_insert_free_bin(heap, elem); + + LeaveCriticalSection(&heap->temp_lock); +@@ -290,9 +282,8 @@ HRESULT wined3d_buffer_heap_free(struct wined3d_buffer_heap *heap, struct wined3 + return WINED3D_OK; + } + +-HRESULT wined3d_buffer_heap_free_fenced(struct wined3d_buffer_heap *heap, struct wined3d_device *device, struct wined3d_map_range range) ++HRESULT wined3d_buffer_heap_free_fenced(struct wined3d_buffer_heap *heap, struct wined3d_device *device, struct wined3d_buffer_heap_element *elem) + { +- struct wined3d_buffer_heap_element *elem = element_new(range.offset, range.size); + int bin_index = element_bin(elem); + struct wined3d_buffer_heap_bin *bin = &heap->pending_fenced_bins.bins[bin_index]; + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index eae2c3a79d..01aa53597f 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -5005,9 +5005,9 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + if (parameters->indexed) + { + struct wined3d_buffer *index_buffer = state->index_buffer; +- if (index_buffer->locations & WINED3D_LOCATION_PERSISTENT_MAP) ++ if (index_buffer->cs_persistent_map) + { +- idx_data = index_buffer->cs_persistent_map.offset; ++ idx_data = index_buffer->cs_persistent_map->range.offset; + } + else if (!index_buffer->buffer_object || !stream_info->all_vbo) + { +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index e61b8dedbb..d1f665d505 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -444,7 +444,7 @@ struct wined3d_cs_discard_buffer + { + enum wined3d_cs_op opcode; + struct wined3d_buffer *buffer; +- struct wined3d_map_range map_range; ++ struct wined3d_buffer_heap_element *map_range; + }; + + struct wined3d_cs_stop +@@ -2496,14 +2496,14 @@ static void wined3d_cs_exec_discard_buffer(struct wined3d_cs *cs, const void *da + wined3d_resource_release(&op->buffer->resource); + } + +-void wined3d_cs_emit_discard_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, struct wined3d_map_range map_range) ++void wined3d_cs_emit_discard_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, struct wined3d_buffer_heap_element *elem) + { + struct wined3d_cs_discard_buffer *op; + + op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_DISCARD_BUFFER; + op->buffer = buffer; +- op->map_range = map_range; ++ op->map_range = elem; + + wined3d_resource_acquire(&buffer->resource); + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index b3fd0136ff..0114444943 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -3531,6 +3531,18 @@ struct wined3d_map_range + GLsizeiptr size; + }; + ++struct wined3d_buffer_heap_element ++{ ++ struct wined3d_map_range range; ++ ++ // rbtree data ++ struct wine_rb_entry entry; ++ ++ // Binned free list positions ++ struct wined3d_buffer_heap_element *next; ++ struct wined3d_buffer_heap_element *prev; ++}; ++ + enum wined3d_cs_queue_id + { + WINED3D_CS_QUEUE_DEFAULT = 0, +@@ -3677,7 +3689,7 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou + void wined3d_cs_emit_update_sub_resource(struct wined3d_cs *cs, struct wined3d_resource *resource, + unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch, + unsigned int slice_pitch) DECLSPEC_HIDDEN; +-void wined3d_cs_emit_discard_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, struct wined3d_map_range map_range) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_discard_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, struct wined3d_buffer_heap_element *map_range) DECLSPEC_HIDDEN; + void wined3d_cs_init_object(struct wined3d_cs *cs, + void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; + HRESULT wined3d_cs_map(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx, +@@ -3711,7 +3723,6 @@ enum wined3d_buffer_conversion_type + CONV_POSITIONT, + }; + +-struct wined3d_buffer_heap_element; + struct wined3d_buffer_heap_fenced_element; + + // Number of power-of-two buckets to populate. +@@ -3750,11 +3761,11 @@ HRESULT wined3d_buffer_heap_create(struct wined3d_context *context, GLsizeiptr s + HRESULT wined3d_buffer_heap_destroy(struct wined3d_buffer_heap *heap, struct wined3d_context *context) DECLSPEC_HIDDEN; + // Fetches a buffer from the heap of at least the given size. + // Attempts to coalesce blocks under memory pressure. +-HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr size, struct wined3d_map_range* out_range) DECLSPEC_HIDDEN; ++HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr size, struct wined3d_buffer_heap_element** out_elem) DECLSPEC_HIDDEN; + // Immediately frees a heap-allocated buffer segment. +-HRESULT wined3d_buffer_heap_free(struct wined3d_buffer_heap *heap, struct wined3d_map_range range) DECLSPEC_HIDDEN; ++HRESULT wined3d_buffer_heap_free(struct wined3d_buffer_heap *heap, struct wined3d_buffer_heap_element *elem) DECLSPEC_HIDDEN; + // Enqueues a buffer segment to return to the heap once its fence has been signaled. +-HRESULT wined3d_buffer_heap_free_fenced(struct wined3d_buffer_heap *heap, struct wined3d_device *device, struct wined3d_map_range range) DECLSPEC_HIDDEN; ++HRESULT wined3d_buffer_heap_free_fenced(struct wined3d_buffer_heap *heap, struct wined3d_device *device, struct wined3d_buffer_heap_element *elem) DECLSPEC_HIDDEN; + // Issues a fence for the current set of pending fenced buffers. + // Double-buffered: if the last fence issued has not yet been triggered, waits + // on it. +@@ -3793,8 +3804,8 @@ struct wined3d_buffer + + /* persistent mapped buffer */ + struct wined3d_buffer_heap *buffer_heap; +- struct wined3d_map_range cs_persistent_map; +- struct wined3d_map_range mt_persistent_map; // TODO: make struct list? ++ struct wined3d_buffer_heap_element *cs_persistent_map; ++ struct wined3d_buffer_heap_element *mt_persistent_map; + }; + + static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resource *resource) +-- +2.16.2 + |