[PATCH v2 6/6] wined3d: Try to allocate new Vulkan BOs from the client thread for DISCARD maps.
Zebediah Figura
zfigura at codeweavers.com
Tue Nov 9 11:36:07 CST 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
v2: Actually move location management to wined3d_buffer_update_sub_resource().
dlls/wined3d/adapter_gl.c | 13 +++++++++
dlls/wined3d/adapter_vk.c | 50 ++++++++++++++++++++++++++++++++++
dlls/wined3d/buffer.c | 37 +++++++++++++++++++++++--
dlls/wined3d/cs.c | 13 ++++++++-
dlls/wined3d/directx.c | 12 ++++++++
dlls/wined3d/wined3d_private.h | 11 ++++++++
6 files changed, 133 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index 7ec30cb4356..85b40b19896 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4606,6 +4606,17 @@ 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 void adapter_gl_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ wined3d_context_gl_destroy_bo(wined3d_context_gl(context), wined3d_bo_gl(bo));
+}
+
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)
@@ -5059,6 +5070,8 @@ 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_destroy_bo = adapter_gl_destroy_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 62a9a342e9b..e83f0a012d6 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);
}
+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_bo_vk *bo_vk;
+
+ if (!(bo_vk = heap_alloc(sizeof(*bo_vk))))
+ 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), bo_vk)))
+ {
+ WARN("Failed to create Vulkan buffer.\n");
+ heap_free(bo_vk);
+ return false;
+ }
+
+ if (!bo_vk->b.map_ptr)
+ {
+ WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n",
+ bo_vk, bo_vk->memory ? bo_vk->memory->chunk : NULL, bo_vk->slab);
+
+ if (!wined3d_bo_vk_map(bo_vk, context_vk))
+ ERR("Failed to map bo.\n");
+ }
+
+ addr->buffer_object = (uintptr_t)bo_vk;
+ addr->addr = NULL;
+ return true;
+ }
+
+ return false;
+}
+
+static void adapter_vk_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ wined3d_context_vk_destroy_bo(wined3d_context_vk(context), wined3d_bo_vk(bo));
+}
+
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,8 @@ 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_destroy_bo = adapter_vk_destroy_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 fca8ab707f2..d5840a488b5 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1069,6 +1069,32 @@ static HRESULT buffer_resource_sub_resource_unmap(struct wined3d_resource *resou
return WINED3D_OK;
}
+static void wined3d_buffer_set_bo(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ struct wined3d_bo *prev_bo = buffer->buffer_object;
+
+ TRACE("buffer %p, context %p, bo %p.\n", buffer, context, bo);
+
+ if (prev_bo)
+ {
+ struct wined3d_bo_user *bo_user;
+
+ LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->users, struct wined3d_bo_user, entry)
+ bo_user->valid = false;
+ assert(list_empty(&bo->users));
+ list_move_head(&bo->users, &prev_bo->users);
+
+ wined3d_context_destroy_bo(context, prev_bo);
+ heap_free(prev_bo);
+ }
+ else
+ {
+ list_add_head(&bo->users, &buffer->bo_user.entry);
+ }
+
+ buffer->buffer_object = bo;
+}
+
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)
{
@@ -1104,6 +1130,13 @@ void wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_off
void wined3d_buffer_update_sub_resource(struct wined3d_buffer *buffer, struct wined3d_context *context,
const struct upload_bo *upload_bo, unsigned int offset, unsigned int size)
{
+ if (upload_bo->flags & UPLOAD_BO_RENAME_ON_UNMAP)
+ {
+ wined3d_buffer_set_bo(buffer, context, (struct wined3d_bo *)upload_bo->addr.buffer_object);
+ wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER);
+ wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
+ }
+
if (upload_bo->addr.buffer_object && upload_bo->addr.buffer_object == (uintptr_t)buffer->buffer_object)
wined3d_context_flush_bo_address(context, &upload_bo->addr, size);
else
@@ -1418,7 +1451,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;
@@ -1442,7 +1475,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;
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 1d909e0c706..262123b5d90 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -3116,12 +3116,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 false;
+ }
+
bo = (const struct wined3d_bo *)client->addr.buffer_object;
map_ptr = bo ? bo->map_ptr : NULL;
map_ptr += (uintptr_t)client->addr.addr;
@@ -3145,6 +3153,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..06387452b89 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2805,6 +2805,16 @@ 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 void adapter_no3d_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
+{
+}
+
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 +3085,8 @@ 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_destroy_bo = adapter_no3d_destroy_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 fc950cda3c3..0c5f7dda228 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -331,6 +331,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)
{
@@ -3353,6 +3355,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
{
@@ -3385,6 +3388,9 @@ 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);
+ void (*adapter_destroy_bo)(struct wined3d_context *context, struct wined3d_bo *bo);
HRESULT (*adapter_create_swapchain)(struct wined3d_device *device,
struct wined3d_swapchain_desc *desc,
struct wined3d_swapchain_state_parent *state_parent, void *parent,
@@ -6307,6 +6313,11 @@ static inline void wined3d_context_flush_bo_address(struct wined3d_context *cont
context->device->adapter->adapter_ops->adapter_flush_bo_address(context, data, size);
}
+static inline void wined3d_context_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
+{
+ context->device->adapter->adapter_ops->adapter_destroy_bo(context, bo);
+}
+
static inline void wined3d_context_vk_reference_bo(const struct wined3d_context_vk *context_vk,
struct wined3d_bo_vk *bo)
{
--
2.33.0
More information about the wine-devel
mailing list