You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-04 22:03:09 +02:00
vulkan: use a single command buffer per command buffer pool
We violated the spec, which, despite the actual command buffer pool *not* being involved in any functions which require external synchronization of the pool, *require* external synchronization even if only the command buffers are used. This also has the effect of *significantly* speeding up execution in case command buffers are contended.
This commit is contained in:
@ -673,7 +673,6 @@ static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEX
|
|||||||
case 0xfd92477a: /* BestPractices-vkAllocateMemory-small-allocation */
|
case 0xfd92477a: /* BestPractices-vkAllocateMemory-small-allocation */
|
||||||
case 0x618ab1e7: /* VUID-VkImageViewCreateInfo-usage-02275 */
|
case 0x618ab1e7: /* VUID-VkImageViewCreateInfo-usage-02275 */
|
||||||
case 0x30f4ac70: /* VUID-VkImageCreateInfo-pNext-06811 */
|
case 0x30f4ac70: /* VUID-VkImageCreateInfo-pNext-06811 */
|
||||||
case 0xa05b236e: /* UNASSIGNED-Threading-MultipleThreads-Write */
|
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -280,15 +280,19 @@ void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
|
|||||||
av_freep(&sd->desc_sets);
|
av_freep(&sd->desc_sets);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool->cmd_bufs)
|
for (int i = 0; i < pool->pool_size; i++) {
|
||||||
vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pool,
|
if (pool->cmd_buf_pools[i])
|
||||||
pool->pool_size, pool->cmd_bufs);
|
vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pools[i],
|
||||||
if (pool->cmd_buf_pool)
|
1, &pool->cmd_bufs[i]);
|
||||||
vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pool, s->hwctx->alloc);
|
|
||||||
|
if (pool->cmd_buf_pools[i])
|
||||||
|
vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pools[i], s->hwctx->alloc);
|
||||||
|
}
|
||||||
if (pool->query_pool)
|
if (pool->query_pool)
|
||||||
vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
|
vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
|
||||||
|
|
||||||
av_free(pool->query_data);
|
av_free(pool->query_data);
|
||||||
|
av_free(pool->cmd_buf_pools);
|
||||||
av_free(pool->cmd_bufs);
|
av_free(pool->cmd_bufs);
|
||||||
av_free(pool->contexts);
|
av_free(pool->contexts);
|
||||||
}
|
}
|
||||||
@ -316,19 +320,10 @@ int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
|
|||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create command pool */
|
/* Allocate space for command buffer pools */
|
||||||
cqueue_create = (VkCommandPoolCreateInfo) {
|
pool->cmd_buf_pools = av_malloc(nb_contexts*sizeof(*pool->cmd_buf_pools));
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
if (!pool->cmd_buf_pools) {
|
||||||
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
|
err = AVERROR(ENOMEM);
|
||||||
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
|
||||||
.queueFamilyIndex = qf->idx,
|
|
||||||
};
|
|
||||||
ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
|
|
||||||
s->hwctx->alloc, &pool->cmd_buf_pool);
|
|
||||||
if (ret != VK_SUCCESS) {
|
|
||||||
av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
|
|
||||||
ff_vk_ret2str(ret));
|
|
||||||
err = AVERROR_EXTERNAL;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,21 +334,40 @@ int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nb_contexts; i++) {
|
||||||
|
/* Create command pool */
|
||||||
|
cqueue_create = (VkCommandPoolCreateInfo) {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
|
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
|
||||||
|
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||||
|
.queueFamilyIndex = qf->idx,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
|
||||||
|
s->hwctx->alloc, &pool->cmd_buf_pools[i]);
|
||||||
|
if (ret != VK_SUCCESS) {
|
||||||
|
av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
|
||||||
|
ff_vk_ret2str(ret));
|
||||||
|
err = AVERROR_EXTERNAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate command buffer */
|
/* Allocate command buffer */
|
||||||
cbuf_create = (VkCommandBufferAllocateInfo) {
|
cbuf_create = (VkCommandBufferAllocateInfo) {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
.commandPool = pool->cmd_buf_pool,
|
.commandPool = pool->cmd_buf_pools[i],
|
||||||
.commandBufferCount = nb_contexts,
|
.commandBufferCount = 1,
|
||||||
};
|
};
|
||||||
ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
|
ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
|
||||||
pool->cmd_bufs);
|
&pool->cmd_bufs[i]);
|
||||||
if (ret != VK_SUCCESS) {
|
if (ret != VK_SUCCESS) {
|
||||||
av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
|
av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
|
||||||
ff_vk_ret2str(ret));
|
ff_vk_ret2str(ret));
|
||||||
err = AVERROR_EXTERNAL;
|
err = AVERROR_EXTERNAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Query pool */
|
/* Query pool */
|
||||||
if (nb_queries) {
|
if (nb_queries) {
|
||||||
|
@ -253,7 +253,7 @@ typedef struct FFVkExecPool {
|
|||||||
FFVkExecContext *contexts;
|
FFVkExecContext *contexts;
|
||||||
atomic_uint_least64_t idx;
|
atomic_uint_least64_t idx;
|
||||||
|
|
||||||
VkCommandPool cmd_buf_pool;
|
VkCommandPool *cmd_buf_pools;
|
||||||
VkCommandBuffer *cmd_bufs;
|
VkCommandBuffer *cmd_bufs;
|
||||||
int pool_size;
|
int pool_size;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user