Render Hell —— 史上最通俗易懂的GPU入门教程(一)-程序员宅基地

技术标签: cuda  机器学习  深度学习  opengl  GPU  gpu  

声明:文本非原创,只是翻译,原文链接如下:
https://simonschreibt.de/gat/renderhell-book1/

Render Hell – Book I

在这里插入图片描述

在这里插入图片描述本文是 “Render Hell” 系列文章的第一篇。

如今对美术师的要求越来越高,因为在计算机眼里,他们提供的资源(asset)不过是一堆 顶点纹理 数据的集合而已。而将这些数据转换为最终的图像,则主要是通过计算机中的 CPU 和 GPU 来完成的。

1. 拷贝数据到系统内存

最初,为了实现快速访问,所有的绘图数据都需要从硬盘(HDD)加载到系统内存(RAM)。而如今,那些顶点和纹理数据则会被加载到显存(VRAM)上,因为显卡访问 VRAM 的速度更快!

在这里插入图片描述
当 VRAM 中的纹理不再被需要时,就可以在 RAM 中将其删除(前提是你确定不再需要它们了,因为重新从硬盘上加载这些资源将会非常耗时)。而顶点数据则仍然需要保留在 RAM 中,因为大多数情况下 CPU 仍需要访问这些数据(比如碰撞检测(Collision Detection))。

在这里插入图片描述
好了,这下我们想要的数据都已经在显卡(VRAM)上了。但是数据从 VRAM 传输到 GPU 的速度还是太慢了!因为 GPU 工作的速度要比数据传输的速度快很多很多!

因此,硬件工程师将一小片内存直接塞进了处理器芯片里,这一小片内存通常被称为 片上缓存(on-chip Cache)。因为它的价格极其昂贵,所以在芯片设计时它的容量并不大,因此 GPU 只会拷贝当前所需的那一小部分数据到缓存上,而非全部数据。

在这里插入图片描述
现在,那一小部分数据被拷贝到了一个叫做 二级缓存(L2 Cache)的地方,它是一块很小的内存(在 NVIDIA GM204 上只有 2MB 大小),被放置在 GPU 内部,且访问速度要比 VRAM 快很多。

但即使是这样,二级缓存的访问速度还是不够快,导致 GPU 无法充分发挥它的性能!因此才有了 一级缓存(L1 Cache)(在 NVIDIA GM204 上只有 384KB 大小,4x4x24KB),它不仅被放置在 GPU 内部,还十分靠近 GPU 的 Core!
在这里插入图片描述如果你想了解更多数字,可以 点此链接 查看。

在这里插入图片描述
另外,还有一块专用于 GPU Core 数据输入与输出的预留内存:寄存器寄存器堆(register file)。GPU Core 从这里读取2个值,然后进行计算,并将计算的结果存放到某个寄存器中(通常该寄存器由寄存器堆中的内存地址来表示)。

接着将寄存器中的结果回写到 L1/L2/VRAM 中,用于腾出空间给寄存器堆存放新的数据。作为一名程序猿,通常是不需要关心这些细节的。

在这里插入图片描述
为什么会这么麻烦?就像前面提到的:这都是为了减少访问时间!如果你对比一下硬盘和一级缓存的访问时间,你会发现它们之间有着天壤之别!点此链接 查看更加精确的延迟数据。

在 GPU 开始执行渲染之前,CPU 会设置一些全局的参数,这些参数是用来描述那些网格该被如何渲染的,这些参数的集合就被称为 Render State(渲染状态)

2. 设置 Render State

Render State 是网格渲染方式的一种全局定义,它包含如下信息:
顶点像素着色器纹理材质光照透明度 等 …” [b01 第711页]

重点: CPU 命令 GPU 绘制的每个网格都将在这些条件下进行渲染!你可以渲染石头、椅子或宝剑 —— 如果在渲染下一个网格之前不更改 Render State,它们都将使用相同的渲染参数(例如材质)。

在这里插入图片描述
准备工作完成后,CPU 总算可以发送命令给 GPU 并告诉它需要画什么了,而这个命令就叫做:Draw Call

3. Draw Call(绘图调用)

所谓 Draw Call 就是一条用来渲染网格的命令,它由 CPU 发出,并被 GPU 接收。该命令仅指向一个需要被渲染的网格,它不包含任何材质信息,因为这些信息早已在 Render State 中被设置。此时的网格正位于你的显卡中(VRAM)呢!

在这里插入图片描述
命令发出后,GPU 使用 Render State(材质、纹理、着色器)和所有顶点数据,通过代码魔法将这些信息转换为屏幕上的彩色像素,这个转换过程也被称为 Pipeline

4. Pipeline (流水线/管线)

就像我文章开头说的,美术师的作品不过是一堆顶点和纹理数据的集合而已。要想把它们转换为令人惊艳的图像,显卡必须借助顶点来创建三角形,计算它们的光照,给它们涂上纹理像素等等,这些操作被称为 statePipeline states
根据你读过的文章,你会发现大部分事情都是由 GPU 来完成的。但有时他们会说,例如下图中的 Create Triangle 和 Create Fragment 步骤,则是由显卡的其他模块来完成的。

