GPU驱动的渲染pipeline

本文探讨了GPU驱动渲染管线的概念及其实现方式,包括利用GPU进行剔除和提交DrawCall等操作,以此减轻CPU负担并提升渲染效率。通过具体案例如《刺客信条》和《孤岛惊魂5》展示了GPU驱动渲染管线带来的显著性能提升。
部署运行你感兴趣的模型镜像

这里写图片描述

==overview==
这里写图片描述
这里写图片描述

随着硬件的发展,我们可以看到GPU的计算能力远远的把CPU抛在后面,所以把更多的CPU端的计算放在GPU端,可以说是一个行业一直努力的方向。
渲染端cpu上面,一直以来,剔除和提交drawcall都是cpu做的,这部分一方面cpu可怜的计算力只能做的很粗糙,一方面消耗颇高,导致国内游戏行业谈性能必谈drawcall数量。
这部分离GPU很近,所以当然要先下手了。
其实早在PS3时代,强劲的spu,一定程度上我们可以理解为是一个更通用的GPGPU,就承担了这个任务,更激进的剔除和替代cpu进行drawcall提交,都让性能在cpu有质的飞跃,gpu也同时受益。

从dx11开始,都支持渲染的对象的部分参数由GPU来生成,可以说GPGPU来做这个事情的条件就也成熟了。
整体上在性能上的收获是非常大的。
从15年的siggraph开始,ubi和EA都相继做了不少的分享:

  • siggraph15, < GPU-Driven Rendering Pipelines> @ ubisoft
  • gdc16, < Optimizing the Graphics Pipeline With Compute> @ EA
  • gdc18, TerrainRenderingFarCry5 @ ubisoft

总的看来,GPU driven pipeline是有两个部分:

  • 剔除–不只是offload了cpu的工作,进一步在gpu上做更aggressive的cull
  • 提交–目标是一个drawcall结束战斗,根据实际情况进行折中了

==剔除==
这部分是通过gpgpu来先对要渲染的object进行剔除,这里ubi和ea都分成两个level来做,cluster和triangle

=cluster level cull=
这里写图片描述
把mesh分成固定的一些cluster,比如6400 vertices就分成100个cluster,每个cluster 64vertices,然后进行bound和orientation的cull。

=triangle level cull=
这里的backface,small area triangle都是老生常谈。
depth buffer这个,可以
- 在pc上使用cpu software rasterizer
- depth prepass, 然后downsample
- 使用上一帧的depth buffer做一个reprojection
使用其中的1个或几个组合。

==提交==
这里普遍的遇到项目老代码的问题,如果是dx12或者基于virtual texture的项目会简单些。
简单讲,就是要绑定的资源如果非常不同,还是难以硬放在一起来渲染。
这里< assassin’s creed:unity >就是没法改的彻底,所以还是依据material来batch,那么可以说gpu driven的就相当不彻底。
而redlynx,pipeline是有比较重的virtual texture,farcry5的地形有virtual texture,那么资源就不需要改变绑定,那么就可以一个drawcall搞定一切,达到一个更彻底的gpu driven的程度。
dx12对此有更好的支持,可以更彻底的gpu driven了。

==效率对比==

  • 刺客信条,应该说几个paper里面受益最少的,但也非常的可观
    • cpu 比前一座,10x的obj,但是cpu却快了25%
    • gpu也少渲染了20%到80%的triangle
      farcry5
  • gpu把quadtree traverse到lod map以及各种cull,0.1ms搞定。。。比cpu真是绝对优势

您可能感兴趣的与本文相关的镜像

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

### C++ 中的 GPU 渲染队列实现 在现代图形编程中,GPU 渲染队列是一个重要的概念,它允许开发者通过优化命令提交来提高性能。以下是关于如何在 C++ 中实现 GPU 渲染队列以及可能遇到的相关问题的一些讨论。 #### 使用 DirectX 或 Vulkan 的渲染队列基础 DirectX 和 Vulkan 是两个常见的低级 API,用于控制 GPU 行为并管理渲染队列。这些 API 提供了灵活的方式来定义和执行渲染操作序列。例如,在 DirectX 中可以利用 `ID3D12GraphicsCommandList` 接口创建命令列表[^1];而在 Vulkan 中,则可以通过 `vkQueueSubmit` 函数向特定队列提交工作负载[^2]。 对于 Direct3D 12 来说,应用程序需要显式地构建资源屏障、管道状态对象 (PSO),并通过绑定根签名等方式配置好所有的绘制调用参数之后才能填充到 Command List 当中去完成实际绘图任务。这种设计虽然增加了复杂度但也赋予了极大的自由度给开发者来进行精细化调整从而达到最佳效率表现。 当涉及到跨平台开发时,Vulkan提供了更加统一的方法论处理不同硬件厂商之间的差异性.VkCommandBuffer作为Vulkan的核心组件之一负责记录一系列指令直到最终被呈现在屏幕上为止.每一个VkCommandBuffer都隶属于某个具体的queue family index所代表的一类逻辑单元下运行. #### 实现步骤概述(不包含具体顺序词) - 创建设备上下文环境. - 定义描述符堆及其布局结构以便于后续访问各种类型的纹理贴图或者常量缓冲区等内容. - 编译着色器程序并将它们封装成可重用的形式即Pipeline State Object(PipelineStateObject). - 构建顶点/索引数据源以及其他必要的几何体表示形式准备输入装配阶段所需材料. - 设置视口(Viewport)剪裁矩形(Rectangle)等窗口特性限制范围内的像素计算过程. - 记录Draw Calls至Command Buffers内部形成完整的帧更新流程. 下面展示了一个简单的伪代码片段说明如何基于上述原则编写一段基本框架: ```cpp // 初始化Direct3D或其他API... std::vector<ID3D12Resource*> resources; ComPtr<ID3D12RootSignature> rootSig; ComPtr<ID3D12PipelineState> pso; void RecordCommands(ID3D12GraphicsCommandList* cmdList){ // Transition resource states if necessary ... cmdList->SetGraphicsRootSignature(rootSig.Get()); cmdList->RSSetViewports(...); cmdList->RSSetScissorRects(...); cmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); cmdList->IASetVertexBuffers(...); cmdList->SetPipelineState(pso.Get()); // Draw call here... } ``` #### 常见挑战与解决方案 ##### 资源同步问题 由于异步性质,GPU可能会尝试读取尚未写入完毕的数据造成未定义行为因此必须妥善安排Barrier Transitions确保正确的依赖关系存在之间相互作用的对象上设置合适的标志位通知驱动何时何地应该发生转换动作以避免潜在冲突情况的发生. ##### 性能瓶颈分析工具运用不足 为了有效定位哪些部分占据了过多时间消耗应当充分利用Profile Tools如NVIDIA Nsight Systems / AMD Radeon GPU Profiler等等帮助识别热点区域进而采取针对性措施改善整体吞吐能力比如减少不必要的内存带宽占用频率或是合并相似属性批次一起发送出去降低CPU端开销成本提升流水线利用率水平.[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值