Основная логика цикла:
- в основном потоке — ожидание на границах, получение образа цепочки обмена.
Код: Выделить всё
PreRender - Отправьте AcademicFrame и RenderFrame в пул потоков.
- Подождите () для завершения задач пула потоков.
Код: Выделить всё
Join - в основном потоке — представьте изображение.
Код: Выделить всё
PostRender - Повторите.
На первой итерации:
- записывает команды (проход очистки цвета).
Код: Выделить всё
PrepareFrame - Но RenderFrame, который отправляет буфер команд, работает с неправильным индексом кадра, отправляя буфер команд, который никогда не записывался.
- Уровни проверки сообщают, что семафор ожидания никогда не сигнализировался.
Вот соответствующая цепочка вызовов:Фрагменты кода (фреймы/Vulkan)Код: Выделить всё
void View::OnUpdate(double deltaTime) { if (m_RenderSurface) { m_RenderSurface->PreRender(); m_ThreadsUpdate.Submit([&]() { m_RenderQueue->SetDeltaTime(static_cast(deltaTime)); m_RenderSurface->PrepareFrame(m_RenderQueue); }); m_ThreadsUpdate.Submit([&]() { m_RenderSurface->RenderFrame(); }); m_ThreadsUpdate.Join(); m_RenderSurface->PostRender(); } }
Структура данных фрейма:Ротация индекса:Код: Выделить всё
struct FrameData { VkFence fence = VK_NULL_HANDLE; VkSemaphore acquireSemaphore = VK_NULL_HANDLE; VkSemaphore renderSemaphore = VK_NULL_HANDLE; VkCommandBuffer cmdBuffer = VK_NULL_HANDLE; uint32_t imageIndex = 0; bool inFlight = false; }; std::array m_Frames;Код: Выделить всё
void IGAPI::EndRender() { m_IndexFrameRender = (m_IndexFrameRender + 1) % BACK_BUFFER_COUNT; m_IndexFramePrepare = (m_IndexFrameRender + 1) % BACK_BUFFER_COUNT; }получает изображение:Код: Выделить всё
PreRender()
vr = vkAcquireNextImageKHR(device, m_Swapchain, UINT64_MAX,frame.acquireSemaphore, VK_NULL_HANDLE, &imageIndex);
Код: Выделить всё
PrepareFrame()Код: Выделить всё
RenderFrame()Код: Выделить всё
vkResetFences(device, 1, &frame.fence);
VkSubmitInfo submitInfo{};
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &frame.acquireSemaphore;
submitInfo.pWaitDstStageMask = &waitStage;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &frame.cmdBuffer;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &frame.renderSemaphore;
vkQueueSubmit(m_VulkanAPI->GetGraphicsQueue(), 1, &submitInfo, frame.fence);
Код: Выделить всё
VkPresentInfoKHR presentInfo{};
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &frame.renderSemaphore;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &m_Swapchain;
presentInfo.pImageIndices = &frame.imageIndex;
vkQueuePresentKHR(m_VulkanAPI->GetPresentQueue(), &presentInfo);
Код: Выделить всё
>>>>> #0 PreRender(). stepCounter: 1, indexPrepare: 0, imageIndex: 0.
>>>>> PrepareFrame(). stepCounter: 1, indexPrepare: 0, frame.imageIndex: 0.
>>>>> RenderFrame(). stepCounter: 1, indexRender: 1.
Vulkan Validation: ERROR | vkQueueSubmit(): pCommandBuffers[0] is unrecorded and contains no commands.
Vulkan Validation: ERROR | vkQueueSubmit(): pWaitSemaphores[0] has no way to be signaled.
>>>>> PostRender(). stepCounter: 1, indexRender: 1.
Vulkan Validation: ERROR | vkQueuePresentKHR(): pPresentInfo->pImageIndices[0] was acquired with a semaphore that has not since been waited on
Я ожидаю, что:
- Первый кадр записывает команды в AcceptFrame и отправляет их в RenderFrame.
- Настоящий семафор правильно сигнализируется и ожидает в vkQueuePresentKHR.
Полный код и ветка с этой реализацией Vulkan доступны здесь:
https://github.com/k119-55524/Zzz
Ветвь: origin/clear-VK-api
Вопрос
- Как правильно записать и отправить первый кадр в этом конвейере Vulkan с кадрами в полете, чтобы избежать ошибок «незаписанного командного буфера» и «несигнализированного семафора»?
- Есть ли ошибка рекомендуемый шаблон для инициализации и отправки самого первого кадра при использовании нескольких динамических кадров и пула потоков?
- В качестве альтернативы предоставьте ссылки на учебные пособия или руководства, в которых объясняется, как реализовать правильный конвейер рендеринга производитель-потребитель в Vulkan с несколькими динамическими кадрами и синхронизацией.
Подробнее здесь: https://stackoverflow.com/questions/799 ... aled-semap