kb1
Junior Member
Posts: 167
Registered: 11-06 |
entryway said:
I duplicated some map data into separate struct to reduce cache misses in P_CrossSubsector
Timedemo on sunder.wad map11 (without shooting of course) in comparison with 2.5.1.1
code:
doom2 (-complevel 2) 85.9 fps -> 109.1 fps = +27%
boom (-complevel 9) 51.4 fps -> 62.9 fps = +22%
prboom (-complevel 17) 87.5 fps -> 107.3 fps = +23%
Very nice! How does it hold up during a game? Yes, the memory caching is so problematic for Doom, especially the renderer. I've been considering prefetch and no-cache commands, seems like they could provide some real benefit in isolated cases.
entryway said:
If you have fully functional and bugs free replacement for LOS based on doom 1.2, then post it here. It will make sense for next complevels (if it will happen ever).
Well, I don't know if it's bug free (see my post above). Once again, upon playing a few coop games, I sometimes noticed that monsters were still in their teleport closets at the end of the maps, so I don't know if those maps rely on the 1.4 - 1.9 sight checking or not. I need to look into this further.
Basically, the code I use is almost directly lifted from ZDoom. However, I started with the PrBoom Plus code, and "adapted it" with ZDoom's fixes, so it felt like I was a part of it :) It's posted below (I use tabs, and a rather strange indent style, I must say...)
code:
#define MAX_SIGHT_COUNT 64
int P_SightPathTraverse_New(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
{
fixed_t xt1;
fixed_t yt1;
fixed_t xt2;
fixed_t yt2;
fixed_t xstep;
fixed_t ystep;
fixed_t partialx;
fixed_t partialy;
fixed_t xintercept;
fixed_t yintercept;
int mapx;
int mapy;
int mapxstep;
int mapystep;
int count;
validcount++;
intercept_p = intercepts;
if (((x1 - bmaporgx) & (MAPBLOCKSIZE - 1)) == 0)
x1 += FRACUNIT; // don't side exactly on a line
if (((y1 - bmaporgy) & (MAPBLOCKSIZE - 1)) == 0)
y1 += FRACUNIT; // don't side exactly on a line
trace.x = x1;
trace.y = y1;
trace.dx = x2 - x1;
trace.dy = y2 - y1;
x1 -= bmaporgx;
y1 -= bmaporgy;
xt1 = x1 >> MAPBLOCKSHIFT;
yt1 = y1 >> MAPBLOCKSHIFT;
x2 -= bmaporgx;
y2 -= bmaporgy;
xt2 = x2 >> MAPBLOCKSHIFT;
yt2 = y2 >> MAPBLOCKSHIFT;
// points should never be out of bounds, but check once instead of
// each block
if (xt1 < 0 || yt1 < 0 || xt1 >= bmapwidth || yt1 >= bmapheight ||
xt2 < 0 || yt2 < 0 || xt2 >= bmapwidth || yt2 >= bmapheight)
{
return 0;
}
if (xt2 > xt1)
{
mapxstep = 1;
partialx = FRACUNIT - ((x1 >> MAPBTOFRAC) & (FRACUNIT - 1));
ystep = FixedDiv(y2 - y1, abs(x2 - x1));
}
else if (xt2 < xt1)
{
mapxstep = -1;
partialx = (x1 >> MAPBTOFRAC) & (FRACUNIT - 1);
ystep = FixedDiv(y2 - y1, abs(x2 - x1));
}
else
{
mapxstep = 0;
partialx = FRACUNIT;
ystep = 256 * FRACUNIT;
}
yintercept = (y1 >> MAPBTOFRAC) + FixedMul(partialx, ystep);
if (yt2 > yt1)
{
mapystep = 1;
partialy = FRACUNIT - ((y1 >> MAPBTOFRAC) & (FRACUNIT - 1));
xstep = FixedDiv(x2 - x1, abs(y2 - y1));
}
else if (yt2 < yt1)
{
mapystep = -1;
partialy = (y1 >> MAPBTOFRAC) & (FRACUNIT - 1);
xstep = FixedDiv(x2 - x1, abs(y2 - y1));
}
else
{
mapystep = 0;
partialy = FRACUNIT;
xstep = 256 * FRACUNIT;
}
xintercept = (x1 >> MAPBTOFRAC) + FixedMul(partialy, xstep);
// [RH] Fix for traces that pass only through blockmap corners. In that case,
// xintercept and yintercept can both be set ahead of mapx and mapy, so the
// for loop would never advance anywhere.
if (abs(xstep) == FRACUNIT && abs(ystep) == FRACUNIT)
{
if (ystep < 0)
{
partialx = FRACUNIT - partialx;
}
if (xstep < 0)
{
partialy = FRACUNIT - partialy;
}
if (partialx == partialy)
{
xintercept = xt1 << FRACBITS;
yintercept = yt1 << FRACBITS;
}
}
//
// step through map blocks
// Count is present to prevent a round off error from skipping the break
mapx = xt1;
mapy = yt1;
for (count = 0; count < MAX_SIGHT_COUNT; count++)
{
if (!P_SightBlockLinesIterator(mapx, mapy))
{
return 0; // early out
}
if ((mapxstep | mapystep) == 0)
break;
switch ((((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx))
{
case 0: // neither xintercept nor yintercept match!
// Continuing won't make things any better, so we might as well stop right here
count = MAX_SIGHT_COUNT;
break;
case 1: // xintercept matches
xintercept += xstep;
mapy += mapystep;
if (mapy == yt2)
mapystep = 0;
break;
case 2: // yintercept matches
yintercept += ystep;
mapx += mapxstep;
if (mapx == xt2)
mapxstep = 0;
break;
case 3: // xintercept and yintercept both match
// The trace is exiting a block through its corner. Not only does the block
// being entered need to be checked (which will happen when this loop
// continues), but the other two blocks adjacent to the corner also need to
// be checked.
if (!P_SightBlockLinesIterator(mapx + mapxstep, mapy) ||
!P_SightBlockLinesIterator(mapx, mapy + mapystep))
{
return 0;
}
xintercept += xstep;
yintercept += ystep;
mapx += mapxstep;
mapy += mapystep;
if (mapx == xt2)
mapxstep = 0;
if (mapy == yt2)
mapystep = 0;
break;
}
}
// couldn't early out, so go through the sorted list
return P_SightTraverseIntercepts();
}
|