From: Henri Verbeet hverbeet@codeweavers.com
Mirroring wined3d_bo_vk_unmap().
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/context_gl.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 9236d2db90f..3a83027522a 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2758,6 +2758,19 @@ map: return map_ptr; }
+static void wined3d_bo_gl_unmap(struct wined3d_bo_gl *bo, struct wined3d_context_gl *context_gl) +{ + const struct wined3d_gl_info *gl_info = context_gl->gl_info; + + if (bo->b.map_ptr) + return; + + wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); + GL_EXTCALL(glUnmapBuffer(bo->binding)); + wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); + checkGLcall("Unmap buffer object"); +} + void *wined3d_context_gl_map_bo_address(struct wined3d_context_gl *context_gl, const struct wined3d_bo_address *data, size_t size, uint32_t flags) { @@ -2817,7 +2830,6 @@ static void flush_bo_ranges(struct wined3d_context_gl *context_gl, const struct void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges) { - const struct wined3d_gl_info *gl_info; struct wined3d_bo_gl *bo;
if (!data->buffer_object) @@ -2825,15 +2837,7 @@ void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, bo = wined3d_bo_gl(data->buffer_object);
flush_bo_ranges(context_gl, wined3d_const_bo_address(data), range_count, ranges); - - if (bo->b.map_ptr) - return; - - gl_info = context_gl->gl_info; - wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); - GL_EXTCALL(glUnmapBuffer(bo->binding)); - wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); - checkGLcall("Unmap buffer object"); + wined3d_bo_gl_unmap(bo, context_gl); }
void wined3d_context_gl_flush_bo_address(struct wined3d_context_gl *context_gl,
We will still block on a subsequent NOOVERWRITE map, so in practice this probably doesn't remove any bottlenecks. However, it leads to clearer code, and it matches what will need to be done for textures.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 2 +- dlls/wined3d/cs.c | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index d389bafcbed..343abac1004 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1242,7 +1242,7 @@ static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_re
if (!bo_vk->b.map_ptr) { - WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n", + WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not mapped.\n", bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab);
if (!wined3d_bo_vk_map(bo_vk, context_vk)) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index bfa5ddec7d8..ed5b289b8d8 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3075,34 +3075,41 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str { /* Limit NOOVERWRITE maps to buffers for now; there are too many ways that * a texture can be invalidated to even count. */ - if (wined3d_map_persistent() && resource->type == WINED3D_RTYPE_BUFFER - && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) + if (resource->type == WINED3D_RTYPE_BUFFER && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))) { struct wined3d_client_resource *client = &resource->client; struct wined3d_device *device = context->device; + struct wined3d_bo_address addr; const struct wined3d_bo *bo; uint8_t *map_ptr;
if (flags & WINED3D_MAP_DISCARD) { - if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &client->addr)) + if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &addr)) return false; + + if (wined3d_map_persistent()) + client->addr = addr; + } + else + { + addr = client->addr; }
- bo = client->addr.buffer_object; + bo = addr.buffer_object; map_ptr = bo ? bo->map_ptr : NULL; - map_ptr += (uintptr_t)client->addr.addr; + map_ptr += (uintptr_t)addr.addr;
if (!map_ptr) { - TRACE("Sub-resource is not persistently mapped.\n"); + TRACE("Sub-resource is not mapped.\n"); return false; }
wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, &map_desc->row_pitch, &map_desc->slice_pitch);
- client->mapped_upload.addr = *wined3d_const_bo_address(&client->addr); + client->mapped_upload.addr = *wined3d_const_bo_address(&addr); client->mapped_upload.flags = 0; if (bo) {
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 4 +++- dlls/wined3d/context_gl.c | 19 +++++++++++-------- dlls/wined3d/cs.c | 2 +- dlls/wined3d/wined3d_private.h | 1 + 4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 343abac1004..17ff6c2678f 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -811,6 +811,8 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_ return NULL; }
+ bo->b.persistent = wined3d_map_persistent(); + return bo->b.map_ptr; }
@@ -820,7 +822,7 @@ static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context struct wined3d_device_vk *device_vk; struct wined3d_bo_slab_vk *slab;
- if (wined3d_map_persistent()) + if (bo->b.persistent) return;
bo->b.map_ptr = NULL; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 3a83027522a..6479413df47 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2674,7 +2674,6 @@ static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, struct wined3d_context_ const struct wined3d_gl_info *gl_info; struct wined3d_bo_user *bo_user; struct wined3d_bo_gl tmp; - uint8_t *map_ptr;
if (flags & WINED3D_MAP_NOOVERWRITE) goto map; @@ -2715,6 +2714,8 @@ map: { GLbitfield gl_flags;
+ bo->b.persistent = wined3d_map_persistent(); + /* When mapping the bo persistently, we need to use the access flags * used to create the bo, instead of the access flags passed to the * map call. Otherwise, if for example the initial map call that @@ -2726,7 +2727,7 @@ map: * resources are mapped. On the other hand, we don't want to use the * access flags used to create the bo for non-persistent maps, because * that may imply dropping GL_MAP_UNSYNCHRONIZED_BIT. */ - if (wined3d_map_persistent()) + if (bo->b.persistent) { gl_flags = bo->flags & ~GL_CLIENT_STORAGE_BIT; if (!(gl_flags & GL_MAP_READ_BIT)) @@ -2740,29 +2741,31 @@ map: } gl_flags |= GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
- if ((map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, gl_flags))) && wined3d_map_persistent()) - bo->b.map_ptr = map_ptr; + bo->b.map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, gl_flags)); } else if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { - map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, wined3d_resource_gl_map_flags(bo, flags))); + bo->b.map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, 0, bo->size, + wined3d_resource_gl_map_flags(bo, flags))); + bo->b.persistent = false; } else { - map_ptr = GL_EXTCALL(glMapBuffer(bo->binding, wined3d_resource_gl_legacy_map_flags(flags))); + bo->b.map_ptr = GL_EXTCALL(glMapBuffer(bo->binding, wined3d_resource_gl_legacy_map_flags(flags))); + bo->b.persistent = false; }
wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); checkGLcall("Map buffer object");
- return map_ptr; + return bo->b.map_ptr; }
static void wined3d_bo_gl_unmap(struct wined3d_bo_gl *bo, struct wined3d_context_gl *context_gl) { const struct wined3d_gl_info *gl_info = context_gl->gl_info;
- if (bo->b.map_ptr) + if (bo->b.persistent) return;
wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id); diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index ed5b289b8d8..67933a90c5d 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3088,7 +3088,7 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &addr)) return false;
- if (wined3d_map_persistent()) + if (!addr.buffer_object || addr.buffer_object->persistent) client->addr = addr; } else diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1b3a13024f9..c0dd2cee037 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1610,6 +1610,7 @@ struct wined3d_bo size_t buffer_offset; size_t memory_offset; bool coherent; + bool persistent; };
struct wined3d_bo_gl
On Mon, 31 Jan 2022 at 04:05, Zebediah Figura zfigura@codeweavers.com wrote:
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Could the "arbitrary" part be avoided? In particular, what would prevent us from unmapping less recently used mappings when we run into the cap?
On 1/31/22 08:11, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 04:05, Zebediah Figura zfigura@codeweavers.com wrote:
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Could the "arbitrary" part be avoided? In particular, what would prevent us from unmapping less recently used mappings when we run into the cap?
Nothing, really. We could relatively easily use an LRU list, or periodically garbage-collect unused mappings, for two possibilities.
I think it's a bit orthogonal to this patch, though. No matter what criteria we use to determine whether a mapping is persistent in wined3d_bo_*_map(), or to possibly unmap it later, we'll at least want some of these users of bo->persistent.
I'm also inclined to argue there's no reason not to accept 4/4 now, and later (assuming we need to) implement a more complex and optimized scheme on top of that. Although it could probably do with a bit more factored out into the "adjust_mapped_memory" helpers.
On Mon, 31 Jan 2022 at 18:22, Zebediah Figura zfigura@codeweavers.com wrote:
On 1/31/22 08:11, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 04:05, Zebediah Figura zfigura@codeweavers.com wrote:
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Could the "arbitrary" part be avoided? In particular, what would prevent us from unmapping less recently used mappings when we run into the cap?
Nothing, really. We could relatively easily use an LRU list, or periodically garbage-collect unused mappings, for two possibilities.
I think it's a bit orthogonal to this patch, though. No matter what criteria we use to determine whether a mapping is persistent in wined3d_bo_*_map(), or to possibly unmap it later, we'll at least want some of these users of bo->persistent.
I'm also inclined to argue there's no reason not to accept 4/4 now, and later (assuming we need to) implement a more complex and optimized scheme on top of that. Although it could probably do with a bit more factored out into the "adjust_mapped_memory" helpers.
To some extent, yes. However, the follow-up question then becomes what the "persistent" field really means. Or put a different way, under what circumstances should we use "bo->persistent" instead of "bo->map_ptr"?
On 1/31/22 11:33, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 18:22, Zebediah Figura zfigura@codeweavers.com wrote:
On 1/31/22 08:11, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 04:05, Zebediah Figura zfigura@codeweavers.com wrote:
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Could the "arbitrary" part be avoided? In particular, what would prevent us from unmapping less recently used mappings when we run into the cap?
Nothing, really. We could relatively easily use an LRU list, or periodically garbage-collect unused mappings, for two possibilities.
I think it's a bit orthogonal to this patch, though. No matter what criteria we use to determine whether a mapping is persistent in wined3d_bo_*_map(), or to possibly unmap it later, we'll at least want some of these users of bo->persistent.
I'm also inclined to argue there's no reason not to accept 4/4 now, and later (assuming we need to) implement a more complex and optimized scheme on top of that. Although it could probably do with a bit more factored out into the "adjust_mapped_memory" helpers.
To some extent, yes. However, the follow-up question then becomes what the "persistent" field really means. Or put a different way, under what circumstances should we use "bo->persistent" instead of "bo->map_ptr"?
Note that we use "bo->map_ptr" inconsistently between the OpenGL and Vulkan backends—the OpenGL backend only sets it for persistent mappings, whereas the Vulkan backend sets it for all mappings. This patch standardizes on the latter behaviour.
The reason we want this is basically patch 2/4. Namely, if the BO is mapped, then wined3d_device_context_map() can return its map pointer to the caller (assuming we just got it from a DISCARD map). If it is mapped persistently, we can also store that map pointer and use it for subsequent NOOVERWRITE maps.
I don't anticipate any other places that would care, though.
On Mon, 31 Jan 2022 at 19:02, Zebediah Figura zfigura@codeweavers.com wrote:
On 1/31/22 11:33, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 18:22, Zebediah Figura zfigura@codeweavers.com wrote:
On 1/31/22 08:11, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 04:05, Zebediah Figura zfigura@codeweavers.com wrote:
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Could the "arbitrary" part be avoided? In particular, what would prevent us from unmapping less recently used mappings when we run into the cap?
Nothing, really. We could relatively easily use an LRU list, or periodically garbage-collect unused mappings, for two possibilities.
I think it's a bit orthogonal to this patch, though. No matter what criteria we use to determine whether a mapping is persistent in wined3d_bo_*_map(), or to possibly unmap it later, we'll at least want some of these users of bo->persistent.
I'm also inclined to argue there's no reason not to accept 4/4 now, and later (assuming we need to) implement a more complex and optimized scheme on top of that. Although it could probably do with a bit more factored out into the "adjust_mapped_memory" helpers.
To some extent, yes. However, the follow-up question then becomes what the "persistent" field really means. Or put a different way, under what circumstances should we use "bo->persistent" instead of "bo->map_ptr"?
Note that we use "bo->map_ptr" inconsistently between the OpenGL and Vulkan backends—the OpenGL backend only sets it for persistent mappings, whereas the Vulkan backend sets it for all mappings. This patch standardizes on the latter behaviour.
The reason we want this is basically patch 2/4. Namely, if the BO is mapped, then wined3d_device_context_map() can return its map pointer to the caller (assuming we just got it from a DISCARD map). If it is mapped persistently, we can also store that map pointer and use it for subsequent NOOVERWRITE maps.
The concern I have is that if we're using "persistent" in the sense the the bo is never going to be unmapped, that essentially precludes futures schemes where we do potentially unmap these. On the other hand, if these aren't all that persistent in practice, we only care whether the bo is currently mapped, but then also need to make sure we can invalidate e.g. client mappings when needed. (And note that in principle a bo can be currently mapped because a different bo in the same slab or chunk is currently mapped, regardless of what wined3d_map_persistent() returns.)
On 1/31/22 16:44, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 19:02, Zebediah Figura zfigura@codeweavers.com wrote:
On 1/31/22 11:33, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 18:22, Zebediah Figura zfigura@codeweavers.com wrote:
On 1/31/22 08:11, Henri Verbeet wrote:
On Mon, 31 Jan 2022 at 04:05, Zebediah Figura zfigura@codeweavers.com wrote:
The ultimate idea being to set a cap on the amount of persistent BO memory, in which case we need to arbitrarily mark BOs as persistent.
Could the "arbitrary" part be avoided? In particular, what would prevent us from unmapping less recently used mappings when we run into the cap?
Nothing, really. We could relatively easily use an LRU list, or periodically garbage-collect unused mappings, for two possibilities.
I think it's a bit orthogonal to this patch, though. No matter what criteria we use to determine whether a mapping is persistent in wined3d_bo_*_map(), or to possibly unmap it later, we'll at least want some of these users of bo->persistent.
I'm also inclined to argue there's no reason not to accept 4/4 now, and later (assuming we need to) implement a more complex and optimized scheme on top of that. Although it could probably do with a bit more factored out into the "adjust_mapped_memory" helpers.
To some extent, yes. However, the follow-up question then becomes what the "persistent" field really means. Or put a different way, under what circumstances should we use "bo->persistent" instead of "bo->map_ptr"?
Note that we use "bo->map_ptr" inconsistently between the OpenGL and Vulkan backends—the OpenGL backend only sets it for persistent mappings, whereas the Vulkan backend sets it for all mappings. This patch standardizes on the latter behaviour.
The reason we want this is basically patch 2/4. Namely, if the BO is mapped, then wined3d_device_context_map() can return its map pointer to the caller (assuming we just got it from a DISCARD map). If it is mapped persistently, we can also store that map pointer and use it for subsequent NOOVERWRITE maps.
The concern I have is that if we're using "persistent" in the sense the the bo is never going to be unmapped, that essentially precludes futures schemes where we do potentially unmap these. On the other hand, if these aren't all that persistent in practice, we only care whether the bo is currently mapped, but then also need to make sure we can invalidate e.g. client mappings when needed. (And note that in principle a bo can be currently mapped because a different bo in the same slab or chunk is currently mapped, regardless of what wined3d_map_persistent() returns.)
Right, took me long enough to realize that's what you were getting at...
I guess it ultimately does depend on how we unmap, but no matter how we do it, we probably want the client thread to be managing it, and in that case the "persistent" field would be redundant.
I'll try to restructure things so that the client thread is managing the existing persistent mapping logic.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- The number comes from patches by Matteo Bruni. I haven't tested it with real applications, though, and I don't make claims as to its appropriateness.
dlls/wined3d/adapter_vk.c | 26 +++++++++++++++++++++----- dlls/wined3d/context_gl.c | 10 +++++++++- dlls/wined3d/context_vk.c | 25 ++++++++++++++++++++----- dlls/wined3d/cs.c | 3 +++ dlls/wined3d/directx.c | 7 +++++++ dlls/wined3d/wined3d_private.h | 15 ++++++++++----- 6 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 17ff6c2678f..c2c47cf8be1 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -381,7 +381,10 @@ static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *c vk_info = &device_vk->vk_info;
if (chunk_vk->c.map_ptr) + { VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory)); + adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE); + } VK_CALL(vkFreeMemory(device_vk->vk_device, chunk_vk->vk_memory, NULL)); TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(chunk_vk->vk_memory)); wined3d_allocator_chunk_cleanup(&chunk_vk->c); @@ -794,6 +797,8 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_ ERR("Failed to map slab.\n"); return NULL; } + + bo->b.persistent = slab->bo.b.persistent; } else if (bo->memory) { @@ -804,14 +809,24 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_ ERR("Failed to map chunk.\n"); return NULL; } + + bo->b.persistent = chunk_vk->c.persistent; } - else if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &bo->b.map_ptr))) < 0) + else { - ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr)); - return NULL; - } + size_t mapped_size; + + if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &bo->b.map_ptr))) < 0) + { + ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr)); + return NULL; + }
- bo->b.persistent = wined3d_map_persistent(); + mapped_size = adapter_adjust_mapped_memory(device_vk->d.adapter, bo->size); + bo->b.persistent = (mapped_size < MAX_PERSISTENT_MAPPED_BYTES); + if (!bo->b.persistent) + WARN_(d3d_perf)("Not mapping BO %p as persistent.\n", bo); + }
return bo->b.map_ptr; } @@ -842,6 +857,7 @@ static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context vk_info = context_vk->vk_info; device_vk = wined3d_device_vk(context_vk->c.device); VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory)); + adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size); }
static void wined3d_bo_slab_vk_lock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk) diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 6479413df47..0ad2a28c461 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2674,6 +2674,7 @@ static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, struct wined3d_context_ const struct wined3d_gl_info *gl_info; struct wined3d_bo_user *bo_user; struct wined3d_bo_gl tmp; + size_t mapped_size;
if (flags & WINED3D_MAP_NOOVERWRITE) goto map; @@ -2710,11 +2711,13 @@ map: gl_info = context_gl->gl_info; wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id);
+ mapped_size = adapter_adjust_mapped_memory(device_gl->d.adapter, bo->size); + if (gl_info->supported[ARB_BUFFER_STORAGE]) { GLbitfield gl_flags;
- bo->b.persistent = wined3d_map_persistent(); + bo->b.persistent = (mapped_size < MAX_PERSISTENT_MAPPED_BYTES);
/* When mapping the bo persistently, we need to use the access flags * used to create the bo, instead of the access flags passed to the @@ -2772,6 +2775,8 @@ static void wined3d_bo_gl_unmap(struct wined3d_bo_gl *bo, struct wined3d_context GL_EXTCALL(glUnmapBuffer(bo->binding)); wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); checkGLcall("Unmap buffer object"); + + adapter_adjust_mapped_memory(context_gl->c.device->adapter, -bo->size); }
void *wined3d_context_gl_map_bo_address(struct wined3d_context_gl *context_gl, @@ -2927,6 +2932,9 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct GL_EXTCALL(glDeleteBuffers(1, &bo->id)); checkGLcall("buffer object destruction"); bo->id = 0; + + if (bo->b.map_ptr) + adapter_adjust_mapped_memory(context_gl->c.device->adapter, -bo->size); }
bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizeiptr size, diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 97c60719489..52f5d0c44aa 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -27,6 +27,7 @@ #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op) { @@ -261,6 +262,7 @@ void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const struct wined3d_vk_info *vk_info = context_vk->vk_info; + size_t mapped_size; void *map_ptr; VkResult vr;
@@ -269,12 +271,20 @@ void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk
wined3d_allocator_chunk_vk_lock(chunk_vk);
- if (!chunk_vk->c.map_ptr && (vr = VK_CALL(vkMapMemory(device_vk->vk_device, - chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0) + if (!chunk_vk->c.map_ptr) { - ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr)); - wined3d_allocator_chunk_vk_unlock(chunk_vk); - return NULL; + if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, + chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0) + { + ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr)); + wined3d_allocator_chunk_vk_unlock(chunk_vk); + return NULL; + } + + mapped_size = adapter_adjust_mapped_memory(device_vk->d.adapter, WINED3D_ALLOCATOR_CHUNK_SIZE); + chunk_vk->c.persistent = (mapped_size < MAX_PERSISTENT_MAPPED_BYTES); + if (!chunk_vk->c.persistent) + WARN_(d3d_perf)("Not mapping chunk %p as persistent.\n", chunk_vk); }
++chunk_vk->c.map_count; @@ -305,6 +315,8 @@ void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_v chunk_vk->c.map_ptr = NULL;
wined3d_allocator_chunk_vk_unlock(chunk_vk); + + adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE); }
VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk, @@ -976,7 +988,10 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const }
if (bo->b.map_ptr) + { VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory)); + adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size); + } wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id); }
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 67933a90c5d..498dd2b69dd 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -22,6 +22,7 @@ #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); WINE_DECLARE_DEBUG_CHANNEL(d3d_sync); WINE_DECLARE_DEBUG_CHANNEL(fps);
@@ -3090,6 +3091,8 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str
if (!addr.buffer_object || addr.buffer_object->persistent) client->addr = addr; + else + WARN_(d3d_perf)("BO %p is not persistently mapped.\n", addr.buffer_object); } else { diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 1b34d2eceaa..e8c86f3dc02 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -157,6 +157,13 @@ UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) return adapter->vram_bytes_used; }
+ssize_t adapter_adjust_mapped_memory(struct wined3d_adapter *adapter, ssize_t size) +{ + ssize_t ret = InterlockedExchangeAddSizeT(&adapter->mapped_size, size) + size; + TRACE("Adjusted mapped adapter memory by %zd to %zd.\n", size, ret); + return ret; +} + void wined3d_adapter_cleanup(struct wined3d_adapter *adapter) { unsigned int output_idx; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c0dd2cee037..fe72559d399 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3457,6 +3457,12 @@ struct wined3d_output
HRESULT wined3d_output_get_gamma_ramp(struct wined3d_output *output, struct wined3d_gamma_ramp *ramp) DECLSPEC_HIDDEN;
+#ifdef _WIN64 +#define MAX_PERSISTENT_MAPPED_BYTES SSIZE_MAX +#else +#define MAX_PERSISTENT_MAPPED_BYTES (512 * 1024 * 1024) +#endif + /* The adapter structure */ struct wined3d_adapter { @@ -3475,6 +3481,8 @@ struct wined3d_adapter void *formats; size_t format_size;
+ ssize_t mapped_size; + const struct wined3d_vertex_pipe_ops *vertex_pipe; const struct wined3d_fragment_pipe_ops *fragment_pipe; const struct wined3d_state_entry_template *misc_state_template; @@ -3554,6 +3562,7 @@ BOOL wined3d_adapter_gl_init_format_info(struct wined3d_adapter *adapter, BOOL wined3d_adapter_no3d_init_format_info(struct wined3d_adapter *adapter) DECLSPEC_HIDDEN; BOOL wined3d_adapter_vk_init_format_info(struct wined3d_adapter_vk *adapter_vk, const struct wined3d_vk_info *vk_info) DECLSPEC_HIDDEN; +ssize_t adapter_adjust_mapped_memory(struct wined3d_adapter *adapter, ssize_t size) DECLSPEC_HIDDEN; UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) DECLSPEC_HIDDEN;
BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx *ctx) DECLSPEC_HIDDEN; @@ -4015,6 +4024,7 @@ struct wined3d_allocator_chunk struct list available[WINED3D_ALLOCATOR_CHUNK_ORDER_COUNT]; struct wined3d_allocator *allocator; unsigned int map_count; + bool persistent; void *map_ptr; };
@@ -6636,11 +6646,6 @@ static inline void wined3d_context_gl_reference_buffer(struct wined3d_context_gl wined3d_context_gl_reference_bo(context_gl, wined3d_bo_gl(buffer->buffer_object)); }
-static inline bool wined3d_map_persistent(void) -{ - return sizeof(void *) >= sizeof(uint64_t); -} - /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
On Mon, Jan 31, 2022 at 4:05 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
The number comes from patches by Matteo Bruni. I haven't tested it with real applications, though, and I don't make claims as to its appropriateness.
Good strategy to pull me in like this :D
FWIW that's the number I ended up with after running a number of games with my patches and raising the limits whenever we kept blocking on maps.
The commit message from the last patch in my branch touching the limit is:
With these new values Gaz Guzzler Combat Carnage is happy (on the i7-870 + Nvidia GTX 970 box). The game needs the LAA flag set to avoid VM exhaustion issues on the GL driver side even without these changes.
That was with a whole lot of other changes (some of them hacky) to avoid various performance bottlenecks. OTOH that system has a slow CPU compared to the GPU and that was with GL, it's certainly possible that we would use as much memory on a newer setup even without the additional hacks.
If you feel that 512MB is too much (it's 1/8 of the whole address space after all...) we could start smaller and possibly raise the threshold afterwards.