drawScanlineWithDepth - optimization

drawScanlineWithDepth - optimization

本文关键字:optimization drawScanlineWithDepth      更新时间:2023-10-16

我有一些绘制扫描线的程序with depth-它将xs作为x开始,将xk作为x结束,y和zs为xs处的z深度,zk为zk中的z深度(z值将线性形式xs更改为xk)浮点深度htram中的缓冲区用于深度测试

这是

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的短扫描线,"展开"一个循环使它更快,但随着更多的未绑定,我看不到有多大改进它能被更多地匿名化吗?

len

对于优化来说,一件非常重要的事情是考虑什么是最重要的工作负载。它是绘制大量的短跨度还是绘制大部分的长跨度?优化的主要目标在每种情况下都是不同的。

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

短跨距:

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

交换侧面也是如此;你也可以打开这些箱子。

长跨度:

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