GAMES106笔记 - 现代图形绘制流水线原理与实践

一、RHI - Render Hardware Interface

 二、Vulkan简介

  • 真正的实现依赖于厂家的驱动实现
  • 与传统API相比可以更大程度上直接操作GPU,在难度更大的同时,可以更加自由的编写高性能程序。

初始化

  1. 创建窗口(操作系统API或者glfw或SDL库)
  2. 初始化Vulkan
  3. 创建Swapchain,联系Vulkan与显示窗口。

关心的问题:窗口类型win32、XCB等。

vulkan层次

通常情况:一个实例,一个物理设备,一个逻辑设备,一个或多个队列。

但Vulkan创建多个实例,来分配不同的的物理设备,实现不同逻辑设备的与命令队列组合来更好利用GPU资源的能力。

VKInstance

Instance是程序与Vulkan库之间的桥梁

  • 需要指定开启的扩展
    • 创建swapchain的类型
    • 给vulkan对象设置名字的调试功能
    • 检查vulkan的错误调用的回调
  • Vulkan Layer可以实现不同的功能,可以开一个layer去实现扩展功能,例如调试,验证等。
  • layer给vulkan提供重写函数的方式,可以重载对应的vulkan函数,传递给下一层layer。

VkPysicalDevice

获取与vulkan instance 和显卡的联系

  • Vulkan可以检索当前计算机的显卡设备,以及他们的能力(对功能的支持)
  • 根据程序的需要,需要判断显卡是否支持
    - 如果程序需要一个扩展,显卡无法提供支持时,可以初始化失败
    - 双显卡笔记本可以指定选择独显或核显

VkQueue

Vulkan的Command都需要上传到命令队列VkQueue(绘制,数据上传等)

不同类型的队列来源不同的队列簇(Queue Family Properties),不同队列簇只允许部分类型的Command

  • VK_QUEUE_GRAPHICS_BIT  图形操作
  • VK_QUEUE_COMPUTE_BIT   着色器计算
  • VK_QUEUE_TRANSFER_BIT  支持复制Buffer和Image操作

根据程序选择队列簇,使用队列簇需要检查显卡是否支持,例如对物理设备调用findQueueFamilies 来检查物理设备对于队列簇种类的支持。

 VkDevice

  • 逻辑设备和Vulkan做交互
  • 通过逻辑设备可以获取VkQueue(物理设备中的队列簇的一条队列)中的Command。
  • 可以选择开启可选的特性,可选特性可以通过VkPhysicalDeviceFeatures来查询几何着色器,细分着色器,压缩纹理等功能。

 

移动端设备支持的特性会少。

SwapChain

  • 通过VkInstance创建Surface,然后vulkan与窗口取得联系。
  • 需要检查使用的队列簇是否同时支持surface与graphic
  • 创建swapchain和surface获取联系
  • 创建swapchai的时候选择属性,颜色空间(SRGB/HDR),刷新模式(Vsync),缓冲数量(双缓冲三缓冲)
  • 从Swapchain获取缓冲的Image,用于后面创建FrameBuffer用于渲染。

渲染主循环

  1. 输入几何信息
  2. 输出屏幕画面
  3. 处理着色器
  4. 更新CPU端逻辑
  5. CPU到GPU的数据拷贝
  6. 生成Vulkan Command Buffer,提交渲染任务到GPU

与opengl不一样,一般没有默认值,我们需要手动设置,例如深度检测等。

顶点输入

顶点数据缓存(vertex buffer),索引缓存(inedx buffer),图元拓扑类型(Primitive Topology),Draw

vertex buffer包括

  • 顶点三维坐标
  • 法线
  • 纹理
  • 其他顶点属性

一种可能的数据排布,P和N可能会在程序运行之中随时变化,而属性和纹理往往保持不变。

索引的意义在于顶点复用,拓扑结构中相同顶点属性可以复用以节省内存。

不建议跳转区域过大的vertex共用缓存,容易产生cache miss降低程序性能。

拓扑结构决定顶点如果组成几何,三角形,线。

Draw

  • VkCmdDraw:对vertex buffer调用drawcall,需要指定顶点数量
  • VkCmdDrawIndexed:有索引的直接绘制
  • VkCmdDrawIndirect: 可以将vertex buffer中传入GPU,可以在GPU端对buffer进行我们想要的处理,例如procedural生成或删除一些顶点,或者对顶点进行剔除后绘制,
  • VkCmdDrawIndexedIndirect:有索引的间接绘制。

Vertex Shader

顶点shader经过编译器生成SPIR-V,主要用于计算顶点位置变换到NDC,顶点其他属性的计算。

光栅化Rasterization

  • 填充方式
  • 剔除方式
  • 正方向
  • 线宽度
  • depth bias解决 z fighting(两个z一致的平面会随机部分相互出现)

ViewPort

设置窗口真正绘制的区域,描述framebuffer作为渲染输出结果目标区域;

一般与窗口一致,也可以设置一个非常大的View Port,增加局部分辨率(例如在做CSM时)。

Fragment Shader

通过插值后的顶点属性与纹理进行fragment上的进行渲染计算。

缓冲区有

  • uniform buffer (std 140) (数字为OpenGL的版本)
  • storage buffer (std 430)
  • push constant (Vulkan特有,频繁更新的数据)

移动端数据要注意精度,顶点位置需要32位浮点数,颜色8位,以减少带宽需求,可以全部先改为半精度,根据实际情况进行进一步修改。

Fragment Buffer

  • 混合(alpha混合等)
  • 检测(模板/深度检测)
  • 深度检测(画家算法,前面的挡住后面的)目前往往会early z,在vertex shader之后就知道了
  • early z的一种实现方法,pre depth pass,先进行一个pass,fragment shader部分什么都不干,通过vertex shader给buffer写入深度,但其实有缺点,多进行一次pass,性能损耗较严重。
  • 移动端往往采用tile based rendering,TBR由于其需要划分tile,在vertex shader之后,确定tile与图元的对应时可以完成pre depth。

renderpass定义了图形绘制最小单元

定义绘制管线的输出 - framebuffer RT

vulkan定义了

  • 1.framebuffer的IO
    • 在开始时是否需要保持原有数据
    • 结束后是否写回数据
    • 在移动端显卡带宽小众需要特别关注 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值