一个简单的文章,记录Vulkan的入门过程。
如何在Vulkan中绘制一个三角形?
1、穿件一个用于描述你的应用与API拓展的Vulkan实例,创建Vulkan实例后可以选择任意个支持Vulkan的VkPhysicalDevices,通过查询类似VRAM大小或是设备能力,从而选择合适的设备。
2、在选择了正确的Vulkan对象后需要创建一个逻辑设备VkDevice,在创建过程中你需要明确你所需要用到的VkPhysicalDevices的特性,如多视窗选软或是64位浮点等。同时需要明确想要使用的队列簇,大部分的Vulkan操作,例如draw commands,memory operations,需要提交到VkQueue后异步的执行。队列由queue families创建,每个queue family支持一组特定的操作。
3、窗口可以由原生平台API或动态库 GLFW与SDL进行创建。在窗口中进行渲染需要额外的两个组件,一个window surface:VkSurfaceKHR与一个swap chain:VkSwapchainKHR。surface是一个跨平台的用于在窗口上渲染的抽象,通常需要同原生窗口的句柄进行关联。Swap chain是一个渲染对象的集合,用于保证在屏幕上的渲染结果是完整的。每当我们想要进行渲染时需要向swap chain请求一个image对象,在完成绘制后返回对象,swap chain会在合适的时候将其展现在屏幕上。常见 swap chain显示模式包括double buffering(vsync)和triple buffering。一些平台允许通过VK_KHR_display和VK_KHR_display_swapchain拓展直接在display上进行绘制,从而实现自己的窗口管理。
4、绘制 swap chain中拿到的image,我们需要将其包装为VkImageView和VkFramebuffer。一个Image view关联了image的部分区域,同时一个framebuffer被image views用于色彩,深度及模板目标。
5、Render passes在Vulkan中用于描述在渲染操作过程中用到的image的类型,如何被使用,以及产生的内容应该被如何处理。
6、Graphics pipeline,在Vulkan中通过创建VkPipline对象调用。在Vulkan中,一个很大的不同是几乎所有的图形管线需要提前进行配置,因此需要实现创建许多VkPipeline对象从而满足在你的渲染操作中的不同组合。只有一些基本配置,如viewport size和clear color可以被动态的修改。所有的状态同样需要明确描述。
7、如同前面提到的,在Vulkan中许多操作我们需要提交到队列。这些操作在提交前首先需要在VkCommandBuffer中进行记录,这些指令的缓冲区是从同特定的queuefamily关联的VkCommandPool中分配的。
8、Vulkan的Main loop非常直接,我们首先通过vkAcquireNextImageKHR从swap chain中获取一个image。接着选择合适的command buffer,并且通过vkQueueSubmit执行这些command。最后,使用vkQueuePresentKHR向swap chain返回image。 所有提交到队列中的操作会被异步执行,因此我们必须通过使用诸如semaphores的手段来保障执行的次序正确。绘制的command buffer必须在image被成功获得后执行,否则可能会发生在一个仍在被读的image上进行渲染。同时vkQueuePresentKHR需要等待渲染完成后再被调用。
因此一个渲染三角形的步骤简单可以被归类为:
* 创建一个VkInstance
* 选择一个支持的图形卡
* 创建一个VkDevice和VkQueue用于绘制
*创建一个window,window surface和swap chain
* 将swap chain包装进入VkImageView
* 创建一个render pass并明确其渲染对象以及使用方法
* 创建用于render pass的 framebuffers
* 建立graphics pipeline
* 为每个可能的swap chain image创建command buffer并记录draw commands