Vulkan从入门到精通1

Vulkan是一个跨平台的2D和3D绘图应用程序接口(API),最早由科纳斯组织在2015年游戏开发者大会(GDC)上发表。号称是glNext。旨在提供更低的CPU开销与更直接的GPU控制,其理念大致与Direct3D 12和Mantle类似。

上周末花了2天时间看了下Vulkan,感觉这个不大好上手;如果3.0前的OpenGL上手难易程序是20,3.3以后OpenGL是30,Vulkan上手难易程度最少有100。难度主要体现在,很多之前图形API内部对Pipeline的操作现在都暴露给了用户,需要用户显式的设置管线。用户的控制粒度更细,程序能跑出更好的性能(另外一个原因是对数据的处理都在显存上进行)。以笔者的VivoBook15X + MMX330配置,绘制一个640×480窗口三角形帧率能达到1200左右。

通过浏览

上面的29讲,结合之前写mesa umd驱动,阅读mesa源码,外加OpenGL经验算是对Vulka入了门。

Vulkan中的主要的概念

Device 一个Device就代表着一个你系统中的物理GPU。它的功能除了让你可以选择用来渲染(或者计算)的GPU以外,主要功能就是为你提供其他GPU上的资源,例如所有要用到显存的资源Pipleline 一个Pipeline包含了传统API中大部分的状态和设定。只不过Pipeline是需要事先创建好的,这样所有的状态组合的验证和编译都可以在初始化的时候完成,运行时不会再因为这些操作有任何性能上的浪费。但正是因为这一点,如果你不同的Pass需要不同的状态,你需要预先创造多个不同的Pipeline。Buffer – Buffer是所有我们所熟悉的Vertex Buffer, Index Buffer, Uniform Buffer等等的统称。而且一个Buffer的用途非常多样。在Vulkan中需要特别注意Buffer是从什么类型的内存中分配的,有的类型CPU可以访问,有的则不行。有的类型会在CPU上被缓存。Image – Image在Vulkan中代表所有具有像素结构的数组,可以用于表示纹理,Render Target等等。和其他组件一样,Image也需要在创建的时候指定使用它的模式,例如Vulkan里有参数指定Image的内存Layout,可以是Linear,也可以是Tiled Linear便于纹理Filter。Command Buffer – Command Buffer就是渲染本身所需要的行为。在Vulkan里,没有任何API允许你直接的,立即的像GPU发出任何命令。所有的命令,包括渲染的Draw Call,计算的调用,甚至内存的操作例如资源的拷贝,都需要通过App自己创建的Command Buffer。Vulkan对于Command Buffer有特有的Flag,让程序制定这些Command只会被调用一次(例如某些资源的初始化),亦或者应该被缓存从而重复调用多次(例如渲染循环中的某个Pass)。另一个值得注意的是,为了让驱动能更加简易的优化这些Command的调用,没有任何渲染状态会在Command Buffer之间继承下来。每一个Command Buffer都需要显式的绑定它所需要的所有渲染状态,Shader,和Descriptor Set等等。这和传统API中,只要你不改某个状态,某个状态就一直不会变,这一点很不一样.Command Buffer Pool – Command Buffer Pool是一个需要注意的多线程相关的组件。它是Command Buffer的父亲组件,负责分配Command Buffer。Command Buffer相关的操作会对其对应的Command Buffer Pool里造成一定的工作,例如内存分配和释放等等。因为多个线程会并行的进行Command Buffer相关的操作,这个时候如果所有的Command Buffer都来自同一个Command Buffer Pool的话,这时Command Buffer Pool内的操作一定要在线程间被同步。Queue – 是Vulkan中唯一给GPU递交任务的渠道。Vulkan将Queue设计成了完全透明的对象,所以在驱动里没有任何其他的隐藏Queue,也不会有任何的Synchronization发生。在Vulkan中,给GPU递交任务不再依赖于任何所谓的绑定在单一线程上的Context,Queue的API极其简单,你向它递交任务(Command Buffer),然后如果有需要的话,你可以等待当前Queue中的任务完成。这些Synchronization操作是由Vulkan提供的各种同步组件完成的。例如Samaphore可以让你同步Queue内部的任务,程序无法干预。Fence和Event则可以让程序知道某个Queue中指定的任务已经完成。所有这些组件组合起来,使得基于Command Buffer和Queue递交任务的Vulkan非常易于编写多线程程序。

从Vulkan程序工作流程看,步骤如下

创建窗口实例化Vulkan Instance – 一个程序可以有多个创建 Surface查找物理驱动查找逻辑驱动创建管线缓存生成swap chain创建image view生成render passFrame BuffersCommand PoolCommand Buffer创建同步对象创建管线

渲染过程中的流程是