下面这个 Pipeline 示例非常简单,仅仅只是一个粗略的介绍,你也可以把它当作一个逻辑 Pipeline:每个三角形或像素都经过逻辑步骤,但实际发生的情况略有不同。所以,请不要太认真了,你也可以查阅我在文章底部留下的其他链接,或者通过邮件推特facebook 给我留言,这样我就可以改进动画演示了。

如下为 GPU 渲染一个三角形的典型步骤:

在这里插入图片描述

渲染 说白了就是做大量的简单小任务,比如:计算上千个顶点,或者在屏幕上绘制数百万个像素点,这些任务至少要满足 30fps 的要求。

上面这些东西需要在同一时刻被计算出来,而不是一个接一个地计算每个顶点或像素。在早些年,CPU 只有一个 Core,也没有图形加速器,因此同一时刻只能处理一个任务,游戏看上去就很 。。。Low!如今的 CPU 已经有6-8个 Core 了,而 GPU 却有上千个 Core(它们不像 CPU Core 那么复杂,但非常适合处理大量的顶点和像素数据)。
在这里插入图片描述更精确的 GPU Core 数字可以在 [a38], [a39], [a40], [a41], [a42]Yeah 先生的留言中查看。

Gustav 和 Christoph 对 Core 的那段描述做了一些补充,以解释为何 CPU 与 GPU 的 Core 数量存在如此差异:

现代的 CPU 有4-8个 Core,每个 Core 可以同时执行4-8个浮点操作,因此我们假设 CPU 有64个浮点执行单元,然而 GPU 却可以有上千个这样的执行单元。仅仅只是比较 GPU 和 CPU 的 Core 数量是不公平的,因为它们的职能不同,组织形式也不同。GPU 厂商倾向于使用 Core 作为最小的执行单元,而 CPU 厂商则倾向于使用更高级的单元。在 Book II 中将会阐述 GPU 内部由高到低执行单元组织形式的更多细节。

当数据(例如一堆顶点)进入到 Pipeline 阶段时,转换顶点或像素的工作就被分配到多个 Core 上去完成,这样才能将大量微小元素经过并行处理后生成一张大图片:

在这里插入图片描述
现在我们知道了,GPU 是可以并行的工作的。但是 CPU 与 GPU 之间的通信又是怎样的呢?CPU 是否需要一直等到 GPU 任务完成后才开始发送下一条指令呢?

在这里插入图片描述
NO!

谢天谢地还好不是!因为这样的通信方式会造成性能瓶颈(比如,CPU 无法足够快的下发命令),同时无法实现 CPU 与 GPU 的并行工作。解决方法就是创建一个列表,该列表可供 CPU 添加指令,由 GPU 读取指令,相互独立,互不干扰!这个列表即为:Command Buffer

5. Command Buffer(命令缓冲区)

Command Buffer 使得 CPU 与 GPU 之间的独立工作成为可能。当 CPU 想要绘制一些东西时,它可以将该指令塞到队列里。当 GPU 有可用硬件资源时,则会从该队列中取出指令并执行。该列表其实是一个 FIFO,因此 GPU 只能取出列表中最先放进去的指令执行。

在这里插入图片描述
顺便说一下,Command Buffer 中可能会存在不同的命令,一个例子是 Draw Call,另一个例子则是修改 Render State。

这就是第一篇,现在你应该对于渲染期间的资源数据、Draw Call、Render State 以及 CPU 与 GPU 之间的通信机制有所了解了。
在这里插入图片描述继续阅读下一篇:Pipeline 详解,或返回目录索引

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hexiaolong2009/article/details/104084445

智能推荐

Leetcode __13. 罗马数字转整数_1227罗马数字-程序员宅基地

文章浏览阅读162次。问题描述罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。字符 数值I 1V 5X 10L 50C 100D 500M 1000例如, 罗马数字 2 写做 II ,即为两个并列的..._1227罗马数字

Spring Cloud(六)配置中心(Spring Cloud Config)_本地运行config-prod.properties-程序员宅基地

文章浏览阅读241次。一、简介在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config 。Spring Cloud Config就是我们通常意义上的配置中心。Spring Cloud Config-把应用原本放在本地文件的配置抽取出来放在中心服务器,本质是配置信息从本地迁移到云端。..._本地运行config-prod.properties

Linux常见基本指令合集及其效果展示_linux 展示-程序员宅基地

文章浏览阅读268次,点赞2次,收藏6次。首先先问大家一个问题:在磁盘上建一个空文件,这个文件会占据磁盘的储存空间吗?实践出真知,我们发现新建一个文本文档,它的大小是0kB,这时有小伙伴就会认为既然它的大小是0KB,那么它当然也就不会占用磁盘空间咯。然而真的是这样吗?我们打开这个文件的属性来一探究竟:我们发现系统不仅记录了这个空文件的大小,同时还有它的文件名、文件类型、所在位置、创建时间等信息,难道这些信息不要占用系统空间吗,当然要!一个空文件同样会占用系统空间文件 = 文件内容 + 属性路径的本质就是这颗多叉树的搜索路径。_linux 展示

