Skip to content

Commit

Permalink
Optimization: Rendpolys are no longer allocated on the stack each and…
Browse files Browse the repository at this point in the history
… every time they are needed. Added a rendpoly allocation mechanism which allows the same rendpolys to be re-used whenever possible.

Number of vertices are also allocated dynamically at this time, this meant I was able to remove the RL_MAX_POLY_SIDES limit. Note, the number of verts is still stored as a byte in rendpoly_t so we have a hard limit of 255 verts now.
Rendpoly wall data is now allocated dynamically and only for rendpolys which are to be used as walls.
These changes should result in a noticeable speed boost in-game.
  • Loading branch information
danij committed Oct 8, 2006
1 parent 6f9a3ee commit 35de1c0
Show file tree
Hide file tree
Showing 17 changed files with 795 additions and 542 deletions.
2 changes: 2 additions & 0 deletions doomsday/build/win32/doomsday_cl.rsp
Expand Up @@ -31,6 +31,7 @@
./../../engine/portable/src/gl_hq2x.c
./../../engine/portable/src/gl_font.c
./../../engine/portable/src/gl_draw.c
./../../engine/portable/src/rend_console.c
./../../engine/portable/src/rend_bias.c
./../../engine/portable/src/edit_bias.c
./../../engine/portable/src/rend_sprite.c
Expand Down Expand Up @@ -104,6 +105,7 @@
./../../engine/portable/src/sys_direc.c
./../../engine/win32/src/sys_console.c
./../../engine/portable/src/con_start.c
./../../engine/portable/src/con_data.c
./../../engine/portable/src/con_main.c
./../../engine/portable/src/con_config.c
./../../engine/portable/src/con_bind.c
Expand Down
9 changes: 6 additions & 3 deletions doomsday/engine/data/cphelp.txt
Expand Up @@ -576,14 +576,17 @@ desc = 1=Render player view in wireframe mode.
desc = Frame counter.

[rend-info-lums]
desc = =Print lumobj count after rendering a frame.
desc = 1=Print lumobj count after rendering a frame.

[rend-light-ambient]
desc = Ambient light level.
[rend-info-rendpolys]
desc = 1=Print rendpoly pool state after rendering a frame.

[rend-light]
desc = 1=Render dynamic lights.

[rend-light-ambient]
desc = Ambient light level.

[rend-light-blend]
desc = Dynamic lights color blending mode: 0=normal, 1=additive, 2=no blending.

Expand Down
10 changes: 5 additions & 5 deletions doomsday/engine/portable/include/dd_help.h
Expand Up @@ -17,7 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

Expand All @@ -30,14 +30,14 @@

// Help string types.
enum {
HST_DESCRIPTION,
HST_CONSOLE_VARIABLE,
HST_DEFAULT_VALUE
HST_DESCRIPTION,
HST_CONSOLE_VARIABLE,
HST_DEFAULT_VALUE
};

void DD_InitHelp(void);
void DD_ShutdownHelp(void);
void *DH_Find(char *id);
void *DH_Find(const char *id);
char *DH_GetString(void *found, int type);

#endif
28 changes: 17 additions & 11 deletions doomsday/engine/portable/include/r_data.h
Expand Up @@ -135,7 +135,6 @@ typedef struct glcommand_vertex_s {
int index;
} glcommand_vertex_t;

#define RL_MAX_POLY_SIDES 64
#define RL_MAX_DIVS 64

// Rendpoly flags.
Expand Down Expand Up @@ -163,6 +162,14 @@ typedef struct {
float dist; // Distance to the vertex.
} rendpoly_vertex_t;

typedef struct rendpoly_wall_s {
float length;
struct div_t {
byte num;
float pos[RL_MAX_DIVS];
} divs[2]; // For wall segments (two vertices).
} rendpoly_wall_t;

