diff options
Diffstat (limited to '0002-wined3d-Add-support-for-backing-dynamic-wined3d_buff.patch')
-rw-r--r-- | 0002-wined3d-Add-support-for-backing-dynamic-wined3d_buff.patch | 682 |
1 files changed, 0 insertions, 682 deletions
diff --git a/0002-wined3d-Add-support-for-backing-dynamic-wined3d_buff.patch b/0002-wined3d-Add-support-for-backing-dynamic-wined3d_buff.patch deleted file mode 100644 index cb910a25df4b..000000000000 --- a/0002-wined3d-Add-support-for-backing-dynamic-wined3d_buff.patch +++ /dev/null @@ -1,682 +0,0 @@ -From 6d2e04a5aeab1e3dc238b548a3f90986da4b5e1e Mon Sep 17 00:00:00 2001 -From: Andrew Comminos <andrew@comminos.com> -Date: Mon, 5 Mar 2018 15:39:11 -0800 -Subject: [PATCH 2/5] wined3d: Add support for backing dynamic wined3d_buffer - objects by a persistent map. - ---- - dlls/wined3d/buffer.c | 220 ++++++++++++++++++++++++++++++++++++++++- - dlls/wined3d/context.c | 6 +- - dlls/wined3d/cs.c | 60 ++++++++++- - dlls/wined3d/resource.c | 18 +++- - dlls/wined3d/state.c | 17 +++- - dlls/wined3d/texture.c | 13 +++ - dlls/wined3d/utils.c | 1 + - dlls/wined3d/wined3d_private.h | 11 +++ - 8 files changed, 336 insertions(+), 10 deletions(-) - -diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c -index cae7ef8788..ad057b7fba 100644 ---- a/dlls/wined3d/buffer.c -+++ b/dlls/wined3d/buffer.c -@@ -28,12 +28,14 @@ - #include "wined3d_private.h" - - WINE_DEFAULT_DEBUG_CHANNEL(d3d); -+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); - - #define WINED3D_BUFFER_HASDESC 0x01 /* A vertex description has been found. */ - #define WINED3D_BUFFER_USE_BO 0x02 /* Use a buffer object for this buffer. */ - #define WINED3D_BUFFER_PIN_SYSMEM 0x04 /* Keep a system memory copy for this buffer. */ - #define WINED3D_BUFFER_DISCARD 0x08 /* A DISCARD lock has occurred since the last preload. */ - #define WINED3D_BUFFER_APPLESYNC 0x10 /* Using sync as in GL_APPLE_flush_buffer_range. */ -+#define WINED3D_BUFFER_PERSISTENT 0x20 /* Uses a persistent-mapped buffer via ARB_buffer_storage. */ - - #define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */ - #define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */ -@@ -269,6 +271,52 @@ fail: - return FALSE; - } - -+/* Context activation is done by the caller. */ -+static BOOL buffer_alloc_persistent_map(struct wined3d_buffer *buffer, struct wined3d_context *context) -+{ -+ struct wined3d_device *device = buffer->resource.device; -+ struct wined3d_buffer_heap *heap; -+ struct wined3d_map_range map_range; -+ HRESULT hr; -+ -+ if (buffer->bind_flags & WINED3D_BIND_CONSTANT_BUFFER) -+ { -+ // Use a heap aligned to constant buffer offset requirements. -+ heap = device->cb_buffer_heap; -+ } -+ else -+ { -+ 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; -+ if (FAILED(hr = wined3d_buffer_heap_alloc(heap, buffer->resource.size, &map_range))) -+ { -+ goto fail; -+ } -+ buffer->cs_persistent_map = map_range; -+ buffer->mt_persistent_map = map_range; -+ return TRUE; -+ -+fail: -+ // FIXME(acomminos): fall back to standalone BO here? -+ ERR("Failed to create persistent map for buffer %p, hr=%x\n", buffer, hr); -+ buffer->buffer_heap = NULL; -+ return FALSE; -+} -+ -+static void buffer_free_persistent_map(struct wined3d_buffer *buffer) -+{ -+ if (!buffer->buffer_heap) -+ return; -+ -+ // TODO(acomminos): get the CS thread to free pending main thread buffers. -+ wined3d_buffer_heap_free(buffer->buffer_heap, buffer->cs_persistent_map); -+ buffer->buffer_heap = NULL; -+} -+ - static BOOL buffer_process_converted_attribute(struct wined3d_buffer *buffer, - const enum wined3d_buffer_conversion_type conversion_type, - const struct wined3d_stream_info_element *attrib, DWORD *stride_this_run) -@@ -631,6 +679,16 @@ static BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, - return FALSE; - } - return buffer_create_buffer_object(buffer, context); -+ case WINED3D_LOCATION_PERSISTENT_MAP: -+ if (buffer->buffer_heap) -+ return TRUE; -+ -+ if (!(buffer->flags & WINED3D_BUFFER_PERSISTENT)) -+ { -+ WARN("Trying to map a persistent region for buffer %p without WINED3D_BUFFER_PERSISTENT.\n", buffer); -+ return FALSE; -+ } -+ return buffer_alloc_persistent_map(buffer, context); - - default: - ERR("Invalid location %s.\n", wined3d_debug_location(location)); -@@ -689,16 +747,32 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, - buffer_conversion_upload(buffer, context); - break; - -+ case WINED3D_LOCATION_PERSISTENT_MAP: -+ // TODO(acomminos): are we guaranteed location_sysmem to be kept? -+ // no. -+ 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->resource.heap_memory, buffer->resource.size); -+ break; -+ - default: - ERR("Invalid location %s.\n", wined3d_debug_location(location)); - return FALSE; - } - - wined3d_buffer_validate_location(buffer, location); -- if (buffer->resource.heap_memory && location == WINED3D_LOCATION_BUFFER -+ if (buffer->resource.heap_memory -+ && location & WINED3D_LOCATION_BUFFER - && !(buffer->resource.usage & WINED3DUSAGE_DYNAMIC)) - wined3d_buffer_evict_sysmem(buffer); - -+ // FIXME(acomminos) -+ if (buffer->resource.heap_memory -+ && location & WINED3D_LOCATION_PERSISTENT_MAP) -+ wined3d_buffer_evict_sysmem(buffer); -+ - return TRUE; - } - -@@ -720,12 +794,25 @@ 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) -+ { -+ // 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; - } - -@@ -761,6 +848,8 @@ static void buffer_unload(struct wined3d_resource *resource) - buffer->flags &= ~WINED3D_BUFFER_HASDESC; - } - -+ buffer_free_persistent_map(buffer); -+ - resource_unload(resource); - } - -@@ -784,6 +873,8 @@ static void wined3d_buffer_destroy_object(void *object) - heap_free(buffer->conversion_map); - } - -+ buffer_free_persistent_map(buffer); -+ - heap_free(buffer->maps); - heap_free(buffer); - } -@@ -900,6 +991,16 @@ void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context * - - buffer_mark_used(buffer); - -+ if (buffer->flags & WINED3D_BUFFER_PERSISTENT) -+ { -+ if (wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_PERSISTENT_MAP)) -+ return; -+ -+ ERR("Failed to preload persistent mapping for %p, falling back to BO.\n", buffer); -+ buffer->flags |= WINED3D_BUFFER_USE_BO; -+ buffer->flags &= ~WINED3D_BUFFER_PERSISTENT; -+ } -+ - /* TODO: Make converting independent from VBOs */ - if (!(buffer->flags & WINED3D_BUFFER_USE_BO)) - { -@@ -1010,6 +1111,25 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI - - count = ++buffer->resource.map_count; - -+ if (buffer->locations & WINED3D_LOCATION_PERSISTENT_MAP) -+ { -+ const struct wined3d_gl_info *gl_info; -+ context = context_acquire(device, NULL, 0); -+ -+ FIXME_(d3d_perf)("Fences not used for persistent buffer maps on CS thread, using glFinish.\n"); -+ -+ gl_info = context->gl_info; -+ gl_info->gl_ops.gl.p_glFinish(); -+ -+ base = buffer->buffer_heap->map_ptr -+ + buffer->cs_persistent_map.offset; -+ *data = base + offset; -+ -+ context_release(context); -+ -+ return WINED3D_OK; -+ } -+ - if (buffer->buffer_object) - { - unsigned int dirty_offset = offset, dirty_size = size; -@@ -1152,6 +1272,12 @@ static void wined3d_buffer_unmap(struct wined3d_buffer *buffer) - return; - } - -+ if (buffer->flags & WINED3D_BUFFER_PERSISTENT) -+ { -+ TRACE("Persistent buffer, ignore unmap.\n"); -+ return; -+ } -+ - if (buffer->map_ptr) - { - struct wined3d_device *device = buffer->resource.device; -@@ -1256,6 +1382,64 @@ static void buffer_resource_preload(struct wined3d_resource *resource) - - static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) -+{ -+ struct wined3d_buffer *buffer = buffer_from_resource(resource); -+ UINT offset = box ? box->left : 0; -+ -+ if (sub_resource_idx) -+ { -+ WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx); -+ return E_INVALIDARG; -+ } -+ -+ // Support immediate mapping of persistent buffers off the command thread, -+ // which require no GL calls to interface with. -+ if (buffer->locations & WINED3D_LOCATION_PERSISTENT_MAP) -+ { -+ map_desc->row_pitch = map_desc->slice_pitch = buffer->desc.byte_width; -+ 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))) -+ { -+ 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; -+ resource->map_count++; -+ -+ buffer->mt_persistent_map = map_range; -+ -+ // 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); -+ return WINED3D_OK; -+ } -+ else if (flags & WINED3D_MAP_NOOVERWRITE) -+ { -+ // 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; -+ map_desc->data = buffer->buffer_heap->map_ptr + map_range.offset + offset; -+ resource->map_count++; -+ return WINED3D_OK; -+ } -+ else -+ { -+ // TODO(acomminos): Should check mapped ranges to see if the region is writeable even though NOOVERWRITE is specified. -+ WARN_(d3d_perf)("Mapping persistent buffer %p in sync with CS thread.\n", buffer); -+ // XXX(acomminos): kill this early return. they're the worst. -+ } -+ } -+ -+ return E_NOTIMPL; -+} -+ -+static HRESULT buffer_resource_sub_resource_map_cs(struct wined3d_resource *resource, unsigned int sub_resource_idx, -+ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) - { - struct wined3d_buffer *buffer = buffer_from_resource(resource); - UINT offset, size; -@@ -1299,6 +1483,18 @@ static HRESULT buffer_resource_sub_resource_map_info(struct wined3d_resource *re - } - - static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx) -+{ -+ struct wined3d_buffer *buffer = buffer_from_resource(resource); -+ if (buffer->locations & WINED3D_LOCATION_PERSISTENT_MAP) -+ { -+ // Nothing to be done to unmap a region of a persistent buffer. -+ resource->map_count--; -+ return WINED3D_OK; -+ } -+ return E_NOTIMPL; -+} -+ -+static HRESULT buffer_resource_sub_resource_unmap_cs(struct wined3d_resource *resource, unsigned int sub_resource_idx) - { - if (sub_resource_idx) - { -@@ -1318,7 +1514,9 @@ static const struct wined3d_resource_ops buffer_resource_ops = - buffer_unload, - buffer_resource_sub_resource_map, - buffer_resource_sub_resource_map_info, -+ buffer_resource_sub_resource_map_cs, - buffer_resource_sub_resource_unmap, -+ buffer_resource_sub_resource_unmap_cs, - }; - - static GLenum buffer_type_hint_from_bind_flags(const struct wined3d_gl_info *gl_info, -@@ -1394,12 +1592,30 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device - buffer->flags |= WINED3D_BUFFER_PIN_SYSMEM; - } - -+ if (buffer->resource.usage & WINED3DUSAGE_DYNAMIC) -+ { -+ if (!gl_info->supported[ARB_BUFFER_STORAGE]) -+ { -+ WARN_(d3d_perf)("Not creating a persistent mapping for a dynamic buffer because ARB_buffer_storage is unsupported.\n"); -+ } -+ else -+ { -+ // If supported, use persistent mapped buffers instead of a -+ // standalone BO for dynamic buffers. -+ buffer->flags |= WINED3D_BUFFER_PERSISTENT; -+ } -+ } -+ - /* Observations show that draw_primitive_immediate_mode() is faster on - * dynamic vertex buffers than converting + draw_primitive_arrays(). - * (Half-Life 2 and others.) */ - dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE]; - -- if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT]) -+ if (buffer->flags & WINED3D_BUFFER_PERSISTENT) -+ { -+ TRACE("Not creating a BO because a persistent mapped buffer will be used.\n"); -+ } -+ else if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT]) - { - TRACE("Not creating a BO because GL_ARB_vertex_buffer is not supported.\n"); - } -diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c -index 0e2e68b4b0..eae2c3a79d 100644 ---- a/dlls/wined3d/context.c -+++ b/dlls/wined3d/context.c -@@ -5005,7 +5005,11 @@ 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->buffer_object || !stream_info->all_vbo) -+ if (index_buffer->locations & WINED3D_LOCATION_PERSISTENT_MAP) -+ { -+ idx_data = index_buffer->cs_persistent_map.offset; -+ } -+ else if (!index_buffer->buffer_object || !stream_info->all_vbo) - { - idx_data = index_buffer->resource.heap_memory; - } -diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c -index 50a4d041cd..e61b8dedbb 100644 ---- a/dlls/wined3d/cs.c -+++ b/dlls/wined3d/cs.c -@@ -73,6 +73,7 @@ enum wined3d_cs_op - WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW, - WINED3D_CS_OP_COPY_UAV_COUNTER, - WINED3D_CS_OP_GENERATE_MIPMAPS, -+ WINED3D_CS_OP_DISCARD_BUFFER, - WINED3D_CS_OP_STOP, - }; - -@@ -439,6 +440,13 @@ struct wined3d_cs_generate_mipmaps - struct wined3d_shader_resource_view *view; - }; - -+struct wined3d_cs_discard_buffer -+{ -+ enum wined3d_cs_op opcode; -+ struct wined3d_buffer *buffer; -+ struct wined3d_map_range map_range; -+}; -+ - struct wined3d_cs_stop - { - enum wined3d_cs_op opcode; -@@ -2002,7 +2010,7 @@ static void wined3d_cs_exec_map(struct wined3d_cs *cs, const void *data) - const struct wined3d_cs_map *op = data; - struct wined3d_resource *resource = op->resource; - -- *op->hr = resource->resource_ops->resource_sub_resource_map(resource, -+ *op->hr = resource->resource_ops->resource_sub_resource_map_cs(resource, - op->sub_resource_idx, op->map_desc, op->box, op->flags); - } - -@@ -2036,7 +2044,7 @@ static void wined3d_cs_exec_unmap(struct wined3d_cs *cs, const void *data) - const struct wined3d_cs_unmap *op = data; - struct wined3d_resource *resource = op->resource; - -- *op->hr = resource->resource_ops->resource_sub_resource_unmap(resource, op->sub_resource_idx); -+ *op->hr = resource->resource_ops->resource_sub_resource_unmap_cs(resource, op->sub_resource_idx); - } - - HRESULT wined3d_cs_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource, unsigned int sub_resource_idx) -@@ -2455,6 +2463,53 @@ void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shad - cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); - } - -+static void wined3d_cs_exec_discard_buffer(struct wined3d_cs *cs, const void *data) -+{ -+ const struct wined3d_cs_discard_buffer *op = data; -+ struct wined3d_buffer *buffer = op->buffer; -+ HRESULT hr; -+ -+ // TODO(acomminos): should call into buffer.c here instead. -+ if (FAILED(hr = wined3d_buffer_heap_free_fenced(buffer->buffer_heap, cs->device, buffer->cs_persistent_map))) -+ { -+ ERR("Failed to do a fenced free on discarded buffer %p, hr %x\n. Freeing anyway.", buffer, hr); -+ wined3d_buffer_heap_free(buffer->buffer_heap, buffer->cs_persistent_map); -+ } -+ -+ buffer->cs_persistent_map = op->map_range; -+ -+ // 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); -+} -+ -+void wined3d_cs_emit_discard_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, struct wined3d_map_range map_range) -+{ -+ 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; -+ -+ wined3d_resource_acquire(&buffer->resource); -+ -+ cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); -+} -+ - static void wined3d_cs_emit_stop(struct wined3d_cs *cs) - { - struct wined3d_cs_stop *op; -@@ -2515,6 +2570,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void - /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view, - /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter, - /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps, -+ /* WINED3D_CS_OP_DISCARD_BUFFER */ wined3d_cs_exec_discard_buffer, - }; - - #if defined(STAGING_CSMT) -diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c -index 8b7f17bb6b..02d469bc20 100644 ---- a/dlls/wined3d/resource.c -+++ b/dlls/wined3d/resource.c -@@ -344,6 +344,7 @@ static DWORD wined3d_resource_sanitise_map_flags(const struct wined3d_resource * - HRESULT CDECL wined3d_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) - { -+ HRESULT hr; - TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n", - resource, sub_resource_idx, map_desc, debug_box(box), flags); - -@@ -366,9 +367,14 @@ HRESULT CDECL wined3d_resource_map(struct wined3d_resource *resource, unsigned i - } - - flags = wined3d_resource_sanitise_map_flags(resource, flags); -- wined3d_resource_wait_idle(resource); -+ if (FAILED(hr = resource->resource_ops->resource_sub_resource_map(resource, sub_resource_idx, map_desc, box, flags))) -+ { -+ TRACE_(d3d_perf)("Mapping resource %p on the command stream.\n", resource); -+ wined3d_resource_wait_idle(resource); -+ hr = wined3d_cs_map(resource->device->cs, resource, sub_resource_idx, map_desc, box, flags); -+ } - -- return wined3d_cs_map(resource->device->cs, resource, sub_resource_idx, map_desc, box, flags); -+ return hr; - } - - HRESULT CDECL wined3d_resource_map_info(struct wined3d_resource *resource, unsigned int sub_resource_idx, -@@ -381,9 +387,15 @@ HRESULT CDECL wined3d_resource_map_info(struct wined3d_resource *resource, unsig - - HRESULT CDECL wined3d_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx) - { -+ HRESULT hr; - TRACE("resource %p, sub_resource_idx %u.\n", resource, sub_resource_idx); - -- return wined3d_cs_unmap(resource->device->cs, resource, sub_resource_idx); -+ if (FAILED(hr = resource->resource_ops->resource_sub_resource_unmap(resource, sub_resource_idx))) -+ { -+ TRACE_(d3d_perf)("Unmapping resource %p on the command stream.\n", resource); -+ hr = wined3d_cs_unmap(resource->device->cs, resource, sub_resource_idx); -+ } -+ return hr; - } - - UINT CDECL wined3d_resource_update_info(struct wined3d_resource *resource, unsigned int sub_resource_idx, -diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c -index 2f506c36d1..6f7805b8bd 100644 ---- a/dlls/wined3d/state.c -+++ b/dlls/wined3d/state.c -@@ -4934,7 +4934,11 @@ static void indexbuffer(struct wined3d_context *context, const struct wined3d_st - else - { - struct wined3d_buffer *ib = state->index_buffer; -- GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer_object)); -+ // FIXME(acomminos): disasterous. -+ if (ib->locations & WINED3D_LOCATION_PERSISTENT_MAP) -+ GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer_heap->buffer_object)); -+ else -+ GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer_object)); - } - } - -@@ -5000,6 +5004,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); - -@@ -5012,7 +5017,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/texture.c b/dlls/wined3d/texture.c -index e6af0c7508..8ca1ee7158 100644 ---- a/dlls/wined3d/texture.c -+++ b/dlls/wined3d/texture.c -@@ -2301,6 +2301,12 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) - - static HRESULT texture_resource_sub_resource_map(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) -+{ -+ return E_NOTIMPL; -+} -+ -+static HRESULT texture_resource_sub_resource_map_cs(struct wined3d_resource *resource, unsigned int sub_resource_idx, -+ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) - { - const struct wined3d_format *format = resource->format; - struct wined3d_texture_sub_resource *sub_resource; -@@ -2461,6 +2467,11 @@ static HRESULT texture_resource_sub_resource_map_info(struct wined3d_resource *r - } - - static HRESULT texture_resource_sub_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx) -+{ -+ return E_NOTIMPL; -+} -+ -+static HRESULT texture_resource_sub_resource_unmap_cs(struct wined3d_resource *resource, unsigned int sub_resource_idx) - { - struct wined3d_texture_sub_resource *sub_resource; - struct wined3d_device *device = resource->device; -@@ -2512,7 +2523,9 @@ static const struct wined3d_resource_ops texture_resource_ops = - wined3d_texture_unload, - texture_resource_sub_resource_map, - texture_resource_sub_resource_map_info, -+ texture_resource_sub_resource_map_cs, - texture_resource_sub_resource_unmap, -+ texture_resource_sub_resource_unmap_cs, - }; - - static HRESULT texture1d_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, -diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c -index b8b7880501..62758ae056 100644 ---- a/dlls/wined3d/utils.c -+++ b/dlls/wined3d/utils.c -@@ -6404,6 +6404,7 @@ const char *wined3d_debug_location(DWORD location) - LOCATION_TO_STR(WINED3D_LOCATION_DRAWABLE); - LOCATION_TO_STR(WINED3D_LOCATION_RB_MULTISAMPLE); - LOCATION_TO_STR(WINED3D_LOCATION_RB_RESOLVED); -+ LOCATION_TO_STR(WINED3D_LOCATION_PERSISTENT_MAP); - #undef LOCATION_TO_STR - if (location) - FIXME("Unrecognized location flag(s) %#x.\n", location); -diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h -index 3d535f4e17..6d32a368a2 100644 ---- a/dlls/wined3d/wined3d_private.h -+++ b/dlls/wined3d/wined3d_private.h -@@ -1470,6 +1470,7 @@ struct wined3d_bo_address - { - GLuint buffer_object; - BYTE *addr; -+ GLsizeiptr length; - }; - - struct wined3d_const_bo_address -@@ -3046,7 +3047,10 @@ struct wined3d_resource_ops - struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags); - HRESULT (*resource_map_info)(struct wined3d_resource *resource, unsigned int sub_resource_idx, - struct wined3d_map_info *info, DWORD flags); -+ HRESULT (*resource_sub_resource_map_cs)(struct wined3d_resource *resource, unsigned int sub_resource_idx, -+ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags); - HRESULT (*resource_sub_resource_unmap)(struct wined3d_resource *resource, unsigned int sub_resource_idx); -+ HRESULT (*resource_sub_resource_unmap_cs)(struct wined3d_resource *resource, unsigned int sub_resource_idx); - }; - - struct wined3d_resource -@@ -3325,6 +3329,7 @@ void wined3d_texture_validate_location(struct wined3d_texture *texture, - #define WINED3D_LOCATION_DRAWABLE 0x00000040 - #define WINED3D_LOCATION_RB_MULTISAMPLE 0x00000080 - #define WINED3D_LOCATION_RB_RESOLVED 0x00000100 -+#define WINED3D_LOCATION_PERSISTENT_MAP 0x00000200 - - const char *wined3d_debug_location(DWORD location) DECLSPEC_HIDDEN; - -@@ -3672,6 +3677,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_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, -@@ -3784,6 +3790,11 @@ struct wined3d_buffer - UINT stride; /* 0 if no conversion */ - enum wined3d_buffer_conversion_type *conversion_map; /* NULL if no conversion */ - UINT conversion_stride; /* 0 if no shifted conversion */ -+ -+ /* 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? - }; - - static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resource *resource) --- -2.16.2 - |