Software Renderer: Implement Column buffering system #205

Merged
alufolie91 merged 44 commits from dsdacol into Saturn-Next 2025-10-15 20:52:45 +02:00
10 changed files with 538 additions and 58 deletions

No files matched your search

+105
View File
@@ -488,6 +488,92 @@ void R_FlushTranslationColormapCache(void)
// in reality, the few routines that can work for either mode, are
// put here
enum columncontext_e columncontext = COLUMNCONTEXT_DIRECT;
enum ColumnFlushType
{
FLUSH_NONE = 0x0000,
FLUSH_OPAQUE = 0x0001,
FLUSH_TRANS = 0x0002,
FLUSH_COLORMAP = 0x0004,
FLUSH_COLORMAP_TRANS = 0x0008,
};
typedef struct drawcolumndata_temp_s
{
INT32 x;
INT32 yl[8], yh[8];
// e6y: resolution limitation is removed
UINT8 *buf;
INT32 startx;
ColumnFlushType type;
INT32 commontop, commonbot;
UINT8 *transmap;
// SoM 7-28-04: Fix the fuzz problem.
UINT8 *translation;
} drawcolumndata_temp_t;
drawcolumndata_temp_t temp_dc = {};
//
// Error functions that will abort if R_FlushColumns tries to flush
// columns without a column type.
//
FUNCNORETURN static ATTRNORETURN void R_FlushWholeError(void)
{
I_Error("R_FlushWholeColumns called without being initialized.\n");
}
FUNCNORETURN static ATTRNORETURN void R_FlushHTError(void)
{
I_Error("R_FlushHTColumns called without being initialized.\n");
}
FUNCNORETURN static ATTRNORETURN void R_QuadFlushError(void)
{
I_Error("R_FlushQuadColumn called without being initialized.\n");
}
static void (*R_FlushWholeColumns)(void) = R_FlushWholeError;
static void (*R_FlushHTColumns)(void) = R_FlushHTError;
static void (*R_FlushQuadColumn)(void) = R_QuadFlushError;
static void R_FlushColumns(void)
{
if (temp_dc.x != 8 || temp_dc.commontop >= temp_dc.commonbot)
R_FlushWholeColumns();
else
{
R_FlushHTColumns();
R_FlushQuadColumn();
}
temp_dc.x = 0;
}
//
// R_ResetColumnBuffer
//
// haleyjd 09/13/04: new function to call from main rendering loop
// which gets rid of the unnecessary reset of various variables during
// column drawing.
//
void R_ResetColumnBuffer(void)
{
// haleyjd 10/06/05: this must not be done if x == 0!
if (temp_dc.x)
{
R_FlushColumns();
}
temp_dc.type = FLUSH_NONE;
R_FlushWholeColumns = R_FlushWholeError;
R_FlushHTColumns = R_FlushHTError;
R_FlushQuadColumn = R_QuadFlushError;
}
/** \brief The R_InitViewBuffer function
Creates lookup tables for getting the framebuffer address
@@ -532,7 +618,26 @@ void R_InitViewBuffer(INT32 width, INT32 height)
viewwindowx = 0;
viewwindowy = 0;
INT32 bufsize = (vid.width * 8) * sizeof(*temp_dc.buf);
if (temp_dc.buf)
{
#if defined(__SSE__)
aligned_free(temp_dc.buf);
#else
Z_Free(temp_dc.buf);
#endif
}
memset(&temp_dc, 0, sizeof(temp_dc));
#if defined(__SSE__)
while (bufsize & 15)
bufsize++;
temp_dc.buf = static_cast<UINT8*>(aligned_alloc(16, bufsize));
#else
temp_dc.buf = static_cast<UINT8*>(Z_Calloc(bufsize, PU_STATIC, NULL));
#endif
}
/** \brief The R_VideoErase function
+20
View File
@@ -100,6 +100,16 @@ extern floatv3_t *ds_su, *ds_sv, *ds_sz;
extern float focallengthf;
enum columncontext_e
{
COLUMNCONTEXT_DIRECT = 0,
COLUMNCONTEXT_FLUSH,
};
extern enum columncontext_e columncontext;
void R_SetColumnContext(enum columncontext_e _columncontext);
void R_ResetColumnBuffer(void);
typedef void (coldrawfunc_t)(drawcolumndata_t*);
typedef void (spandrawfunc_t)(drawspandata_t*);
@@ -220,8 +230,18 @@ void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc);
void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc);
void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc);
// column drawers which use buffered drawing with flush
void R_DrawColumnFlush(drawcolumndata_t* dc);
void R_DrawTranslucentColumnFlush(drawcolumndata_t* dc);
void R_DrawTranslatedColumnFlush(drawcolumndata_t* dc);
void R_DrawColumnShadowedFlush(drawcolumndata_t* dc);
void R_DrawTranslatedTranslucentColumnFlush(drawcolumndata_t* dc);
void R_Draw2sMultiPatchColumnFlush(drawcolumndata_t* dc);
void R_Draw2sMultiPatchTranslucentColumnFlush(drawcolumndata_t* dc);
void R_DrawFogColumn(drawcolumndata_t* dc);
// span drawers
void R_DrawSpan(drawspandata_t* ds);
+76 -18
View File
@@ -21,6 +21,8 @@
// a has a constant z depth from top to bottom.
//
#include "r_draw_flush.cpp"
enum DrawColumnType
{
DC_BASIC = 0x0000,
@@ -28,10 +30,12 @@ enum DrawColumnType
DC_TRANSMAP = 0x0002,
DC_HOLES = 0x0004,
DC_LIGHTLIST = 0x0008,
DC_DIRECT = 0x0010, // draw our columns directly to screen!
};
template<DrawColumnType Type>
static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap)
FUNCINLINE static ATTRINLINE constexpr UINT8
R_GetColumnTranslated(const drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap)
{
if constexpr (Type & DrawColumnType::DC_COLORMAP)
{
@@ -41,8 +45,10 @@ static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, co
return colormap[col];
}
// translucency is handled on flush side now!
template<DrawColumnType Type>
static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap)
FUNCINLINE static ATTRINLINE constexpr UINT8
R_GetColumnTranslucent(const drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap)
{
col = R_GetColumnTranslated<Type>(dc, col, colormap);
@@ -57,7 +63,8 @@ static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * rest
}
template<DrawColumnType Type>
static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const UINT8 * restrict source, const UINT8 * restrict colormap)
FUNCINLINE static ATTRINLINE constexpr UINT8
R_DrawColumnPixel(const drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const UINT8 * restrict source, const UINT8 * restrict colormap)
{
UINT8 col = source[bit];
@@ -69,7 +76,14 @@ static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict
}
}
return R_GetColumnTranslucent<Type>(dc, dest, col, colormap);
if constexpr (Type & DrawColumnType::DC_DIRECT)
{ // if we dont buffer our columns, we need to handle translucency again
return R_GetColumnTranslucent<Type>(dc, dest, col, colormap);
}
else
{
return R_GetColumnTranslated<Type>(dc, col, colormap);
}
}
/** \brief The R_DrawColumn function
@@ -80,8 +94,18 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
{
INT32 count;
// leban 1/17/99:
// removed the + 1 here, adjusted the if test, and added an increment
// later. this helps a compiler pipeline a bit better. the x86
// assembler also does this.
count = dc->yh - dc->yl;
// leban 1/17/99:
// this case isn't executed too often. depending on how many instructions
// there are between here and the second if test below, this case could
// be moved down and might save instructions overall. since there are
// probably different wads that favor one way or the other, i'll leave
// this alone for now.
if (count < 0) // Zero length, column does not exceed a pixel.
{
return;
@@ -150,6 +174,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
}
R_DrawColumnTemplate<NewType>(&dc_copy);
if (solid)
{
dc_copy.yl = bheight;
@@ -183,19 +208,37 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
// killough 2/1/98: more performance tuning
intptr_t frac;
// Looks familiar.
const intptr_t fracstep = dc->iscale;
const intptr_t heightmask = dc->sourcelength-1;
const intptr_t heightmask = dc->sourcelength-1; // CPhipps - specify type
constexpr INT32 npow2min = -1;
const INT32 npow2max = dc->sourcelength;
const INT32 stride = vid.width;
const UINT8 * restrict source = dc->source;
const lighttable_t * restrict colormap = dc->colormap;
// Framebuffer destination address.
UINT8 * restrict dest = R_Address(dc->x, dc->yl);
// SoM: MAGIC
UINT8 * restrict dest;
count++;
if constexpr (Type & DrawColumnType::DC_DIRECT)
dest = R_Address(dc->x, dc->yl);
else if constexpr ((Type & (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP))
== (DrawColumnType::DC_COLORMAP | DrawColumnType::DC_TRANSMAP))
dest = R_GetBufferColormapTrans(dc);
else if constexpr (Type & DrawColumnType::DC_TRANSMAP)
dest = R_GetBufferTrans(dc);
else if constexpr (Type & DrawColumnType::DC_COLORMAP)
dest = R_GetBufferColormap(dc);
else
dest = R_GetBufferOpaque(dc);
INT32 stride = 8; //SoM: Oh, Oh it's MAGIC! You know...
if constexpr (Type & DrawColumnType::DC_DIRECT)
stride = vid.width;
count++; // killough 1/99: minor tuning
// Determine scaling, which is the only mapping to be done.
frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep));
@@ -205,15 +248,16 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
case 255:
case 127:
{
while(count--)
while (count--)
{
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
dest += stride;
frac += fracstep;
}
}
break;
case -1:
case npow2min:
{
if (frac < 0)
// adjust in case we underread
@@ -223,6 +267,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
while (--count >= 0)
{
*dest = R_DrawColumnPixel<Type>(dc, dest, frac>>FRACBITS, source, colormap);
dest += stride;
frac += fracstep;
}
@@ -235,10 +280,12 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
while ((count -= 2) >= 0) // texture height is a power of 2 -- killough
{
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
dest += stride;
frac += fracstep;
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
dest += stride;
frac += fracstep;
}
@@ -271,7 +318,7 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
// heightmask is the Tutti-Frutti fix -- killough
// -1 is the lower clamp bound because column posts have a "safe" byte before the real data
// and a few bytes after as well
@@ -311,13 +358,24 @@ static void R_DrawColumnTemplate(drawcolumndata_t *dc)
R_DrawColumnTemplate<opt>(dc); \
}
DEFINE_COLUMN_FUNC(R_DrawColumn, DC_BASIC)
DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_COLORMAP)
DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST)
DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_DrawColumn, DC_DIRECT|DC_BASIC)
DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_DIRECT|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_DIRECT|DC_COLORMAP)
DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_DIRECT|DC_LIGHTLIST)
DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_DIRECT|DC_COLORMAP|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_DIRECT|DC_HOLES)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_DIRECT|DC_HOLES|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_DrawColumnFlush, DC_BASIC)
DEFINE_COLUMN_FUNC(R_DrawTranslucentColumnFlush, DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_DrawTranslatedColumnFlush, DC_COLORMAP)
DEFINE_COLUMN_FUNC(R_DrawColumnShadowedFlush, DC_LIGHTLIST)
DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumnFlush, DC_COLORMAP|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumnFlush, DC_HOLES)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumnFlush, DC_HOLES|DC_TRANSMAP)
//skymyass
//DEFINE_COLUMN_FUNC(R_DrawSkyColumn, DC_SKY)
/** \brief The R_DrawFogColumn function
Fog wall.
+247
View File
@@ -0,0 +1,247 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
// Copyright (C) 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
// Copyright (C) Copyright 2005, 2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
// Copyright (C) 2013 by James Haley, Stephen McGranahan, et al.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_draw_flush.cpp
/// \brief Optimized quad column buffer code. By SoM.
/// \note no includes because this is included as part of r_draw.cpp
template<ColumnFlushType Type>
FUNCINLINE static ATTRINLINE constexpr UINT8
R_GetFlushPixelTranslated(const drawcolumndata_temp_t *t_dc, UINT8 col)
{
if constexpr (Type & (ColumnFlushType::FLUSH_COLORMAP | ColumnFlushType::FLUSH_COLORMAP_TRANS))
{
col = t_dc->translation[col];
}
return col;
}
template<ColumnFlushType Type>
FUNCINLINE static ATTRINLINE constexpr UINT8
R_GetFlushPixelTranslucent(const drawcolumndata_temp_t *t_dc, UINT8 * restrict dest, UINT8 col)
{
col = R_GetFlushPixelTranslated<Type>(t_dc, col);
if constexpr (Type & (ColumnFlushType::FLUSH_TRANS | ColumnFlushType::FLUSH_COLORMAP_TRANS))
{
// haleyjd 09/11/04: use temptranmap here
return *(t_dc->transmap + (col << 8) + (*dest));
}
else
{
return col;
}
}
template<ColumnFlushType Type>
FUNCINLINE static ATTRINLINE constexpr UINT8
R_DrawFlushPixel(const drawcolumndata_temp_t *t_dc, UINT8 * restrict dest, const UINT8 * restrict source)
{
UINT8 col = *source;
return R_GetFlushPixelTranslucent<Type>(t_dc, dest, col);
}
//
// R_FlushWhole
//
// Flushes the entire columns in the buffer, one at a time.
// This is used when a quad flush isn't possible.
//
template<ColumnFlushType Type>
static void R_FlushWhole(void)
{
UINT8 * restrict source;
UINT8 * restrict dest;
INT32 count, yl;
const INT32 stride = vid.width;
drawcolumndata_temp_t *t_dc = &temp_dc;
UINT8 *restrict buf = t_dc->buf;
while (--t_dc->x >= 0)
{
yl = t_dc->yl[t_dc->x];
source = &buf[t_dc->x + (yl << 3)];
dest = R_Address(t_dc->startx + t_dc->x, yl);
count = t_dc->yh[t_dc->x] - yl + 1;
while (--count >= 0)
{
*dest = R_DrawFlushPixel<Type>(t_dc, dest, source);
source += 8;
dest += stride;
}
}
}
//
// R_FlushHT
//
// Flushes the head and tail of columns in the buffer in
// preparation for a quad flush.
//
template<ColumnFlushType Type>
static void R_FlushHT(void)
{
UINT8 * restrict source;
UINT8 * restrict dest;
INT32 count, colnum = 0;
INT32 yl, yh;
const INT32 stride = vid.width;
const drawcolumndata_temp_t *t_dc = &temp_dc;
UINT8 *restrict buf = t_dc->buf;
while (colnum < 8)
{
yl = t_dc->yl[colnum];
yh = t_dc->yh[colnum];
// flush column head
if (yl < t_dc->commontop)
{
source = &buf[colnum + (yl << 3)];
dest = R_Address(t_dc->startx + colnum, yl);
count = t_dc->commontop - yl;
while (--count >= 0)
{
*dest = R_DrawFlushPixel<Type>(t_dc, dest, source);
source += 8;
dest += stride;
}
}
// flush column tail
if (yh > t_dc->commonbot)
{
source = &buf[colnum + ((t_dc->commonbot + 1) << 3)];
dest = R_Address(t_dc->startx + colnum, t_dc->commonbot + 1);
count = yh - t_dc->commonbot;
while (--count >= 0)
{
*dest = R_DrawFlushPixel<Type>(t_dc, dest, source);
source += 8;
dest += stride;
}
}
++colnum;
}
}
// Begin: Quad column flushing functions.
template<ColumnFlushType Type>
static void R_FlushQuad(void)
{
const INT32 stride = vid.width;
const drawcolumndata_temp_t *t_dc = &temp_dc;
INT32 count = t_dc->commonbot - t_dc->commontop + 1;
const UINT8 *restrict buf = t_dc->buf;
if constexpr (Type & ColumnFlushType::FLUSH_OPAQUE)
{
const INT64 *source = reinterpret_cast<const INT64 *>(buf + (t_dc->commontop << 3));
INT64 *dest = reinterpret_cast<INT64 *>(R_Address(t_dc->startx, t_dc->commontop));
const INT32 deststep = stride / 8;
while (--count >= 0)
{
*dest = *source++;
dest += deststep;
}
}
else
{
const UINT8 * restrict source = buf + (t_dc->commontop << 3);
UINT8 * restrict dest = R_Address(t_dc->startx, t_dc->commontop);
while (--count >= 0)
{
dest[0] = R_DrawFlushPixel<Type>(t_dc, &dest[0], &source[0]);
dest[1] = R_DrawFlushPixel<Type>(t_dc, &dest[1], &source[1]);
dest[2] = R_DrawFlushPixel<Type>(t_dc, &dest[2], &source[2]);
dest[3] = R_DrawFlushPixel<Type>(t_dc, &dest[3], &source[3]);
dest[4] = R_DrawFlushPixel<Type>(t_dc, &dest[4], &source[4]);
dest[5] = R_DrawFlushPixel<Type>(t_dc, &dest[5], &source[5]);
dest[6] = R_DrawFlushPixel<Type>(t_dc, &dest[6], &source[6]);
dest[7] = R_DrawFlushPixel<Type>(t_dc, &dest[7], &source[7]);
source += 8;
dest += stride;
}
}
}
// haleyjd 09/12/04: split up R_GetBuffer into various different
// functions to minimize the number of branches and take advantage
// of as much precalculated information as possible.
template<ColumnFlushType Type>
static UINT8 *R_GetBuffer(drawcolumndata_t *dc)
{
drawcolumndata_temp_t *t_dc = &temp_dc;
// haleyjd: reordered predicates
if (t_dc->x == 8 ||
(t_dc->x && (t_dc->type != Type || t_dc->x + t_dc->startx != dc->x)))
R_FlushColumns();
if (!t_dc->x)
{
++t_dc->x;
t_dc->startx = dc->x;
t_dc->yl[0] = t_dc->commontop = dc->yl;
t_dc->yh[0] = t_dc->commonbot = dc->yh;
t_dc->type = Type;
if constexpr (Type & (ColumnFlushType::FLUSH_TRANS | ColumnFlushType::FLUSH_COLORMAP_TRANS))
{
t_dc->transmap = dc->transmap;
}
if constexpr (Type & (ColumnFlushType::FLUSH_COLORMAP | ColumnFlushType::FLUSH_COLORMAP_TRANS))
{
t_dc->translation = dc->translation;
}
R_FlushWholeColumns = R_FlushWhole<Type>;
R_FlushHTColumns = R_FlushHT<Type>;
R_FlushQuadColumn = R_FlushQuad<Type>;
return &t_dc->buf[dc->yl << 3];
}
t_dc->yl[t_dc->x] = dc->yl;
t_dc->yh[t_dc->x] = dc->yh;
if (dc->yl > t_dc->commontop)
t_dc->commontop = dc->yl;
if (dc->yh < t_dc->commonbot)
t_dc->commonbot = dc->yh;
return &t_dc->buf[(dc->yl << 3) + t_dc->x++];
}
#define DEFINE_GETBUF_FUNC(name, flags) \
FUNCINLINE static ATTRINLINE UINT8 *name(drawcolumndata_t *dc) \
{ \
constexpr ColumnFlushType opt = static_cast<ColumnFlushType>(flags); \
return R_GetBuffer<opt>(dc); \
}
DEFINE_GETBUF_FUNC(R_GetBufferOpaque, FLUSH_OPAQUE)
DEFINE_GETBUF_FUNC(R_GetBufferTrans, FLUSH_TRANS)
DEFINE_GETBUF_FUNC(R_GetBufferColormap, FLUSH_COLORMAP)
DEFINE_GETBUF_FUNC(R_GetBufferColormapTrans, FLUSH_COLORMAP_TRANS)
+41 -20
View File
@@ -50,7 +50,8 @@ enum DrawSpanType
};
template<DrawSpanType Type>
static constexpr UINT8 R_GetSpanTranslated(drawspandata_t* ds, UINT8 col)
FUNCINLINE static ATTRINLINE constexpr UINT8
R_GetSpanTranslated(const drawspandata_t* ds, UINT8 col)
{
if constexpr (Type & DrawSpanType::DS_COLORMAP)
{
@@ -63,7 +64,8 @@ static constexpr UINT8 R_GetSpanTranslated(drawspandata_t* ds, UINT8 col)
}
template<DrawSpanType Type>
static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col)
FUNCINLINE static ATTRINLINE constexpr UINT8
R_GetSpanTranslucent(const drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col)
{
col = colormap[R_GetSpanTranslated<Type>(ds, col)];
@@ -78,7 +80,8 @@ static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, con
}
template<DrawSpanType Type>
static constexpr UINT8 R_DrawSpanPixel(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source)
FUNCINLINE static ATTRINLINE constexpr UINT8
R_DrawSpanPixel(const drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source)
{
UINT8 col = source[bit];
@@ -157,14 +160,18 @@ static void R_DrawSpanTemplate(drawspandata_t* ds)
{
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
if constexpr (Type & DS_RIPPLE)
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
else
dest[i] = R_DrawSpanPixel<Type>(ds, &dest[i], colormap, bit, source);
xposition += xstep;
yposition += ystep;
}
dest += 8;
dsrc += 8;
if constexpr (Type & DS_RIPPLE)
dsrc += 8;
count -= 8;
}
@@ -173,10 +180,14 @@ static void R_DrawSpanTemplate(drawspandata_t* ds)
{
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
if constexpr (Type & DS_RIPPLE)
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
else
*dest = R_DrawSpanPixel<Type>(ds, dest, colormap, bit, source);
dest++;
dsrc++;
if constexpr (Type & DS_RIPPLE)
dsrc++;
xposition += xstep;
yposition += ystep;
@@ -243,15 +254,14 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
local_for_thread std::vector<INT32> tiltlighting;
iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx);
vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx);
// Lighting is simple. It's just linear interpolation from start to end
R_GetTiltedLighting(tiltlighting, ds, iz, width, stride);
uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx);
vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx);
const UINT8 *source = ds->source;
const UINT8 *colormap = ds->colormap;
const UINT8 * restrict source = ds->source;
const UINT8 * restrict colormap = ds->colormap;
if constexpr (Type & DS_RIPPLE)
{
@@ -313,12 +323,16 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
{
bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift);
colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps);
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
if constexpr (Type & DS_RIPPLE)
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
else
dest[i] = R_DrawSpanPixel<Type>(ds, &dest[i], colormap, bit, source);
}
ds->x1 += SPANSIZE;
dest += SPANSIZE;
dsrc += SPANSIZE;
if constexpr (Type & DS_RIPPLE)
dsrc += SPANSIZE;
startu = endu;
startv = endv;
width -= SPANSIZE;
@@ -332,7 +346,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
v = (INT64)(startv);
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
if constexpr (Type & DS_RIPPLE)
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
else
*dest = R_DrawSpanPixel<Type>(ds, dest, colormap, bit, source);
ds->x1++;
}
else
@@ -355,10 +372,14 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
{
bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift);
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
if constexpr (Type & DS_RIPPLE)
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
else
*dest = R_DrawSpanPixel<Type>(ds, dest, colormap, bit, source);
dest++;
if constexpr (Type & DS_RIPPLE)
dsrc++;
ds->x1++;
dsrc++;
u += stepu;
v += stepv;
}
@@ -389,11 +410,11 @@ DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE)
*/
void R_DrawFogSpan(drawspandata_t* ds)
{
INT32 count = ds->x2 - ds->x1 + 1;
const UINT8 * restrict colormap = ds->colormap;
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
intptr_t count = ds->x2 - ds->x1 + 1;
while (count >= 4)
{
dest[0] = colormap[dest[0]];
@@ -401,7 +422,7 @@ void R_DrawFogSpan(drawspandata_t* ds)
dest[2] = colormap[dest[2]];
dest[3] = colormap[dest[3]];
dest += 4;
dest += 4;
count -= 4;
}
+7 -1
View File
@@ -1402,9 +1402,12 @@ void R_RenderPlayerView(player_t *player)
R_ClearPlanes();
R_ClearSprites();
R_SetColumnContext(COLUMNCONTEXT_FLUSH);
R_RenderViewpoint(&masks[nummasks - 1], false);
R_ClipSprites(drawsegs, NULL);
R_ResetColumnBuffer();
R_SetColumnContext(COLUMNCONTEXT_DIRECT);
R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts
R_DrawPlanes();
R_DrawMasked(masks, nummasks);
@@ -1439,6 +1442,7 @@ void R_RenderPlayerView(player_t *player)
// check for new console commands.
NetUpdate();
R_SetColumnContext(COLUMNCONTEXT_FLUSH);
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderViewpoint(&masks[nummasks - 1], true);
@@ -1446,6 +1450,7 @@ void R_RenderPlayerView(player_t *player)
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime);
R_ResetColumnBuffer();
ps_numsprites.value.i = numvisiblesprites;
@@ -1482,12 +1487,14 @@ void R_RenderPlayerView(player_t *player)
R_RenderViewpoint(&masks[nummasks - 1], true);
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
R_ResetColumnBuffer();
Portal_Remove(portal);
}
}
PS_STOP_TIMING(ps_sw_portaltime);
R_SetColumnContext(COLUMNCONTEXT_DIRECT);
PS_START_TIMING(ps_sw_planetime);
if (!skybox)
R_DrawSkyPlanes();
@@ -1498,7 +1505,6 @@ void R_RenderPlayerView(player_t *player)
PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked(masks, nummasks);
PS_STOP_TIMING(ps_sw_maskedtime);
free(masks);
// Check for new console commands.
+2 -5
View File
@@ -716,13 +716,10 @@ void R_DrawPlanes(void)
visplane_t *pl;
INT32 i;
drawspandata_t ds = {};
#ifdef HAVE_THREADS
srb2::ThreadPool::Sema tp_sema;
#endif
R_UpdatePlaneRipple(&ds);
#ifdef HAVE_THREADS
srb2::ThreadPool::Sema tp_sema;
srb2::g_main_threadpool->begin_sema();
#endif
for (i = 0; i < MAXVISPLANES; i++, pl++)
@@ -1159,7 +1156,7 @@ void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_paralle
offset = (scry*vid.width) + scrx;
// No idea if this works
VID_BlitLinearScreen(renderscreen + offset,
VID_BlitLinearScreen(vid.screens[0] + offset,
vid.screens[1] + (top*vid.width), // intentionally not +offset
viewwidth, bottom-top,
vid.width, vid.width);
+5 -5
View File
@@ -2801,6 +2801,11 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
drawseg_t* ds;
INT32 i;
if (visspritecount - clippedvissprites <= 0)
{
return;
}
// e6y
// Reducing of cache misses in the following R_DrawSprite()
// Makes sense for scenes with huge amount of drawsegs.
@@ -2810,11 +2815,6 @@ void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
drawsegs_xranges[i].count = 0;
}
if (visspritecount - clippedvissprites <= 0)
{
return;
}
if (drawsegs_xrange_size < maxdrawsegs)
{
// haleyjd: fix reallocation to track 2x size
+34 -9
View File
@@ -80,7 +80,7 @@ consvar_t cv_accuratefps = {"fpssampling", "1", CV_SAVE, accuratefps_cons_t, NUL
// SCREEN VARIABLES
// =========================================================================
static void SCR_SetDrawFuncs(void)
static void SCR_SetDrawFuncs(enum columncontext_e _columncontext)
{
//
// setup the right draw routines
@@ -99,13 +99,27 @@ static void SCR_SetDrawFuncs(void)
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan;
spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawFogSpan_Tilted;
colfuncs[BASEDRAWFUNC] = R_DrawColumn;
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn;
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn;
if (_columncontext == COLUMNCONTEXT_FLUSH)
{
colfuncs[BASEDRAWFUNC] = R_DrawColumnFlush;
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumnFlush;
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumnFlush;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowedFlush;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumnFlush;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumnFlush;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumnFlush;
}
else
{
colfuncs[BASEDRAWFUNC] = R_DrawColumn;
colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn;
colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn;
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed;
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn;
}
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn;
R_SetColumnFunc(BASEDRAWFUNC);
@@ -127,12 +141,23 @@ void SCR_SetMode(void)
V_SetPalette(0);
SCR_SetDrawFuncs();
SCR_SetDrawFuncs(COLUMNCONTEXT_DIRECT);
// set the apprpriate drawer for the sky (tall or INT16)
setmodeneeded = 0;
}
// used to switch between column buffering and drawing them directly to screen
// our sky "plane" drawer cannot handle the buffer system due to multithreading
// (that would require alot of extra complexity for smth with massive diminishing results)
// Our masked drawing step draws things in a very particular order, which results in alot of flushing to screen
// effectively adding massive overhead due to excessive flushing, so we draw our masked thing directly to screen instead
void R_SetColumnContext(enum columncontext_e _columncontext)
{
columncontext = _columncontext;
SCR_SetDrawFuncs(_columncontext); // set our column drawers
}
void R_SetColumnFunc(size_t id)
{
I_Assert(id < COLDRAWFUNC_MAX);
+1
View File
@@ -94,6 +94,7 @@ extern consvar_t cv_vidwait;
extern consvar_t cv_votebgscaling;
//void R_SetColumnContext(enum columncontext_e _columncontext); // declared in r_draw!
void R_SetColumnFunc(size_t id);
void R_SetSpanFunc(size_t id);
boolean R_CheckColumnFunc(size_t id);