Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 游戏天堂 > 游戏开发 > 在Pixel Shader 3.0中使用动态流控制(Dynamic Flow Control)
【标  题】:在Pixel Shader 3.0中使用动态流控制(Dynamic Flow Control)
【关键字】:Pixel,Shader,3.0,Dynamic,Flow,Control
【来  源】:http://blog.csdn.net/cywater2000/archive/2007/01/27/1495655.aspx

在Pixel Shader 3.0中使用动态流控制(Dynamic Flow Control)

Your Ad Here

Pixel Shader 3.0中使用动态流控制(Dynamic Flow Control)

 

作者:cywater2000

日期:2007-1-27

来自:http://blog.csdn.net/cywater2000

 

 

前段时间需要用到pixel shader 3.0 (以下简称ps3)的动态流控制特性。结果郁闷地发现ps3还是像ps2.x那样把分支与循环给展开了。百思不得其解!

于是google之,在GameDev上发现了一些线索。再后来,终于在DirectX Documentation找到了真正的答案。

原来一切都是梯度惹的祸!

DX文档的“Flow Control Limitations”中,下面有一段介绍“Interaction of Per-Pixel Flow Control With Screen Gradients”。大意是说很多ps指令(主要是与纹理采样有关)需要用到屏幕梯度信息(比如计算LOD),而计算梯度需要相邻象素的信息(▽p=(δp/δx, δp/δy)),如果使用动态分支则会影响到硬件计算这些梯度信息。因此如果要在动态分支中使用带梯度信息的指令,则必须满足一定的条件。原文讲得很详细,我就不重复了。

 

下面举例说明:

void test(float2       coords   : TEXCOORD0,

       out float4      newColor : COLOR)

      

{

float j = tex2D(s0, coords).x;

while(j != 100)

{

coords += float2(1, 1) / 256;

  j += tex2D(s0, coords).x;

}

 

newColor = j;

}

使用fxc.exe /Od /Zi /T ps_3_0 /E test /Fc test.txt test.fx编译一下看看有什么效果?error X3511: loop does not appear to terminate in a timely manner (1024 iterations)

 

好吧,让我们告诉微软的编译器只需要循环2次即可(听说新版编译器fxc10解决了这个bug,但是还是展开的)

void test(float2       coords   : TEXCOORD0,

       out float4      newColor : COLOR)

      

{

float j = tex2D(s0, coords).x;

int i = 0;

while(j != 100 && i++ < 2)

{

coords += float2(1, 1) / 256;

     j += tex2D(s0, coords).x;

}

newColor = j;

}

       再编译一下看看会生成什么?

    ps_3_0

    def c0, -100, 0, 1, 0.00390625

    dcl_texcoord v0.xy  // coords<0,1>

    dcl_2d s0

 

    texld r5, v0, s0

    mov r2.z, r5.x  // j<0>

 

    add r12.w, r2.z, c0.x

    mov r11.w, -r12.w

    mov r13.w, -r11.w

    add r10.w, r12.w, r13.w

    cmp r8.w, r10.w, r12.w, r11.w

    mov r8.w, -r8.w

    add r9.w, r8.w, r8.w

    cmp r7.w, r9.w, c0.y, c0.z

    mul r6.w, r7.w, c0.z

    mul r7.w, r6.w, c0.z

    add r8.xy, v0, c0.w

    mov r8.xy, r8  // coords<0,1>

    texld r4, r8, s0

    add r8.z, r2.z, r4.x  // j<0>

 

    mov r9.xyz, -r7.w

    mov r2.xy, v0

    cmp r6.xyz, r9, r2, r8  // coords<0,1>, j<0>

    mov r8.xy, r8  // coords<0,1>

    texld r3, r8, s0

    add r5.w, r2.z, r3.x  // j<0>

 

    add r2.w, r5.w, c0.x

    mov r3.w, -r2.w

    mov r4.w, -r3.w

    add r1.w, r2.w, r4.w

    cmp r0.w, r1.w, r2.w, r3.w

    mov r0.w, -r0.w

    add r15.w, r0.w, r0.w

    cmp r14.w, r15.w, c0.y, c0.z

    mul r13.w, r14.w, c0.z

    mul r11.w, r7.w, r13.w

    add r10.xy, r6, c0.w  // coords<0,1>

    texld r1, r10, s0

    add r12.w, r6.z, r1.x  // j<0>

 

    mov r11.w, -r11.w

    cmp r0, r11.w, r6.z, r12.w  // j<0,0,0,0>

 

    mov oC0, r0  // newColor<0,1,2,3>

