#vulkan
Вопрос:
У меня есть небольшая программа Vulkan, которая запускает вычислительный шейдер в цикле.
Существует только один буфер команд, выделенный из единственного имеющегося у меня пула команд.
После создания буфера команд я отправляю его в очередь и жду, пока он завершится vkQueueWaitIddle
. Я действительно немного подождал в этой строке кода. После этого я вызываю vkResetCommandPool
, который должен сбросить все командные буферы , выделенные этому пулу (в любом случае есть только один).
...
vkEndCommandBuffer(commandBuffer);
{
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.commandBufferCount = 1;
info.pCommandBuffers = amp;commandBuffer;
vkQueueSubmit(queue, 1, amp;info, VK_NULL_HANDLE);
}
vkQueueWaitIdle(queue);
vkResetCommandPool(device, commandPool, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
Когда он пытается сбросить командный пул, проверка выдает мне следующую ошибку.
VUID-vkResetCommandPool-commandPool-00040(ERROR / SPEC): msgNum: -1254218959
- Validation Error: [ VUID-vkResetCommandPool-commandPool-00040 ]
Object 0: handle = 0x20d2ce0b718, type = VK_OBJECT_TYPE_COMMAND_BUFFER; |
MessageID = 0xb53e2331 |
Attempt to reset command pool with VkCommandBuffer 0x20d2ce0b718[] which is in use.
The Vulkan spec states: All VkCommandBuffer objects allocated from commandPool must not be in the pending state
(https://vulkan.lunarg.com/doc/view/1.2.176.1/windows/1.2-extensions/vkspec.html#VUID-vkResetCommandPool-commandPool-00040)
Objects: 1
[0] 0x20d2ce0b718, type: 6, name: NULL
Но я не понимаю, почему, так как я уже жду с vkQueueWaitIdle
. Согласно документации, как только командный буфер будет выполнен, он должен перейти в invalid
состояние, и я смогу его сбросить.
Вот соответствующий окружающий код:
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
beginInfo.pInheritanceInfo = nullptr;
for (i64 i = 0; i < numIterations; i )
{
vkBeginCommandBuffer(commandBuffer, amp;beginInfo);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout,
0, 2, descriptorSets, 0, nullptr);
uniforms.start = i * numThreads;
vkCmdUpdateBuffer(commandBuffer, unifsBuffer, 0, sizeof(uniforms), amp;uniforms);
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
0, nullptr,
1, amp;memBarriers[0],
0, nullptr);
vkCmdDispatch(commandBuffer, numThreads, 1, 1);
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
0, nullptr,
1, amp;memBarriers[1],
0, nullptr);
VkBufferCopy copyInfo = {};
copyInfo.srcOffset = 0;
copyInfo.dstOffset = 0;
copyInfo.size = sizeof(i64) * numThreads;
vkCmdCopyBuffer(commandBuffer,
buffer, stagingBuffer, 1, amp;copyInfo);
vkEndCommandBuffer(commandBuffer);
{
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.commandBufferCount = 1;
info.pCommandBuffers = amp;commandBuffer;
vkQueueSubmit(queue, 1, amp;info, VK_NULL_HANDLE);
}
vkQueueWaitIdle(queue);
vkResetCommandPool(device, commandPool, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
i64* resu<
vkMapMemory(device, stagingBufferMem, 0, sizeof(i64) * numThreads, 0, (void**)amp;result);
for (int i = 0; i < numThreads; i )
{
if (result[i]) {
auto res = result[i];
vkUnmapMemory(device, stagingBufferMem);
return res;
}
}
vkUnmapMemory(device, stagingBufferMem);
}
Комментарии:
1. Похоже на ложноположительный результат. Обновлены ли ваши слои до последней версии?
2. Похоже, есть соответствующий билет в KhronosGroup/Вулкан-Валидаторы#2756
3. @krOoze Я установил Vulkan SDK на прошлой неделе. Спасибо, похоже, это и есть та проблема, которая у меня возникла.
Ответ №1:
Я нашел свою проблему. В vkCmdDispatch
, я думал, что пареметры указывают глобальный размер (количество вызовов вычислительных шейдеров), но на самом деле это количество рабочих групп. Поэтому я отправлял больше потоков, чем намеревался, и мой буфер был недостаточно большим, поэтому потоки выходили за рамки. Я считаю, что уровень проверки не давал мне правильных подсказок, хотя.