iTOP-3588开发板快速启动手册Windows安装串口终端调试串口常见问题(二)_windows 调试串口-程序员宅基地

文章浏览阅读140次,点赞10次,收藏3次。问题二:非旺玖原装PL2303,请联系供货商或PL2303TA不支持WINDOWS11及后续版本问题。进设备管理器,找到端口COM,有问题会提示“非旺玖原装的PL2303,请联系您的供货商”。更多内容可以B站搜索迅为RK3588开发板;2.4.2 驱动问题。_windows 调试串口

python怎么输出_Python如何输出整数-程序员宅基地

文章浏览阅读7.7k次。Python输出整数的方法:先使用str()函数将数字转换成字符串赋值给变量i,再用“if i.count('.') == 0”语句判断字符串中是否没有小数点,如果是则输出这个字符串,这样输出的数字就都是整数了示例代码如下:x = [23.5, 45.6, 987, 698, 123, 654]for i in x:i = str(i)if i.count('.') == 0:print(I)执行..._python的print整数

js中好用的方法(复制剪贴板、时间转换、大数字单位转换)_js 粘贴板时间-程序员宅基地

文章浏览阅读146次。js中好用的工具方法复制内容到手机剪贴板:/** * 拷贝数据到剪贴板 */ public static CopyToClipBoard(str){ let copyDom = document.createElement("input"); // 获得需要复制的内容 copyDom.setAttribute("value",str); //不需要让他displaynone // copyDom._js 粘贴板时间

随便推点

EDM邮件群发的关键要素?如何高效地发信?-程序员宅基地

文章浏览阅读267次,点赞6次,收藏4次。EDM邮件群发虽然看似简单,但其中蕴含的要素却十分丰富。AokSend,依托强大API/SMTP接口,实现EDM邮件高效群发。精准触达,一键发送,让您的营销信息迅速覆盖目标客户,提升品牌影响力!

对话框未进入PreTranslateMessage函数-程序员宅基地

文章浏览阅读235次。定义了两个对话框CDlgParent和CDlgChild,CDlgChild已设置Child属性,CDlgParent未重定义PreTranslateMessage函数,在CDlgChild的PreTranslateMessage函数中设断点,未运用原因: 对话框均在动态库中定义,且为使用共享MFC DLL的规则DLL,此方式无法响应PreTranslateMessage消息,但应用程序可不使..._mfc pretranslatemessage 不进入

UI自动化测试之5大常见问题(建议收藏)(1),2024年最新从青铜到王者的路线-程序员宅基地

文章浏览阅读722次,点赞10次,收藏19次。1)UFT即原来的QTP与ST合并而来,由HP公司开发,是一个企业级的商业自动化测试工具,提供了强大易用的录制回放功能,同时兼容对象识别模式与图像识别模式,支持B/S和C/S两种架构的软件测试;一款基于python语言编写的自动化测试框架工具,具备良好的扩展性,支持关键字驱动,支持多种类型的客户端和接口,可进行分布式测试;3)Selenium自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

Linux创建操作网桥的两种命令及持久化_bridge命令-程序员宅基地

文章浏览阅读1.4w次,点赞4次,收藏48次。1.基础介绍1.1 简述1.2 网桥配置命令及安装(CentOS系统)2. brctl和bridge命令建桥2.1 brctl命令说明及范式2.2 brctl场景使用2.3 bridge命令及范式3.ip命令建桥3.1 ip命令建桥说明4.桥的持久化1.基础介绍1.1 简述什么是网桥  网桥是一种在链路层实现中继,对帧进行转发的技术,根据MAC分区块,可隔离碰撞,将网络的多个网段在数据链路层连接起来的网络设备。它是Linux上用来做TCP/IP二层协议交._bridge命令

css3大全-程序员宅基地

文章浏览阅读153次。孔子曰:学而不思则罔,思而不学则殆。废话不多说,直接上。浅谈兼容css相较于js html来说,兼容性问题最不是事,CSS在最初设计时,就有一个协议:如果不能识别选择器属性,那么就默认不处理,不报错。这个也是CSS得以发展的非常重要的特征。下面是各个浏览器私有前缀:IE -ms-Chrome -webkit-Firefox -moz-Safari -webkit-..._css 文字后仰

Linux学习笔记 01 - Linux概况_linux 从哪个版本开始支持lvm-程序员宅基地

文章浏览阅读760次。一、操作系统的发展历程操作系统是用来=控制和管理系统资源、方便用户使用计算机的程序的集合,是人机交互的接口。大致包括5个方面的管理功能:进程与处理机管理、作业管理、存储管理、设备管理、文件管理。1. 服务器专用的 UNIX 操作系统UNIX 操作系统与1969年由美国贝尔实验室肯·汤普森(K.Thompson)和丹尼斯·麦卡利斯泰尔·里奇(D.M.Ritchie)开发完成,是真正意义上的多用户多任务操作系统。UNIX的商业版版本主要包括SUN公司(现被Oracle公司收购)的Solaris、IBM_linux 从哪个版本开始支持lvm

推荐文章

热门文章

相关标签