Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- And I'm sure there's a lot to complain about here ;-)
dlls/wined3d/adapter_gl.c | 15 ++++++ dlls/wined3d/adapter_vk.c | 68 ++++++++++++++++++++++++++ dlls/wined3d/buffer.c | 10 ++++ dlls/wined3d/cs.c | 88 +++++++++++++++++++++++++++++++--- dlls/wined3d/directx.c | 14 ++++++ dlls/wined3d/texture.c | 9 ++++ dlls/wined3d/wined3d_private.h | 32 +++++++++++++ 7 files changed, 230 insertions(+), 6 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index bba728e2fb5..228e64b5a56 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4597,6 +4597,19 @@ 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 void *adapter_gl_alloc_upload_bo(struct wined3d_device *device, 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, struct upload_bo *upload_bo) +{ + return NULL; +} + 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) @@ -5049,6 +5062,8 @@ 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_alloc_upload_bo = adapter_gl_alloc_upload_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 91a6b92b4aa..9596bef3cd5 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1169,6 +1169,72 @@ 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); + const struct wined3d_vk_info *vk_info; + struct wined3d_device_vk *device_vk; + VkMappedMemoryRange range; + struct wined3d_bo_vk *bo; + + if (!(bo = (struct wined3d_bo_vk *)data->buffer_object)) + return; + + vk_info = context_vk->vk_info; + device_vk = wined3d_device_vk(context->device); + + 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.size = size; + VK_CALL(vkFlushMappedMemoryRanges(device_vk->vk_device, 1, &range)); +} + +static void *adapter_vk_alloc_upload_bo(struct wined3d_device *device, 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, struct upload_bo *upload_bo) +{ + wined3d_not_from_cs(device->cs); + + /* 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_sub_resource *sub_resource; + const struct wined3d_bo_vk *bo_vk; + uint8_t *map_ptr; + + sub_resource = wined3d_resource_get_client_sub_resource(resource, sub_resource_idx); + + bo_vk = (const struct wined3d_bo_vk *)sub_resource->addr.buffer_object; + map_ptr = bo_vk ? bo_vk->map_ptr : NULL; + map_ptr += (uintptr_t)sub_resource->addr.addr; + + if (!map_ptr) + { + TRACE("Sub-resource is not persistently mapped.\n"); + return NULL; + } + + wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, row_pitch, slice_pitch); + + upload_bo->addr = *wined3d_const_bo_address(&sub_resource->addr); + upload_bo->flags = 0; + if (bo_vk) + map_ptr += bo_vk->memory_offset; + map_ptr = resource_offset_map_pointer(resource, sub_resource_idx, map_ptr, box); + + if (!(bo_vk->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) + upload_bo->flags |= UPLOAD_BO_FLUSH_ON_UNMAP; + + return map_ptr; + } + + return NULL; +} + 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 +1886,8 @@ 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_alloc_upload_bo = adapter_vk_alloc_upload_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 3ea3bf4b180..c090a24ceb6 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -840,6 +840,14 @@ struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffe return &buffer->resource; }
+static struct wined3d_client_sub_resource *buffer_resource_get_client_sub_resource(struct wined3d_resource *resource, + unsigned int sub_resource_idx) +{ + struct wined3d_buffer *buffer = buffer_from_resource(resource); + + return &buffer->client; +} + static HRESULT buffer_resource_sub_resource_get_desc(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) { @@ -938,6 +946,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->client.addr = addr;
if (((DWORD_PTR)buffer->map_ptr) & (RESOURCE_ALIGNMENT - 1)) { @@ -1099,6 +1108,7 @@ static const struct wined3d_resource_ops buffer_resource_ops = buffer_resource_decref, buffer_resource_preload, buffer_resource_unload, + buffer_resource_get_client_sub_resource, buffer_resource_sub_resource_get_desc, buffer_resource_sub_resource_get_map_pitch, buffer_resource_sub_resource_map, diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index c35e85c3cc2..3e83b78999e 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -116,6 +116,14 @@ ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list) return refcount; }
+static void invalidate_persistent_map(struct wined3d_resource *resource, unsigned int sub_resource_idx) +{ + struct wined3d_client_sub_resource *sub_resource; + + sub_resource = wined3d_resource_get_client_sub_resource(resource, sub_resource_idx); + memset(&sub_resource->addr, 0, sizeof(sub_resource->addr)); +} + enum wined3d_cs_op { WINED3D_CS_OP_NOP, @@ -2404,6 +2412,13 @@ 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) + { + const struct wined3d_deferred_upload *upload = &list->uploads[i]; + + invalidate_persistent_map(upload->resource, upload->sub_resource_idx); + } }
static void wined3d_cs_exec_preload_resource(struct wined3d_cs *cs, const void *data) @@ -2441,6 +2456,19 @@ void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resou { struct wined3d_cs_unload_resource *op;
+ if (resource->type == WINED3D_RTYPE_BUFFER) + { + invalidate_persistent_map(resource, 0); + } + else + { + struct wined3d_texture *texture = wined3d_texture_from_resource(resource); + unsigned int i; + + for (i = 0; i < texture->layer_count * texture->level_count; ++i) + invalidate_persistent_map(resource, i); + } + op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_UNLOAD_RESOURCE; op->resource = resource; @@ -2511,6 +2539,9 @@ HRESULT wined3d_device_context_emit_map(struct wined3d_device_context *context,
wined3d_resource_wait_idle(resource);
+ /* We might end up loading the resource into sysmem. */ + invalidate_persistent_map(resource, sub_resource_idx); + if (!(op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_MAP))) return E_OUTOFMEMORY; op->opcode = WINED3D_CS_OP_MAP; @@ -2554,7 +2585,7 @@ HRESULT wined3d_device_context_emit_unmap(struct wined3d_device_context *context unsigned int row_pitch, slice_pitch;
wined3d_resource_get_sub_resource_map_pitch(resource, sub_resource_idx, &row_pitch, &slice_pitch); - if (bo.flags & UPLOAD_BO_UPLOAD_ON_UNMAP) + if (bo.flags & (UPLOAD_BO_UPLOAD_ON_UNMAP | UPLOAD_BO_FLUSH_ON_UNMAP)) wined3d_device_context_upload_bo(context, resource, sub_resource_idx, &box, &bo, row_pitch, slice_pitch); return WINED3D_OK; } @@ -2581,8 +2612,7 @@ static void wined3d_cs_exec_blt_sub_resource(struct wined3d_cs *cs, const void * if (op->dst_resource->type == WINED3D_RTYPE_BUFFER) { wined3d_buffer_copy(buffer_from_resource(op->dst_resource), op->dst_box.left, - buffer_from_resource(op->src_resource), op->src_box.left, - op->src_box.right - op->src_box.left); + buffer_from_resource(op->src_resource), op->src_box.left, op->src_box.right - op->src_box.left); } else if (op->dst_resource->type == WINED3D_RTYPE_TEXTURE_3D) { @@ -2688,6 +2718,10 @@ void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context { struct wined3d_cs_blt_sub_resource *op;
+ /* This might result in an implicit discard. */ + if (dst_resource->type == WINED3D_RTYPE_BUFFER && dst_box->right - dst_box->left == dst_resource->size) + invalidate_persistent_map(dst_resource, 0); + 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; @@ -2727,8 +2761,22 @@ 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.flags & UPLOAD_BO_FLUSH_ON_UNMAP) + { + 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; + } + + if (op->bo.flags & UPLOAD_BO_FLUSH_ON_UNMAP) + { + wined3d_context_flush_bo_address(context, &op->bo.addr, resource->size); goto done; }
@@ -2770,6 +2818,10 @@ void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_conte struct upload_bo bo; void *map_ptr;
+ /* This might result in an implicit discard. */ + if (resource->type == WINED3D_RTYPE_BUFFER && box->right - box->left == resource->size) + invalidate_persistent_map(resource, 0); + if ((map_ptr = context->ops->map_upload_bo(context, resource, sub_resource_idx, box, &dst_row_pitch, &dst_slice_pitch, WINED3D_MAP_WRITE))) { @@ -3094,13 +3146,37 @@ static void *wined3d_cs_map_upload_bo(struct wined3d_device_context *context, st unsigned int sub_resource_idx, const struct wined3d_box *box, unsigned int *row_pitch, unsigned int *slice_pitch, uint32_t flags) { - /* FIXME: We would like to return mapped or newly allocated memory here. */ - return NULL; + struct wined3d_client_sub_resource *sub_resource; + struct upload_bo bo; + void *map_ptr; + + if ((map_ptr = context->device->adapter->adapter_ops->adapter_alloc_upload_bo(context->device, + resource, sub_resource_idx, box, row_pitch, slice_pitch, flags, &bo))) + { + sub_resource = wined3d_resource_get_client_sub_resource(resource, sub_resource_idx); + sub_resource->upload_bo = bo; + sub_resource->upload_box = *box; + TRACE("Returning map pointer %p, bo %s, flags %#x, row pitch %u, slice pitch %u.\n", map_ptr, + debug_const_bo_address(&bo.addr), bo.flags, *row_pitch, *slice_pitch); + } + return map_ptr; }
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) { + struct wined3d_client_sub_resource *sub_resource; + + sub_resource = wined3d_resource_get_client_sub_resource(resource, sub_resource_idx); + if (sub_resource->upload_bo.addr.buffer_object || sub_resource->upload_bo.addr.addr) + { + *bo = sub_resource->upload_bo; + *box = sub_resource->upload_box; + memset(&sub_resource->upload_bo, 0, sizeof(sub_resource->upload_bo)); + memset(&sub_resource->upload_box, 0, sizeof(sub_resource->upload_box)); + return true; + } + return false; }
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 990164fd68d..884eec4ac92 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2798,6 +2798,18 @@ 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 void *adapter_no3d_alloc_upload_bo(struct wined3d_device *device, 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, struct upload_bo *upload_bo) +{ + return NULL; +} + 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 +3079,8 @@ 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_alloc_upload_bo = adapter_no3d_alloc_upload_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/texture.c b/dlls/wined3d/texture.c index 339bf4e205a..d96492fc9e9 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3438,6 +3438,14 @@ static void texture_resource_unload(struct wined3d_resource *resource) resource_unload(&texture->resource); }
+static struct wined3d_client_sub_resource *texture_resource_get_client_sub_resource(struct wined3d_resource *resource, + unsigned int sub_resource_idx) +{ + const struct wined3d_texture *texture = texture_from_resource(resource); + + return &texture->sub_resources[sub_resource_idx].client; +} + static HRESULT texture_resource_sub_resource_get_desc(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) { @@ -3603,6 +3611,7 @@ static const struct wined3d_resource_ops texture_resource_ops = texture_resource_decref, texture_resource_preload, texture_resource_unload, + texture_resource_get_client_sub_resource, texture_resource_sub_resource_get_desc, texture_resource_sub_resource_get_map_pitch, texture_resource_sub_resource_map, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 87d69b7b6fe..216bffabc90 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3329,6 +3329,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_FLUSH_ON_UNMAP 0x2
struct upload_bo { @@ -3359,6 +3360,11 @@ 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); + void *(*adapter_alloc_upload_bo)(struct wined3d_device *device, 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, struct upload_bo *upload_bo); HRESULT (*adapter_create_swapchain)(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, @@ -4107,6 +4113,14 @@ 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_sub_resource +{ + struct wined3d_bo_address addr; + + struct upload_bo upload_bo; + struct wined3d_box upload_box; +}; + static inline BOOL wined3d_resource_access_is_managed(unsigned int access) { return !(~access & (WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU)); @@ -4118,6 +4132,8 @@ struct wined3d_resource_ops ULONG (*resource_decref)(struct wined3d_resource *resource); void (*resource_preload)(struct wined3d_resource *resource); void (*resource_unload)(struct wined3d_resource *resource); + struct wined3d_client_sub_resource *(*resource_get_client_sub_resource)(struct wined3d_resource *resource, + unsigned int sub_resource_idx); HRESULT (*resource_sub_resource_get_desc)(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc); void (*resource_sub_resource_get_map_pitch)(struct wined3d_resource *resource, @@ -4183,6 +4199,12 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) assert(refcount >= 0); }
+static inline struct wined3d_client_sub_resource *wined3d_resource_get_client_sub_resource( + struct wined3d_resource *resource, unsigned int sub_resource_idx) +{ + return resource->resource_ops->resource_get_client_sub_resource(resource, sub_resource_idx); +} + static inline HRESULT wined3d_resource_get_sub_resource_desc(struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_sub_resource_desc *desc) { @@ -4337,6 +4359,8 @@ struct wined3d_texture
struct wined3d_texture_sub_resource { + struct wined3d_client_sub_resource client; + void *parent; const struct wined3d_parent_ops *parent_ops;
@@ -4978,6 +5002,8 @@ struct wined3d_buffer void *map_ptr; uintptr_t buffer_object;
+ struct wined3d_client_sub_resource client; + struct wined3d_range *maps; SIZE_T maps_size, modified_areas;
@@ -6227,6 +6253,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) {