Hello Vulkan(六)| 图形渲染新技术Vulkan Command Buffers及光追


回顾
上一期技术分享中,我们讲述了如何关于Vulkan的纹理绘制部分,将纹理贴图映射到3D模型上,也介绍了Vulkan里存储类型,纹理贴图是存放在GPU的设备内存,为了能够快速的读取。
本期将继续分享关于Vulkan的关于「Command Buffers」以及「光追Ray Tracing」,本期也将会是我们此次教程的最后一章了,后续会再推出其他系列讲解,也会加入我们虹图产品在不同平台的使用方法教程和一些有趣的使用场景分享。
Command Buffers
首先我们来看下Vulkan的整体框架图:

Vulkan通过创建实例Instance,建立起我们的应用和Vulkan库之间的桥梁,通过Instance初始化Vulkan后,我们需要在系统中查找并选择一个支持我们所需功能的显卡。实际上,我们可以选择任意数量的显卡并同时使用他们。而Queue队列是用来和物理设备沟通的桥梁,而具体的沟通过程就需要 Command Buffer命令缓冲区,它是若干命令的集合,我们向 Queue 提交 Command Buffer,然后才交由物理设备 GPU 进行处理。我们不需要自己创建Queue,物理设备已经有了队列。
Command buffer用于记录(record)GPU指令(command)。在Vulkan中,指令是通过类似于vkCmdxxx()的接口来写入到Command buffer,驱动会负责生成适配当前GPU的二进制指令内容。

创建Command buffer
创建command buffer需先创建command buffer池:
VkResult Init06CommandPool( ){VkResult result;VkCommandPoolCreateInfo vcpci;vcpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;vcpci.pNext = nullptr;vcpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT| VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;#ifdef CHOICESVK_COMMAND_POOL_CREATE_TRANSIENT_BIT VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT#endifvcpci.queueFamilyIndex = FindQueueFamilyThatDoesGraphics( );result = vkCreateCommandPool( LogicalDevice, IN &vcpci, PALLOCATOR, OUT &CommandPool );return result;}
Command buffer池与queue簇是一一对应的关系,创建command buffer池需指定使用的queue簇类型。
创建完Command buffer池后,就可以分配Command buffer了:
VkResult Init06CommandBuffers( ){VkResult result;// allocate 2 command buffers for the double-buffered rendering:{VkCommandBufferAllocateInfo vcbai;vcbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;vcbai.pNext = nullptr;vcbai.commandPool = CommandPool;vcbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;vcbai.commandBufferCount = 2; // 2, because of double-bufferingresult = vkAllocateCommandBuffers( LogicalDevice, IN &vcbai, OUT &CommandBuffers[0] );}// allocate 1 command buffer for the transferring pixels from a staging buffer to a texture buffer:{VkCommandBufferAllocateInfo vcbai;vcbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;vcbai.pNext = nullptr;vcbai.commandPool = CommandPool;vcbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;vcbai.commandBufferCount = 1;result = vkAllocateCommandBuffers( LogicalDevice, IN &vcbai, OUT &TextureCommandBuffer );}return result;}
Command buffer分配好之后,就可以记录GPU指令了。vkBeginCommandBuffer()用于开启Command buffer的记录状态,vkCmdxxx()用于记录指令,比如:vkCmdSetLineWidth()、vkCmdDraw(),完成记录后用vkEndCommandBuffer()关闭记录状态,变成可提交状态。
VkSemaphoreCreateInfo vsci;vsci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;vsci.pNext = nullptr;vsci.flags = 0;VkSemaphore imageReadySemaphore;result = vkCreateSemaphore( LogicalDevice, IN &vsci, PALLOCATOR, OUT &imageReadySemaphore);uint32_t nextImageIndex;vkAcquireNextImageKHR( LogicalDevice, IN SwapChain, IN UINT64_MAX, IN imageReadySemaphore, IN VK_NULL_HANDLE, OUT &nextImageIndex);VkCommandBufferBeginInfo vcbbi;vcbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;vcbbi.pNext = nullptr;vcbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;vcbbi.pInheritanceInfo = (VkCommandBufferInheritanceInfo *)nullptr;result = vkBeginCommandBuffer( CommandBuffers[nextImageIndex], IN &vcbbi );. . .vkEndCommandBuffer( CommandBuffers[nextImageIndex] );
到这儿就可以完成了开启Command Buffer的过程,一张图回顾下:

光追Ray Tracing
最后简单给大家介绍下Vulkan里的光线追踪Ray Tracing应用,这个本身其实还是比较复杂的,这里只做最简单的应用讲解。比如折射、反射都是属于光追计算。

Ray Tracing管线具有5个新着色器Shader种类:

创建光线追踪管线需要读取着色器数据,按照光线生成,光线未命中,光线命中,可调用四个组合,将它们根据顶层加速结构的实例,以索引代替着色器头,构建出着色器表的简化版本。将它传递给管线创建所需要的struct,创建管线。
我们来看下光线在球体上的处理方式,我们知道三维球面的方程是(x-xc) 2 + (y-yc) 2 + (z-zc) 2 = R2 ,切线的方程是(x,y,z) = (x0,y0,z0) + t*(dx,dy,dz) ,带入(x,y,z) 到第一个方程,能够得到1个关于t的一元二次方程,能够接触t1和t2两个解。如果t1和t2两个解都是复数,则光线未触及球面,如果t1和t2相等,则光线贴着球面沿切线方向擦过,如果t1和t2不等且都为实数,则光线直接触及球面。
这就是一个简单的计算针对球体物体的光线汇聚方法。在Vulkan里,gl_WorldRayOriginNV=(x0,y0,z0),gl_HitNV=t,gl_WorldRayDirectionNV = (dx,dy,dz) 。
根据光线与物体的命中规律,才引入了上述新的着色器种类,简单讲述着色器的种类:光线生成、光线未命中、最近命中、任意命中、相交命中。它们之间的数据互相传递,可以参见上述管线图,其他的就不再做更深入的讲解,代码部分会以zip形式在后台发放,演示了如何进行下面的光追效果。

具体读取代码工程zip已经放至公众号后台,回复“raytracing.zip”即可获取。到这儿所有的Vulkan教程的全部内容就结束了。欢迎大家关注虹图AI开放平台公众号,后台留言交流,也欢迎大家移步至我们刚上线的开发者社区中交流和分享。我们会在后续内容中继续与大家分享,开发者如何利用我们虹图AI的产品进行快速开发以及如果做使用上的优化等。
敬请期待~
到顶部