diff options
Diffstat (limited to '0004-wined3d-Implement-aligned-persistent-heaps-for-persi.patch')
-rw-r--r-- | 0004-wined3d-Implement-aligned-persistent-heaps-for-persi.patch | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/0004-wined3d-Implement-aligned-persistent-heaps-for-persi.patch b/0004-wined3d-Implement-aligned-persistent-heaps-for-persi.patch new file mode 100644 index 000000000000..7b4a9e433488 --- /dev/null +++ b/0004-wined3d-Implement-aligned-persistent-heaps-for-persi.patch @@ -0,0 +1,240 @@ +From 65595c191d2a01b2486ba10618f743c930af362b Mon Sep 17 00:00:00 2001 +From: Andrew Comminos <andrew@comminos.com> +Date: Sat, 24 Feb 2018 14:38:59 -0800 +Subject: [PATCH 4/8] wined3d: Implement aligned persistent heaps for + persistently mapped UBOs. + +--- + dlls/wined3d/buffer.c | 16 ++++++++++++---- + dlls/wined3d/buffer_heap.c | 12 +++++++++--- + dlls/wined3d/cs.c | 15 ++++++++++++++- + dlls/wined3d/device.c | 15 ++++++++++++++- + dlls/wined3d/state.c | 11 ++++++++++- + dlls/wined3d/wined3d_private.h | 5 ++++- + 6 files changed, 63 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index ccb090c907..7d7e506817 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -279,14 +279,16 @@ static BOOL buffer_alloc_persistent_map(struct wined3d_buffer *buffer, struct wi + struct wined3d_map_range map_range; + HRESULT hr; + +- if (buffer->resource.usage & WINED3DUSAGE_WRITEONLY) ++ if (buffer->bind_flags & WINED3D_BIND_CONSTANT_BUFFER) + { +- heap = device->wo_buffer_heap; ++ // Use a heap aligned to constant buffer offset requirements. ++ heap = device->cb_buffer_heap; + } + else + { +- FIXME("Using write-only heap for a persistent buffer without WINED3DUSAGE_WRITEONLY.\n"); +- heap = device->rw_buffer_heap; ++ if (!(buffer->resource.usage & WINED3DUSAGE_WRITEONLY)) ++ FIXME("Using a write-only persistent buffer for %p without WINED3DUSAGE_WRITEONLY.\n", buffer); ++ heap = device->wo_buffer_heap; + } + + buffer->buffer_heap = heap; +@@ -791,6 +793,7 @@ DWORD wined3d_buffer_get_memory(struct wined3d_buffer *buffer, + { + data->buffer_object = buffer->buffer_object; + data->addr = NULL; ++ data->length = buffer->resource.size; + return WINED3D_LOCATION_BUFFER; + } + if (locations & WINED3D_LOCATION_PERSISTENT_MAP) +@@ -798,12 +801,17 @@ 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; ++ // 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; + return WINED3D_LOCATION_PERSISTENT_MAP; + } + if (locations & WINED3D_LOCATION_SYSMEM) + { + data->buffer_object = 0; + data->addr = buffer->resource.heap_memory; ++ data->length = buffer->resource.size; + return WINED3D_LOCATION_SYSMEM; + } + +diff --git a/dlls/wined3d/buffer_heap.c b/dlls/wined3d/buffer_heap.c +index f24fddffb4..02b925b658 100644 +--- a/dlls/wined3d/buffer_heap.c ++++ b/dlls/wined3d/buffer_heap.c +@@ -95,7 +95,7 @@ static void element_merge_adjacent(struct wined3d_buffer_heap *heap, struct wine + } + + /* Context activation is done by the caller. */ +-HRESULT wined3d_buffer_heap_create(struct wined3d_context *context, GLsizeiptr size, BOOL write_only, struct wined3d_buffer_heap **buffer_heap) ++HRESULT wined3d_buffer_heap_create(struct wined3d_context *context, GLsizeiptr size, GLsizeiptr alignment, BOOL write_only, struct wined3d_buffer_heap **buffer_heap) + { + const struct wined3d_gl_info *gl_info = context->gl_info; + const GLenum buffer_target = GL_ARRAY_BUFFER; +@@ -133,6 +133,7 @@ HRESULT wined3d_buffer_heap_create(struct wined3d_context *context, GLsizeiptr s + + object->free_list_head = element_new(0, size); + object->fenced_head = object->fenced_tail = NULL; ++ object->alignment = alignment; + InitializeCriticalSection(&object->temp_lock); + + *buffer_heap = object; +@@ -147,12 +148,17 @@ 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_map_range *out_range) ++{ + EnterCriticalSection(&heap->temp_lock); + + // TODO(acomminos): free list binning? + struct wined3d_buffer_heap_element *elem = heap->free_list_head; +- // XXX(acomminos): Avoid fragmentation by rounding to nearest power of two. ++ ++ // Round up the size to a multiple of the heap's alignment. ++ if (heap->alignment) ++ size += heap->alignment - (size % heap->alignment); ++ + while (elem != NULL) + { + TRACE("allocation at %p, size %lld\n", heap->map_ptr + elem->range.offset, elem->range.size); +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index edcf521b72..d7bdc21a25 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -2668,7 +2668,20 @@ static void wined3d_cs_exec_discard_buffer(struct wined3d_cs *cs, const void *da + + buffer->cs_persistent_map = op->map_range; + +- device_invalidate_state(cs->device, STATE_STREAMSRC); ++ // TODO(acomminos): merge this logic with buffer.c functions for standalone BOs ++ if (buffer->bind_flags & WINED3D_BIND_VERTEX_BUFFER) ++ device_invalidate_state(cs->device, STATE_STREAMSRC); ++ if (buffer->bind_flags & WINED3D_BIND_INDEX_BUFFER) ++ device_invalidate_state(cs->device, STATE_INDEXBUFFER); ++ if (buffer->bind_flags & WINED3D_BIND_CONSTANT_BUFFER) ++ { ++ device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX)); ++ device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL)); ++ device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN)); ++ device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY)); ++ device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL)); ++ device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE)); ++ } + + wined3d_resource_release(&op->buffer->resource); + } +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 363dcb17f0..e0871d1636 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -853,12 +853,22 @@ static void create_buffer_heap(struct wined3d_device *device, struct wined3d_con + // TODO(acomminos): definitely don't take up all of vram. this is gonna get + // paged anyway, though. + const GLsizeiptr HBO_SIZE = device->adapter->vram_bytes / 4; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ ++ GLint ub_alignment; ++ gl_info->gl_ops.gl.p_glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &ub_alignment); + + HRESULT hr; +- if (FAILED(hr = wined3d_buffer_heap_create(context, HBO_SIZE, TRUE, &device->wo_buffer_heap))) ++ if (FAILED(hr = wined3d_buffer_heap_create(context, HBO_SIZE, 0, TRUE, &device->wo_buffer_heap))) + { + ERR("Failed to create write-only persistent buffer heap, hr %#x.\n", hr); + } ++ ++ // TODO(acomminos): can likely use a way smaller heap for CBs by querying limits ++ if (FAILED(hr = wined3d_buffer_heap_create(context, HBO_SIZE, ub_alignment, TRUE, &device->cb_buffer_heap))) ++ { ++ ERR("Failed to create persistent buffer heap for constant buffers, hr %#x.\n", hr); ++ } + } + + /* Context activation is done by the caller. */ +@@ -866,6 +876,9 @@ static void destroy_buffer_heap(struct wined3d_device *device, struct wined3d_co + { + if (device->wo_buffer_heap) + wined3d_buffer_heap_destroy(device->wo_buffer_heap, context); ++ ++ if (device->cb_buffer_heap) ++ wined3d_buffer_heap_destroy(device->cb_buffer_heap, context); + } + + static LONG fullscreen_style(LONG style) +diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c +index 142a932d07..ce007d1a8e 100644 +--- a/dlls/wined3d/state.c ++++ b/dlls/wined3d/state.c +@@ -4980,6 +4980,7 @@ static void state_cb(struct wined3d_context *context, const struct wined3d_state + enum wined3d_shader_type shader_type; + struct wined3d_buffer *buffer; + unsigned int i, base, count; ++ struct wined3d_bo_address bo_addr; + + TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id); + +@@ -4992,7 +4993,15 @@ static void state_cb(struct wined3d_context *context, const struct wined3d_state + for (i = 0; i < count; ++i) + { + buffer = state->cb[shader_type][i]; +- GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, buffer ? buffer->buffer_object : 0)); ++ if (buffer) ++ { ++ wined3d_buffer_get_memory(buffer, &bo_addr, buffer->locations); ++ GL_EXTCALL(glBindBufferRange(GL_UNIFORM_BUFFER, base + i, bo_addr.buffer_object, bo_addr.addr, bo_addr.length)); ++ } ++ else ++ { ++ GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, 0)); ++ } + } + checkGLcall("bind constant buffers"); + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index d049d57206..cfa48a5f3e 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1462,6 +1462,7 @@ struct wined3d_bo_address + { + GLuint buffer_object; + BYTE *addr; ++ GLsizeiptr length; + }; + + struct wined3d_const_bo_address +@@ -2972,6 +2973,7 @@ struct wined3d_device + + /* Dynamic buffer heap */ + struct wined3d_buffer_heap *wo_buffer_heap; ++ struct wined3d_buffer_heap *cb_buffer_heap; + }; + + void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb, +@@ -3671,6 +3673,7 @@ struct wined3d_buffer_heap + { + GLuint buffer_object; + void *map_ptr; ++ GLsizeiptr alignment; + CRITICAL_SECTION temp_lock; // Temporary lock while we implement the fenced free list. + + // TODO: add buckets for free regions of a given size. +@@ -3684,7 +3687,7 @@ struct wined3d_buffer_heap + struct wined3d_buffer_heap_fenced_element *fenced_tail; + }; + +-HRESULT wined3d_buffer_heap_create(struct wined3d_context *context, GLsizeiptr size, BOOL write_only, struct wined3d_buffer_heap **heap) DECLSPEC_HIDDEN; ++HRESULT wined3d_buffer_heap_create(struct wined3d_context *context, GLsizeiptr size, GLsizeiptr alignment, BOOL write_only, struct wined3d_buffer_heap **heap) DECLSPEC_HIDDEN; + 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. + HRESULT wined3d_buffer_heap_alloc(struct wined3d_buffer_heap *heap, GLsizeiptr size, struct wined3d_map_range* out_range) DECLSPEC_HIDDEN; +-- +2.16.2 + |