上文介绍了D3D11的两个重要特性compute shader和multi-threaded,本篇专注于两个不能在D3D10硬件上使用的、纯D3D11的新特性tessellation和BC6H/BC7纹理压缩。
Tessellation
很 多人会说D3D11增加了tessellation shader这个stage,但真相是增加了hull shader、tessellator和domain shader三个stage。Hull shader的输入是patch的控制点(三角形、四边形这样的图元,最多有32个控制点),计算出tessellation等级、确定 tessellation的方法等。它的输出被送给固定单元的tessellation进行细分。Domain shader的输入是细分后的bary centric坐标、来自hull shader的控制点,它负责计算插值后的顶点坐标。
Tessellation早就存在于一些GPU。 D3D9的API中其实就正式存在一些使用patch的能力。比如NVIDIA的Geforce 2就支持PN-Patch,但在Forceware 29.xx之后(如果我没记错的话)就因为效率和使用率问题而禁用了。后来ATI设计的XBox360的GPU里面就有个不可编程的 tessellator,这个架构一直延续到Radeon HD 5000系列为止。和D3D11不同的是,这个tessellator位于VS之前,而不是VS之后。这么做的好处是流水线变简单了,由VS完成DS的功 能即可。但缺点也很明显——性能会受到严重影响:
- tessellation等级必须在另一个pass计算
- 本来应该在per vertex上做的事情(比如乘上wvp)变成要在细分插值后的顶点上作,显著地增加了计算量;要么就还要一个pass来做这件事情
所以D3D11用这种设计对性能提升很有帮助的。
NVIDIA Direct3D SDK 11里特别提供了一个名为Tessellation Pattern Viewer的工具,用来查看在不同参数下,三角形和四边形被tessellate后的拓扑。
BC6H/BC7
D3D11 增加了BC6H和BC7两种纹理压缩格式,分别擅长HDR压缩和高质量LDR压缩,都能达到8bpp。BC6H和BC7的原理类似,但比原先的BC1-5 复杂了非常多。所以压缩的运算量也大了巨多。比如512×512的原始图片,用D3DX里面提供的BC6H或BC7压缩,需要10分钟左右。解决方法是用 DX SDK提供的BC6HBC7EncoderDecoder11这个例子来进行GPU加速压缩,只要几秒钟即可。更新的版本可以从这里下载到。
下图是用BC6H来压缩一张HDR图片的结果。左边是原图(给定曝光度),中间是误差绝对值,右边是压缩后的图。
下图是一个BC3(也就是DXT5)和BC7的压缩误差比较。左边是原图,中间是误差绝对值,右边是压缩后的图。很明显可以看出,BC7的误差远小于BC3,尤其是在边界的地方。
介绍了这些D3D11的“基本”概念后,本系列就此打住。希望能给对D3D11一知半解的人有所帮助。