图形管道创建完毕就可以渲染绘制内容到屏幕了
void CVulkanApp::drawFrame()
{
uint32_t imageIndex;
vkAcquireNextImageKHR(logicDevice_, swapChain_, UINT64_MAX, imageAvaliableSemaphore_[curFrame], nullptr, &imageIndex);
vkWaitForFences(logicDevice_, 1, &inFlightFence_[curFrame], VK_TRUE, UINT64_MAX);
vkResetFences(logicDevice_, 1, &inFlightFence_[curFrame]);
vkResetCommandBuffer(commandBuffer_[curFrame], 0);
recordCommandBuffer(commandBuffer_[curFrame], imageIndex);
updateUBOBuffer(curFrame);
VkSemaphore waitSemaphores[] = { imageAvaliableSemaphore_[curFrame]};
VkSemaphore signalSemaphores[] = { renderFinishedSemaphore_[curFrame]};
VkPipelineStageFlags waitPipelineStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitPipelineStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer_[curFrame];
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
if (vkQueueSubmit(graphicsQueue_, 1, &submitInfo, inFlightFence_[curFrame]) != VK_SUCCESS)
{
throw std::runtime_error("failed to submit queue!");
}
VkSwapchainKHR swapChain[] = { swapChain_ };
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChain;
presentInfo.pImageIndices = &imageIndex;
presentInfo.pResults = nullptr;
vkQueuePresentKHR(presentsQueue_, &presentInfo);
curFrame = (curFrame + 1) % MAX_FRAME;
}
以下是对这段代码解释
1. 图像获取与同步准备
-
vkAcquireNextImageKHR:从交换链获取下一帧可用的图像索引(
imageIndex)。-
UINT64_MAX表示无限等待直到图像可用; -
imageAvaliableSemaphore_[curFrame]作为信号量,在图像就绪时被触发。
-
-
同步等待与重置:
-
vkWaitForFences:阻塞CPU直到前一帧的围栏(inFlightFence_[curFrame])完成(避免GPU过载)。 -
vkResetFences:重置围栏状态,为当前帧做准备。 -
vkResetCommandBuffer:重置命令缓冲区,确保其可被重新录制。
-
2. 命令缓冲区录制与提交
-
recordCommandBuffer:录制绘制命令到当前帧的命令缓冲区(如绑定管线、设置视口、执行绘制调用。
-
updateUBOBuffer:更新Uniform缓冲区数据(如模型/视图矩阵等动态数据)。
-
提交渲染命令:
-
waitSemaphores:等待imageAvaliableSemaphore_确保图像就绪; -
waitPipelineStages:指定等待阶段为颜色附件输出(避免提前渲染); -
signalSemaphores:渲染完成后触发renderFinishedSemaphore_; -
绑定当前帧的命令缓冲区。
-
VkSubmitInfo配置: -
vkQueueSubmit:提交命令到图形队列,并关联当前帧的围栏(GPU完成后触发该围栏)。
-
3. 图像呈现与帧循环
-
vkQueuePresentKHR:将渲染结果提交到呈现队列:
-
等待
renderFinishedSemaphore_确保渲染完成; -
指定交换链和获取的图像索引(
imageIndex)。
-
-
帧索引循环:
-
curFrame = (curFrame + 1) % MAX_FRAME:循环使用帧资源(实现多帧并行,如双缓冲/三缓冲)。
-
4. 关键同步机制解析
-
信号量(Semaphore):
-
imageAvaliableSemaphore_:协调 图像获取 与 渲染开始(GPU间同步)。 -
renderFinishedSemaphore_:协调 渲染完成 与 图像呈现(GPU间同步)。
-
-
围栏(Fence):
-
inFlightFence_:确保CPU等待GPU完成前一帧,防止命令缓冲区冲突(CPU-GPU同步)。
-
5. 多帧并行设计
-
MAX_FRAME的作用:允许同时处理多帧(如设为2时,CPU可录制第N帧命令,而GPU执行第N-1帧),提升GPU利用率。
-
资源隔离:
每帧拥有独立的命令缓冲区、信号量和围栏,避免同步干扰。
显示样式如下:
1394

被折叠的 条评论
为什么被折叠?



