[PATCH 8/8] wined3d: Try to allocate new Vulkan BOs from the client thread for DISCARD maps.
Zebediah Figura
zfigura at codeweavers.com
Wed Nov 3 15:47:36 CDT 2021
On 11/3/21 12:11 PM, Henri Verbeet wrote:
> On Wed, 3 Nov 2021 at 00:37, Zebediah Figura <zfigura at codeweavers.com> wrote:
>> +static bool adapter_vk_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
>> + unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
>> +{
>> + wined3d_not_from_cs(device->cs);
>> +
>> + if (resource->type == WINED3D_RTYPE_BUFFER)
>> + {
>> + struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource));
>> + struct wined3d_client_bo_vk *client_bo;
>> +
>> + if (!(client_bo = heap_alloc(sizeof(*client_bo))))
>> + return false;
>> +
>> + if (!wined3d_buffer_vk_create_buffer_object(buffer_vk, NULL, &client_bo->bo))
>> + {
>> + heap_free(client_bo);
>> + return false;
>> + }
>> +
>> + if (!client_bo->bo.b.map_ptr)
>> + {
>> + struct wined3d_client_bo_vk_map_ctx ctx = {.device = device, .client_bo = client_bo};
>> +
>> + WARN_(d3d_perf)("BO %p (chunk %p, slab %p) is not persistently mapped.\n", &client_bo->bo,
>> + client_bo->bo.memory ? client_bo->bo.memory->chunk : NULL, client_bo->bo.slab);
>> +
>> + wined3d_cs_map_object(device->cs, wined3d_client_bo_vk_map_cs, &ctx);
>> + wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_MAP);
>> + }
> wined3d_cs_map_object() almost sounds like it would emit a
> WINED3D_CS_OP_MAP, somewhat like wined3d_device_context_map() back
> when that was still called wined3d_cs_map()...
Indeed, except that WINED3D_CS_OP_MAP takes the resource. I don't think
we want to change that, either, although we could create a new CS op
instead of using WINED3D_CS_OP_CALLBACK.
(Now that I think about it, *is* there any sort of a rule as to what
deserves WINED3D_CS_OP_CALLBACK and what doesn't? I know that currently
it's just a matter of init and destroy, but it seeems a bit arbitrary on
reflection.)
> Here too, Vulkan could map from application threads, it just needs to
> be synchronised. In the general case we'd need to make sure the GPU
> isn't still using the bo, but that's not an issue for newly allocated
> bo's.
>
>> +void wined3d_buffer_rename(struct wined3d_buffer *buffer, struct wined3d_context *context, struct wined3d_bo *bo)
>> +{
>> + TRACE("buffer %p, context %p, bo %p.\n", buffer, context, bo);
>> +
>> + buffer->buffer_ops->buffer_rename_bo(buffer, context, bo);
>> + buffer->buffer_object = (uintptr_t)bo;
>> + wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER);
>> + wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
>> +}
>> +
> If we're doing this at the wined3d_buffer level, perhaps it would make
> sense to name this something like wined3d_buffer_set_bo(),
> wined3d_buffer_assign_bo(), or something along those lines.
>
>> +static void wined3d_buffer_vk_rename_bo(struct wined3d_buffer *buffer,
>> + struct wined3d_context *context, struct wined3d_bo *bo)
>> +{
>> + struct wined3d_bo_vk *prev_bo = (struct wined3d_bo_vk *)buffer->buffer_object;
>> + struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
>> + struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(buffer);
>> + struct wined3d_bo_vk *bo_vk = wined3d_bo_vk(bo);
>> +
>> + if (prev_bo)
>> + {
>> + struct wined3d_bo_user *bo_user;
>> +
>> + LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->b.users, struct wined3d_bo_user, entry)
>> + bo_user->valid = false;
>> + assert(list_empty(&bo_vk->b.users));
>> + list_move_head(&bo_vk->b.users, &prev_bo->b.users);
>> +
>> + if (prev_bo != &buffer_vk->bo)
>> + {
>> + struct wined3d_client_bo_vk *client_bo = CONTAINING_RECORD(prev_bo, struct wined3d_client_bo_vk, bo);
>> +
>> + wined3d_context_vk_destroy_bo(context_vk, &client_bo->bo);
>> + heap_free(client_bo);
>> + }
>> + }
>> + else
>> + {
>> + list_add_head(&bo_vk->b.users, &buffer_vk->b.bo_user.entry);
>> + }
>> +}
>> +
> I admit I didn't try very hard, but it's not immediately clear to me
> why we wouldn't always assign the new bo to "buffer_vk->bo" here, and
> mark the previous one for destruction.
>
Right, the basic reason is that the client thread might still be holding
a pointer to "bo_vk" in the wined3d_client_resource structure. I'll add
a comment to that effect...
More information about the wine-devel
mailing list