From ce2a1aa3b24108691d7ba58ca6945a8653f0d7c7 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 11 Jan 2020 16:24:00 +0000 Subject: [PATCH] Minor optimisations surrounding R_DrawFlippedMaskedColumn. * Replace the texheight parameter provided directly to it with a previously existing (now renamed) global used for the same purpose, so that it can be used as an interchangeable function pointer with R_DrawMaskedColumn. * Using the above, optimise R_DrawVisSprite to call a function pointer in a tighter loop rather than check SC_VFLIP each time around. * SHORT macro can involve repeated operations; calculate once and put in memory for both RANGECHECK and papersprite. * Remove irrelevant range check (already covered by existing range check immediately above) from R_DrawFlippedMaskedColumn and R_DrawMaskedColumn. * "Warning: avoiding a crash in %s %d" is a terrible error message, and it chips away at the tightness of the loop just for something most people will never see printed. Replace with a PARANOIA I_Error in case someone actively wants to go hunting for its cause. --- src/r_segs.c | 22 ++++++---------- src/r_things.c | 68 ++++++++++++++++++++++++-------------------------- src/r_things.h | 3 ++- 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/r_segs.c b/src/r_segs.c index 0233b1161..32a922147 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -240,14 +240,13 @@ static void R_DrawWallSplats(void) // way we don't have to store extra post_t info with each column for // multi-patch textures. They are not normally needed as multi-patch // textures don't have holes in it. At least not for now. -static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height static void R_Render2sidedMultiPatchColumn(column_t *column) { INT32 topscreen, bottomscreen; topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall - bottomscreen = topscreen + spryscale * column2s_length; + bottomscreen = topscreen + spryscale * lengthcol; dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -279,13 +278,6 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) } } -// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value -// uses column2s_length for texture->height as above -static void R_DrawFlippedMaskedSegColumn(column_t *column) -{ - R_DrawFlippedMaskedColumn(column, column2s_length); -} - void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -364,8 +356,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { if (textures[texnum]->flip & 2) // vertically flipped? { - colfunc_2s = R_DrawFlippedMaskedSegColumn; - column2s_length = textures[texnum]->height; + colfunc_2s = R_DrawFlippedMaskedColumn; + lengthcol = textures[texnum]->height; } else colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture @@ -373,7 +365,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) else { colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) - column2s_length = textures[texnum]->height; + lengthcol = textures[texnum]->height; } // Setup lighting based on the presence/lack-of 3D floors. @@ -733,7 +725,7 @@ static void R_DrawRepeatMaskedColumn(column_t *col) static void R_DrawRepeatFlippedMaskedColumn(column_t *col) { do { - R_DrawFlippedMaskedColumn(col, column2s_length); + R_DrawFlippedMaskedColumn(col); sprtopscreen += dc_texheight*spryscale; } while (sprtopscreen < sprbotscreen); } @@ -1065,7 +1057,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (textures[texnum]->flip & 2) // vertically flipped? { colfunc_2s = R_DrawRepeatFlippedMaskedColumn; - column2s_length = textures[texnum]->height; + lengthcol = textures[texnum]->height; } else colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture @@ -1073,7 +1065,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else { colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) - column2s_length = textures[texnum]->height; + lengthcol = textures[texnum]->height; } #ifdef ESLOPE diff --git a/src/r_things.c b/src/r_things.c index 2fc44faf8..d2f3b4902 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -641,10 +641,10 @@ void R_DrawMaskedColumn(column_t *column) dc_yl = mceilingclip[dc_x]+1; if (dc_yl < 0) dc_yl = 0; - if (dc_yh >= vid.height) + if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop dc_yh = vid.height - 1; - if (dc_yl <= dc_yh && dc_yl < vid.height && dc_yh > 0) + if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = (UINT8 *)column + 3; dc_texturemid = basetexturemid - (topdelta<length + 4); } @@ -671,7 +666,9 @@ void R_DrawMaskedColumn(column_t *column) dc_texturemid = basetexturemid; } -void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) +INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height + +void R_DrawFlippedMaskedColumn(column_t *column) { INT32 topscreen; INT32 bottomscreen; @@ -687,7 +684,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) if (topdelta <= prevdelta) topdelta += prevdelta; prevdelta = topdelta; - topdelta = texheight-column->length-topdelta; + topdelta = lengthcol-column->length-topdelta; topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*column->length : sprbotscreen + spryscale*column->length; @@ -709,10 +706,10 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) dc_yl = mceilingclip[dc_x]+1; if (dc_yl < 0) dc_yl = 0; - if (dc_yh >= vid.height) + if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop dc_yh = vid.height - 1; - if (dc_yl <= dc_yh && dc_yl < vid.height && dc_yh > 0) + if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = ZZ_Alloc(column->length); for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) @@ -722,15 +719,10 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) // Still drawn by R_DrawColumn. if (ylookup[dc_yl]) colfunc(); - else if (colfunc == colfuncs[COLDRAWFUNC_BASE]) - { - static INT32 first = 1; - if (first) - { - CONS_Debug(DBG_RENDER, "WARNING: avoiding a crash in %s %d\n", __FILE__, __LINE__); - first = 0; - } - } +#ifdef PARANOIA + else + I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl); +#endif Z_Free(dc_source); } column = (column_t *)((UINT8 *)column + column->length + 4); @@ -746,7 +738,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; + void (*localcolfunc)(column_t *); INT32 texturecolumn; + INT32 pwidth; fixed_t frac; patch_t *patch = vis->patch; fixed_t this_scale = vis->mobj->scale; @@ -895,50 +889,52 @@ static void R_DrawVisSprite(vissprite_t *vis) if (vis->x2 >= vid.width) vis->x2 = vid.width-1; + localcolfunc = (vis->cut & SC_VFLIP) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn; + lengthcol = patch->height; + // Split drawing loops for paper and non-paper to reduce conditional checks per sprite if (vis->scalestep) { - // Papersprite drawing loop + pwidth = SHORT(patch->width); + // Papersprite drawing loop for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep) { angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + if (texturecolumn < 0 || texturecolumn >= pwidth) continue; if (vis->xiscale < 0) // Flipped sprite - texturecolumn = SHORT(patch->width) - 1 - texturecolumn; + texturecolumn = pwidth - 1 - texturecolumn; sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); - if (vis->cut & SC_VFLIP) - R_DrawFlippedMaskedColumn(column, patch->height); - else - R_DrawMaskedColumn(column); + localcolfunc (column); } } else { +#ifdef RANGECHECK + pwidth = SHORT(patch->width); +#endif + // Non-paper drawing loop for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) { #ifdef RANGECHECK texturecolumn = frac>>FRACBITS; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + if (texturecolumn < 0 || texturecolumn >= pwidth) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); #else column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); #endif - if (vis->cut & SC_VFLIP) - R_DrawFlippedMaskedColumn(column, patch->height); - else - R_DrawMaskedColumn(column); + localcolfunc (column); } } diff --git a/src/r_things.h b/src/r_things.h index 05d6fb27b..7a0fe3a60 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -44,9 +44,10 @@ extern fixed_t sprtopscreen; extern fixed_t sprbotscreen; extern fixed_t windowtop; extern fixed_t windowbottom; +extern INT32 lengthcol; void R_DrawMaskedColumn(column_t *column); -void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight); +void R_DrawFlippedMaskedColumn(column_t *column); // ---------------- // SPRITE RENDERING