vulkan/cmd_queue: Add a common vk_cmd_enqueue_CmdBindDescriptorSets

In order for this to work, the driver must reference-count pipeline
layouts so we can take a reference while the command is in the queue.

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15329>
This commit is contained in:
Jason Ekstrand 2022-03-09 15:27:33 -06:00 committed by Marge Bot
parent c1070556a0
commit 94ea3b9c03
2 changed files with 84 additions and 0 deletions

View File

@ -25,6 +25,7 @@
#include "vk_alloc.h"
#include "vk_cmd_enqueue_entrypoints.h"
#include "vk_command_buffer.h"
#include "vk_device.h"
#include "vk_util.h"
VKAPI_ATTR void VKAPI_CALL
@ -194,3 +195,70 @@ vk_cmd_enqueue_CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,
}
}
}
static void
unref_pipeline_layout(struct vk_cmd_queue *queue,
struct vk_cmd_queue_entry *cmd)
{
struct vk_command_buffer *cmd_buffer =
container_of(queue, struct vk_command_buffer, cmd_queue);
struct vk_device *device = cmd_buffer->base.device;
assert(cmd->type == VK_CMD_BIND_DESCRIPTOR_SETS);
device->unref_pipeline_layout(device, cmd->u.bind_descriptor_sets.layout);
}
VKAPI_ATTR void VKAPI_CALL
vk_cmd_enqueue_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t *pDynamicOffsets)
{
VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
struct vk_device *device = cmd_buffer->base.device;
struct vk_cmd_queue_entry *cmd =
vk_zalloc(cmd_buffer->cmd_queue.alloc, sizeof(*cmd), 8,
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (!cmd)
return;
cmd->type = VK_CMD_BIND_DESCRIPTOR_SETS;
list_addtail(&cmd->cmd_link, &cmd_buffer->cmd_queue.cmds);
/* We need to hold a reference to the descriptor set as long as this
* command is in the queue. Otherwise, it may get deleted out from under
* us before the command is replayed.
*/
device->ref_pipeline_layout(device, layout);
cmd->u.bind_descriptor_sets.layout = layout;
cmd->driver_free_cb = unref_pipeline_layout;
cmd->u.bind_descriptor_sets.pipeline_bind_point = pipelineBindPoint;
cmd->u.bind_descriptor_sets.first_set = firstSet;
cmd->u.bind_descriptor_sets.descriptor_set_count = descriptorSetCount;
if (pDescriptorSets) {
cmd->u.bind_descriptor_sets.descriptor_sets =
vk_zalloc(cmd_buffer->cmd_queue.alloc,
sizeof(*cmd->u.bind_descriptor_sets.descriptor_sets) * descriptorSetCount, 8,
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
memcpy(cmd->u.bind_descriptor_sets.descriptor_sets, pDescriptorSets,
sizeof(*cmd->u.bind_descriptor_sets.descriptor_sets) * descriptorSetCount);
}
cmd->u.bind_descriptor_sets.dynamic_offset_count = dynamicOffsetCount;
if (pDynamicOffsets) {
cmd->u.bind_descriptor_sets.dynamic_offsets =
vk_zalloc(cmd_buffer->cmd_queue.alloc,
sizeof(*cmd->u.bind_descriptor_sets.dynamic_offsets) * dynamicOffsetCount, 8,
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
memcpy(cmd->u.bind_descriptor_sets.dynamic_offsets, pDynamicOffsets,
sizeof(*cmd->u.bind_descriptor_sets.dynamic_offsets) * dynamicOffsetCount);
}
}

View File

@ -96,6 +96,22 @@ struct vk_device {
bool signal_memory,
struct vk_sync **sync_out);
/** Increments the reference count on a pipeline layout
*
* This is required for vk_enqueue_CmdBindDescriptorSets() to avoid
* use-after-free problems with pipeline layouts. If you're not using
* the command queue, you can ignore this.
*/
void (*ref_pipeline_layout)(struct vk_device *device,
VkPipelineLayout layout);
/** Decrements the reference count on a pipeline layout
*
* See ref_pipeline_layout above.
*/
void (*unref_pipeline_layout)(struct vk_device *device,
VkPipelineLayout layout);
/* Set by vk_device_set_drm_fd() */
int drm_fd;