0

我有一些程序来绘制具有深度的扫描线 - 它将 xs 作为 ax start xk 作为 ax end,y 和 zs 作为 xs 处的 z-depth 和 zk 作为 zk 中的 z-depth(z 值将线性形式 xs 更改为 xk) Float ram 中的 deptht 缓冲区用于深度测试

这里是

    inline void drawScanlineWithDepth(int y, int xs, int xk, float zs, float zk, unsigned color)
   {
    if(y<0)         return;       //clip
    if(y>=CLIENT_Y) return;       //

    if(xs>xk)  // swap to assure xs is on left xk at right
     {
      int temp = xs; xs=xk; xk=temp;
      float tempp = zs; zs=zk; zk=tempp;
    }


    if(xs<0)     //cut left end to 0
    {

      if(xk<0) return;

      float dod_zs = (-xs)*float(zk-zs)/float(xk-xs);
      zs += dod_zs;

      xs=0;
   }


     if(xk>=CLIENT_X)  //cut right end to CLIENT_X-1
    {
      if(xs>=CLIENT_X) return;

     float sub_zk = (xk-(CLIENT_X-1))*float(zk-zs)/float(xk-xs);
     zk -= sub_zk;

     xk = CLIENT_X-1;

    }


    int len = xk-xs;
    int yc = CLIENT_Y-y-1; //reverse y coordinate becouse blitter reverses it

    int adr_        =   yc*CLIENT_X + xs;
    int adr_depth  =  ( yc<<12 ) +   xs;    // depth[] is a static table with 4096 width 

    float*     db =  ((float*) depth) + adr_depth;
    unsigned* adr = ((unsigned*)pBits) + adr_; 

   if(len<=3) //unwind short scanlines
   {


     if(len==0)
     {
      if(zs< *db) *db = zs, *adr = color;
      return;
     }
     else if(len==1)
    {
      if(zs< *db) *db = zs, *adr = color; db++; adr++;
      if(zk< *db) *db = zk, *adr = color;
      return;
     }
    else if(len==2)
    {
     float zs_1 = zs + len*0.5;

     if(zs  <*db)   *db = zs,   *adr = color;  db++; adr++;
     if(zs_1<*db)   *db = zs_1, *adr = color;  db++; adr++;
     if(zk  <*db)   *db = zk,   *adr = color;
     return;
    }

   else if(len==3)
   {
     float zs_1 = zs + (len)*(1./3.);
     float zs_2 = zs + (len)*(2./3.);

     if(zs  < *db)    *db = zs   , *adr = color;   db++; adr++;
     if(zs_1< *db)    *db = zs_1 , *adr = color;   db++; adr++;
     if(zs_2< *db)    *db = zs_2 , *adr = color;   db++; adr++;
     if(zk  < *db)    *db = zk   , *adr = color;
     return;
    }
}

 if(len==0) ERROR_("len == 0");
 if(len<0)  ERROR_("len < 0");


 float dz = float(zk-zs)/float(len);

 float z = zs;

 for(int i=0; i<=len; i++)
 {
   if(z < *db)  //depthtest
   {
     *db = z;        //set pixel
     *adr = color;
   }

 adr++;
 db++;
 z+=dz;
 }

 }

对于 1、2、3、4 长度的上述短扫描线的“展开”循环使其更快,但随着更多的展开,我没有看到太大的改进可以优化更多吗?

4

1 回答 1

1

优化的一件非常重要的事情是考虑最重要的工作负载是什么。是绘制了很多短(ish)跨度还是绘制了大部分非常长的跨度?优化的主要目标在每种情况下都是不同的。

此外,您使用的处理器也很重要;分支预测是否未命中(即整体分支)会减慢您的速度。

短跨度:

有一点是,将一些测试(y 裁剪等)移到此函数之外是一个好主意,以确保根本不会使用这些 Y 值调用它。

换边也一样;您也可以展开这些案例。

长跨度:

答案取决于您的编译器和 CPU;使用一些多媒体扩展作为 SSE 将是一个好主意。此外,您可以展开 for() 内的循环以在一次迭代中执行两个像素以赢得一点点(除非您可以让编译器为您执行此操作;您是否查看了程序集输出并调整了优化器设置?)

于 2012-12-06T20:59:32.883 回答