Ошибка проверки Вулкана, когда я пытаюсь сбросить пул команд после vkQueueWaitIddle

#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 , я думал, что пареметры указывают глобальный размер (количество вызовов вычислительных шейдеров), но на самом деле это количество рабочих групп. Поэтому я отправлял больше потоков, чем намеревался, и мой буфер был недостаточно большим, поэтому потоки выходили за рамки. Я считаю, что уровень проверки не давал мне правильных подсказок, хотя.