0

深度でスキャンラインを描画する手順があります-xsをax start xkとしてax end、yとzsをxsのz-depth、zkをzkのz-depthとして取ります(z値はxsからxkへの線形形式のz値の変更)フロート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

最適化で非常に重要なことの 1 つは、最も重要なワークロードを検討することです。短い(っぽい)スパンがたくさん描かれていますか、それとも本当に長いスパンがほとんど描かれていますか?最適化の主な対象は、ケースごとに異なります。

また、使用しているプロセッサも重要です。分岐予測の失敗 (つまり、全体としての分岐) によって速度が低下するかどうか。

短いスパン:

1 つのポイントは、いくつかのテスト (y クリッピングなど) をこの関数の外に移動して、これらの Y 値で呼び出されないようにすることをお勧めします。

側面を交換する場合も同じです。これらのケースをアンロールすることもできます。

長いスパン:

答えは、コンパイラと CPU によって異なります。いくつかのマルチメディア拡張機能を SSE のように使用するのは素晴らしいアイデアです。また、for() 内のループをアンロールして、1 回の反復内で 2 つのピクセルを実行して少し勝つこともできます (コンパイラにそれを実行させることができない限り、アセンブリの出力を見て、オプティマイザの設定を微調整しましたか? ?)

于 2012-12-06T20:59:32.883 に答える