Clayman的专栏

It's all about XNA & GPU Programming

孙凌峰ID:soilwork
187843次访问,排名376好友0人,关注者10
soilwork的文章
原创 85 篇
翻译 15 篇
转载 0 篇
评论 324 篇
clayman的公告
嘿嘿 ^o^....
最近评论
CYF:哈哈,楼上的楼上真搞笑。
在企业应用中,WEB是主流,也是趋势。
企业应用与图形完全是两个领域,不相干的东西,何必扯在一起?完全没可比性。。。。。。。
skbaker:应该整理一下,形成系列,方便查找。
文章对入门级用户帮助很大
kobeair:每当我要放弃的时候,我都会来你的博客,回到你写这篇帖子。学习的过程很枯燥并且现在学习的时间越来越少。但是看到这篇文章有种莫名的冲动,而且不断的问自己:“别人能做到!为什么我不行?”
lijunjun:做WEB的人最终是会后悔的.
老鬼菠萝:继续~~~
文章分类
收藏
    相册
    blogs
    David Weller
    nVidia Developer blog
    Rico Mariani
    Shawn Hargreaves
    XNA Team blog
    XNA资源
    XNA Creators Club
    ZBuffer
    Ziggyware XNA Resources
    中国XNA开发网
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 Direct3D 10系统(三) 收藏

    新一篇: 通用折射模拟 | 旧一篇: Direct3D 10系统(二)

    Direct3D 10系统(三)  

    作者:David Blythe
    本文版权归原作者所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
    由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。欢迎大家和我多多交流。
    翻译:clayman
    Blog:http://blog.csdn.net/soilwork

    4Shader Model 4.0

             在以前的Direct3D版本中,可编程管道阶段都是通过每个阶段独立的虚拟机来实现,i.e.,顶点和片断处理器。每个虚拟机都被描述为一个基于寄存器的冯.诺依曼式处理器(register-based Von Neumann-style),包含一组和汇编语言类似的指令,作为交互阶段之间的通信的输入和输出寄存器,通用寄存器(也称为临时寄存器),以及一组连接到纹理之类资源的资源绑定点。

             Direct3D 10定义了一个称为“公共核心(common core)”的虚拟机,作为每个编程阶段的基础,如图3所示。这个虚拟机保留了以前模型中的许多特性,比如基本的4 –tuple寄存器,以及浮点运算操作,此外,还增加了以下特性:

    l          32-bit的整数指令(数学运算,位运算以及转换);

    l          通用和索引寄存器将使用统一的内存池(4096 x 4);

    l          独立的不过滤或者过滤内存读取指令(加载和采样指令);

    l          不相关(decoupled)的纹理绑定点(128)和采样状态(16);

    l          支持阴影贴图采样;

    l          多层(16)常量(参数)缓冲(4096 x 4);

    以上几点,就是显卡功能的主要增加部分。这个统一的模型,能让GPU上各种算法,逻辑和流程控制指令更接近于CPU。寄存器,纹理绑定点以及指令储存空间都得到了显著的提升,将不会是未来几年,困扰开发者的问题。随着资源量的增长,为了不影响性能,硬件实现将发生一定的线性退化。

    很显然,随着纹理绑定点的增加, 并不需要增加相同数量的独特纹理过滤组合(unique texture filtering combinations)。相反,我们将减少采样阶段的耦合,用单独的对象和采样指令来指定纹理和对其进行采样的采样器。通过load指令,以非标准化寻址(non-normalized addresses)的方式,可以读取未经过滤的纹理。

    满足常量储存空间的增长和高效更新常量的需求,是一个挑战。当前系统的问题在于高效的更新单独的常量单元,以及管道化(pipelining)更新的操作两方面。当需要在多个shader程序之间转换时,这个问题会更加严重,每一次都需要重新加载与新shader相关的所有常量。其中,很明显的解决方案之一,就是以不同的频率来每次更新一个常量组(e.g 每帧一次,每个对象一次,每个对象实体一次)。这样,我们就能把常量储存空间分为独立的缓冲,同时,把更新常量与把常量绑定到管道的操作分离开。分离这些操作,允许(注:硬件)实现更好的完成两种操作的管道化。因为这些操作将等同于处理纹理资源,我们考虑过随纹理移除(remove)或统一(unifying)常量。

    但是,在许多重要方面,常量和纹理的引用方式是不同的。通常,常量的访问频率比纹理高的多,同时,对一组顶点或者像素来说,将使用相同索引。相反,纹理的访问频率则比较低,此外,索引值(纹理坐标值)也是不同的。这表示在实际的硬件实现中,处理常量和纹理的方式是截然不同的。

             还有一个不太明显,但对处理核心来说同样重要的地方,就是数据的呈现方式,算法精度,以及(注:数据)行为和以前的版本相比,都有更加严格的规范。因为大部分人都只把着色程序,常量以及其他管道阶段认为是应用程序艺术创作内容的一部分,而没有认识到他们是执行引擎(execution engine)的一部分。因此,为了保证这些内容在不同实现间的可移植性(portable)以及不同代系统间的兼容性,有很大压力。当然,这也反映出了可编程着色所取得的成功。

             我们尽可能的在所有地方都避免了使用自定义的行为,而遵守CPU标准。为了获得精确的行为,我们花了几年时间,转向IEEE-754[IEEE 1985]定义的单精度浮点数据呈现方式。对这一代的显卡来说,基本的运算操作(加,减,乘)都精确到1 ulp(而不是IEEE-754中定义的0.5ulp)。除法和平方根精确到2ulp。非规格化数将被近似为0 (Denormalized numbers are flushed to zero)(但是将被定义为float16类型的数据),并且完全实现了IEEE-754文档(NaNs,无限大)。部分差异是由于实现代价和实用性的考虑而产生的,在设计中,我们放在第一位考虑的是在不同硬件实现间创建良好定义的(well-defined)、一致的行为,其次才是在合理的硬件代价之下,提高精度。

             其中比较大的设计决定争议之一就在直接采用IEEE-754特定行为(special behavior)。在前一代(shader model 3.0)的系统中,我们就引入了这一行为,但对于那些依赖于把NaNs近似(flushed)为0的系统来说,带来了一些与可移植性相关的问题。虽然我们考虑了添加一个独特的模式来允许特定的抑制(suppression of specials),但最终我们决定:让未来所有的硬件都支持这个功能,虽然在很长一个时期内都将付出昂贵的维护代价,但能在短期减少shader开发的复杂性。

             这个严格的规范不仅限制了可编程单元,还将影响到过滤、光栅化,subpixel precision,数据转换,混合操作等各方面规则的定义。我们的目标有两个:对应用程序的开发者来说,保证行为的一致性和可预言性(predictability)。

             为了实现这些目标,需要仔细讨论关于NaN-propagation,算法优化或者内存操作,包括01的系数???等等(Pursuit of these objectives necessitated detailed discussions about NaN-propagation, optimizations of arithmetic or memory operations involving coefficients of 0 and 1, etc)。总的来说,我们尽量在对性能有重大优化的地方达成妥协。

     

    4.1 Stage-Specific Functionality

             每个独特的着色阶段可能会有一些独特功能,来扩展普通行为。这些特点包括输入和输出属性寄存器的结构差异,以及额外的指令。对VS来说,16x4浮点数据元素的输入和输出结构,定义了公共核心。

             GS可以读取上面这个值6倍数量的顶点,因为它不但必须读取一个三角形的所有顶点,还必须访问3个邻接顶点。由于GS可以输出一个以上的顶点或图元,它可以使用其它阶段的流模型:把值累积(accumulated)在输出寄存器,在程序结束时产生输出信号。我们添加了一条emit指令,作为把累积的结果输出给下一阶段的信号。同样,我们还增加了一条cut指令,作为一条图元带结束的标志。GS使用一条编译时配置指令(compile-time configuration directive)来指定最大输出量。每个输出的顶点都可以包含多达324 x float32的元素,作为RS的输入,并且接下来再作为PS的输入。这个值是vertex shader的两倍。这些额外的资源将把裁剪和剔除信息传递给RS,同时也可作为传递给PS的基于每个图元数据的额外信息。

             PS32x4个输入寄存器,但只能在GS处于激活(active)状态时才能完全使用它们。如果GS没有处于激活状态,那么PS只能使用来自于VS16x4个值作为输入。这些输入值将包含编译时的指令,用来指定对每种属性的赋值(插值)方式。PS的输出直接连接到8个渲染目标上,因此,它有8x4个输出寄存器,外加一个深度寄存器。PS添加用于丢弃像素的指令,避免把这些像素渲染到渲染目标上,此外还将添加计算图像空间(image-space)微分(derivatives)的指令。只有PS阶段包含内建(built-in)的屏幕空间概念,因此,即使VSPS都包含纹理采样的指令,但它们并不包含用来计算mipmap过滤的LOD指令,也不包含微分指令。当条件表达式在像素间发生变化时,在流程控制语句中的微分行为将会出问题(ill-defined)。因此,通过编译时的强制,不允许在非标准(non-uniform)流程控制中使用微分指令。

             最后一组支持数据交换的特性是为IARS之类的固定功能的阶段而设计的。举个例子,IA产生一组系统生成的值(system-generated values):顶点,实体,图元id,同时RS产生一个值用来指定某个多边形是正面还是背面。类似的,RS接受来自于shader的系统插值数据(system interpreted values),比如图元中每个位置的纹理坐标,剪切和剔出距离,以及渲染目标数组索引。系统生成的值,声明为相应的系统生成名称(system-generated name)之后,作为可编程阶段的输入数据。相反,系统插值数据是通过在可编程阶段把输出数据定义为相应的系统插值值的名称(name of the system-interpreted value)来生成。这些值可能会在shader所用的众多输入输出寄存器中产生不利影响,因此某些情况下必须对它们进行定义,否侧将返回错误结果(e.g. RS需要从各种属性中分辨出位置信息)。共享其他类型的寄存器用来输入和输出保证了整体构架更加规则,同时避免浪费资源,

             虽然在可编程阶段中创建一种机制来管理固定功能阶段(e.g. 混合模式,depth or stencil configurations)是很有吸引力的,但当前,我们我们只允在对一定阶段进行这些操作。

    发表于 @ 2006年07月21日 16:33:00|评论(loading...)|编辑

    新一篇: 通用折射模拟 | 旧一篇: Direct3D 10系统(二)

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © clayman