去年我写过两篇博文《在程序中掌控NVIDIA Optimus》和《在程序中掌控NVIDIA Optimus后续》,讲解了如何利用NV提供的导出NvOptimusEnablement的方法,在程序里切换到独立显卡。然后,当我升级到Win 8.1后,发现Optimus有了一些变化。
右键菜单中没有了选择用哪个显卡启动的选项。
不管NvOptimusEnablement设置成什么值,只要导出了NvOptimusEnablement,D3D程序都会用独立显卡来执行。
程序中获取显卡名字的话,能正确地返回NV独立显卡的名字,而不是一味返回Intel集成显卡的名字。
原先我以为是显卡驱动没装好,装了最新的Intel驱动和NV驱动之后,情况照旧。会不会是Win8.1的新功能?查了WDDM 1.3的新特性后,发现还确实是这样的 ...
前一阵子在把KlayGE的OpenGLES插件升级到OpenGL ES 3的过程中,原先还满怀希望地觉得GLES3总该全面支持浮点纹理的读写了,结果发现GLES3的标准支持float16和float32的读取,但不支持渲染到float16/float32的纹理上。只有支持GL_EXT_color_buffer_float或GL_EXT_color_buffer_half_float扩展的硬件,比如Tegra 4和Adreno 3xx才能很好地支持。所以,在其他设备上如果要渲染到浮点纹理,就得另想办法了。
编码和解码
单通道的float是32-bit,RGBA8也是,所以按说把float编码到RGBA8的纹理中应该没啥问题。很可惜的是,不支持浮点纹理的硬件往往也不支持整数指令和位运算操作。所以在这里需要有些限制。在网上搜了一下,最靠谱的应该是大牛Aras ...
网上看到的GPU比较,都是桌面和桌面比,移动和移动比。很多人对此没有概念,总觉得移动的CPU/GPU在性能上也能比肩桌面CPU/GPU。那么就让我们来看看把各家的顶级GPU放在一起比硬指标,是什么样的结果吧。资料来自wikipedia和厂商自家宣传。
计算单元对比
Model
Fab (nm)
Core
Clock rate
API
Core (MHz)
Memory (MHz)
NVIDIA GeForce GTX Titan
28
2688
836-993
6008
D3D 11.0, OpenGL 4.4, CUDA 5.5, OpenCL 1.2
NVIDIA Quadro K6000
28
2880
901.5
6008
D3D 11.0, OpenGL 4.4, CUDA 5.5, OpenCL 1.2
AMD Fusion APU 8670D
32
384
844-950
1066
D3D 11.0, OpenGL 4.3, OpenCL 1.2
AMD ...
上一篇提到了PSSM的方法,及其它的两个缺点。I3D2011上的Sample Distribution Shadow Maps可以用很低的代价同时解决掉那些缺点,在最大程度上优化shadow map上sample的分布。
SDSM
PSSM的那两个缺点实际上都来自于同一个根源:光锥区域是根据视锥的大小,而不是可见pixel的范围来调整。这里所说的pixel范围涉及到两个方面。第一是pixel在view space的深度范围,这会影响区域的划分。另一个是pixel投影到light space的坐标范围,这影响到scale和bias的计算。很显然最佳情况是,shadow map的sample分布在所有可见pixel上,其他地方不浪费。而这两个方面都可以很简单地通过场景的depth texture得到。
原论文提到了多种sample distribution ...
大家一定很熟悉大场景的阴影渲染容易出现的锯齿问题,我这里就不废话了。这个问题常用的解决方式是Cascaded Shadow Map(CSM),用一系列同样大小的shadow map,每个管视锥的一个范围。现在大部分引擎也都支持CSM,各种资料也很齐全,所以我这里不详细阐述原理了。想了解细节的可以看原论文,或者GPU Gems 3的文章。
CSM还是PSSM
一个常见的疑问是为什么有的叫它CSM,有的叫他PSSM(Parallel-Split Shadow Map)。实际上原论文是把它叫做PSSM,工业界实现的时候选择了个更广泛的名字CSM。从名字本身来说,只要是一系列层级关系的shadow map,就能叫CSM,而只有平行切分视锥的才叫做PSSM。换句话说,CSM是个种类,PSSM是具体方法。
PSSM
...
Normal map已经在实时应用中被广泛使用了,但长期以来一直有个缺陷:无法很好地做mipmap。所以在一定的视角和距离下,会出现明显的aliasing现象。在非实时渲染中,因为sampling rate很高,对于一个pixel,积分发生在计算完shading之后,也就是
[latex]spec = \sum {\left (\frac {N_{i} \cdot H}{|N_{i}|} \right )^\alpha}[/latex]
而实时渲染的sampling rate极其有限,一般只有1,积分是在建立mipmap的时候对normal做的,shading用的是积分后的normal:
[latex]spec = \left (\frac {(\sum {N_{i}}) \cdot H}{|\sum {N_{i}}|} \right )^\alpha[/latex]
很显然这两个不等价,造成了aliasing。
LEAN Mapping
I3D 2010的LEAN Mapping ...
上次实现的是Per-pixel Linked Lists方法,能做到高效地在单pass内剥离多层物体,但内存消耗不可控,而且性能和每个pixel的fragment list长度很有关系。HPG 2011上intel有个改进的方法,称为Adaptive Transparency(AT),号称能在可控的内存内做到稳定的性能和高质量的OIT。于是我打算实现一下这个方法。
方法描述
AT首先从alpha blending的方程本身下手。Alpha blending需要一个迭代的过程:
[latex]C_{n} = \alpha_{n} C_{n}+(1-\alpha_{n}) C_{n-1}[/latex]
透明渲染需要按照顺序,也就是因为这个迭代所致。AT引入了一个可见性函数
[latex]vis(z) = \prod_{0<z_{i}<z}(1-\alpha_{i})[/latex]
于是alpha blending方程就能重构 ...
2009年AMD在发布HD 5800的时候也发布了一个Order Independent Transparency(OIT)的demo,但只有介绍,没有多少可以参考的东西。GDC 2010上的OIT and GI using DX11 linked lists才给出了比较完整的算法细节。虽说这几年也有不少新的OIT算法出现,但作为具有标杆意义的OIT算法,Per-Pixel Linked Lists还是值得实现到KlayGE的开发版本中,以做对比。
算法
顾名思义,Per-Pixel Linked Lists的意思就是每个pixel上一个链表,存放属于该pixel的所有fragment。这种不均匀的数据结构对GPU来说是很要命的。
在Per-Pixel Linked Lists中,链表需要两个额外的buffer,一个称为fragments buffer,需要是屏幕尺寸的N倍,负责存放所有的fragment ...
Surface的GPU是Tegra3,但它对应的D3D能力,在网上却很难查到。昨天我自己在Surface上执行了一下Windows Kits 8带的ARM版dxcapsviewer,dump出了这个文件。我已经去掉了Microsoft Basic Renderer Driver和WARP这两个和PC上相同的部分,就剩下Tegra3本身的。
从这个列表可以看出,Surface只能支持D3D_FEATURE_LEVEL_9_1。估计是因为Tegra3不支持完整的occlusion query,以及最大纹理只支持到了2048,必须放弃9_2和9_3。很可惜的是MRT的功能也因此被禁用了。
FFT镜头效果已经完成,并集成入KlayGE开发版中,命名为FFTLensEffectPostProcess。除此之外,还写了一个命令行工具,用于产生镜头效果的纹理。虽然FFT的方法能在一个pass内产生各种复杂的镜头效果,但目前性能低于默认的多重gaussian blur。其中最主要的开销来自于FFT本身,下面就着重就讨论一下GPU FFT的进展和未来。
前不久我在用Pixel Shader实现FFT的时候,提到了用Compute Shader来实现FFT效率可以更高。之前Ocean的例子里就有用于实现波浪模拟的CS4 FFT(从NV的例子改进而成),它的输入和输出是1D Buffer的形式。为了更通用,在进入KlayGE核心的时候改成了2D Texture的形式。可惜的是,CS4不能写入纹理,就需要增加一个把Buffer转 ...