重新创建管线 – 条件执行同步Fence – vkWaitForFences获取交换链图像 – vkAcquireNextImageKHRresetFence inFlightFences – 如何翻译?提交command – vkQueueSubmitvkQueuePresentKHR -请求当前图像更新当前帧索引

笔者第一个出图的是一个三角形如下

主程序代码如下

#include #include “VK_Context.h”using namespace std;const std::vector vertices1 = { {{0.0f, -0.5f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, {{0.5f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, {{-0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}};VK_Context* context = nullptr;int main(){ VK_ContextConfig config; config.debug = false; context = createVkContext(config); context->createWindow(640, 480, true); VK_Context::VK_Config vkConfig; context->initVulkan(vkConfig); auto shaderSet = context->createShaderSet(); shaderSet->addShader(“shader/vertex/vert.spv”, VK_SHADER_STAGE_VERTEX_BIT); shaderSet->addShader(“shader/vertex/frag.spv”, VK_SHADER_STAGE_FRAGMENT_BIT); if(!shaderSet->isValid()) { std::cerr release(); return -1; } context->initPipeline(shaderSet); auto buffer = context->createBuffer(vertices1); context->addBuffer(buffer); context->createCommandBuffers(); context->run(); context->release(); return 0;}

笔者对Vulkan做了封装处理,全代码请访问

下篇

文章列表

蛋蛋的爸爸:Vulkan 从入门到精通蛋蛋的爸爸:Vulkan从入门到精通1蛋蛋的爸爸:Vulkan从入门到精通2-绘制三角形蛋蛋的爸爸:Vulkan入门到精通3-管线缓存和验校蛋蛋的爸爸:Vulkan从入门到精通4-颜色混合和清屏蛋蛋的爸爸:Vulkan从入门到精通5-Shader封装蛋蛋的爸爸:Vulkan从入门到精通6-使用uniform让三角形动起来蛋蛋的爸爸:Vulkan从入门到精通7-vkImage,Image视图和采样器蛋蛋的爸爸:Vulkan从入门到精通8-视口和裁剪蛋蛋的爸爸:Vulkan从入门到精通9-纹理显示蛋蛋的爸爸:Vulkan从入门到精通10-不变采样器蛋蛋的爸爸:Vulkan从入门到精通11 – 深度缓存蛋蛋的爸爸:Vulkan从入门到精通12-实例化和验证层蛋蛋的爸爸:Vulkan从入门到精通13-代码整合蛋蛋的爸爸:Vulkan从入门到精通14-绘制一个立方体蛋蛋的爸爸:Vulkan从入门到精通15-绘制一个立方体2蛋蛋的爸爸:Vulkan从入门到精通16-网格模型蛋蛋的爸爸:Vulkan从入门到精通17-几何着色器蛋蛋的爸爸:Vulkan从入门到精通18-细分着色器蛋蛋的爸爸:Vulkan从入门到精通19-Mip贴图蛋蛋的爸爸:Vulkan从入门到精通20-内存分配器蛋蛋的爸爸:Vulkan从入门到精通21-显示模型蛋蛋的爸爸:Vulkan从入门到精通22-多重采样蛋蛋的爸爸:Vulkan从入门到精通23-管线动态状态蛋蛋的爸爸:Vulkan从入门到精通24-模型卡通蛋蛋的爸爸:Vulkan从入门到精通25-代码重构蛋蛋的爸爸:Vulkan从入门到精通26-派生管线和多管线蛋蛋的爸爸:Vulkan从入门到精通27-推送常量蛋蛋的爸爸:Vulkan从入门到精通28-枚举设备和物理设备蛋蛋的爸爸:Vulkan从入门到精通29-栅栏蛋蛋的爸爸:Vulkan从入门到精通30-光照蛋蛋的爸爸:Vulkan从入门到精通31-队列族和逻辑设备蛋蛋的爸爸:Vulkan从入门到精通32-描述符集布局和管线布局蛋蛋的爸爸:Vulkan从入门到精通33-推送描述符蛋蛋的爸爸:Vulkan从入门到精通34-指令池和指令缓冲蛋蛋的爸爸:Vulkan从入门到精通35-窗口表面蛋蛋的爸爸:Vulkan从入门到精通36-间接渲染蛋蛋的爸爸:Vulkan从入门到精通37-管线屏障和vkCmdClearColorImage蛋蛋的爸爸:Vulkan从入门到精通38-使用vkCmdCopyImageToBuffer保存VkImage图像蛋蛋的爸爸:Vulkan从入门到精通39-次级命令缓冲蛋蛋的爸爸:Vulkan从入门到精通40-Image Blit/Copy蛋蛋的爸爸:Vulkan从入门到精通41-Texel Buffer蛋蛋的爸爸:Vulkan从入门到精通42-管线统计查询蛋蛋的爸爸:Vulkan从入门到精通44-SSBO


比丘资源网 » Vulkan从入门到精通1

提供最优质的资源集合

立即查看 了解详情