wined3d: Accelerate texture DISCARD maps as well.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2022-02-23 20:21:42 -06:00 committed by Alexandre Julliard
parent aa9b1fb3a3
commit 125f5b7210
4 changed files with 125 additions and 71 deletions

View File

@ -4618,60 +4618,70 @@ static bool adapter_gl_alloc_bo(struct wined3d_device *device, struct wined3d_re
{
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
struct wined3d_device_gl *device_gl = wined3d_device_gl(device);
struct wined3d_bo_gl *bo_gl;
GLenum binding, usage;
bool coherent = true;
GLbitfield flags;
GLsizeiptr size;
wined3d_not_from_cs(device->cs);
assert(device->context_count);
if (resource->type == WINED3D_RTYPE_BUFFER)
{
GLenum usage = GL_STATIC_DRAW;
struct wined3d_bo_gl *bo_gl;
bool coherent = true;
size = resource->size;
binding = wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags);
usage = GL_STATIC_DRAW;
flags = wined3d_resource_gl_storage_flags(resource);
if (resource->usage & WINED3DUSAGE_DYNAMIC)
{
usage = GL_STREAM_DRAW_ARB;
usage = GL_STREAM_DRAW;
coherent = false;
}
}
else
{
struct wined3d_texture *texture = texture_from_resource(resource);
if (!(bo_gl = heap_alloc(sizeof(*bo_gl))))
return false;
if (!(wined3d_device_gl_create_bo(device_gl, NULL, resource->size,
wined3d_buffer_gl_binding_from_bind_flags(gl_info, resource->bind_flags),
usage, coherent, wined3d_resource_gl_storage_flags(resource), bo_gl)))
{
WARN("Failed to create OpenGL buffer.\n");
heap_free(bo_gl);
return false;
}
if (bo_gl->memory)
{
struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk);
wined3d_allocator_chunk_gl_lock(chunk);
if ((bo_gl->b.map_ptr = chunk->c.map_ptr))
++chunk->c.map_count;
wined3d_allocator_chunk_gl_unlock(chunk);
}
addr->buffer_object = &bo_gl->b;
addr->addr = NULL;
if (!bo_gl->b.map_ptr)
{
WARN_(d3d_perf)("BO %p (chunk %p) is not persistently mapped.\n",
bo_gl, bo_gl->memory ? bo_gl->memory->chunk : NULL);
wined3d_cs_map_bo_address(device->cs, addr, resource->size, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD);
}
return true;
size = texture->sub_resources[sub_resource_idx].size;
binding = GL_PIXEL_UNPACK_BUFFER;
usage = GL_STREAM_DRAW;
flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT;
}
return false;
if (!(bo_gl = heap_alloc(sizeof(*bo_gl))))
return false;
if (!(wined3d_device_gl_create_bo(device_gl, NULL, size, binding, usage, coherent, flags, bo_gl)))
{
WARN("Failed to create OpenGL buffer.\n");
heap_free(bo_gl);
return false;
}
if (bo_gl->memory)
{
struct wined3d_allocator_chunk_gl *chunk = wined3d_allocator_chunk_gl(bo_gl->memory->chunk);
wined3d_allocator_chunk_gl_lock(chunk);
if ((bo_gl->b.map_ptr = chunk->c.map_ptr))
++chunk->c.map_count;
wined3d_allocator_chunk_gl_unlock(chunk);
}
addr->buffer_object = &bo_gl->b;
addr->addr = NULL;
if (!bo_gl->b.map_ptr)
{
WARN_(d3d_perf)("BO %p (chunk %p) is not persistently mapped.\n",
bo_gl, bo_gl->memory ? bo_gl->memory->chunk : NULL);
wined3d_cs_map_bo_address(device->cs, addr, resource->size, WINED3D_MAP_WRITE | WINED3D_MAP_DISCARD);
}
return true;
}
static void adapter_gl_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)

View File

@ -1253,41 +1253,51 @@ static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_re
{
struct wined3d_device_vk *device_vk = wined3d_device_vk(device);
struct wined3d_context_vk *context_vk = &device_vk->context_vk;
VkMemoryPropertyFlags memory_type;
VkBufferUsageFlags buffer_usage;
struct wined3d_bo_vk *bo_vk;
VkDeviceSize size;
wined3d_not_from_cs(device->cs);
assert(device->context_count);
if (resource->type == WINED3D_RTYPE_BUFFER)
{
struct wined3d_bo_vk *bo_vk;
buffer_usage = vk_buffer_usage_from_bind_flags(resource->bind_flags);
memory_type = vk_memory_type_from_access_flags(resource->access, resource->usage);
size = resource->size;
}
else
{
struct wined3d_texture *texture = texture_from_resource(resource);
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 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 = &bo_vk->b;
addr->addr = NULL;
return true;
buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
memory_type = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
size = texture->sub_resources[sub_resource_idx].size;
}
return false;
if (!(bo_vk = heap_alloc(sizeof(*bo_vk))))
return false;
if (!(wined3d_context_vk_create_bo(context_vk, size, buffer_usage, memory_type, 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 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 = &bo_vk->b;
addr->addr = NULL;
return true;
}
static void adapter_vk_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)

View File

@ -3091,9 +3091,7 @@ 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)
{
/* Limit NOOVERWRITE maps to buffers for now; there are too many ways that
* a texture can be invalidated to even count. */
if (resource->type == WINED3D_RTYPE_BUFFER && (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
{
const struct wined3d_d3d_info *d3d_info = &context->device->adapter->d3d_info;
struct wined3d_client_resource *client = &resource->client;
@ -3124,7 +3122,10 @@ static bool wined3d_cs_map_upload_bo(struct wined3d_device_context *context, str
if (!device->adapter->adapter_ops->adapter_alloc_bo(device, resource, sub_resource_idx, &addr))
return false;
client->addr = addr;
/* Limit NOOVERWRITE maps to buffers for now; there are too many
* ways that a texture can be invalidated to even count. */
if (resource->type == WINED3D_RTYPE_BUFFER)
client->addr = addr;
}
else
{

View File

@ -4570,6 +4570,30 @@ void wined3d_texture_download_from_texture(struct wined3d_texture *dst_texture,
wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~dst_location);
}
static void wined3d_texture_set_bo(struct wined3d_texture *texture,
unsigned sub_resource_idx, struct wined3d_context *context, struct wined3d_bo *bo)
{
struct wined3d_texture_sub_resource *sub_resource = &texture->sub_resources[sub_resource_idx];
struct wined3d_bo *prev_bo = sub_resource->bo;
TRACE("texture %p, sub_resource_idx %u, context %p, bo %p.\n", texture, sub_resource_idx, 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);
}
sub_resource->bo = bo;
}
void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx,
struct wined3d_context *context, const struct upload_bo *upload_bo, const struct wined3d_box *box,
unsigned int row_pitch, unsigned int slice_pitch)
@ -4580,6 +4604,15 @@ void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsign
unsigned int depth = wined3d_texture_get_level_depth(texture, level);
struct wined3d_box src_box;
if (upload_bo->flags & UPLOAD_BO_RENAME_ON_UNMAP)
{
wined3d_texture_set_bo(texture, sub_resource_idx, context, upload_bo->addr.buffer_object);
wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_BUFFER);
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_BUFFER);
/* Try to free address space if we are not mapping persistently. */
wined3d_context_unmap_bo_address(context, (const struct wined3d_bo_address *)&upload_bo->addr, 0, NULL);
}
/* Only load the sub-resource for partial updates. */
if (!box->left && !box->top && !box->front
&& box->right == width && box->bottom == height && box->back == depth)