// approximately 38 instruction slots used (4 texture, 34 arithmetic)

 

What the heck! 你给我展开做什么?!~~~~~

 

原来是因为tex2D对应的指令是texld,后者是要用到梯度信息的。咋办?

看看DX的文档,上面说想要在动态分支中使用这些指令,就必须由用户自己提供相关的信息。比如使用texldl,就由用户提供LOD信息。

好,让我们改一下代码:

void test(float2       coords   : TEXCOORD0,

       out float4      newColor : COLOR)

      

{

float j = tex2D(s0, coords).x;

while(j != 100)

{

     coords += float2(1, 1) / 256;

     j += tex2Dlod( s0, float4(coords,0,0) ).x;

}

newColor = j;

}

 会发生什么事?

ps_3_0

    def c0, 0, -100, 0.00390625, 0

    defi i0, 255, 0, 0, 0

    dcl_texcoord v0.xy  // coords<0,1>

    dcl_2d s0

 

    texld r8, v0, s0

    mov r7.w, r8.x  // j<0>

    mov r2.w, v0.x  // coords<0>

    mov r1.w, v0.y  // coords<1>

    mov r0.w, r7.w  // j<0>

    rep i0

 

      add r12.w, r0.w, c0.y

      mov r13.w, -r12.w

      mov r14.w, -r13.w

      add r11.w, r12.w, r14.w

      cmp r10.w, r11.w, r12.w, r13.w

      mov r9.w, -r10.w

      if_ge r9.w, r10.w

        mov r4.w, r1.w

        break

      endif

      mov r1.x, r2.w

      add r5.yw, r1.xwzx, c0.z  // coords<1,0>

      mov r5.xz, c0.w

      texldl r6, r5.wyzx, s0

      add r0.w, r0.w, r6.x  // j<0>

      mov r4.w, r5.y

      mov r2.w, r5.w

      mov r1.w, r4.w

    endrep

    mov r3, r0.w  // j<0,0,0,0>

 

    mov oC0, r3  // newColor<0,1,2,3>

// approximately 27 instruction slots used (2 texture, 25 arithmetic)

 

终于看到rep, if, break! ~~~~~

 

高兴之余提醒一下:tex2Dlod需要提供LOD信息(在纹理坐标的第4个分量中),我这里只是简单地设定为0。如果你的纹理没有创建LOD层级,当然没问题,否则你必须要手动计算LOD

另外,关于其他一些ps指令(比如texld, texldb, texldp)的限制用法请参考DX文档Interaction of Per-Pixel Flow Control With Screen Gradients”。

 

好了,让我们利用动态分支开始写更复杂的pixel shader程序吧! 

 
在PB中实现一个类似于Word打印对话框:【上一篇】
NotePad完整源代码:【下一篇】
【相关文章】
  • The Windows Driver Developer's Digest Numeric Overflows in Complex IOCTL Handlers
  • 跟我一起学Windows Workflow Foundation(4)-----使用Listen,Delay,和其他envnt-based定制活动
  • Controlling Hardware with ioctls
  • Asp.net完美日历控件,支持FireFox,IE7(AjaxControlToolKit.Calendar)中文版
  • 细数Ajax Control Toolkit 1.0 正式版32个服务器端控件
  • BOOST 1.33.0 Regex
  • WSS3.0入门第二天
  • Microsoft Visual C++ 6.0 SP6 resource compiler buffer overflow
  • MS07-004 VML integer overflow exploit
  • WSS3.0入门第一天
  • 【随机文章】
  • [转载]操作系统学习常见疑惑问与答(不断添加中...)
  • NTP客户端时间同步的脚本
  • J2ME移动开发环境配置详细教程
  • ESFramework使用技巧(1)-- ESFramework 日志记录器的自动装配
  • Java中处理日期的类
  • 关于我们的BEIYU
  • 今天真的很Perfect
  • 恋爱一族约会词汇
  • WEB权限管理利器——HooPoWer
  • 安全七招之隐藏硬盘
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.