英文原文:The Evolution of Direct3D
译者:@浅水清流
本文作者 Alex St. John 和 Craig Eisler、 Eric Engstrom 三位一起创建了早期的微软 DirectX 技术平台。1992-1997 年 Alex 在微软的工作,后来成为 DirectX 技术布道师。
我在 Direct3D 上工作了很多年,多年来技术有了极大的发展。多年来,现代图形处理器(GPU)发生了巨大的变化,拥有了我曾经以为在有生之年不可能见到的运算速度和能力。现代 GPU 的演变是在很多充满魅力的市场驱动下进行的,其中我觉得最重要并且有趣的是,在 Direct3D 的影响下,新一代的 GPU 支持数以千计的处理核心,数十亿晶体管(超过 CPU)而且在大多数应用中都要快很多倍。我可以讲很多关于 D3D 的趣闻和政治传说,但是我更想记录下 D3D 的由来以及对现代 GPU 架构的深远影响。
本文使用的是 1995 年 Direct3D 第一次发布时的老文档。这份文档包含了对 3D 硬件加速架构的愿景,在很大程度上主导了现代 GPU 演变成为今天我们所见的强大得另人难以置信并且用途普遍的无所不在的消费型超级计算机。
D3DOVER
我进入计算图形学不是对游戏感兴趣,而是对想了解物理模拟计算。为了了解如何模拟量子力学、化学和生物系统,在 20 世纪 80 年代中后期,我开始参与 Siggraph 研究 3D 图形学。模拟光和材质互相作用在 Siggraph 曾经风靡一时,在此期间我学习了 3D。了解 3D 数学和光照模拟,让我通过我在职业早期创建的 PostScript RIP(光栅图像处理器),成为了在出版业的图形和色彩专家。我曾经和剑桥大学的工程师一起开发了在连续色调印刷发明之前印刷彩色图形的软件方案。我的专业背景获得了微软的青睐,在 1990 年初我获邀参与为 Windows 95 和 Windows NT 重新设计具备与当时表现卓越的苹果竞争的能力的打印架构。峰回路转之后,我的职业生涯到了回到 3D 的时候,我开始主动和几个朋友为 Windows 重新设计支持实时游戏和视频架构的图形和多媒体架构,这最终导致游戏成为了微软的一个重要战略。在索尼推出 3D 游戏机 PS1 之后,为 Windows 找个一个 3D 解决方案,成为了负责开发 Directx 的我们义不容辞的责任。
对我来说,制定微软在游戏市场 3D 战略的挑战是一个经济问题。微软应该采取什么样的策略,去创建一个充满活力竞争激烈的市场给消费者带来实惠并且引导未来的发展。在那个时代,3D 实时渲染的复杂度远远超出了当时的硬件能力,找出一个远离数学的理想方案让任何 hack 都能构建出足够好的 3D 应用看起来是不可能,我们有希望改变世界。
当时唯一的商业解决方案是为 CAD 设计的 3D 硬件。这些工作站需要花费数十万美元。虽然 OpenGL API 是当时市场上唯一的 3D API 标准,但是它并不是为 3D 游戏设计的。例如,纹理映射是渲染逼真的图形的一个重要技术,但是 CAD 优先考虑的是功能而不是看起来 cool。同样,丰富的动态光影效果对提高游戏的表现力很重要,但是对 CAD 并不重要。而高精度的模型对于 CAD 重要,但是对游戏并不重要。最重要的是 OpenGL 并没有为实时高度互动的图形而设计的离线缓冲区来避免渲染过程中撕裂纹理。这并不是说 OpenGL 并不能适应这些游戏所需的特性,而是它的实际市场是昂贵的工作站而不是$200 的游戏显卡。
在 20 世纪 90 年代计算机的 RAM 非常昂贵,正因为如此,早期消费型显卡选择了内存需求最小的方案。Sony 在优化 PS1 的 3D 硬件时,没有依赖内存密集型的Z-buffer,而是使用多边形区域排序算法,虽然会在活动的骨骼间产生丑陋的交点。“画家算法”对 3D 渲染来说非常快速,并且几乎不要额外的内存。对于游戏开发来说这是一个丑陋而务实的做法,但是这种做法对 CAD 来说是不可接受的。
在制定 Direct3D 架构时,我们面临的类似艰难选择不胜枚举。我们希望当时领先的显卡厂商,ATI、Cirrus、Trident、S3、Matrox 和其他厂商能彼此竞争,快速更新 3D 显卡,而无需在一片混乱中建立市场。微软的 OpenGL 团队信赖 Michael Abrash 的技术方案,一个被称为 3DDDI (3D Device Driver Interface)的驱动程序模型。3DDDI 是一个非常简单的驱动模型,只支持硬件加速 3D 光栅化。3D 场景光照变换的复杂数学运算被留到了 CPU。3DDDI 使用“功能位”来指定额外的渲染功能(比如过滤),消费型显卡厂商可以选择实现一部分。3DDDI 的问题是在邀请游戏厂商参与时,事情失去了控制。这么多“功能位”,游戏厂商要么选择支持各种“未知”的硬件特性,利用一切可能的方式充分挖掘显卡的能力(硬件厂商可能会选择支持不同的硬件特性导致用户的硬件配置难以预测,为了在任何设备上都良好的表现,游戏将不得不准备大量的美术资源)或者游戏只使用一组所有硬件都支持的简单常见的 3D 特性,但是没有硬件公司提供的最新特性,在市场上就会缺乏表现力。OpenGL 的人在微软没有意识到这是个大问题,因为在他们的世界里,所有人都使用支持他们需要的所有特性,价值$100,000 的昂贵工作站。
认识到我们不可能从 OpenGL 团队得到我们想要的东西之后,我们决定创建一个新的,只为游戏而设计的 3D API。这些 API 什么都不做,但是我们需要通过制定明确的驱动程序架构,来创建一个竞争激烈而有序的市场。在这方面,D3D API 不是 OpenGL API 的替代品,它是一个驱动 API,创造出来的一个经济战略目的,是引导消费型显卡市场进行激烈而有序的竞争。换句话说,D3D API 更多出于经济目的,而不是技术目的。在这方面 D3D API 的几个革命性的有趣之处是,API 什么都没有做,而是制定它所依赖的驱动程序架构。
当我们决定收购一只团队打造 Direct3D 时,我被特许参与评审候选企业是否有足够的技术能力帮助我们制定我们所需要的 API。正如我以前所说,我们考核了 Epic Games ( UnReal 引擎厂商), Criterion (后来被 EA 收购), Argonaut 和 Rendermorphics。我们选择了总部设在伦敦的 Rendermorphics,因其创始人 Servan Kiondijian 对如何设计一个尽可能兼具兼容性和创新的 3D 驱动程序架构有一个非常明确愿景。Direct3D 的第一个版本非常的简陋,但是 API 迅速向在未来有巨大潜力的方向演进。
我在这一时期的主要记忆是,我作为常驻 DirectX 团队的 3D 专家,被要求为 D3D 选择一个坐标系标准。我选择了左手坐标系,一部分原因出于个人喜好。我至今还记得,因为这是一个轻率的决定,此后带来无数的麻烦,因为其他 3D 建模工具都采用了 OpenGL 标准的右手坐标系。当时没有人会想到,AutoDesk 和 Maya 的建模工具会成为游戏开发行业的建模的标准工具。微软已经有了收购 SoftImage 取代 Autodesk 和 Maya 的计划。Whoops…
早期的 Direct3D HAL (Hardware Abstraction Layer) 以一种有趣的方式设计,它以垂直的 3 个阶段构成。
最高层是几何变换层,中间层专用于光照计算,底层进行光栅化过程,生成像素图像。这种垂直驱动架构背后的目的是让硬件厂商在实现一个相对一致的特性要求进行创新。他们可以细分他们的产品,设计更加高效的 3D 管线,从而获取更高的性能,并且和现有产品保持兼容,否则就会需要配置一个庞大的矩阵进行兼容性测试,或是需要大量的冗余美术资源。由于 Rendermorphics 创建 Direct3D API 时提供了一个“相当高效的”无需硬件加速的软件实现,游戏开发者可以把重心放在 Direct3D API 上,而无需关注无数不兼容的硬件特性组合。至少理论上是这样。可惜和 3DDDI 驱动程序规范一样,Direct3D 仍然包含了“功能位”设计,允许加入垂直架构之外的硬件特性。虽然我极力反对让 Direct3D 倾向于堆积“功能位”,但是小组受到了来至微软 OpenGL 组的巨大竞争压力,硬件提供商支持他们。
硬件厂商为了让自己的产品可以更有优势,威胁将会支持和促进游戏厂商使用 OpenGL,因为 OpenGL 驱动程序模型支持“功能位”,他们可以设计别人不具备的硬件特性。这很常见(现在还是),硬件厂商赞助游戏厂商使用他们与基础功能不兼容的硬件特性,迫使消费者不断更新他们的显卡来玩游戏啊厂商最新的 PC 游戏。游戏厂商讨厌不断变化的“功能位”,因为它们复杂并且不兼容,但是又希望通过支持“非标准”3D 特性获取游戏厂商的赞助。
总的来说,我认为这种趋势破坏了 PC 游戏市场的健康发展,并且主张抵制这种趋势,无论 OpenGL 或是 OEM 厂商的人怎么想。我相信创建一个稳定的消费市场,比安抚 OEM 厂商更加重要。就是这样,我是 Direct3D 垂直管线的强力倡导者,我们预计随着时间的推移,只实现 D3DAPI 的功能将会越来越普遍。我坦白承认,这种观点隐含对在其他领域创新的重大约束,引导市场被放在 Direct3D 团队的第一位。
最终我的估计相对准确。Direct3D 固定管线,如大家所知的,通过在 DirectX 7.0 上进行的健康的激烈竞争,产生了内容丰富、增长迅速的 PC 游戏市场。在 2000 年初,PC 游戏市场赢来了爆发性的增长,成为了全球上最大的游戏市场。这也导致 GPU 体系结构此后发生了许多有趣的变化。
最终 Direct3D HAL 是一个光栅化驱动模型加微软的 OpenGL 团队所倡导的“功能位”,显卡厂商将通过加速底层渲染管线的效率和添加差异化特性与对手展开竞争。引入的垂直分层架构的结果是,促使所有硬件厂商以更接近通用 CPU 架构的方式添加特性到 GPU 中,即以一致的方式进行快速浮点计算。因此消费型 GPU 经过多年的发展,越来越像 CPU,但是有个主要的区别。因为 3D 管线还是刚性的固定管线,Direct3D 体系结构很少需要像 CPU 一样针对分支代码的优化。GPU 实现惊人的性能和高度并行,很大程度上得益于 Direct3D 图形管线内部很少甚至根本没有分支代码。因此不是发展成为一个类似于 Intel CPU 那样将大量晶体管用于高效的分支预测的巨大的单片 CPU 核心,Direct3D 的 GPU 拥有数百至数千简单的没有分支预测的 CPU 核心。他们可以达到惊人的吞吐量,以令人难以置信的速度执行,如果不遇到分支代码或是随机内存访问,流水线就不会被打断。
通过支持 DirectX 7.0,GPU 底层的并行计算被从游戏中隐藏。游戏开发只需要知道一些硬件比另一些硬件性能更强,但是无需关系这些如何实现。早期的固定管线取得了辉煌的成果,使几十家显卡厂商采取各种方法提高性能、降低成本而不是陷入混乱的竞争中。它的图像不够漂亮,精度也不够高,但是已经足以在 2000 年初创建一个活跃的游戏市场。
在我讨论现代 Direct3D 的演变之前,我想强调几个早期 Direct3D 体系结构的重要思想对现代 GPU 的影响。在 1990 年的早期到中期,RAM 相对昂贵,这导致消费型显卡采用了需要 RAM 较少的技术。这个观点对我将来很多负面故事的(well-deserved)The Talisman 架构的影响很大。
Talisman 依赖各种图形学上的 tricks,尽可能的降低对显存的需求,并不是一种常规做法。为了创建一个面向大众的消费型显卡市场,Direct3D 团队受到了 Rendermorphics 创始人做出的一个艰难选择的严重影响。我们决定采用在 3D 上更通用更简单但是依赖更多显存的Z-buffer,来实现更好的显示效果。Rendermorphics 在使用了软件Z-buffer 的 Rendermorphics 引擎上实现了很好的 3D 性能,这给了我们信心去赌注,用一个更简单通用的 3D API 和驱动程序模型,并且相信硬件市场和 RAM 的价格会降下来。
但是请注意,我们在设计的 Direct3D 的时候,我们没有了解到微软研究院“秘密”的 Talisman 计划,他们也没有预计到一小群先行者,会设计了一个新的游戏 3D API 标准,并且在他们奇怪倡议被部署之前启动了它。总之这是一个巨大的赌注,Direct3D 为游戏开发者提供了简洁和优雅的Z-buffer,值得去冒这个险,消费型 3D 显卡市场在早期很难以合理的价位支持它。
尽管支持Z-buffer 是一个巨大的赌注,但是我们还是有两个架构上的问题需要解决。首先是 PC 总线一般很慢,第二是从显卡读取数据比写入数据到显卡慢的多。这通常意味着,我们的设计 API 需要尽可能紧凑封装数据发送给 GPU 的处理,和尽可能减少,将 GPU 处理完的数据复制回 CPU 处理。这通常意味着的 Direct3D API 进行了优化,数据打包和发送一次完成。当然这是一个不幸的约束,因为有很多华丽的 3D 效果,可以通过混合 CPU 高效的分支预测和 GPU 强大的浮点运算能力达到令人难以置信的并行渲染性能。
该约束正面作用之一是,它迫使 GPU 向更通用的方向发展,以补偿无法有效地与 CPU 共享数据。恰恰相反,Intel 可能希望控制总线速度的发展,因为其他协处理器越来越多的取代 CPU 在 PC 中的核心地位和功能,这对 Intel 是个威胁。有理由相信,Intel 故意限制了 PC 总线性能的提高,以防他们的 CPU 在多媒体应用市场上出现替代品。回想一下我以前的博客,推出 DirectX 的主要原因是防止 Intel 通过虚拟化支持所有 Windows 多媒体应用。如果 Intel 采用了可以使协处理器快速共享 RAM 的总线架构,那么 GPU 不大可能如今天这样支持丰富的分支预测和浮点计算。
为了克服 PC 总线性能的限制,大量技术投入到了用 CPU 压缩和简化发送到 GPU 的 DirectX 资源,以减少总线带宽的性能限制,和尽量减少需要从 GPU 返回 CPU 的操作。早期的固定 3D 管线在后来造成了有趣的后果,当我们开始探索通过互联网分发 3D 资源。
我们认识到早期支持压缩纹理,将极大提高总线性能和降低对显存的需求,问题是在一个没有标准 3D 纹理格式的年代,我不想过早的将一个微软指定强加给行业。为了克服这个问题,我们抱着没有标准格式的的想法前进。这个想法是我们提出的 DirectX 诸多专利的一个,我们提出一个 GPU 可以编码和解码不明格式的纹理,而 DirectX 的 API 将允许应用程序如同原始位图一样读取和写入纹理。Direct3D 驱动程序进行编码和解码,而应用程序没有必要知道驱动是如何工作的。
直到到 1998 年,显卡厂商开始为 DirectX6.0 制定高标准的 3D 纹理格式,我们将其中之一(S3)列入 Direct3D 许可。
http://www.microsoft.com/en-us/news/press/1998/mar98/s3pr.aspx
DirectX 6.0 是被列入发布版操作系统版本(Windows 98)的第一个版本。直到那时,DirectX 实际上只是一个内部库,被一个 Windows 游戏使用。直到第一个版本的之后的第 5 代,DirectX 才正是成为 Windows API。
DirectX7.0 是最后一代依靠在 DirectX2.0 时代就已经奠定基础的固定管线的 Direct3D API。这是 Direct3D 非常微妙的一个过渡期,有以下几个原因;
DirectX 8.0 是 Direct3D 一个迷人的标志性过渡版本,因为 Talisman 项目的失败和 OpenGL 支持战略的利益受损,许多 3D 开发人员从这 2 个项目加入到 Direct3D 的工作中来。这个结果是非常有趣的。现在回头看,我不会做出和他们一样的选择,但是回想起来,在我看来一切都以最佳方式在工作。
Direct3D 8.0 以几个有趣的方式影响了 20 世纪末的显卡市场。微软在很大程度上统一对 OpenGL 的结论,并且发现自己发展 Direct3D 要比 Kronos 的集团标准委员会推动的 OpenGL 要快。随着 SGI 死亡,OpenGL 标准的控制落到了那些希望标准允许创造差异化竞争和迫使微软支持他们想推动的 3D 特性的 3D 硬件 OEM 的手里。最后的结果是,Direct3D 和 OpenGL 变得更加复杂,他们在此期间趋于收敛。从 DirectX8.0 到 DirectX11.0,游戏开发商停止采纳新的 3D 特性。创建游戏引擎变得如此复杂,以至于市场上只剩下几家领先的引擎开发商,包括 Epic 的 Unreal Engine 和 id Software 公司的 Quake engine。
如果我一直在 Direct3D 工作,我会坚决抵制微软被 3D 显卡 OEM 厂商牵着鼻子追逐 OpenGL 的特性,而是专注于让游戏开发商有一致的品质和消费体验。我会反对引入 shader,保持尽可能垂直整合硬件厂商之间的功能,以确保符合 Direct3D 驱动程序层的支持。同样,我也强烈反对放弃支持 DirectDraw。3D 的家伙们失去了控制,并且认定采用 3D API 之后不会有人需要纯 2D 的 API,没有认识到简单的 2D API 满足了大量需求而且易于使用,毕竟大多数开发者不是天才,并不能轻松理解和使用 3D API。强制市场接受 3D API 造成了巨大的准入门槛。微软后来发现了这一错误,并且从新引入了 DirectDraw,也就是新的 Direct2D API。基本上 Direct3D 8.0 的天才设计让它辉煌,强大并且对普通开发人员没用。
在 DirectX 8.0 开始开发时,我正在创办我的第一家公司 WildTangent Inc,并且不再关注 DirectX3D 的进展。然而,几年之后我回到了梦想开始的地方,并且重新开始学习 3D,最新的 DirectX11.1。回过头看看这些很有趣,DirectX8 的主要设计做了哪些改变,导致了今天几乎难以理解的 Direct3D API。还记得 3 级流水线的 DirectX2,旋转,灯光和光栅化分为三个基本阶段?这里是一个现代的 DirectX 11.1 三维管线图。
是的,它增加到了9-13 级,其中包含一些可选项如 compute shader。作为一个拥有极其资深的背景并且非常低级别的 3D 图形编程人员,我不好意思承认我学习 Direct3D 11.1 学得非常的痛苦。Direct3D API 变得非常的不可理解和难以学习。我无法想象没有和我一样深厚的 3D 图形背景的人该如何开始入手学习现代可编程 3D 渲染管线。这条管线惊人的强大而且难以使用,但是极少数最聪明的人都在从事 3D 图形。在我赶上现代 Direct3D 的过程中,我发现我敬畏现代 GPU 的惊人力量,它们会发展到哪一步,同时震惊、厌恶 3D 管线已经发展到绝对的混乱。在过去的几年中,Direct3D API 已经成为 OEM 要求的 3D 特性倾销地。
如果我不是享受着长达十年参与 DirectX 的回报,毫无疑问,我会酸溜溜的写些什么乱七八糟的我的前辈创建了伟大而优雅的消费型 3D 图形显示的悠久历史。然而,古怪的是当时间定格到了现在,我必须承认,我不能确认但这毕竟是件坏事。PC 游戏市场的停滞,和微软与 OEM 推动 Direct3D API 的背后是 XBox 的成功。大量零散的 3D API 并不是个大问题,如果和游戏机一样,开发者只需要支持一种硬件配置。早期的 DirectX 8.0 支持 Shader Model 1.0 是第一代 Xbox 的图形 API 的基础。作为第一代 XBox 的选择,NVIDIA 芯片在 PC 3D 图形芯片市场拥有了巨大的优势。DirectX 9.0 和更先进的 Shader Model2.0,是 XBox360 的基础,微软重新选择了 ATI 设计 3D 芯片,AMD 这个时候在 PC 图形市场拥有了巨大优势。从某种意义上说 OEM 自己绞死了自己。通过成功影响微软和 OpenGL 标准组织采取高度错综复杂的图形管线,以支持他们所有特性,他们迫使自己去归纳他们的 GPU 架构,而显卡芯片市场会围绕一种架构合并… 无论微软为它的游戏机选哪个。
最终的结果是,PC 游戏的零售市场接近于死亡。这对于开发一个高产值的游戏来说,简直是个太太昂贵,太没有安全感,太不稳定的平台,除了 MMOG。微软和 OEM 的同谋毁掉了众所周知的摇钱树。这对微软来说没什么大不了的,因为微软很高兴通过 XBox 控制了 PC 游戏前端业务。
从很早的 DirectX 视觉的角度来看,我认为这个结果是一个愚蠢且短视的灾难。微软应该保持 DirectX 团队的纪律,把战略重心放在 Direct3D API,他们可以确保没有其他游戏机和 XBox 同一个时代,通过 XBox 加强 PC 游戏市场,而不是无意之中破坏它。虽然祝贺微软开发了首款美国产的成功的游戏机,但是我会计算如果微软保持一个有凝聚力的跨平台战略,从索尼,任天堂和移动平台所能获得的回报。我说这些是从过去的角度来看,因为今天,我不能肯定,我对所以的结果感到不满。
索尼和微软的新一代游戏机已经恢复到 PC 架构!下一代 GPU 将是大规模并行,与 CPU 共享私有缓存的通用处理器。事实上,GPU 架构变得如此通用,是因为在 DirectX 11 中加入了一个称为 DirectCompute 的新流水线阶段,允许 CPU 绕过整个 Direct3D 图形管线直接编程。随着 DirectCompute 的引入,简单的 3D 编程以一个意想不到的形式返回。现代 GPU 已经变得如此强大和灵活,直接采用 GPU 编程开发 3D 引擎是一个越来越实用和有吸引力的编程选择。从我的角度来看,我预计在短短数代的时间里,传统的 Direct3D 和 OpenGL API 将会消失,新的引擎将会亲睐与采用如 Nvidia 的 CUDA 和微软的 AMP 之类的独立的 shader 语言来编写更丰富,更多样化的特效。
今天,作为一个 3D 物理引擎开发者,我从来没有如此兴奋,因为现代 GPU 编程纯粹而强大,并且相对容易编程,而无需学习错综复杂的 Direct3D 和 OpenGL API 的 3D 管道。如果今天是我负责 Direct3D 的战略,我会主张抛弃传统的 3D 管线,快速转向丰富的 GPU 编程环境。我个人从来没有想过,我早期工作过的 Direct3D,在几十年中,促进演变出了一种新的无处不在的处理器,可以支持在 1980 年我所学到的那种令人难以置信的逼真的光照和物理模型,我从没想过电脑能强大到在我的职业生涯中出现实时渲染模型。
Direct3D API 的遗产: