So that it can be accessed from the client thread.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 9 ++++++ dlls/wined3d/context_vk.c | 52 ++++++++++++++++++++++++++-------- dlls/wined3d/wined3d_private.h | 11 +++++++ 3 files changed, 60 insertions(+), 12 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 02a359c4f07..cbf7c94fd3a 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -521,6 +521,10 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi goto fail; }
+ InitializeCriticalSection(&device_vk->allocator_cs); + if (device_vk->allocator_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) + device_vk->allocator_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wined3d_device_vk.allocator_cs"); + *device = &device_vk->d;
return WINED3D_OK; @@ -538,6 +542,11 @@ static void adapter_vk_destroy_device(struct wined3d_device *device)
wined3d_device_cleanup(&device_vk->d); wined3d_allocator_cleanup(&device_vk->allocator); + + if (device_vk->allocator_cs.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) + device_vk->allocator_cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&device_vk->allocator_cs); + VK_CALL(vkDestroyDevice(device_vk->vk_device, NULL)); heap_free(device_vk); } diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index ad7b0a8ba86..54c5eb6bc24 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -313,27 +313,43 @@ static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct struct wined3d_allocator *allocator = &device_vk->allocator; struct wined3d_allocator_block *block;
+ wined3d_device_vk_allocator_lock(device_vk); + if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2) { *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size); + wined3d_device_vk_allocator_unlock(device_vk); return NULL; }
if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size))) { + wined3d_device_vk_allocator_unlock(device_vk); *vk_memory = VK_NULL_HANDLE; return NULL; }
*vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
+ wined3d_device_vk_allocator_unlock(device_vk); return block; }
+static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + + assert(block->chunk->allocator == &device_vk->allocator); + wined3d_device_vk_allocator_lock(device_vk); + wined3d_allocator_block_free(block); + wined3d_device_vk_allocator_unlock(device_vk); +} + static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo) { const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter); + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits; struct wined3d_bo_slab_vk_key key; struct wined3d_bo_slab_vk *slab; @@ -360,6 +376,8 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context key.usage = usage; key.size = 32 * object_size;
+ wined3d_device_vk_allocator_lock(device_vk); + if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key))) { slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry); @@ -369,27 +387,30 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context { if (!(slab = heap_alloc_zero(sizeof(*slab)))) { + wined3d_device_vk_allocator_unlock(device_vk); ERR("Failed to allocate bo slab.\n"); return false; }
+ if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0) + { + wined3d_device_vk_allocator_unlock(device_vk); + ERR("Failed to add slab to available tree.\n"); + heap_free(slab); + return false; + } + slab->requested_memory_type = memory_type; if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo)) { + wined3d_device_vk_allocator_unlock(device_vk); ERR("Failed to create slab bo.\n"); + wine_rb_remove(&context_vk->bo_slab_available, &slab->entry); heap_free(slab); return false; } slab->map = ~0u;
- if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0) - { - ERR("Failed to add slab to available tree.\n"); - wined3d_context_vk_destroy_bo(context_vk, &slab->bo); - heap_free(slab); - return false; - } - TRACE("Created new bo slab %p.\n", slab); }
@@ -407,6 +428,8 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context } }
+ wined3d_device_vk_allocator_unlock(device_vk); + *bo = slab->bo; bo->memory = NULL; bo->slab = slab; @@ -480,7 +503,7 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic { ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr)); if (bo->memory) - wined3d_allocator_block_free(bo->memory); + wined3d_context_vk_free_memory(context_vk, bo->memory); else VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL)); VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL)); @@ -574,7 +597,7 @@ BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkIm { VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL)); if (image->memory) - wined3d_allocator_block_free(image->memory); + wined3d_context_vk_free_memory(context_vk, image->memory); else VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL)); ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr)); @@ -688,7 +711,7 @@ void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *conte
if (context_vk->completed_command_buffer_id > command_buffer_id) { - wined3d_allocator_block_free(block); + wined3d_context_vk_free_memory(context_vk, block); TRACE("Freed block %p.\n", block); return; } @@ -707,11 +730,14 @@ void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *conte static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab, SIZE_T idx, struct wined3d_context_vk *context_vk) { + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); struct wined3d_bo_slab_vk_key key; struct wine_rb_entry *entry;
TRACE("slab %p, idx %lu, context_vk %p.\n", slab, idx, context_vk);
+ wined3d_device_vk_allocator_lock(device_vk); + if (!slab->map) { key.memory_type = slab->requested_memory_type; @@ -729,6 +755,8 @@ static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab, } } slab->map |= 1u << idx; + + wined3d_device_vk_allocator_unlock(device_vk); }
static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk, @@ -1000,7 +1028,7 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK: TRACE("Destroying block %p.\n", o->u.block); - wined3d_allocator_block_free(o->u.block); + wined3d_context_vk_free_memory(context_vk, o->u.block); break;
case WINED3D_RETIRED_BO_SLAB_SLICE_VK: diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index aa8974366a6..62b92ce7c34 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4084,6 +4084,7 @@ struct wined3d_device_vk struct wined3d_null_resources_vk null_resources_vk; struct wined3d_null_views_vk null_views_vk;
+ CRITICAL_SECTION allocator_cs; struct wined3d_allocator allocator;
struct wined3d_uav_clear_state_vk uav_clear_state; @@ -4094,6 +4095,16 @@ static inline struct wined3d_device_vk *wined3d_device_vk(struct wined3d_device return CONTAINING_RECORD(device, struct wined3d_device_vk, d); }
+static inline void wined3d_device_vk_allocator_lock(struct wined3d_device_vk *device_vk) +{ + EnterCriticalSection(&device_vk->allocator_cs); +} + +static inline void wined3d_device_vk_allocator_unlock(struct wined3d_device_vk *device_vk) +{ + LeaveCriticalSection(&device_vk->allocator_cs); +} + bool wined3d_device_vk_create_null_resources(struct wined3d_device_vk *device_vk, struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; bool wined3d_device_vk_create_null_views(struct wined3d_device_vk *device_vk,
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/buffer.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 55dcd9e67e8..886fb95f3e5 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1399,12 +1399,8 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined return wined3d_buffer_init(&buffer_gl->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops); }
-static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buffer_vk, - struct wined3d_context_vk *context_vk) +static VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) { - struct wined3d_resource *resource = &buffer_vk->b.resource; - uint32_t bind_flags = resource->bind_flags; - VkMemoryPropertyFlags memory_type; VkBufferUsageFlags usage;
usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; @@ -1424,6 +1420,14 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; if (bind_flags & (WINED3D_BIND_RENDER_TARGET | WINED3D_BIND_DEPTH_STENCIL)) FIXME("Ignoring some bind flags %#x.\n", bind_flags); + return usage; +} + +static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buffer_vk, + struct wined3d_context_vk *context_vk) +{ + struct wined3d_resource *resource = &buffer_vk->b.resource; + VkMemoryPropertyFlags memory_type;
memory_type = 0; if (resource->access & WINED3D_RESOURCE_ACCESS_MAP_R) @@ -1433,7 +1437,8 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf else if (!(resource->usage & WINED3DUSAGE_DYNAMIC)) memory_type |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- if (!(wined3d_context_vk_create_bo(context_vk, resource->size, usage, memory_type, &buffer_vk->bo))) + if (!(wined3d_context_vk_create_bo(context_vk, resource->size, + vk_buffer_usage_from_bind_flags(resource->bind_flags), memory_type, &buffer_vk->bo))) { WARN("Failed to create Vulkan buffer.\n"); return FALSE;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/buffer.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 886fb95f3e5..62f84c96f96 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1423,22 +1423,27 @@ static VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) return usage; }
+static VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage) +{ + VkMemoryPropertyFlags memory_type = 0; + + if (access & WINED3D_RESOURCE_ACCESS_MAP_R) + memory_type |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + else if (access & WINED3D_RESOURCE_ACCESS_MAP_W) + memory_type |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + else if (!(usage & WINED3DUSAGE_DYNAMIC)) + memory_type |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + return memory_type; +} + static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buffer_vk, struct wined3d_context_vk *context_vk) { struct wined3d_resource *resource = &buffer_vk->b.resource; - VkMemoryPropertyFlags memory_type; - - memory_type = 0; - if (resource->access & WINED3D_RESOURCE_ACCESS_MAP_R) - memory_type |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - else if (resource->access & WINED3D_RESOURCE_ACCESS_MAP_W) - memory_type |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - else if (!(resource->usage & WINED3DUSAGE_DYNAMIC)) - memory_type |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
if (!(wined3d_context_vk_create_bo(context_vk, resource->size, - vk_buffer_usage_from_bind_flags(resource->bind_flags), memory_type, &buffer_vk->bo))) + vk_buffer_usage_from_bind_flags(resource->bind_flags), + vk_memory_type_from_access_flags(resource->access, resource->usage), &buffer_vk->bo))) { WARN("Failed to create Vulkan buffer.\n"); return FALSE;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
So as to allow the "buffer_object" field to point to other another wined3d_bo_vk; namely, one allocated and still in use by the client thread.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 4 ++-- dlls/wined3d/buffer.c | 13 ++++++++----- dlls/wined3d/context_vk.c | 8 ++++---- dlls/wined3d/view.c | 14 ++++++++++---- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index cbf7c94fd3a..5c83db9bfc9 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1720,7 +1720,7 @@ static void adapter_vk_draw_primitive(struct wined3d_device *device,
if (parameters->indirect) { - struct wined3d_bo_vk *bo = &indirect_vk->bo; + struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)indirect_vk->b.buffer_object; uint32_t stride, size;
wined3d_context_vk_reference_bo(context_vk, bo); @@ -1792,7 +1792,7 @@ static void adapter_vk_dispatch_compute(struct wined3d_device *device,
if (parameters->indirect) { - struct wined3d_bo_vk *bo = &indirect_vk->bo; + struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)indirect_vk->b.buffer_object;
wined3d_context_vk_reference_bo(context_vk, bo); VK_CALL(vkCmdDispatchIndirect(vk_command_buffer, bo->vk_buffer, diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 62f84c96f96..0a72f19935b 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1459,11 +1459,13 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf
const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_buffer_vk *buffer_vk) { + struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object; + if (buffer_vk->b.bo_user.valid) return &buffer_vk->buffer_info;
- buffer_vk->buffer_info.buffer = buffer_vk->bo.vk_buffer; - buffer_vk->buffer_info.offset = buffer_vk->bo.buffer_offset; + buffer_vk->buffer_info.buffer = bo->vk_buffer; + buffer_vk->buffer_info.offset = bo->buffer_offset; buffer_vk->buffer_info.range = buffer_vk->b.resource.size; buffer_vk->b.bo_user.valid = true;
@@ -1537,7 +1539,7 @@ static void wined3d_buffer_vk_upload_ranges(struct wined3d_buffer *buffer, struc if (!ranges->offset && ranges->size == resource->size) flags |= WINED3D_MAP_DISCARD;
- dst_bo = &wined3d_buffer_vk(buffer)->bo; + dst_bo = (struct wined3d_bo_vk *)buffer->buffer_object; if (!(dst_bo->memory_type & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || (!(flags & WINED3D_MAP_DISCARD) && dst_bo->command_buffer_id > context_vk->completed_command_buffer_id)) { @@ -1629,6 +1631,7 @@ void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk,
if (src_bind_mask) { + const struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object; const struct wined3d_vk_info *vk_info = context_vk->vk_info; VkBufferMemoryBarrier vk_barrier;
@@ -1643,8 +1646,8 @@ void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk, vk_barrier.dstAccessMask = vk_access_mask_from_bind_flags(bind_mask); vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - vk_barrier.buffer = buffer_vk->bo.vk_buffer; - vk_barrier.offset = buffer_vk->bo.buffer_offset; + vk_barrier.buffer = bo->vk_buffer; + vk_barrier.offset = bo->buffer_offset; vk_barrier.size = buffer_vk->b.resource.size; VK_CALL(vkCmdPipelineBarrier(wined3d_context_vk_get_command_buffer(context_vk), vk_pipeline_stage_mask_from_bind_flags(src_bind_mask), diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 54c5eb6bc24..854a800c0e4 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -2496,7 +2496,7 @@ static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *co { buffer_vk = wined3d_buffer_vk(buffer); buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk); - wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo); + wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer->buffer_object); buffers[count] = buffer_info->buffer; offsets[count] = buffer_info->offset + stream->offset; ++count; @@ -2535,7 +2535,7 @@ static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context { buffer_vk = wined3d_buffer_vk(buffer); buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk); - wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo); + wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer->buffer_object); buffers[count] = buffer_info->buffer; if ((offsets[count] = stream->offset) == ~0u) { @@ -2737,7 +2737,7 @@ static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_sha if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL)) return false; - wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo); + wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer->buffer_object); return true; }
@@ -3385,7 +3385,7 @@ VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *c idx_type = VK_INDEX_TYPE_UINT32; buffer_vk = wined3d_buffer_vk(state->index_buffer); buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk); - wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo); + wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer_vk->b.buffer_object); VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer, buffer_info->offset + state->index_offset, idx_type)); } diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 374e693b17d..ee398be15f0 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -672,17 +672,19 @@ static VkBufferView wined3d_view_vk_create_vk_buffer_view(struct wined3d_context struct wined3d_device_vk *device_vk; VkBufferView vk_buffer_view; unsigned int offset, size; + struct wined3d_bo_vk *bo; VkResult vr;
get_buffer_view_range(&buffer_vk->b, desc, &view_format_vk->f, &offset, &size); wined3d_buffer_prepare_location(&buffer_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER); + bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
create_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; create_info.pNext = NULL; create_info.flags = 0; - create_info.buffer = buffer_vk->bo.vk_buffer; + create_info.buffer = bo->vk_buffer; create_info.format = view_format_vk->vk_format; - create_info.offset = buffer_vk->bo.buffer_offset + offset; + create_info.offset = bo->buffer_offset + offset; create_info.range = size;
device_vk = wined3d_device_vk(buffer_vk->b.resource.device); @@ -1082,6 +1084,7 @@ static void wined3d_shader_resource_view_vk_cs_init(void *object) VkBufferView vk_buffer_view; uint32_t default_flags = 0; VkImageView vk_image_view; + struct wined3d_bo_vk *bo;
TRACE("srv_vk %p.\n", srv_vk);
@@ -1099,12 +1102,13 @@ static void wined3d_shader_resource_view_vk_cs_init(void *object)
if (!vk_buffer_view) return; + bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object;
TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
srv_vk->view_vk.u.vk_buffer_view = vk_buffer_view; srv_vk->view_vk.bo_user.valid = true; - list_add_head(&buffer_vk->bo.b.users, &srv_vk->view_vk.bo_user.entry); + list_add_head(&bo->b.users, &srv_vk->view_vk.bo_user.entry);
return; } @@ -2204,11 +2208,13 @@ static void wined3d_unordered_access_view_vk_cs_init(void *object)
if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, format_vk))) { + struct wined3d_bo_vk *bo = (struct wined3d_bo_vk *)buffer_vk->b.buffer_object; + TRACE("Created buffer view 0x%s.\n", wine_dbgstr_longlong(vk_buffer_view));
uav_vk->view_vk.u.vk_buffer_view = vk_buffer_view; uav_vk->view_vk.bo_user.valid = true; - list_add_head(&buffer_vk->bo.b.users, &view_vk->bo_user.entry); + list_add_head(&bo->b.users, &view_vk->bo_user.entry); }
if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND)) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 62b92ce7c34..f1f03abc2b5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -6298,7 +6298,7 @@ static inline void wined3d_context_vk_reference_resource(const struct wined3d_co struct wined3d_resource *resource) { if (resource->type == WINED3D_RTYPE_BUFFER) - wined3d_context_vk_reference_bo(context_vk, &wined3d_buffer_vk(buffer_from_resource(resource))->bo); + wined3d_context_vk_reference_bo(context_vk, (struct wined3d_bo_vk *)buffer_from_resource(resource)->buffer_object); else wined3d_context_vk_reference_texture(context_vk, wined3d_texture_vk(texture_from_resource(resource))); }
So as to allow chunks to be mapped from the client thread.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 2 +- dlls/wined3d/context_vk.c | 27 +++++++++++++++++++++++++-- dlls/wined3d/wined3d_private.h | 5 +++++ 3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 5c83db9bfc9..8413429bd42 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -380,7 +380,7 @@ static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk *c
TRACE("chunk %p.\n", chunk);
- device_vk = CONTAINING_RECORD(chunk_vk->c.allocator, struct wined3d_device_vk, allocator); + device_vk = wined3d_device_vk_from_allocator(chunk_vk->c.allocator); vk_info = &device_vk->vk_info;
if (chunk_vk->c.map_ptr) diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 854a800c0e4..619f722f809 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -247,26 +247,42 @@ static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op) } }
+static void wined3d_allocator_chunk_vk_lock(struct wined3d_allocator_chunk_vk *chunk_vk) +{ + wined3d_device_vk_allocator_lock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator)); +} + +static void wined3d_allocator_chunk_vk_unlock(struct wined3d_allocator_chunk_vk *chunk_vk) +{ + wined3d_device_vk_allocator_unlock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator)); +} + void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk, struct wined3d_context_vk *context_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; + void *map_ptr; VkResult vr;
TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk, wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
+ 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) + chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &map_ptr))) < 0) { ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr)); return NULL; } + chunk_vk->c.map_ptr = map_ptr;
++chunk_vk->c.map_count;
- return chunk_vk->c.map_ptr; + wined3d_allocator_chunk_vk_unlock(chunk_vk); + + return map_ptr; }
void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk, @@ -277,11 +293,18 @@ void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_v
TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
+ wined3d_allocator_chunk_vk_lock(chunk_vk); + if (--chunk_vk->c.map_count) + { + wined3d_allocator_chunk_vk_unlock(chunk_vk); return; + }
VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory)); chunk_vk->c.map_ptr = NULL; + + wined3d_allocator_chunk_vk_unlock(chunk_vk); }
VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f1f03abc2b5..d8f680f50f4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4095,6 +4095,11 @@ static inline struct wined3d_device_vk *wined3d_device_vk(struct wined3d_device return CONTAINING_RECORD(device, struct wined3d_device_vk, d); }
+static inline struct wined3d_device_vk *wined3d_device_vk_from_allocator(struct wined3d_allocator *allocator) +{ + return CONTAINING_RECORD(allocator, struct wined3d_device_vk, allocator); +} + static inline void wined3d_device_vk_allocator_lock(struct wined3d_device_vk *device_vk) { EnterCriticalSection(&device_vk->allocator_cs);
On Thu, 4 Nov 2021 at 06:04, Zebediah Figura zfigura@codeweavers.com wrote:
void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk, struct wined3d_context_vk *context_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;
void *map_ptr; VkResult vr;
TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk, wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
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)
{ ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr)); return NULL; }chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &map_ptr))) < 0)
- chunk_vk->c.map_ptr = map_ptr;
That doesn't work. If the chunk was already mapped (i.e., "chunk_vk->c.map_ptr" isn't NULL), this will overwrite "chunk_vk->c.map_ptr" with the uninitialised "map_ptr".
On 11/4/21 7:07 AM, Henri Verbeet wrote:
On Thu, 4 Nov 2021 at 06:04, Zebediah Figura zfigura@codeweavers.com wrote:
void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk, struct wined3d_context_vk *context_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;
void *map_ptr; VkResult vr;
TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk, wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
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)
chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &map_ptr))) < 0) { ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr)); return NULL; }
- chunk_vk->c.map_ptr = map_ptr;
That doesn't work. If the chunk was already mapped (i.e., "chunk_vk->c.map_ptr" isn't NULL), this will overwrite "chunk_vk->c.map_ptr" with the uninitialised "map_ptr".
Indeed; I'm surprised that gcc didn't catch that...
So as to allow slabs to be mapped from the client thread.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 8413429bd42..f8fa9b78811 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -845,28 +845,53 @@ static void wined3d_bo_vk_unmap(struct wined3d_bo_vk *bo, struct wined3d_context VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory)); }
+static void wined3d_bo_slab_vk_lock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk) +{ + wined3d_device_vk_allocator_lock(wined3d_device_vk(context_vk->c.device)); +} + +static void wined3d_bo_slab_vk_unlock(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk) +{ + wined3d_device_vk_allocator_unlock(wined3d_device_vk(context_vk->c.device)); +} + void *wined3d_bo_slab_vk_map(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk) { + void *map_ptr; + TRACE("slab_vk %p, context_vk %p.\n", slab_vk, context_vk);
+ wined3d_bo_slab_vk_lock(slab_vk, context_vk); + if (!slab_vk->map_ptr && !(slab_vk->map_ptr = wined3d_bo_vk_map(&slab_vk->bo, context_vk))) { + wined3d_bo_slab_vk_unlock(slab_vk, context_vk); ERR("Failed to map slab.\n"); return NULL; }
++slab_vk->map_count; + map_ptr = slab_vk->map_ptr;
- return slab_vk->map_ptr; + wined3d_bo_slab_vk_unlock(slab_vk, context_vk); + + return map_ptr; }
void wined3d_bo_slab_vk_unmap(struct wined3d_bo_slab_vk *slab_vk, struct wined3d_context_vk *context_vk) { + wined3d_bo_slab_vk_lock(slab_vk, context_vk); + if (--slab_vk->map_count) + { + wined3d_bo_slab_vk_unlock(slab_vk, context_vk); return; + }
wined3d_bo_vk_unmap(&slab_vk->bo, context_vk); slab_vk->map_ptr = NULL; + + wined3d_bo_slab_vk_unlock(slab_vk, context_vk); }
VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage)
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 | 49 +++++++++++++++++++++++++ dlls/wined3d/buffer.c | 65 ++++++++++++++++++++++++++++++++-- dlls/wined3d/cs.c | 16 ++++++++- dlls/wined3d/directx.c | 7 ++++ dlls/wined3d/wined3d_private.h | 18 ++++++++++ 6 files changed, 159 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index f1cdbffe718..37f055662ea 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4604,6 +4604,12 @@ static void adapter_gl_flush_bo_address(struct wined3d_context *context, wined3d_context_gl_flush_bo_address(wined3d_context_gl(context), data, size); }
+static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr) +{ + return false; +} + 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) @@ -5057,6 +5063,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = .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_alloc_bo = adapter_gl_alloc_bo, .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 f8fa9b78811..372d49d6e3d 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -23,6 +23,7 @@ #include "wine/vulkan_driver.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
static const struct wined3d_state_entry_template misc_state_template_vk[] = { @@ -1216,6 +1217,53 @@ static void adapter_vk_flush_bo_address(struct wined3d_context *context, flush_bo_range(context_vk, bo, (uintptr_t)data->addr, size); }
+struct wined3d_client_bo_vk_map_ctx +{ + struct wined3d_device *device; + struct wined3d_client_bo_vk *client_bo; +}; + +static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(device); + struct wined3d_context_vk *context_vk = &device_vk->context_vk; + + wined3d_not_from_cs(device->cs); + assert(device->context_count); + + if (resource->type == WINED3D_RTYPE_BUFFER) + { + struct wined3d_client_bo_vk *client_bo; + + if (!(client_bo = heap_alloc(sizeof(*client_bo)))) + return false; + + if (!(wined3d_context_vk_create_bo(context_vk, resource->size, + vk_buffer_usage_from_bind_flags(resource->bind_flags), + vk_memory_type_from_access_flags(resource->access, resource->usage), &client_bo->bo))) + { + WARN("Failed to create Vulkan buffer.\n"); + return FALSE; + } + + if (!client_bo->bo.b.map_ptr) + { + WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n", &client_bo->bo, + client_bo->bo.memory ? client_bo->bo.memory->chunk : NULL, client_bo->bo.slab); + + if (!wined3d_bo_vk_map(&client_bo->bo, context_vk)) + ERR("Failed to map bo.\n"); + } + + addr->buffer_object = (uintptr_t)&client_bo->bo; + addr->addr = NULL; + return true; + } + + return false; +} + 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) @@ -1868,6 +1916,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = .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_alloc_bo = adapter_vk_alloc_bo, .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 0a72f19935b..d0ec4d5aef3 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1061,6 +1061,16 @@ static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resou return WINED3D_OK; }
+void wined3d_buffer_set_bo(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo) +{ + TRACE("buffer %p, context %p, bo %p.\n", buffer, context, bo); + + buffer->buffer_ops->buffer_set_bo(buffer, context, bo); + buffer->buffer_object = (uintptr_t)bo; + wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER); + wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER); +} + void wined3d_buffer_copy_bo_address(struct wined3d_buffer *dst_buffer, struct wined3d_context *context, unsigned int dst_offset, const struct wined3d_const_bo_address *src_addr, unsigned int size) { @@ -1256,12 +1266,19 @@ static void wined3d_buffer_no3d_download_ranges(struct wined3d_buffer *buffer, s FIXME("Not implemented.\n"); }
+static void wined3d_buffer_no3d_set_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) +{ + FIXME("Not implemented.\n"); +} + static const struct wined3d_buffer_ops wined3d_buffer_no3d_ops = { wined3d_buffer_no3d_prepare_location, wined3d_buffer_no3d_unload_location, wined3d_buffer_no3d_upload_ranges, wined3d_buffer_no3d_download_ranges, + wined3d_buffer_no3d_set_bo, };
HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device, @@ -1366,12 +1383,19 @@ static void wined3d_buffer_gl_download_ranges(struct wined3d_buffer *buffer, str checkGLcall("buffer download"); }
+static void wined3d_buffer_gl_set_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) +{ + FIXME("Not implemented.\n"); +} + static const struct wined3d_buffer_ops wined3d_buffer_gl_ops = { wined3d_buffer_gl_prepare_location, wined3d_buffer_gl_unload_location, wined3d_buffer_gl_upload_ranges, wined3d_buffer_gl_download_ranges, + wined3d_buffer_gl_set_bo, };
HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined3d_device *device, @@ -1399,7 +1423,7 @@ HRESULT wined3d_buffer_gl_init(struct wined3d_buffer_gl *buffer_gl, struct wined return wined3d_buffer_init(&buffer_gl->b, device, desc, data, parent, parent_ops, &wined3d_buffer_gl_ops); }
-static VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) +VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) { VkBufferUsageFlags usage;
@@ -1423,7 +1447,7 @@ static VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) return usage; }
-static VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage) +VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage) { VkMemoryPropertyFlags memory_type = 0;
@@ -1577,12 +1601,49 @@ static void wined3d_buffer_vk_download_ranges(struct wined3d_buffer *buffer, str FIXME("Not implemented.\n"); }
+static void wined3d_buffer_vk_set_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) +{ + struct wined3d_bo_vk *prev_bo = (struct wined3d_bo_vk *)buffer->buffer_object; + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer); + struct wined3d_bo_vk *bo_vk = wined3d_bo_vk(bo); + + /* We can't just copy the contents of bo_vk into buffer_vk->bo, because the + * new BO might still be in use by the client thread. We could allow both to + * be valid, although knowing when to destroy a BO then becomes tricky, and + * ensuring it's not mapped more than once also becomes tricky. */ + + if (prev_bo) + { + struct wined3d_bo_user *bo_user; + + LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->b.users, struct wined3d_bo_user, entry) + bo_user->valid = false; + assert(list_empty(&bo_vk->b.users)); + list_move_head(&bo_vk->b.users, &prev_bo->b.users); + + if (prev_bo != &buffer_vk->bo) + { + struct wined3d_client_bo_vk *client_bo = CONTAINING_RECORD(prev_bo, struct wined3d_client_bo_vk, bo); + + wined3d_context_vk_destroy_bo(context_vk, &client_bo->bo); + heap_free(client_bo); + } + } + else + { + list_add_head(&bo_vk->b.users, &buffer_vk->b.bo_user.entry); + } +} + static const struct wined3d_buffer_ops wined3d_buffer_vk_ops = { wined3d_buffer_vk_prepare_location, wined3d_buffer_vk_unload_location, wined3d_buffer_vk_upload_ranges, wined3d_buffer_vk_download_ranges, + wined3d_buffer_vk_set_bo, };
HRESULT wined3d_buffer_vk_init(struct wined3d_buffer_vk *buffer_vk, struct wined3d_device *device, diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index e6ff448b028..fbbfce006ff 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2747,6 +2747,9 @@ static void wined3d_cs_exec_update_sub_resource(struct wined3d_cs *cs, const voi struct wined3d_buffer *buffer = buffer_from_resource(resource); size_t size = box->right - box->left;
+ if (op->bo.flags & UPLOAD_BO_RENAME_ON_UNMAP) + wined3d_buffer_set_bo(buffer, context, (struct wined3d_bo *)op->bo.addr.buffer_object); + 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 @@ -3121,12 +3124,20 @@ 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_NOOVERWRITE)) + if (wined3d_map_persistent() && 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; 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)) + return NULL; + } + bo = (const struct wined3d_bo *)client->addr.buffer_object; map_ptr = bo ? bo->map_ptr : NULL; map_ptr += (uintptr_t)client->addr.addr; @@ -3150,6 +3161,9 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str } map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box);
+ if (flags & WINED3D_MAP_DISCARD) + client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP | UPLOAD_BO_RENAME_ON_UNMAP; + client->mapped_box = *box;
TRACE("Returning bo %s, flags %#x.\n", debug_const_bo_address(&client->mapped_upload.addr), diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index c265bdc8c95..f14f57fd3f4 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2805,6 +2805,12 @@ static void adapter_no3d_flush_bo_address(struct wined3d_context *context, { }
+static bool adapter_no3d_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr) +{ + return false; +} + 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) @@ -3075,6 +3081,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops = .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_alloc_bo = adapter_no3d_alloc_bo, .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 d8f680f50f4..1c25876719c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -328,6 +328,8 @@ VkPipelineStageFlags vk_pipeline_stage_mask_from_bind_flags(uint32_t bind_flags) VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN; VkAccessFlags vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage) DECLSPEC_HIDDEN; VkPipelineStageFlags vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage) DECLSPEC_HIDDEN; +VkBufferUsageFlags vk_buffer_usage_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN; +VkMemoryPropertyFlags vk_memory_type_from_access_flags(uint32_t access, uint32_t usage) DECLSPEC_HIDDEN;
static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func) { @@ -1639,6 +1641,16 @@ struct wined3d_bo_vk bool host_synced; };
+static inline struct wined3d_bo_vk *wined3d_bo_vk(struct wined3d_bo *bo) +{ + return CONTAINING_RECORD(bo, struct wined3d_bo_vk, b); +} + +struct wined3d_client_bo_vk +{ + struct wined3d_bo_vk bo; +}; + struct wined3d_bo_slab_vk_key { VkMemoryPropertyFlags memory_type; @@ -3338,6 +3350,7 @@ bool wined3d_driver_info_init(struct wined3d_driver_info *driver_info, UINT64 vram_bytes, UINT64 sysmem_bytes) DECLSPEC_HIDDEN;
#define UPLOAD_BO_UPLOAD_ON_UNMAP 0x1 +#define UPLOAD_BO_RENAME_ON_UNMAP 0x2
struct upload_bo { @@ -3370,6 +3383,8 @@ struct wined3d_adapter_ops 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); + bool (*adapter_alloc_bo)(struct wined3d_device *device, struct wined3d_resource *resource, + unsigned int sub_resource_idx, struct wined3d_bo_address *addr); HRESULT (*adapter_create_swapchain)(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, @@ -5016,6 +5031,7 @@ struct wined3d_buffer_ops unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges); void (*buffer_download_ranges)(struct wined3d_buffer *buffer, struct wined3d_context *context, void *data, unsigned int data_offset, unsigned int range_count, const struct wined3d_range *ranges); + void (*buffer_set_bo)(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo); };
struct wined3d_buffer @@ -5061,6 +5077,8 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN; BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, struct wined3d_context *context, unsigned int location) DECLSPEC_HIDDEN; +void wined3d_buffer_set_bo(struct wined3d_buffer *buffer, + struct wined3d_context *context, struct wined3d_bo *bo) DECLSPEC_HIDDEN;
HRESULT wined3d_buffer_no3d_init(struct wined3d_buffer *buffer_no3d, struct wined3d_device *device, const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
+static void wined3d_buffer_vk_set_bo(struct wined3d_buffer *buffer,
struct wined3d_context *context, struct wined3d_bo *bo)
+{
- struct wined3d_bo_vk *prev_bo = (struct wined3d_bo_vk *)buffer->buffer_object;
- struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
- struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
- struct wined3d_bo_vk *bo_vk = wined3d_bo_vk(bo);
- /* We can't just copy the contents of bo_vk into buffer_vk->bo, because the
* new BO might still be in use by the client thread. We could allow both to
* be valid, although knowing when to destroy a BO then becomes tricky, and
* ensuring it's not mapped more than once also becomes tricky. */
Would it make sense then to either make "buffer_vk->bo" a pointer, or get rid of it entirely? Right now, we're handling the initial bo different from subsequent ones, and I'm not sure there's a good reason to justify that.
Incidentally, now that we have an actual wined3d_bo structure, it would probably make sense to change the type of "buffer_object" in e.g. struct wined3d_buffer, struct wined3d_bo_address, etc. from uintptr_t (and variants) to a wined3d_bo pointer. That's not a prerequisite for this series, but would probably be a nice cleanup.
@@ -3121,12 +3124,20 @@ 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_NOOVERWRITE))
if (wined3d_map_persistent() && 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; 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))
return NULL;
}
Returning NULL here works, but "false" would be more appropriate.
On 11/4/21 7:31 AM, Henri Verbeet wrote:
+static void wined3d_buffer_vk_set_bo(struct wined3d_buffer *buffer,
struct wined3d_context *context, struct wined3d_bo *bo)
+{
- struct wined3d_bo_vk *prev_bo = (struct wined3d_bo_vk *)buffer->buffer_object;
- struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
- struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
- struct wined3d_bo_vk *bo_vk = wined3d_bo_vk(bo);
- /* We can't just copy the contents of bo_vk into buffer_vk->bo, because the
* new BO might still be in use by the client thread. We could allow both to
* be valid, although knowing when to destroy a BO then becomes tricky, and
* ensuring it's not mapped more than once also becomes tricky. */
Would it make sense then to either make "buffer_vk->bo" a pointer, or get rid of it entirely? Right now, we're handling the initial bo different from subsequent ones, and I'm not sure there's a good reason to justify that.
It seems reasonable. I guess in the ideal case we're not going to make much use of buffer_vk->bo anyway.
In that case I guess struct wined3d_client_bo_vk doesn't really have much reason to exist. I don't believe I had plans to put anything else in it; I just wanted a way to communicate that the BO belonged to a separate allocation.
I'll try to order that patch before this one; it seems feasible.
Incidentally, now that we have an actual wined3d_bo structure, it would probably make sense to change the type of "buffer_object" in e.g. struct wined3d_buffer, struct wined3d_bo_address, etc. from uintptr_t (and variants) to a wined3d_bo pointer. That's not a prerequisite for this series, but would probably be a nice cleanup.
That one occurred to me as well. (I wasn't sure if there was a reason it wasn't done like that in the first place. Not that wined3d_bo_vk and wined3d_bo_gl used to have anything in common, but at least "void *" would have made more sense...)
@@ -3121,12 +3124,20 @@ 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_NOOVERWRITE))
if (wined3d_map_persistent() && 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; 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))
return NULL;
}
Returning NULL here works, but "false" would be more appropriate.
Oops, holdover from an old version of this patch...
On Thu, 4 Nov 2021 at 16:31, Zebediah Figura zfigura@codeweavers.com wrote:
That one occurred to me as well. (I wasn't sure if there was a reason it wasn't done like that in the first place. Not that wined3d_bo_vk and wined3d_bo_gl used to have anything in common, but at least "void *" would have made more sense...)
It evolved from being a GLuint containing a GL buffer object id. When the wined3d_bo_vk structure was originally introduced, that changed to being a uintptr_t containing either a pointer to a wined3d_bo_vk structure or a GL buffer object id. The wined3d_bo_gl structure is a bit more recent still, and not all of the consequences from introducing that have entirely settled yet.