Apple Silicon TBDR:应用开发者实际能获得什么
Apple silicon GPU的渲染方式与其他GPU不同。Apple的Metal文档明确给出了这种架构的名称:”Apple silicon中的GPU实现了一种称为基于图块的延迟渲染(TBDR)的渲染技术,可优化性能与功耗效率。”1 TBDR的形态正是Metal 4 API、设备端ML堆栈以及imageblock-and-tile-shader编程模型之所以如此设计的原因。
下文将逐一介绍TBDR所支持的四项Apple文档化特性,以及每一项为应用带来的价值:imageblock、tile shader、光栅顺序组,以及增强的多重采样抗锯齿实现。此前关于Metal 4 essentials的文章已经覆盖了核心API层面;本文聚焦于该层所面向的GPU基底。
TL;DR
- TBDR将渲染目标拆分为图块,在多个独立GPU核心上并行运行,并将着色推迟到每个图块的所有几何体被评估之后。1
- 图块内存的带宽比设备内存快许多倍,延迟低许多倍,能耗也显著更低。1
- A11及之后的Apple GPU新增了imageblock、tile shading、光栅顺序组以及imageblock采样覆盖控制。应用通过Metal即可访问全部能力。1
- Imageblock允许应用在图块内存中定义自定义的逐像素数据结构,在多个绘制与调度之间持久保留数据,并在单个pass中混合渲染与计算工作。1
- 光栅顺序组同步指向同一像素的fragment线程,消除了破坏顺序相关混合的读-改-写竞争。1
TBDR究竟是什么
Apple的原文表述:”GPU将渲染目标分解为由更小区域组成的网格,称为图块。它使用其GPU核心之一来处理每个图块,并经常同时运行多个核心。GPU会推迟,或者说延后,每个图块的渲染阶段,直到它评估完该图块的所有几何体。”1
与立即模式(IM)GPU的对比同样来自Apple:”IM GPU会完整处理图元,例如线和三角形,无论它们在渲染中是否可见。”1 TBDR通过先收集图块内的所有几何体、再仅对通过遮挡测试的部分进行着色,从而避免了这类工作。Apple直接道出了收益所在:”TBDR GPU通过同时处理一个渲染pass的所有几何体并仅着色可见图元,避免了不必要的工作。”1
图块内存正是回报所在。Apple描述了它相对于设备内存的优势:1
- “带宽比设备内存快许多倍”
- “访问延迟比设备内存低许多倍”
- “能耗显著低于访问设备内存”
两个渲染pass也可以在硬件上重叠执行。Apple指出:”当GPU运行某个渲染pass的最终阶段并写入图块内存时,它可以同时启动未来某个渲染pass的顶点阶段。GPU可以通过并行运行这两个阶段同时使用更多硬件块,因为它们倾向于使用不同的计算和内存组件。”1
这就是基底。下文一切都建立在它之上。
Imageblock:图块内存中的自定义逐像素数据
Apple对imageblock的定义:”Imageblock是存储在本地内存中的结构化图像数据图块,让您能够在Apple GPU可以高效操作的图块内存中描述图像数据。”1 它们是具有宽度、高度和像素深度的二维数据结构,并且”imageblock中的每个像素可以由多个分量组成,您可以将每个分量作为其自身的图像切片来寻址”。1 Apple的示例:一个imageblock可以容纳三个图像切片,分别对应albedo、specular和normal分量。
Apple文档化的形态:1
- 可同时供kernel函数和fragment函数使用。
- 在图块的生命周期内持久存在,跨多个绘制与调度。
- 现有的渲染代码会自动创建与渲染附件格式匹配的imageblock。
- 应用可以在着色器中定义带有附加通道、数组和嵌套结构的自定义imageblock。
- Fragment着色器只能看到该fragment位置上的imageblock数据;compute函数线程则可以访问整个imageblock。
跨绘制与调度的持久性正是从运维角度最值得关注的部分。Apple的表述:”Imageblock的持久性意味着您可以在单个渲染pass中通过tile shader混合渲染与计算操作,二者都可以访问同一块本地内存。通过将多个操作保留在一个图块内,您可以创建保留在本地GPU内存中的复杂算法。”1
对于发布多阶段渲染管线(延迟着色、屏幕空间效果、自定义混合)的应用而言,将中间结果保留在图块内存中而不是往返于设备内存,正是TBDR所归还的每帧预算。
Tile Shader:渲染与计算,同一个pass
Apple对tile shader的表述:”Tile shader是作为渲染pass一部分执行的compute或fragment函数。它们允许您的应用计算并将数据保存到图块内存中,这些数据在多个渲染pass之间在GPU上持久存在。”1
传统的GPU模型正是tile shader所规避的。Apple原文:”传统GPU将渲染和计算命令分离到不同的pass中。这些pass通常无法直接互相通信。应用通过将一个pass的结果保存到设备内存,然后再为下一个pass加载该数据来绕过这一限制。在某些场景中,例如在多阶段渲染算法里,应用可能会多次将中间数据复制到设备内存。”1
Tile shader将这部分中间数据移入图块内存。Apple文档化的收益:”使用tile shader的应用可以避免将中间结果存储到设备内存,并通过将数据存储在更快的图块内存中来节省时间。”1
对于Metal 4应用而言,tile shader与统一的MTL4ComputeCommandEncoder设计相互配合,相关内容已在Metal 4 essentials post中介绍。编码器统一与tile-shader编程模型,正是同一项架构决策在两个层面的体现:折叠传统GPU上存在的渲染-计算边界,因为Apple GPU硬件并不需要这些边界。
光栅顺序组:为并发fragment线程排序
光栅顺序组所要解决的问题,用Apple的话说:”Metal保证GPU按绘制调用顺序进行混合,给人一种GPU顺序渲染场景的错觉。……每个三角形的fragment着色器都在其各自的线程上并发运行。后方三角形的fragment着色器可能不会在前方三角形的fragment着色器之前执行,这对于需要从另一个三角形着色器获取结果以进行自定义混合的着色器而言可能是一个问题。由于并发的存在,这种读-改-写序列可能产生竞争条件。”1
机制:”光栅顺序组通过同步针对相同像素坐标和采样(如果您启用逐采样着色)的线程来克服这种访问冲突。”1
实现层面:”要实现光栅顺序组,请使用属性限定符注解指向内存的指针。通过这些指针访问像素的着色器将按逐像素提交顺序执行。硬件会等待与当前线程重叠的任何更早的fragment着色器线程完成,然后才让当前线程继续执行。”1
近期的Apple GPU扩展了这一机制。Apple原文:”近期Apple GPU上的Metal为光栅顺序组扩展了额外能力。它们允许您同步imageblock的各个通道以及threadgroup内存。您还可以创建多个顺序组,从而获得更细粒度的同步并最大限度减少线程等待访问的次数。”1
Apple给出的实战示例是延迟着色。传统的两阶段方法将多个纹理组成的g-buffer写入设备内存,然后在光照阶段将其读回。Apple的表述:”您可以通过使用多个顺序组将两个渲染阶段合并为一个,从而消除对中间纹理的需求。要做到这一点,请将几何缓冲保留为图块大小的块,使其能够留在本地imageblock内存中。”1
Apple建议的拆分方式:1
- 第一个顺序组:三个g-buffer字段(albedo、normal、depth)。
- 第二个顺序组:累积的光照结果。
- “Apple GPU可以分别对两个组进行排序,使得对第二个组的未完成写入不会阻碍对第一个组的读取。”1
两个线程在执行末尾仍会同步以累积光照。收益在于不冲突的读取可以并发而非串行运行。
跟踪每个像素唯一采样的MSAA
Apple在A11+ GPU上文档化的MSAA实现与教科书描述并不相同。Apple的表述:”硬件会跟踪每个像素是否包含图元的边缘,因此仅在必要时运行逐采样混合。如果另一个图元覆盖了像素内的采样,GPU只需为整个像素混合一次。”1
Apple的示例展示了这一优化。一个被两条重叠三角形边覆盖的像素,在四个采样位置上有三种不同的颜色。Apple原文:”A11之前的Apple GPU会对该像素的三个被覆盖采样分别进行混合。从A11开始,Apple GPU只混合两次,因为有两个采样共享相同的颜色。”1
颜色缩减还更进一步。Apple:”Apple GPU可以减少像素内唯一颜色的数量。例如,如果GPU在更早的三角形之上渲染了一个不透明三角形,它会用单一颜色来表示该像素。”1
应用可以通过tile shader扩展该实现。Apple文档化的用例:”您可以通过在tile shader中修改采样覆盖数据来实现自定义解析算法。例如,考虑一个包含不透明几何体和半透明几何体独立渲染阶段的复杂场景。您可以添加一个tile shader,在混合半透明几何体之前解析不透明几何体的采样数据。”1
该tile shader在本地内存中的数据上运行,并且可以作为不透明几何体阶段的一部分,将解析保留在图块内存中,而不是绕道一个独立的pass。
这对应用架构意味着什么
从Apple文档化的层面,可以得出三个要点。
-
图块内存就是预算。 上述四项特性(imageblock、tile shader、光栅顺序组、采样覆盖)的存在都是为了让工作留在图块内存中、远离设备内存。Apple文档化的数据:带宽比设备内存快许多倍,延迟低许多倍,能耗显著更低。1 尊重这一预算的应用架构,运行起来比不尊重的更快、更凉。
-
渲染与计算并非两个不同的世界。 Apple GPU不像传统GPU那样将渲染与计算分割为不同的pass。Imageblock持久性和tile shader让应用可以在单个渲染pass内运行多阶段算法。Metal 4统一计算编码器是同一架构事实在API层级的体现。
-
并发是默认;排序需要主动选择。 光栅顺序组是应用表达”这一读-改-写序列依赖顺序”的方式。默认就是无序并发,这是GPU天然的形态。需要为混合、透明或g-buffer写入采用有序访问的应用,则对特定的指针进行注解,让硬件来安排线程顺序。
完整的Apple Ecosystem系列:面向该硬件的并行API层——Metal 4 core API;在同一硅片上运行ML的框架——Foundation Models on-device LLM;更广泛的ML堆栈——Core ML on-device inference。中心枢纽位于Apple Ecosystem Series。
FAQ
TBDR是Metal 4特有的吗?
不是。Apple silicon GPU已经在多代GPU中实现了TBDR;Metal 4只是面向它们的全新核心API层。本文记录的TBDR特性(imageblock、tile shader、光栅顺序组、A11+采样覆盖控制)通过Metal在原始的MTL前缀API与MTL4前缀的Metal 4类型上均可使用。1
Imageblock与threadgroup内存有什么区别?
Apple文档化的区分:”Threadgroup内存适用于非结构化数据,而imageblock更适合图像数据。”1 Imageblock承载具有宽度、高度、像素深度以及命名逐像素分量的二维结构;threadgroup内存则是扁平的分配。需要带可寻址切片的结构化图像数据的应用使用imageblock;需要为compute kernel提供暂存缓冲的应用使用threadgroup内存。
既然Metal已经保证按绘制调用顺序混合,为什么还需要光栅顺序组?
Metal保证的是顺序混合的表象,但GPU实际上并发地运行fragment着色器。Apple的表述:当一个着色器要针对另一个三角形的结果做自定义混合时,会遇到竞争条件,因为两个线程实际上并不是顺序执行的。光栅顺序组是只同步针对同一像素的线程的机制,其余部分仍保持并发。1
我什么时候应该编写自己的MSAA解析算法?
Apple文档化了一个具体场景:一个包含不透明几何体和半透明几何体独立阶段的场景,其中解析在不透明阶段之后、半透明混合之前运行。1 对于大多数应用而言,硬件内置的MSAA实现已经能处理这项工作;自定义解析是为Apple文档所描述的特定边缘场景准备的工具。
Apple的MSAA优化是如何节省工作的?
Apple的硬件会在渲染新图元时跟踪每个像素中唯一采样的数量。Apple的示例:一个被两条三角形边覆盖的像素在四个采样位置上有三种不同的颜色;A11+ GPU混合两次而非三次,因为两个采样共享一种颜色,而稍后一个不透明三角形又会将该像素降回单一颜色。1 该优化在硬件层面运行;应用无需API层面的改动即可获得。
除了TBDR页面以外,Apple GPU架构是否还有其他文档?
Apple在Metal文档中的”Apple silicon”主题链接到了支撑本文的TBDR页面。Apple的WWDC关于Metal的session也覆盖了GPU架构细节,Metal Shading Language Specification则覆盖了着色器层面的接口。Apple尚未在开发者文档中发布给定Apple GPU代际的底层硅片细节(cluster数量、ALU宽度、光栅引擎细节);任何来自developer.apple.com之外的此类数字都应视为未经验证。
References
-
Apple Developer, “Tailor your apps for Apple GPUs and tile-based deferred rendering”. The TBDR architecture, A11+ enhancements (imageblocks, tile shaders, raster order groups, imageblock sample coverage control), tile memory characteristics, deferred shading worked example, MSAA optimization. Retrieved 2026-05-04. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