vulkan: Add common cmd buffer state tracking

For drivers already using vk_common_ResetCommandBuffer(), it now only
calls the driver's reset hook if the command buffer is not in the
INITIAL state.  Pulled this trick from the PowerVR driver.

v2 (Jason Ekstrand):
 - Rename from "status" to "state" since that's what's in the spec
 - Add vk_command_buffer_begin/end instead of drivers setting it all
   manually

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16922>
This commit is contained in:
Dave Airlie 2022-06-08 10:45:44 +10:00 committed by Marge Bot
parent eca63c5e5c
commit a26755458e
3 changed files with 56 additions and 1 deletions

View file

@ -41,6 +41,7 @@ vk_command_buffer_init(struct vk_command_pool *pool,
command_buffer->level = level;
command_buffer->ops = ops;
vk_dynamic_graphics_state_init(&command_buffer->dynamic_graphics_state);
command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INITIAL;
command_buffer->record_result = VK_SUCCESS;
vk_cmd_queue_init(&command_buffer->cmd_queue, &pool->alloc);
util_dynarray_init(&command_buffer->labels, NULL);
@ -55,6 +56,7 @@ void
vk_command_buffer_reset(struct vk_command_buffer *command_buffer)
{
vk_dynamic_graphics_state_clear(&command_buffer->dynamic_graphics_state);
command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INITIAL;
command_buffer->record_result = VK_SUCCESS;
vk_command_buffer_reset_render_pass(command_buffer);
vk_cmd_queue_reset(&command_buffer->cmd_queue);
@ -62,6 +64,30 @@ vk_command_buffer_reset(struct vk_command_buffer *command_buffer)
command_buffer->region_begin = true;
}
void
vk_command_buffer_begin(struct vk_command_buffer *command_buffer,
const VkCommandBufferBeginInfo *pBeginInfo)
{
if (command_buffer->state != MESA_VK_COMMAND_BUFFER_STATE_INITIAL &&
command_buffer->ops->reset != NULL)
command_buffer->ops->reset(command_buffer, 0);
command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_RECORDING;
}
VkResult
vk_command_buffer_end(struct vk_command_buffer *command_buffer)
{
assert(command_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_RECORDING);
if (vk_command_buffer_has_error(command_buffer))
command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_INVALID;
else
command_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_EXECUTABLE;
return vk_command_buffer_get_record_result(command_buffer);
}
void
vk_command_buffer_finish(struct vk_command_buffer *command_buffer)
{
@ -92,7 +118,8 @@ vk_common_ResetCommandBuffer(VkCommandBuffer commandBuffer,
{
VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
cmd_buffer->ops->reset(cmd_buffer, flags);
if (cmd_buffer->state != MESA_VK_COMMAND_BUFFER_STATE_INITIAL)
cmd_buffer->ops->reset(cmd_buffer, flags);
return VK_SUCCESS;
}

View file

@ -88,6 +88,14 @@ struct vk_command_buffer_ops {
void (*destroy)(struct vk_command_buffer *);
};
enum mesa_vk_command_buffer_state {
MESA_VK_COMMAND_BUFFER_STATE_INVALID,
MESA_VK_COMMAND_BUFFER_STATE_INITIAL,
MESA_VK_COMMAND_BUFFER_STATE_RECORDING,
MESA_VK_COMMAND_BUFFER_STATE_EXECUTABLE,
MESA_VK_COMMAND_BUFFER_STATE_PENDING,
};
struct vk_command_buffer {
struct vk_object_base base;
@ -100,6 +108,9 @@ struct vk_command_buffer {
struct vk_dynamic_graphics_state dynamic_graphics_state;
/** State of the command buffer */
enum mesa_vk_command_buffer_state state;
/** Command buffer recording error state. */
VkResult record_result;
@ -179,6 +190,13 @@ vk_command_buffer_reset(struct vk_command_buffer *command_buffer);
void
vk_command_buffer_recycle(struct vk_command_buffer *command_buffer);
void
vk_command_buffer_begin(struct vk_command_buffer *command_buffer,
const VkCommandBufferBeginInfo *pBeginInfo);
VkResult
vk_command_buffer_end(struct vk_command_buffer *command_buffer);
void
vk_command_buffer_finish(struct vk_command_buffer *command_buffer);

View file

@ -695,6 +695,16 @@ vk_queue_submit(struct vk_queue *queue,
assert(info->command_buffers[i].deviceMask == 0 ||
info->command_buffers[i].deviceMask == 1);
assert(cmd_buffer->pool->queue_family_index == queue->queue_family_index);
/* Some drivers don't call vk_command_buffer_begin/end() yet and, for
* those, we'll see initial layout. However, this is enough to catch
* command buffers which get submitted without calling EndCommandBuffer.
*/
assert(cmd_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_INITIAL ||
cmd_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_EXECUTABLE ||
cmd_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_PENDING);
cmd_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_PENDING;
submit->command_buffers[i] = cmd_buffer;
}