// rendpoly_t is only for convenience; the data written in the rendering
// list data buffer is taken from this struct.
typedef struct rendpoly_s {
Expand All @@ -181,16 +188,9 @@ typedef struct rendpoly_s {

// The geometry:
byte numvertices; // Number of vertices for the poly.
rendpoly_vertex_t vertices[RL_MAX_POLY_SIDES];

// Wall specific data
struct rendpoly_wall_s {
float length;
struct div_t {
byte num;
float pos[RL_MAX_DIVS];
} divs[2]; // For wall segments (two vertices).
} wall;
rendpoly_vertex_t *vertices;

rendpoly_wall_t *wall; // Wall specific data if any.
} rendpoly_t;

// This is the dummy mobj_t used for blockring roots.
Expand Down Expand Up @@ -429,6 +429,12 @@ extern int levelFullBright;
extern int glowingTextures;
extern byte precacheSprites, precacheSkins;

void R_InitRendPolyPool(void);
rendpoly_t *R_AllocRendPoly(rendpolytype_t type, boolean isWall,
unsigned int numverts);
void R_FreeRendPoly(rendpoly_t *poly);
void R_InfoRendPolys(void);

void R_InitData(void);
void R_UpdateData(void);
void R_ShutdownData(void);
Expand Down
3 changes: 1 addition & 2 deletions doomsday/engine/portable/include/r_world.h
Expand Up @@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

Expand All @@ -45,7 +45,6 @@ void R_SetupLevel(char *level_id, int flags);
void R_InitLinks(void);
void R_SetupFog(void);
void R_SetupSky(void);
void R_SetSectorLinks(sector_t *sec);
sector_t *R_GetLinkedSector(sector_t *startsec, int plane);
void R_UpdatePlanes(void);
void R_ClearSectorFlags(void);
Expand Down
2 changes: 0 additions & 2 deletions doomsday/engine/portable/include/rend_dyn.h
Expand Up @@ -103,8 +103,6 @@ void DL_InitForNewFrame();
int DL_NewLuminous(void);
lumobj_t *DL_GetLuminous(int index);
void DL_ProcessSubsector(subsector_t *ssec);
void DL_ProcessWallSeg(lumobj_t * lum, seg_t *seg,
sector_t *frontsector);
dynlight_t *DL_GetSegLightLinks(int seg, int whichpart);
dynlight_t *DL_GetSubSecLightLinks(int ssec, int plane);

Expand Down
20 changes: 2 additions & 18 deletions doomsday/engine/portable/src/net_main.c
Expand Up @@ -44,6 +44,7 @@
#include "de_ui.h"

#include "rend_bias.h"
#include "rend_console.h"
#include "r_lgrid.h"

// MACROS ------------------------------------------------------------------
Expand Down Expand Up @@ -816,24 +817,7 @@ void Net_Drawer(void)
FR_TextOut(buf, 10, 10+10*(i+1));
} */
}
if(consoleShowFPS)
{
int x, y = 30, w, h;

// If the ui is active draw the counter a bit further down
if(ui_active)
y += 20;

sprintf(buf, "%.1f FPS", DD_GetFrameRate());
w = FR_TextWidth(buf) + 16;
h = FR_TextHeight(buf) + 16;
x = glScreenWidth - w - 10;
UI_GradientEx(x, y, w, h, 6, UI_COL(UIC_BG_MEDIUM),
UI_COL(UIC_BG_LIGHT), .5f, .5f);
UI_DrawRectEx(x, y, w, h, 6, false, UI_COL(UIC_BRD_HI), NULL, .5f, -1);
UI_Color(UI_COL(UIC_TEXT));
UI_TextOutEx(buf, x + 8, y + h / 2, false, true, UI_COL(UIC_TITLE), 1);
}
Rend_ConsoleFPS();

// Restore original matrix.
gl.MatrixMode(DGL_PROJECTION);
Expand Down
194 changes: 194 additions & 0 deletions doomsday/engine/portable/src/r_data.c
Expand Up @@ -47,6 +47,12 @@ typedef struct flathash_s {
flat_t *first;
} flathash_t;

typedef struct {
boolean inUse;
unsigned int numVerts;
rendpoly_t poly;
} rendpolydata_t;

// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------

// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
Expand Down Expand Up @@ -77,10 +83,198 @@ animgroup_t *groups;
// Glowing textures are always rendered fullbright.
int glowingTextures = true;

byte rendInfoRPolys = 0;

// PRIVATE DATA DEFINITIONS ------------------------------------------------

static unsigned int numrendpolys = 0;
static unsigned int maxrendpolys = 0;
static rendpolydata_t **rendPolys;

// CODE --------------------------------------------------------------------

void R_InfoRendPolys(void)
{
unsigned int i;

if(!rendInfoRPolys)
return;

Con_Printf("RP Count: %-4i\n", numrendpolys);

for(i = 0; i < numrendpolys; ++i)
{
Con_Printf("RP: %-4i %c %c (vtxs=%i)\n", i,
rendPolys[i]->inUse? 'Y':'N',
rendPolys[i]->poly.isWall? 'w':'p',
rendPolys[i]->numVerts);
}
}

