目录
- 先叨叨
- Git信息
- 关键代码
- VulkanEnv::RenderOneFrame(uint32_t* pixels)
- VulkanEnv::CreateSyncObjects()
- main()
- 编译运行
先叨叨
经过快两周的努力,终于可以开始渲染了。
Git信息
- repository: https://gitee.com/J8_series/easy-car-ui
- tag: 13-Render
- url: https://gitee.com/J8_series/easy-car-ui/tree/13-Render
关键代码
VulkanEnv::RenderOneFrame(uint32_t* pixels)
- 本方法的功能是外界调用一次,Vulkan渲染一帧。并将图像拷贝到pixels只向的空间中。
- 流程
- 调用vkResetCommandBuffer重置CommanderBuffer
- 调用上篇编写RecordCommandBuffer记录指令
- 调用vkQueueSubmit将指令缓存推到队列中
- 调用vkWaitForFences等待Vulkan描画结束
- 调用vkMapMemory将现存内容映射出来
- 调用std::memcpy将现存图像拷贝出来
void VulkanEnv::RenderOneFrame(uint32_t* pixels)
{vkResetCommandBuffer(m_commandBuffer, /*VkCommandBufferResetFlagBits*/ 0);RecordCommandBuffer();//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#submitInfoVkSubmitInfo submitInfo{};submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;submitInfo.commandBufferCount = 1;submitInfo.pCommandBuffers = &m_commandBuffer;if (vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_fence) != VK_SUCCESS) {throw std::runtime_error("failed to submit draw command buffer!");}//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkWaitForFencesvkWaitForFences(m_device, 1, &m_fence, VK_TRUE, UINT64_MAX);vkResetFences(m_device, 1, &m_fence);void* gpuBuffer = nullptr;//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkMapMemoryVkResult mapRet = vkMapMemory(m_device, m_testPipeline.GetImageMemory(), 0, m_width * m_height * 4, 0, &gpuBuffer);if (VK_SUCCESS != mapRet){throw std::runtime_error("failed to map frame!");}std::memcpy(pixels, gpuBuffer, m_width * m_height * 4);vkUnmapMemory(m_device, m_testPipeline.GetImageMemory());
}
VulkanEnv::CreateSyncObjects()
在RenderOneFrame()方法中需要等待Vulkan渲染结束,这需要用到Fence对象。Fence对象是用来同步CPU和GPU的。GPU描画完设置Fence后,CPU侧的vkWaitForFences()方法才会返回。因此需要创建一个Fence对象。
void VulkanEnv::CreateSyncObjects()
{VkFenceCreateInfo fenceInfo{};fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;fenceInfo.flags = 0;//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkCreateFenceif (vkCreateFence(m_device, &fenceInfo, nullptr, &m_fence) != VK_SUCCESS){throw std::runtime_error("failed to create synchronization objects for a frame!");}
}
main()
在main函数中添加一条调用vulkanEnv.RenderOneFrame的代码。
int main(int argc, char** argv)
{
using namespace namespace_easy_car_ui;try{VulkanEnv vulkanEnv;vulkanEnv.Initalize(true, 640, 480);vulkanEnv.PrintPhysicalDevices();vulkanEnv.PrintSelectedPhysicalDevice();uint32_t pixels[640 * 480] {};vulkanEnv.RenderOneFrame(pixels);}...return EXIT_SUCCESS;
}
编译运行
编译运行如果没有任何错误,恭喜你已经完成了Vulkan的HelloWorld程序。当然目前还没看到渲染的效果,下一节会介绍如何使用SDL显示图像。