Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/context_gl.c | 27 +++++++++++++++------------ dlls/wined3d/resource.c | 8 ++++++-- dlls/wined3d/wined3d_private.h | 2 +- 3 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index b08003c697a..4510fe5b155 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2712,7 +2712,7 @@ map:
if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { - map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, offset, size, wined3d_resource_gl_map_flags(flags))); + map_ptr = GL_EXTCALL(glMapBufferRange(bo->binding, offset, size, wined3d_resource_gl_map_flags(bo, flags))); } else { @@ -2754,21 +2754,24 @@ void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, gl_info = context_gl->gl_info; wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id);
- if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + if (!bo->coherent) { - for (i = 0; i < range_count; ++i) + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { - GL_EXTCALL(glFlushMappedBufferRange(bo->binding, - (UINT_PTR)data->addr + ranges[i].offset, ranges[i].size)); + for (i = 0; i < range_count; ++i) + { + GL_EXTCALL(glFlushMappedBufferRange(bo->binding, + (UINT_PTR)data->addr + ranges[i].offset, ranges[i].size)); + } } - } - else if (!bo->coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) - { - for (i = 0; i < range_count; ++i) + else if (gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) { - GL_EXTCALL(glFlushMappedBufferRangeAPPLE(bo->binding, - (uintptr_t)data->addr + ranges[i].offset, ranges[i].size)); - checkGLcall("glFlushMappedBufferRangeAPPLE"); + for (i = 0; i < range_count; ++i) + { + GL_EXTCALL(glFlushMappedBufferRangeAPPLE(bo->binding, + (uintptr_t)data->addr + ranges[i].offset, ranges[i].size)); + checkGLcall("glFlushMappedBufferRangeAPPLE"); + } } }
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 8f31996595c..abf07682c76 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -388,12 +388,16 @@ GLbitfield wined3d_resource_gl_storage_flags(const struct wined3d_resource *reso return flags; }
-GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) +GLbitfield wined3d_resource_gl_map_flags(const struct wined3d_bo_gl *bo, DWORD d3d_flags) { GLbitfield ret = 0;
if (d3d_flags & WINED3D_MAP_WRITE) - ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; + { + ret |= GL_MAP_WRITE_BIT; + if (!bo->coherent) + ret |= GL_MAP_FLUSH_EXPLICIT_BIT; + } if (d3d_flags & WINED3D_MAP_READ) ret |= GL_MAP_READ_BIT; else diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 161d36ad76c..41956f1f061 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4217,7 +4217,7 @@ void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HI const struct wined3d_format *wined3d_resource_get_decompress_format( const struct wined3d_resource *resource) DECLSPEC_HIDDEN; unsigned int wined3d_resource_get_sample_count(const struct wined3d_resource *resource) DECLSPEC_HIDDEN; -GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; +GLbitfield wined3d_resource_gl_map_flags(const struct wined3d_bo_gl *bo, DWORD d3d_flags) DECLSPEC_HIDDEN; GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; GLbitfield wined3d_resource_gl_storage_flags(const struct wined3d_resource *resource) DECLSPEC_HIDDEN; BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- We still don't translate coherency to MAP_COHERENT_BIT, but MAP_COHERENT_BIT only makes sense (and in fact only is allowed) for persistent mappings. When ARB_buffer_storage is available we currently use FLUSH_EXPLICIT_BIT, which offers the correct semantics.
dlls/wined3d/adapter_vk.c | 4 ++-- dlls/wined3d/context_gl.c | 6 +++--- dlls/wined3d/context_vk.c | 1 + dlls/wined3d/resource.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 8c3e63aac49..ffeffb4d145 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -983,7 +983,7 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context, wined3d_context_vk_reference_bo(context_vk, bo); }
- if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + if (!bo->b.coherent) { range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range.pNext = NULL; @@ -1024,7 +1024,7 @@ static void adapter_vk_unmap_bo_address(struct wined3d_context *context, vk_info = context_vk->vk_info; device_vk = wined3d_device_vk(context->device);
- if (!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + if (!bo->b.coherent) { range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range.pNext = NULL; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 4510fe5b155..2bc63464f7b 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2684,7 +2684,7 @@ static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, if ((flags & WINED3D_MAP_DISCARD) && bo->command_fence_id > device_gl->completed_fence_id) { if (wined3d_context_gl_create_bo(context_gl, bo->size, - bo->binding, bo->usage, bo->coherent, bo->flags, &tmp)) + bo->binding, bo->usage, bo->b.coherent, bo->flags, &tmp)) { list_move_head(&tmp.b.users, &bo->b.users); wined3d_context_gl_destroy_bo(context_gl, bo); @@ -2754,7 +2754,7 @@ void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, gl_info = context_gl->gl_info; wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id);
- if (!bo->coherent) + if (!bo->b.coherent) { if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { @@ -2889,7 +2889,7 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei bo->binding = binding; bo->usage = usage; bo->flags = flags; - bo->coherent = coherent; + bo->b.coherent = coherent; list_init(&bo->b.users); bo->command_fence_id = 0; bo->b.memory_offset = 0; diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index ad2f7adfe0b..8e055202ec2 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -492,6 +492,7 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic bo->size = size; bo->usage = usage; bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags; + bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); list_init(&bo->b.users); bo->command_buffer_id = 0; bo->slab = NULL; diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index abf07682c76..c8fb4cf2e29 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -395,7 +395,7 @@ GLbitfield wined3d_resource_gl_map_flags(const struct wined3d_bo_gl *bo, DWORD d if (d3d_flags & WINED3D_MAP_WRITE) { ret |= GL_MAP_WRITE_BIT; - if (!bo->coherent) + if (!bo->b.coherent) ret |= GL_MAP_FLUSH_EXPLICIT_BIT; } if (d3d_flags & WINED3D_MAP_READ) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 41956f1f061..993d0b3c4e4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1592,6 +1592,7 @@ struct wined3d_bo { struct list users; size_t memory_offset; + bool coherent; };
struct wined3d_bo_gl @@ -1604,7 +1605,6 @@ struct wined3d_bo_gl GLenum usage;
GLbitfield flags; - bool coherent; uint64_t command_fence_id; };
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 14 +++++++------- dlls/wined3d/context_gl.c | 1 + dlls/wined3d/context_vk.c | 8 ++++---- dlls/wined3d/wined3d_private.h | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index ffeffb4d145..c7005835d16 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -775,15 +775,15 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_ struct wined3d_bo_slab_vk *slab; VkResult vr;
- if (bo->map_ptr) - return bo->map_ptr; + if (bo->b.map_ptr) + return bo->b.map_ptr;
vk_info = context_vk->vk_info; device_vk = wined3d_device_vk(context_vk->c.device);
if ((slab = bo->slab)) { - if (!(bo->map_ptr = wined3d_bo_slab_vk_map(slab, context_vk))) + if (!(bo->b.map_ptr = wined3d_bo_slab_vk_map(slab, context_vk))) { ERR("Failed to map slab.\n"); return NULL; @@ -793,19 +793,19 @@ static void *wined3d_bo_vk_map(struct wined3d_bo_vk *bo, struct wined3d_context_ { struct wined3d_allocator_chunk_vk *chunk_vk = wined3d_allocator_chunk_vk(bo->memory->chunk);
- if (!(bo->map_ptr = wined3d_allocator_chunk_vk_map(chunk_vk, context_vk))) + if (!(bo->b.map_ptr = wined3d_allocator_chunk_vk_map(chunk_vk, context_vk))) { ERR("Failed to map chunk.\n"); return NULL; } } - else if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device, bo->vk_memory, 0, VK_WHOLE_SIZE, 0, &bo->map_ptr))) < 0) + else 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; }
- return bo->map_ptr; + return bo->b.map_ptr; }
static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context_vk *context_vk) @@ -817,7 +817,7 @@ static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context if (wined3d_map_persistent()) return;
- bo->map_ptr = NULL; + bo->b.map_ptr = NULL;
if ((slab = bo->slab)) { diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 2bc63464f7b..5cde971cd43 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2893,6 +2893,7 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei list_init(&bo->b.users); bo->command_fence_id = 0; bo->b.memory_offset = 0; + bo->b.map_ptr = NULL;
return true; } diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 8e055202ec2..8bcd6d61eb3 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -487,7 +487,7 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic return FALSE; }
- bo->map_ptr = NULL; + bo->b.map_ptr = NULL; bo->buffer_offset = 0; bo->size = size; bo->usage = usage; @@ -907,7 +907,7 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const
if ((slab_vk = bo->slab)) { - if (bo->map_ptr) + if (bo->b.map_ptr) wined3d_bo_slab_vk_unmap(slab_vk, context_vk); object_size = slab_vk->bo.size / 32; idx = bo->buffer_offset / object_size; @@ -918,13 +918,13 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const wined3d_context_vk_destroy_vk_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id); if (bo->memory) { - if (bo->map_ptr) + if (bo->b.map_ptr) wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk); wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id); return; }
- if (bo->map_ptr) + if (bo->b.map_ptr) VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory)); wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 993d0b3c4e4..1f167c9e7dd 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1591,6 +1591,7 @@ do { \ struct wined3d_bo { struct list users; + void *map_ptr; size_t memory_offset; bool coherent; }; @@ -1628,7 +1629,6 @@ struct wined3d_bo_vk struct wined3d_bo_slab_vk *slab;
VkDeviceMemory vk_memory; - void *map_ptr;
VkDeviceSize buffer_offset; VkDeviceSize size;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 7 +++ dlls/wined3d/adapter_vk.c | 44 +++++++++++------ dlls/wined3d/buffer.c | 5 ++ dlls/wined3d/context_gl.c | 61 +++++++++++++++++------- dlls/wined3d/cs.c | 86 ++++++++++++++++++++++++++++++++-- dlls/wined3d/directx.c | 6 +++ dlls/wined3d/wined3d_private.h | 25 +++++++++- 7 files changed, 198 insertions(+), 36 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 3a6ff54eec2..f1cdbffe718 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4598,6 +4598,12 @@ static void adapter_gl_copy_bo_address(struct wined3d_context *context, wined3d_context_gl_copy_bo_address(wined3d_context_gl(context), dst, src, size); }
+static void adapter_gl_flush_bo_address(struct wined3d_context *context, + const struct wined3d_const_bo_address *data, size_t size) +{ + wined3d_context_gl_flush_bo_address(wined3d_context_gl(context), data, size); +} + static HRESULT adapter_gl_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain) @@ -5050,6 +5056,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = .adapter_map_bo_address = adapter_gl_map_bo_address, .adapter_unmap_bo_address = adapter_gl_unmap_bo_address, .adapter_copy_bo_address = adapter_gl_copy_bo_address, + .adapter_flush_bo_address = adapter_gl_flush_bo_address, .adapter_create_swapchain = adapter_gl_create_swapchain, .adapter_destroy_swapchain = adapter_gl_destroy_swapchain, .adapter_create_buffer = adapter_gl_create_buffer, diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index c7005835d16..02a359c4f07 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1008,34 +1008,35 @@ map: return (uint8_t *)map_ptr + bo->b.memory_offset + (uintptr_t)data->addr; }
+static void flush_bo_range(struct wined3d_context_vk *context_vk, + struct wined3d_bo_vk *bo, unsigned int offset, unsigned int size) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkMappedMemoryRange range; + + range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range.pNext = NULL; + range.memory = bo->vk_memory; + range.offset = bo->b.memory_offset + offset; + range.size = size; + VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range)); +} + static void adapter_vk_unmap_bo_address(struct wined3d_context *context, const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges) { struct wined3d_context_vk *context_vk = wined3d_context_vk(context); - const struct wined3d_vk_info *vk_info; - struct wined3d_device_vk *device_vk; - VkMappedMemoryRange range; struct wined3d_bo_vk *bo; unsigned int i;
if (!(bo = (struct wined3d_bo_vk *)data->buffer_object)) return;
- vk_info = context_vk->vk_info; - device_vk = wined3d_device_vk(context->device); - if (!bo->b.coherent) { - range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range.pNext = NULL; - range.memory = bo->vk_memory; - for (i = 0; i < range_count; ++i) - { - range.offset = bo->b.memory_offset + ranges[i].offset; - range.size = ranges[i].size; - VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range)); - } + flush_bo_range(context_vk, bo, ranges[i].offset, ranges[i].size); }
wined3d_bo_vk_unmap(bo, context_vk); @@ -1169,6 +1170,18 @@ void adapter_vk_copy_bo_address(struct wined3d_context *context, adapter_vk_unmap_bo_address(context, src, 0, NULL); }
+static void adapter_vk_flush_bo_address(struct wined3d_context *context, + const struct wined3d_const_bo_address *data, size_t size) +{ + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct wined3d_bo_vk *bo; + + if (!(bo = (struct wined3d_bo_vk *)data->buffer_object)) + return; + + flush_bo_range(context_vk, bo, (uintptr_t)data->addr, size); +} + static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain) @@ -1820,6 +1833,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = .adapter_map_bo_address = adapter_vk_map_bo_address, .adapter_unmap_bo_address = adapter_vk_unmap_bo_address, .adapter_copy_bo_address = adapter_vk_copy_bo_address, + .adapter_flush_bo_address = adapter_vk_flush_bo_address, .adapter_create_swapchain = adapter_vk_create_swapchain, .adapter_destroy_swapchain = adapter_vk_destroy_swapchain, .adapter_create_buffer = adapter_vk_create_buffer, diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index e1a5ec26c29..3430b8b1e97 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -938,6 +938,11 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc addr.buffer_object = buffer->buffer_object; addr.addr = 0; buffer->map_ptr = wined3d_context_map_bo_address(context, &addr, resource->size, flags); + /* We are accessing buffer->resource.client from the CS thread, + * but it's safe because the client thread will wait for the + * map to return, thus completely serializing this call with + * other client code. */ + buffer->resource.client.addr = addr;
if (((DWORD_PTR)buffer->map_ptr) & (RESOURCE_ALIGNMENT - 1)) { diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 5cde971cd43..83cf87f8404 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2741,45 +2741,72 @@ void *wined3d_context_gl_map_bo_address(struct wined3d_context_gl *context_gl, return map_ptr; }
-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) +static void flush_bo_ranges(struct wined3d_context_gl *context_gl, const struct wined3d_const_bo_address *data, + unsigned int range_count, const struct wined3d_range *ranges) { const struct wined3d_gl_info *gl_info; struct wined3d_bo_gl *bo; unsigned int i;
- if (!(bo = (struct wined3d_bo_gl *)data->buffer_object)) + if (!(bo = (struct wined3d_bo_gl *)data->buffer_object) || bo->b.coherent) return;
gl_info = context_gl->gl_info; wined3d_context_gl_bind_bo(context_gl, bo->binding, bo->id);
- if (!bo->b.coherent) + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) { - if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + for (i = 0; i < range_count; ++i) { - for (i = 0; i < range_count; ++i) - { - GL_EXTCALL(glFlushMappedBufferRange(bo->binding, - (UINT_PTR)data->addr + ranges[i].offset, ranges[i].size)); - } + GL_EXTCALL(glFlushMappedBufferRange(bo->binding, + (UINT_PTR)data->addr + ranges[i].offset, ranges[i].size)); } - else if (gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) + } + else if (gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) + { + for (i = 0; i < range_count; ++i) { - for (i = 0; i < range_count; ++i) - { - GL_EXTCALL(glFlushMappedBufferRangeAPPLE(bo->binding, - (uintptr_t)data->addr + ranges[i].offset, ranges[i].size)); - checkGLcall("glFlushMappedBufferRangeAPPLE"); - } + GL_EXTCALL(glFlushMappedBufferRangeAPPLE(bo->binding, + (uintptr_t)data->addr + ranges[i].offset, ranges[i].size)); + checkGLcall("glFlushMappedBufferRangeAPPLE"); } }
+ wined3d_context_gl_bind_bo(context_gl, bo->binding, 0); + checkGLcall("Flush buffer object"); +} + +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 (!(bo = (struct wined3d_bo_gl *)data->buffer_object)) + return; + + flush_bo_ranges(context_gl, wined3d_const_bo_address(data), range_count, ranges); + + 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"); }
+void wined3d_context_gl_flush_bo_address(struct wined3d_context_gl *context_gl, + const struct wined3d_const_bo_address *data, size_t size) +{ + struct wined3d_range range; + + TRACE("context_gl %p, data %s, size %zu.\n", context_gl, debug_const_bo_address(data), size); + + range.offset = (uintptr_t)data->addr; + range.size = size; + + flush_bo_ranges(context_gl, data, 1, &range); +} + void wined3d_context_gl_copy_bo_address(struct wined3d_context_gl *context_gl, const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size) { diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 5ffa27f5ce0..c1adde3c4ef 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -118,6 +118,13 @@ ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list) return refcount; }
+static void invalidate_client_address(struct wined3d_resource *resource) +{ + struct wined3d_client_resource *client = &resource->client; + + memset(&client->addr, 0, sizeof(client->addr)); +} + enum wined3d_cs_op { WINED3D_CS_OP_NOP, @@ -2412,6 +2419,9 @@ static void wined3d_cs_acquire_command_list(struct wined3d_device_context *conte
for (i = 0; i < list->command_list_count; ++i) wined3d_cs_acquire_command_list(context, list->command_lists[i]); + + for (i = 0; i < list->upload_count; ++i) + invalidate_client_address(list->uploads[i].resource); }
static void wined3d_cs_exec_preload_resource(struct wined3d_cs *cs, const void *data) @@ -2449,6 +2459,8 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou { struct wined3d_cs_unload_resource *op;
+ invalidate_client_address(resource); + op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_UNLOAD_RESOURCE; op->resource = resource; @@ -2512,6 +2524,9 @@ HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context,
wined3d_resource_wait_idle(resource);
+ /* We might end up invalidating the resource on the CS thread. */ + invalidate_client_address(resource); + if (!(op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_MAP))) return E_OUTOFMEMORY; op->opcode = WINED3D_CS_OP_MAP; @@ -2686,6 +2701,11 @@ void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context { struct wined3d_cs_blt_sub_resource *op;
+ /* If we are replacing the whole resource, the CS thread might discard and + * rename the buffer object, in which case ours is no longer valid. */ + if (dst_resource->type == WINED3D_RTYPE_BUFFER && dst_box->right - dst_box->left == dst_resource->size) + invalidate_client_address(dst_resource); + op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_BLT_SUB_RESOURCE; op->dst_resource = dst_resource; @@ -2725,8 +2745,12 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi if (resource->type == WINED3D_RTYPE_BUFFER) { struct wined3d_buffer *buffer = buffer_from_resource(resource); + size_t size = box->right - box->left;
- wined3d_buffer_copy_bo_address(buffer, context, box->left, &op->bo.addr, box->right - box->left); + if (op->bo.addr.buffer_object && op->bo.addr.buffer_object == buffer->buffer_object) + wined3d_context_flush_bo_address(context, &op->bo.addr, size); + else + wined3d_buffer_copy_bo_address(buffer, context, box->left, &op->bo.addr, size); goto done; }
@@ -2767,6 +2791,11 @@ void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_conte struct wined3d_box dummy_box; struct upload_bo bo;
+ /* If we are replacing the whole resource, the CS thread might discard and + * rename the buffer object, in which case ours is no longer valid. */ + if (resource->type == WINED3D_RTYPE_BUFFER && box->right - box->left == resource->size) + invalidate_client_address(resource); + if (context->ops->map_upload_bo(context, resource, sub_resource_idx, &map_desc, box, WINED3D_MAP_WRITE)) { wined3d_format_copy_data(resource->format, data, row_pitch, slice_pitch, map_desc.data, map_desc.row_pitch, @@ -3090,14 +3119,65 @@ static void wined3d_cs_st_finish(struct wined3d_device_context *context, enum wi static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, uint32_t flags) { - /* FIXME: We would like to return mapped or newly allocated memory here. */ + /* 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_NOOVERWRITE)) + { + struct wined3d_client_resource *client = &resource->client; + const struct wined3d_bo *bo; + uint8_t *map_ptr; + + bo = (const struct wined3d_bo *)client->addr.buffer_object; + map_ptr = bo ? bo->map_ptr : NULL; + map_ptr += (uintptr_t)client->addr.addr; + + if (!map_ptr) + { + TRACE("Sub-resource is not persistently 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.flags = 0; + if (bo) + { + map_ptr += bo->memory_offset; + if (!bo->coherent) + client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP; + } + map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box); + + client->mapped_box = *box; + + TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client->mapped_upload.addr), + client->mapped_upload.flags); + return true; + } + return false; }
+static bool wined3d_bo_address_is_null(struct wined3d_const_bo_address *addr) +{ + return !addr->buffer_object && !addr->addr; +} + static bool wined3d_cs_unmap_upload_bo(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_box *box, struct upload_bo *bo) { - return false; + struct wined3d_client_resource *client = &resource->client; + + if (wined3d_bo_address_is_null(&client->mapped_upload.addr)) + return false; + + *bo = client->mapped_upload; + *box = client->mapped_box; + memset(&client->mapped_upload, 0, sizeof(client->mapped_upload)); + memset(&client->mapped_box, 0, sizeof(client->mapped_box)); + return true; }
static const struct wined3d_device_context_ops wined3d_cs_st_ops = diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 990164fd68d..58aaf44fc45 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2798,6 +2798,11 @@ static void adapter_no3d_copy_bo_address(struct wined3d_context *context, memcpy(dst->addr, src->addr, size); }
+static void adapter_no3d_flush_bo_address(struct wined3d_context *context, + const struct wined3d_const_bo_address *data, size_t size) +{ +} + static HRESULT adapter_no3d_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain) @@ -3067,6 +3072,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops = .adapter_map_bo_address = adapter_no3d_map_bo_address, .adapter_unmap_bo_address = adapter_no3d_unmap_bo_address, .adapter_copy_bo_address = adapter_no3d_copy_bo_address, + .adapter_flush_bo_address = adapter_no3d_flush_bo_address, .adapter_create_swapchain = adapter_no3d_create_swapchain, .adapter_destroy_swapchain = adapter_no3d_destroy_swapchain, .adapter_create_buffer = adapter_no3d_create_buffer, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1f167c9e7dd..588e39db9b2 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1674,7 +1674,7 @@ struct wined3d_const_bo_address const BYTE *addr; };
-static inline struct wined3d_const_bo_address *wined3d_const_bo_address(struct wined3d_bo_address *data) +static inline struct wined3d_const_bo_address *wined3d_const_bo_address(const struct wined3d_bo_address *data) { return (struct wined3d_const_bo_address *)data; } @@ -2358,6 +2358,8 @@ void wined3d_context_gl_draw_textured_quad(struct wined3d_context_gl *context_gl const RECT *src_rect, const RECT *dst_rect, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; void wined3d_context_gl_enable_clip_distances(struct wined3d_context_gl *context_gl, uint32_t mask) DECLSPEC_HIDDEN; void wined3d_context_gl_end_transform_feedback(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; +void wined3d_context_gl_flush_bo_address(struct wined3d_context_gl *context_gl, + const struct wined3d_const_bo_address *data, size_t size) DECLSPEC_HIDDEN; void wined3d_context_gl_free_fence(struct wined3d_fence *fence) DECLSPEC_HIDDEN; void wined3d_context_gl_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; void wined3d_context_gl_free_pipeline_statistics_query(struct wined3d_pipeline_statistics_query *query) DECLSPEC_HIDDEN; @@ -3366,6 +3368,8 @@ struct wined3d_adapter_ops unsigned int range_count, const struct wined3d_range *ranges); void (*adapter_copy_bo_address)(struct wined3d_context *context, const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size); + void (*adapter_flush_bo_address)(struct wined3d_context *context, + const struct wined3d_const_bo_address *data, size_t size); HRESULT (*adapter_create_swapchain)(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, @@ -4113,6 +4117,17 @@ const char *wined3d_debug_view_desc(const struct wined3d_view_desc *d, const struct wined3d_resource *resource) DECLSPEC_HIDDEN; const char *wined3d_debug_vkresult(VkResult vr) DECLSPEC_HIDDEN;
+struct wined3d_client_resource +{ + /* The resource's persistently mapped address, which we may use to perform + * NOOVERWRITE maps from the client thread. */ + struct wined3d_bo_address addr; + + /* The currently mapped upload BO, if applicable, and box. */ + struct upload_bo mapped_upload; + struct wined3d_box mapped_box; +}; + static inline BOOL wined3d_resource_access_is_managed(unsigned int access) { return !(~access & (WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU)); @@ -4158,6 +4173,8 @@ struct wined3d_resource DWORD priority; void *heap_memory;
+ struct wined3d_client_resource client; + void *parent; const struct wined3d_parent_ops *parent_ops; const struct wined3d_resource_ops *resource_ops; @@ -6233,6 +6250,12 @@ static inline void wined3d_context_copy_bo_address(struct wined3d_context *conte context->device->adapter->adapter_ops->adapter_copy_bo_address(context, dst, src, size); }
+static inline void wined3d_context_flush_bo_address(struct wined3d_context *context, + const struct wined3d_const_bo_address *data, size_t size) +{ + context->device->adapter->adapter_ops->adapter_flush_bo_address(context, data, size); +} + static inline void wined3d_context_vk_reference_bo(const struct wined3d_context_vk *context_vk, struct wined3d_bo_vk *bo) {
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com