/**
* Called at the start of each level.
*/
void R_InitRendPolyPool(void)
{
int i;
rendpoly_t *p;

numrendpolys = maxrendpolys = 0;
rendPolys = NULL;

// Allocate the common ones to get us started.
p = R_AllocRendPoly(RP_QUAD, true, 4); // wall
R_FreeRendPoly(p); // mark unused.

// sprites/models use rendpolys with 1/2 vtxs to unify lighting.
for(i = 1; i < 16; ++i)
{
p = R_AllocRendPoly(i < 3? RP_NONE:RP_FLAT, false, i);
R_FreeRendPoly(p); // mark unused.
}
}

/**
* Re-uses existing rendpolys whenever possible, there are a few conditions
* which prevent this:
*
* There is no unused rendpoly which:
* a) has enough vertices.
* b) matches the "isWall" specification.
*
* @param numverts The number of verts required.
* @param isWall <code>true</code>= wall data is required.
*
* @return Ptr to a suitable rendpoly.
*/
static rendpoly_t *R_NewRendPoly(unsigned int numverts, boolean isWall)
{
unsigned int idx;
rendpoly_t *p;
boolean found = false;

for(idx = 0; idx < maxrendpolys; ++idx)
{
if(rendPolys[idx]->inUse)
continue;

if(rendPolys[idx]->numVerts == numverts &&
rendPolys[idx]->poly.isWall == isWall)
{
// Use this one.
rendPolys[idx]->inUse = true;
return &rendPolys[idx]->poly;
}
else if(rendPolys[idx]->numVerts == 0)
{
// There is an unused one but we haven't allocated verts yet.
numrendpolys++;
found = true;
break;
}
}

if(!found)
{
// We may need to allocate more.
if(++numrendpolys > maxrendpolys)
{
unsigned int i, newCount;
rendpolydata_t *newPolyData, *ptr;

maxrendpolys = (maxrendpolys > 0? maxrendpolys * 2 : 8);

rendPolys =
Z_Realloc(rendPolys, sizeof(rendpolydata_t*) * maxrendpolys,
PU_LEVEL);

newCount = maxrendpolys - numrendpolys + 1;

newPolyData =
Z_Malloc(sizeof(rendpolydata_t) * newCount, PU_LEVEL, 0);

ptr = newPolyData;
for(i = numrendpolys-1; i < maxrendpolys; ++i, ptr++)
{
ptr->inUse = false;
ptr->numVerts = 0;
rendPolys[i] = ptr;
}
}
idx = numrendpolys - 1;
}

p = &rendPolys[idx]->poly;
rendPolys[idx]->inUse = true;
rendPolys[idx]->numVerts = numverts;

p->numvertices = numverts;
p->vertices = Z_Malloc(sizeof(rendpoly_vertex_t) * p->numvertices,
PU_LEVEL, 0);
p->isWall = isWall;

if(p->isWall) // Its a wall so allocate the wall data.
p->wall = Z_Malloc(sizeof(rendpoly_wall_t), PU_LEVEL, 0);
else
p->wall = NULL;

return p;
}

/**
* Retrieves a suitable rendpoly. Possibly allocates a new one if necessary.
*
* @param type The type of the poly to create.
* @param isWall <code>true</code>= wall data is required for this poly.
* @param numverts The number of verts required.
*
* @return Ptr to a suitable rendpoly.
*/
rendpoly_t *R_AllocRendPoly(rendpolytype_t type, boolean isWall,
unsigned int numverts)
{
rendpoly_t *poly = R_NewRendPoly(numverts, isWall);

poly->type = type;

poly->flags = 0;
poly->texoffx = 0;
poly->texoffy = 0;
poly->interpos = 0;
poly->lights = 0;
poly->decorlightmap = 0;
poly->sector = 0;
poly->blendmode = BM_NORMAL;

return poly;
}

/**
* Doesn't actually free anything. Instead, mark it as unused ready for the
* next time a rendpoly with this number of verts is needed.
*
* @param poly Ptr to the poly to mark unused.
*/
void R_FreeRendPoly(rendpoly_t *poly)
{
unsigned int i;

if(!poly)
return;

for(i = 0; i < numrendpolys; ++i)
{
if(&rendPolys[i]->poly == poly)
{
rendPolys[i]->inUse = false;
return;
}
}
#if _DEBUG
Con_Message("R_FreeRendPoly: Dangling poly ptr!\n");
#endif
}

void R_ShutdownData(void)
{
}
Expand Down

0 comments on commit 35de1c0

Please sign in to comment.