summarylogtreecommitdiffstats
path: root/0002-wined3d-Add-support-for-backing-dynamic-wined3d_buff.patch
diff options
context:
space:
mode:
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.patch682
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
-