Partially undoes 61024aa12f.
We may want to be able to return an existing BO from context->ops->map_upload_bo(), in which case it is structurally awkward to request a specific memory layout. We may also want to give map_upload_bo() the freedom to allocate either a new (smaller) BO, or use an existing (larger) one, for partial uploads.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/cs.c | 37 ++++++++++++++++++++++------------ dlls/wined3d/device.c | 5 +---- dlls/wined3d/wined3d_private.h | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 51718a8a4d0..ce9e6fca214 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2491,27 +2491,32 @@ static void wined3d_cs_exec_map(struct wined3d_cs *cs, const void *data) op->sub_resource_idx, op->map_ptr, op->box, op->flags); }
-HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context, struct wined3d_resource *resource, - unsigned int sub_resource_idx, void **map_ptr, const struct wined3d_box *box, unsigned int flags) +HRESULT wined3d_device_context_emit_map(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, unsigned int flags) { unsigned int row_pitch, slice_pitch; struct wined3d_cs_map *op; + void *map_ptr; HRESULT hr;
- wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, &row_pitch, &slice_pitch); - - if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) - && (*map_ptr = context->ops->map_upload_bo(context, resource, - sub_resource_idx, box, row_pitch, slice_pitch, flags))) - { - TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n", *map_ptr, row_pitch, slice_pitch); - return WINED3D_OK; - } - /* Mapping resources from the worker thread isn't an issue by itself, but * increasing the map count would be visible to applications. */ wined3d_not_from_cs(context->device->cs);
+ wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, &row_pitch, &slice_pitch); + + if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) + && (map_ptr = context->ops->map_upload_bo(context, resource, + sub_resource_idx, box, row_pitch, slice_pitch, flags))) + { + TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n", map_ptr, row_pitch, slice_pitch); + map_desc->data = map_ptr; + map_desc->row_pitch = row_pitch; + map_desc->slice_pitch = slice_pitch; + return WINED3D_OK; + } + wined3d_resource_wait_idle(resource);
if (!(op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_MAP))) @@ -2519,7 +2524,7 @@ HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context, op->opcode = WINED3D_CS_OP_MAP; op->resource = resource; op->sub_resource_idx = sub_resource_idx; - op->map_ptr = map_ptr; + op->map_ptr = &map_ptr; op->box = box; op->flags = flags; op->hr = &hr; @@ -2527,6 +2532,12 @@ HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context, wined3d_device_context_submit(context, WINED3D_CS_QUEUE_MAP); wined3d_device_context_finish(context, WINED3D_CS_QUEUE_MAP);
+ if (FAILED(hr)) + return hr; + + map_desc->data = map_ptr; + map_desc->row_pitch = row_pitch; + map_desc->slice_pitch = slice_pitch; return hr; }
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 436c4dfe854..b8c1630ee25 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4957,10 +4957,7 @@ HRESULT CDECL wined3d_device_context_map(struct wined3d_device_context *context, }
wined3d_mutex_lock(); - if (SUCCEEDED(hr = wined3d_device_context_emit_map(context, resource, - sub_resource_idx, &map_desc->data, box, flags))) - wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, - &map_desc->row_pitch, &map_desc->slice_pitch); + hr = wined3d_device_context_emit_map(context, resource, sub_resource_idx, map_desc, box, flags); wined3d_mutex_unlock(); return hr; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 56c90ba6606..a2899e6a778 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4867,7 +4867,7 @@ void wined3d_device_context_emit_execute_command_list(struct wined3d_device_cont void wined3d_device_context_emit_generate_mipmaps(struct wined3d_device_context *context, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context, - struct wined3d_resource *resource, unsigned int sub_resource_idx, void **map_ptr, + struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, unsigned int flags) DECLSPEC_HIDDEN; void wined3d_device_context_emit_reset_state(struct wined3d_device_context *context, bool invalidate) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context *context,
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/cs.c | 78 +++++++++++++++------------------- dlls/wined3d/wined3d_private.h | 6 +-- 2 files changed, 38 insertions(+), 46 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index ce9e6fca214..5ffa27f5ce0 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2495,25 +2495,18 @@ HRESULT wined3d_device_context_emit_map(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, unsigned int flags) { - unsigned int row_pitch, slice_pitch; struct wined3d_cs_map *op; - void *map_ptr; HRESULT hr;
/* Mapping resources from the worker thread isn't an issue by itself, but * increasing the map count would be visible to applications. */ wined3d_not_from_cs(context->device->cs);
- wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, &row_pitch, &slice_pitch); - if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) - && (map_ptr = context->ops->map_upload_bo(context, resource, - sub_resource_idx, box, row_pitch, slice_pitch, flags))) + && context->ops->map_upload_bo(context, resource, sub_resource_idx, map_desc, box, flags)) { - TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n", map_ptr, row_pitch, slice_pitch); - map_desc->data = map_ptr; - map_desc->row_pitch = row_pitch; - map_desc->slice_pitch = slice_pitch; + TRACE("Returning map pointer %p, row pitch %u, slice pitch %u.\n", + map_desc->data, map_desc->row_pitch, map_desc->slice_pitch); return WINED3D_OK; }
@@ -2524,7 +2517,7 @@ HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context, op->opcode = WINED3D_CS_OP_MAP; op->resource = resource; op->sub_resource_idx = sub_resource_idx; - op->map_ptr = &map_ptr; + op->map_ptr = &map_desc->data; op->box = box; op->flags = flags; op->hr = &hr; @@ -2532,12 +2525,9 @@ HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context, wined3d_device_context_submit(context, WINED3D_CS_QUEUE_MAP); wined3d_device_context_finish(context, WINED3D_CS_QUEUE_MAP);
- if (FAILED(hr)) - return hr; - - map_desc->data = map_ptr; - map_desc->row_pitch = row_pitch; - map_desc->slice_pitch = slice_pitch; + if (SUCCEEDED(hr)) + wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, + &map_desc->row_pitch, &map_desc->slice_pitch); return hr; }
@@ -2773,17 +2763,17 @@ void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_conte const void *data, unsigned int row_pitch, unsigned int slice_pitch) { struct wined3d_cs_update_sub_resource *op; + struct wined3d_map_desc map_desc; struct wined3d_box dummy_box; struct upload_bo bo; - void *map_ptr;
- if ((map_ptr = context->ops->map_upload_bo(context, resource, sub_resource_idx, box, - row_pitch, slice_pitch, WINED3D_MAP_WRITE))) + 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_ptr, row_pitch, slice_pitch, - box->right - box->left, box->bottom - box->top, box->back - box->front); + wined3d_format_copy_data(resource->format, data, row_pitch, slice_pitch, map_desc.data, map_desc.row_pitch, + map_desc.slice_pitch, box->right - box->left, box->bottom - box->top, box->back - box->front); context->ops->unmap_upload_bo(context, resource, sub_resource_idx, &dummy_box, &bo); - wined3d_device_context_upload_bo(context, resource, sub_resource_idx, box, &bo, row_pitch, slice_pitch); + wined3d_device_context_upload_bo(context, resource, sub_resource_idx, + box, &bo, map_desc.row_pitch, map_desc.slice_pitch); return; }
@@ -3097,12 +3087,11 @@ static void wined3d_cs_st_finish(struct wined3d_device_context *context, enum wi { }
-static void *wined3d_cs_map_upload_bo(struct wined3d_device_context *context, struct wined3d_resource *resource, - unsigned int sub_resource_idx, const struct wined3d_box *box, unsigned int row_pitch, - unsigned int slice_pitch, uint32_t flags) +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. */ - return NULL; + return false; }
static bool wined3d_cs_unmap_upload_bo(struct wined3d_device_context *context, struct wined3d_resource *resource, @@ -3542,9 +3531,9 @@ static struct wined3d_deferred_upload *deferred_context_get_upload(struct wined3 return NULL; }
-static void *wined3d_deferred_context_map_upload_bo(struct wined3d_device_context *context, - struct wined3d_resource *resource, unsigned int sub_resource_idx, const struct wined3d_box *box, - unsigned int row_pitch, unsigned int slice_pitch, uint32_t flags) +static bool wined3d_deferred_context_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) { struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context); const struct wined3d_format *format = resource->format; @@ -3552,39 +3541,41 @@ static void *wined3d_deferred_context_map_upload_bo(struct wined3d_device_contex uint8_t *sysmem; size_t size;
- size = (box->back - box->front - 1) * slice_pitch - + ((box->bottom - box->top - 1) / format->block_height) * row_pitch + wined3d_format_calculate_pitch(format, 1, box->right - box->left, + box->bottom - box->top, &map_desc->row_pitch, &map_desc->slice_pitch); + + size = (box->back - box->front - 1) * map_desc->slice_pitch + + ((box->bottom - box->top - 1) / format->block_height) * map_desc->row_pitch + ((box->right - box->left + format->block_width - 1) / format->block_width) * format->block_byte_count;
if (!(flags & WINED3D_MAP_WRITE)) { WARN("Flags %#x are not valid on a deferred context.\n", flags); - return NULL; + return false; }
if (flags & ~(WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)) { FIXME("Unhandled flags %#x.\n", flags); - return NULL; + return false; }
if (flags & WINED3D_MAP_NOOVERWRITE) { - if ((upload = deferred_context_get_upload(deferred, resource, sub_resource_idx))) - { - upload->upload_flags = 0; - return (void *)align((size_t)upload->sysmem, RESOURCE_ALIGNMENT); - } + if (!(upload = deferred_context_get_upload(deferred, resource, sub_resource_idx))) + return false;
- return NULL; + upload->upload_flags = 0; + map_desc->data = (void *)align((size_t)upload->sysmem, RESOURCE_ALIGNMENT); + return true; }
if (!wined3d_array_reserve((void **)&deferred->uploads, &deferred->uploads_capacity, deferred->upload_count + 1, sizeof(*deferred->uploads))) - return NULL; + return false;
if (!(sysmem = heap_alloc(size + RESOURCE_ALIGNMENT - 1))) - return NULL; + return false;
upload = &deferred->uploads[deferred->upload_count++]; upload->upload_flags = UPLOAD_BO_UPLOAD_ON_UNMAP; @@ -3594,7 +3585,8 @@ static void *wined3d_deferred_context_map_upload_bo(struct wined3d_device_contex upload->sysmem = sysmem; upload->box = *box;
- return (void *)align((size_t)upload->sysmem, RESOURCE_ALIGNMENT); + map_desc->data = (void *)align((size_t)upload->sysmem, RESOURCE_ALIGNMENT); + return true; }
static bool wined3d_deferred_context_unmap_upload_bo(struct wined3d_device_context *context, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a2899e6a778..0884ba5c023 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4776,9 +4776,9 @@ struct wined3d_device_context_ops void (*finish)(struct wined3d_device_context *context, enum wined3d_cs_queue_id queue_id); void (*push_constants)(struct wined3d_device_context *context, enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants); - void *(*map_upload_bo)(struct wined3d_device_context *context, struct wined3d_resource *resource, - unsigned int sub_resource_idx, const struct wined3d_box *box, unsigned int row_pitch, - unsigned int slice_pitch, uint32_t flags); + bool (*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); bool (*unmap_upload_bo)(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_box *box, struct upload_bo *upload_bo); void (*issue_query)(struct wined3d_device_context *context, struct wined3d_query *query, unsigned int flags);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 8 ++++---- dlls/wined3d/buffer.c | 4 ++-- dlls/wined3d/context_gl.c | 10 +++++----- dlls/wined3d/context_vk.c | 4 ++-- dlls/wined3d/view.c | 8 ++++---- dlls/wined3d/wined3d_private.h | 11 +++++++++-- 6 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 5667cd8d0d3..fe738a4bcaa 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -939,13 +939,13 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context, if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp)) { bool host_synced = bo->host_synced; - list_move_head(&tmp.users, &bo->users); + list_move_head(&tmp.b.users, &bo->b.users); wined3d_context_vk_destroy_bo(context_vk, bo); *bo = tmp; bo->host_synced = host_synced; - list_init(&bo->users); - list_move_head(&bo->users, &tmp.users); - LIST_FOR_EACH_ENTRY(bo_user, &bo->users, struct wined3d_bo_user, entry) + list_init(&bo->b.users); + list_move_head(&bo->b.users, &tmp.b.users); + LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry) { bo_user->valid = false; } diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 3ea3bf4b180..e1a5ec26c29 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -193,7 +193,7 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf return FALSE; }
- list_add_head(&buffer_gl->bo.users, &buffer_gl->bo_user.entry); + list_add_head(&buffer_gl->bo.b.users, &buffer_gl->bo_user.entry); buffer_gl->b.buffer_object = (uintptr_t)bo; buffer_invalidate_bo_range(&buffer_gl->b, 0, 0);
@@ -1429,7 +1429,7 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf }
list_init(&buffer_vk->bo_user.entry); - list_add_head(&buffer_vk->bo.users, &buffer_vk->bo_user.entry); + list_add_head(&buffer_vk->bo.b.users, &buffer_vk->bo_user.entry); buffer_vk->b.buffer_object = (uintptr_t)&buffer_vk->bo; buffer_invalidate_bo_range(&buffer_vk->b, 0, 0);
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 0e4b900efe0..55782f1ba8e 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2686,12 +2686,12 @@ static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, if (wined3d_context_gl_create_bo(context_gl, bo->size, bo->binding, bo->usage, bo->coherent, bo->flags, &tmp)) { - list_move_head(&tmp.users, &bo->users); + list_move_head(&tmp.b.users, &bo->b.users); wined3d_context_gl_destroy_bo(context_gl, bo); *bo = tmp; - list_init(&bo->users); - list_move_head(&bo->users, &tmp.users); - LIST_FOR_EACH_ENTRY(bo_user, &bo->users, struct wined3d_bo_user, entry) + list_init(&bo->b.users); + list_move_head(&bo->b.users, &tmp.b.users); + LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry) { bo_user->valid = false; } @@ -2887,7 +2887,7 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei bo->usage = usage; bo->flags = flags; bo->coherent = coherent; - list_init(&bo->users); + list_init(&bo->b.users); bo->command_fence_id = 0;
return true; diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 8f0751785ad..efb079899c7 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -413,7 +413,7 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context bo->buffer_offset = idx * object_size; bo->memory_offset = slab->bo.memory_offset + bo->buffer_offset; bo->size = size; - list_init(&bo->users); + list_init(&bo->b.users); bo->command_buffer_id = 0; bo->host_synced = false;
@@ -492,7 +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; - list_init(&bo->users); + list_init(&bo->b.users); bo->command_buffer_id = 0; bo->slab = NULL; bo->host_synced = false; diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 565d35d1c5a..a8b3a7b4f75 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -966,7 +966,7 @@ static void wined3d_shader_resource_view_gl_cs_init(void *object) context = context_acquire(resource->device, NULL, 0); create_buffer_view(&view_gl->gl_view, context, desc, buffer, view_format); view_gl->bo_user.valid = true; - list_add_head(&wined3d_buffer_gl(buffer)->bo.users, &view_gl->bo_user.entry); + list_add_head(&wined3d_buffer_gl(buffer)->bo.b.users, &view_gl->bo_user.entry); context_release(context); } else @@ -1096,7 +1096,7 @@ static void wined3d_shader_resource_view_vk_cs_init(void *object)
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.users, &srv_vk->view_vk.bo_user.entry); + list_add_head(&buffer_vk->bo.b.users, &srv_vk->view_vk.bo_user.entry);
return; } @@ -1646,7 +1646,7 @@ static void wined3d_unordered_access_view_gl_cs_init(void *object) context_gl = wined3d_context_gl(context_acquire(resource->device, NULL, 0)); create_buffer_view(&view_gl->gl_view, &context_gl->c, desc, buffer, view_gl->v.format); view_gl->bo_user.valid = true; - list_add_head(&wined3d_buffer_gl(buffer)->bo.users, &view_gl->bo_user.entry); + list_add_head(&wined3d_buffer_gl(buffer)->bo.b.users, &view_gl->bo_user.entry); if (desc->flags & (WINED3D_VIEW_BUFFER_COUNTER | WINED3D_VIEW_BUFFER_APPEND)) { struct wined3d_bo_gl *bo = &view_gl->counter_bo; @@ -2196,7 +2196,7 @@ static void wined3d_unordered_access_view_vk_cs_init(void *object)
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.users, &view_vk->bo_user.entry); + list_add_head(&buffer_vk->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 0884ba5c023..ab262e3425c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1588,8 +1588,15 @@ do { \ #define checkGLcall(A) do {} while(0) #endif
+struct wined3d_bo +{ + struct list users; +}; + struct wined3d_bo_gl { + struct wined3d_bo b; + GLuint id; GLsizeiptr size; GLenum binding; @@ -1597,7 +1604,6 @@ struct wined3d_bo_gl
GLbitfield flags; bool coherent; - struct list users; uint64_t command_fence_id; };
@@ -1614,6 +1620,8 @@ struct wined3d_bo_user
struct wined3d_bo_vk { + struct wined3d_bo b; + VkBuffer vk_buffer; struct wined3d_allocator_block *memory; struct wined3d_bo_slab_vk *slab; @@ -1627,7 +1635,6 @@ struct wined3d_bo_vk VkBufferUsageFlags usage; VkMemoryPropertyFlags memory_type;
- struct list users; uint64_t command_buffer_id; bool host_synced; };
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 6 +++--- dlls/wined3d/context_gl.c | 1 + dlls/wined3d/context_vk.c | 6 +++--- dlls/wined3d/wined3d_private.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index fe738a4bcaa..8c3e63aac49 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -988,7 +988,7 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context, range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range.pNext = NULL; range.memory = bo->vk_memory; - range.offset = bo->memory_offset + (uintptr_t)data->addr; + range.offset = bo->b.memory_offset + (uintptr_t)data->addr; range.size = size; VK_CALL(vkInvalidateMappedMemoryRanges(device_vk->vk_device, 1, &range)); } @@ -1005,7 +1005,7 @@ map: return NULL; }
- return (uint8_t *)map_ptr + bo->memory_offset + (uintptr_t)data->addr; + return (uint8_t *)map_ptr + bo->b.memory_offset + (uintptr_t)data->addr; }
static void adapter_vk_unmap_bo_address(struct wined3d_context *context, @@ -1032,7 +1032,7 @@ static void adapter_vk_unmap_bo_address(struct wined3d_context *context,
for (i = 0; i < range_count; ++i) { - range.offset = bo->memory_offset + ranges[i].offset; + range.offset = bo->b.memory_offset + ranges[i].offset; range.size = ranges[i].size; VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range)); } diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 55782f1ba8e..b08003c697a 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2889,6 +2889,7 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei bo->coherent = coherent; list_init(&bo->b.users); bo->command_fence_id = 0; + bo->b.memory_offset = 0;
return true; } diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index efb079899c7..f23d4d8f9fb 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -411,7 +411,7 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context bo->memory = NULL; bo->slab = slab; bo->buffer_offset = idx * object_size; - bo->memory_offset = slab->bo.memory_offset + bo->buffer_offset; + bo->b.memory_offset = slab->bo.b.memory_offset + bo->buffer_offset; bo->size = size; list_init(&bo->b.users); bo->command_buffer_id = 0; @@ -473,10 +473,10 @@ BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDevic VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL)); return FALSE; } - bo->memory_offset = bo->memory ? bo->memory->offset : 0; + bo->b.memory_offset = bo->memory ? bo->memory->offset : 0;
if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer, - bo->vk_memory, bo->memory_offset))) < 0) + bo->vk_memory, bo->b.memory_offset))) < 0) { ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr)); if (bo->memory) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ab262e3425c..161d36ad76c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1591,6 +1591,7 @@ do { \ struct wined3d_bo { struct list users; + size_t memory_offset; };
struct wined3d_bo_gl @@ -1630,7 +1631,6 @@ struct wined3d_bo_vk void *map_ptr;
VkDeviceSize buffer_offset; - VkDeviceSize memory_offset; VkDeviceSize size; VkBufferUsageFlags usage; VkMemoryPropertyFlags memory_type;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_vk.c | 4 ++-- dlls/wined3d/context_gl.c | 6 +++--- dlls/wined3d/context_vk.c | 2 ++ dlls/wined3d/wined3d_private.h | 2 +- 4 files changed, 8 insertions(+), 6 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 b08003c697a..0bae527cc93 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); @@ -2762,7 +2762,7 @@ void wined3d_context_gl_unmap_bo_address(struct wined3d_context_gl *context_gl, (UINT_PTR)data->addr + ranges[i].offset, ranges[i].size)); } } - else if (!bo->coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) + else if (!bo->b.coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) { for (i = 0; i < range_count; ++i) { @@ -2886,7 +2886,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 f23d4d8f9fb..bc04c9dca88 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -413,6 +413,7 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context bo->buffer_offset = idx * object_size; bo->b.memory_offset = slab->bo.b.memory_offset + bo->buffer_offset; bo->size = size; + bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); list_init(&bo->b.users); bo->command_buffer_id = 0; bo->host_synced = false; @@ -492,6 +493,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/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 161d36ad76c..bc7b396e122 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; };
On Tue, 12 Oct 2021 at 23:31, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -413,6 +413,7 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context bo->buffer_offset = idx * object_size; bo->b.memory_offset = slab->bo.b.memory_offset + bo->buffer_offset; bo->size = size;
- bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Is that necessary? I think the "*bo = slab->bo;" line above should already set the "coherent" field correctly.
Note that for GL, the "coherent" field is currently only meaningful for the APPLE_flush_buffer_range path. In particular, we never set MAP_COHERENT_BIT for the ARB_buffer_storage path, and we use MAP_FLUSH_EXPLICIT_BIT for the ARB_map_buffer_range path. That's not necessarily an issue in this patch, but would become an issue in patch 7/7 if we started doing persistent maps with GL.
On 10/13/21 4:03 PM, Henri Verbeet wrote:
On Tue, 12 Oct 2021 at 23:31, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -413,6 +413,7 @@ static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context bo->buffer_offset = idx * object_size; bo->b.memory_offset = slab->bo.b.memory_offset + bo->buffer_offset; bo->size = size;
- bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Is that necessary? I think the "*bo = slab->bo;" line above should already set the "coherent" field correctly.
Indeed, this line can be removed.
Note that for GL, the "coherent" field is currently only meaningful for the APPLE_flush_buffer_range path. In particular, we never set MAP_COHERENT_BIT for the ARB_buffer_storage path, and we use MAP_FLUSH_EXPLICIT_BIT for the ARB_map_buffer_range path. That's not necessarily an issue in this patch, but would become an issue in patch 7/7 if we started doing persistent maps with GL.
Indeed, I assumed that "coherent" already had the semantics we wanted, but clearly it does not...
I'm inclined to think we want "coherent" to behave that way for GL, though, so I'll add a couple of patches to v3.
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 0bae527cc93..fbec3b5b0da 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2890,6 +2890,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 bc04c9dca88..804c66ce9f6 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -488,7 +488,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; @@ -905,7 +905,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; @@ -916,13 +916,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 bc7b396e122..73d8aab56be 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: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/adapter_gl.c | 7 +++ dlls/wined3d/adapter_vk.c | 44 ++++++++++++------ dlls/wined3d/buffer.c | 1 + dlls/wined3d/cs.c | 85 ++++++++++++++++++++++++++++++++-- dlls/wined3d/directx.c | 6 +++ dlls/wined3d/wined3d_private.h | 21 +++++++++ 6 files changed, 146 insertions(+), 18 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 3a6ff54eec2..33ec38ba6fc 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) +{ + FIXME("context %p, data %s, size %zu, stub!\n", context, debug_const_bo_address(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..a983a05f300 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_buffer_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_buffer_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_buffer_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..35c17cb8b65 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -938,6 +938,7 @@ 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); + buffer->resource.client.addr = addr;
if (((DWORD_PTR)buffer->map_ptr) & (RESOURCE_ALIGNMENT - 1)) { diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 5ffa27f5ce0..40935c9cdd8 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,64 @@ 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; + map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box); + + if (!bo->coherent) + client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP; + + 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 73d8aab56be..609dd3c6f9c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3366,6 +3366,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 +4115,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 +4171,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 +6248,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) {
On Tue, 12 Oct 2021 at 23:31, Zebediah Figura zfigura@codeweavers.com wrote:
+static void adapter_gl_flush_bo_address(struct wined3d_context *context,
const struct wined3d_const_bo_address *data, size_t size)
+{
- FIXME("context %p, data %s, size %zu, stub!\n", context, debug_const_bo_address(data), size);
+}
Note that we do have an implementation for this in wined3d_context_gl_unmap_bo_address().
+static void flush_buffer_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));
+}
flush_buffer_range() doesn't actually operate on a buffer though...
@@ -938,6 +938,7 @@ 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);
buffer->resource.client.addr = addr;
Does that update need to be atomic? I.e., is there any risk of the application thread seeing e.g. a new "addr.buffer_object" in combination with an old "addr.addr"? I think the idea is that we're protected from that by needing to go through the CS if the buffer isn't mapped yet, right?
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;
}
So if "bo" is NULL, "map_ptr" can in theory end up being non-NULL here. I guess that in practice "client->addr.addr" is always going to be NULL if "bo" is, but in that case there's not much point in adding the offset before checking "map_ptr" either.
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;
Then we account for "bo" potentially being NULL here,
map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box);
if (!bo->coherent)
client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP;
but not here.
On 10/13/21 4:03 PM, Henri Verbeet wrote:
On Tue, 12 Oct 2021 at 23:31, Zebediah Figura zfigura@codeweavers.com wrote:
+static void adapter_gl_flush_bo_address(struct wined3d_context *context,
const struct wined3d_const_bo_address *data, size_t size)
+{
- FIXME("context %p, data %s, size %zu, stub!\n", context, debug_const_bo_address(data), size);
+}
Note that we do have an implementation for this in wined3d_context_gl_unmap_bo_address().
I left it out of this patch for simplicity (this patch is already large), but I'm certainly open to adding it in.
+static void flush_buffer_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));
+}
flush_buffer_range() doesn't actually operate on a buffer though...
Fair enough; I'll rename it ;-)
@@ -938,6 +938,7 @@ 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);
buffer->resource.client.addr = addr;
Does that update need to be atomic? I.e., is there any risk of the application thread seeing e.g. a new "addr.buffer_object" in combination with an old "addr.addr"? I think the idea is that we're protected from that by needing to go through the CS if the buffer isn't mapped yet, right?
Right, the client thread is waiting for this operation to complete and holding a mutex until it does, so it should be thread-safe.
I can add a comment to that effect if it'd help.
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;
}
So if "bo" is NULL, "map_ptr" can in theory end up being non-NULL here. I guess that in practice "client->addr.addr" is always going to be NULL if "bo" is, but in that case there's not much point in adding the offset before checking "map_ptr" either.
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;
Then we account for "bo" potentially being NULL here,
map_desc->data = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box);
if (!bo->coherent)
client->mapped_upload.flags |= UPLOAD_BO_UPLOAD_ON_UNMAP;
but not here.
I tried to account for the possibility that the persistent address for a buffer could be sysmem (which isn't done yet, but I'm inclined to understand is a reasonable potentiality), in which case the "!map_ptr" check should be correct as-is, but the "!bo->coherent" is clearly wrong. I'll fix the latter...