mirror of
https://github.com/yquake2/yquake2
synced 2026-08-20 00:26:04 -04:00
GL3: Make gl3drawCmd_t smaller. Step 2: Move transModelMat elsewhere
Most of the time the transformation matrix is the identity matrix anyway, so let's not waste 64 bytes in every gl3drawCmd_t... Now it's just an index into a hmm_mat4 array. Index 0 is always the identity matrix, if a different one is required, GL3_SetDrawCmdTransMatrix(&drawCmd, mat) can be used to set it - it will be added to that array and its index is set in drawCmd. Bonus: This doesn't only reduce the gl3drawCmd_t to 36 bytes but also makes comparing two of them a lot cheaper: Instead of comparing the values of the matrices, we can just compare their index. Also frees up one flag (`flag & DCFlag_IsIdentityMat` is replaced by `transModelMatIdx == 0`).
This commit is contained in:
parent
2013aecee3
commit
964492e0fd
4 changed files with 49 additions and 64 deletions
|
|
@ -136,11 +136,12 @@ static cvar_t *gl_znear;
|
|||
DA_TYPEDEF(gl3_3D_vtx_t, Vtx3DArray_t);
|
||||
DA_TYPEDEF(GLushort, UShortArray_t);
|
||||
DA_TYPEDEF(gl3drawCmd_t, DrawCommandArray_t);
|
||||
DA_TYPEDEF(hmm_mat4, Mat4Array_t);
|
||||
// dynamic arrays to batch all consecutive 3D draws (with gl3_3D_vtx_t) with same texture to reduce drawcalls
|
||||
static Vtx3DArray_t vtxBuf = {0};
|
||||
static UShortArray_t idxBuf = {0};
|
||||
static DrawCommandArray_t drawCmds = {0};
|
||||
|
||||
static Mat4Array_t transModelMats = {0};
|
||||
|
||||
// Yaw-Pitch-Roll
|
||||
// equivalent to R_z * R_y * R_x where R_x is the trans matrix for rotating around X axis for aroundXdeg
|
||||
|
|
@ -190,7 +191,7 @@ GL3_RotateUni3DforEntity(entity_t *e)
|
|||
// if replaceTransModelMat is true, the existing value of drawCmd->transModelMat
|
||||
// is ignored and it's replaced with the one calculated here (otherwise they're multiplied)
|
||||
void
|
||||
GL3_RotateForEntity(entity_t *e, gl3drawCmd_t* drawCmd, qboolean replaceTransModelMat)
|
||||
GL3_RotateForEntity(entity_t *e, gl3drawCmd_t* drawCmd)
|
||||
{
|
||||
// TODO: shortcut for "not rotated at all"?
|
||||
|
||||
|
|
@ -203,11 +204,7 @@ GL3_RotateForEntity(entity_t *e, gl3drawCmd_t* drawCmd, qboolean replaceTransMod
|
|||
transMat.Elements[3][i] = e->origin[i]; // set translation
|
||||
}
|
||||
|
||||
if (replaceTransModelMat)
|
||||
drawCmd->transModelMat = transMat;
|
||||
else
|
||||
drawCmd->transModelMat = HMM_MultiplyMat4(drawCmd->transModelMat, transMat);
|
||||
drawCmd->flags &= ~DCFlag_IsIdentityMat;
|
||||
GL3_SetDrawCmdTransMatrix(drawCmd, transMat);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -551,6 +548,9 @@ GL3_Init(void)
|
|||
GetPCXPalette (&colormap, d_8to24table);
|
||||
free(colormap);
|
||||
|
||||
da_clear(transModelMats);
|
||||
da_add(transModelMats, gl3_identityMat4); // element 0 is always the identity matrix
|
||||
|
||||
GL3_Register();
|
||||
|
||||
/* set our "safe" mode */
|
||||
|
|
@ -694,6 +694,7 @@ GL3_Shutdown(void)
|
|||
da_free(vtxBuf);
|
||||
da_free(idxBuf);
|
||||
da_free(drawCmds);
|
||||
da_free(transModelMats);
|
||||
|
||||
/* shutdown OS specific OpenGL stuff like contexts, etc. */
|
||||
GL3_ShutdownContext();
|
||||
|
|
@ -765,21 +766,21 @@ void GL3_Draw3DBatchesNow()
|
|||
|
||||
// set curState to something that reflects the actual state, as far as possible,
|
||||
// and otherwise makes sure it'll be set in the loop
|
||||
gl3drawCmd_t curState = GL3_CreateDrawCmd(true);
|
||||
curState.flags = ~drawCmds.p[0].flags; // just the opposite flags of the first element
|
||||
gl3drawCmd_t curState = GL3_CreateDrawCmd();
|
||||
|
||||
curState.texnum = gl3state.currenttexture;
|
||||
curState.lmtexnum = gl3state.currentlightmap;
|
||||
curState.alpha = gl3state.uni3DData.alpha;
|
||||
curState.scroll = gl3state.uni3DData.scroll;
|
||||
curState.lightScaleForTurb = gl3state.uni3DData.lightScaleForTurb;
|
||||
|
||||
gl3ShaderInfo_t* shader = NULL;
|
||||
// for the next two the approach is setting a value that
|
||||
// is different from the one in the first drawCmd, to make sure
|
||||
// the corresponding state is set in the first iteration
|
||||
curState.flags = ~drawCmds.p[0].flags; // just the opposite flags of the first element
|
||||
curState.transModelMatIdx = drawCmds.p[0].transModelMatIdx + 1;
|
||||
|
||||
// .. but at least set the identity mat so DCFlag_IsIdentityMat can be set
|
||||
// as a sane default
|
||||
curState.flags |= DCFlag_IsIdentityMat;
|
||||
gl3state.uni3DData.transModelMat4 = gl3_identityMat4;
|
||||
GL3_UpdateUBO3D();
|
||||
gl3ShaderInfo_t* shader = NULL;
|
||||
|
||||
for(int i=0, n=da_count(drawCmds); i < n; ++i)
|
||||
{
|
||||
|
|
@ -862,20 +863,11 @@ void GL3_Draw3DBatchesNow()
|
|||
updateUni3D = true;
|
||||
}
|
||||
|
||||
if((flags & DCFlag_IsIdentityMat) != (curFlags & DCFlag_IsIdentityMat))
|
||||
if(cmd->transModelMatIdx != curState.transModelMatIdx)
|
||||
{
|
||||
// one is the identity matrix, the other isn't => we need to update
|
||||
gl3state.uni3DData.transModelMat4 = cmd->transModelMat;
|
||||
gl3state.uni3DData.transModelMat4 = da_get(transModelMats, cmd->transModelMatIdx);
|
||||
updateUni3D = true;
|
||||
}
|
||||
else if( !(flags & DCFlag_IsIdentityMat) )
|
||||
{
|
||||
// neither is an identity matrix
|
||||
// TODO: could check if they're identical and only update if not
|
||||
gl3state.uni3DData.transModelMat4 = cmd->transModelMat;
|
||||
updateUni3D = true;
|
||||
}
|
||||
// else both are the identity matrix - nothing to do
|
||||
|
||||
if(updateUni3D)
|
||||
GL3_UpdateUBO3D();
|
||||
|
|
@ -891,13 +883,15 @@ void GL3_Draw3DBatchesNow()
|
|||
da_clear(idxBuf);
|
||||
da_clear(drawCmds);
|
||||
|
||||
da_setcount(transModelMats, 1); // keep index 0 (identity matrix)
|
||||
|
||||
// restore sane default for other draw operations (models, particles, 2D)
|
||||
int curFlags = curState.flags;
|
||||
if( !(curFlags & DCFlag_IsIdentityMat) )
|
||||
if(curState.transModelMatIdx != 0)
|
||||
{
|
||||
gl3state.uni3DData.transModelMat4 = gl3_identityMat4;
|
||||
GL3_UpdateUBO3D();
|
||||
}
|
||||
int curFlags = curState.flags;
|
||||
if(curFlags & DCFlag_Blend)
|
||||
glDisable(GL_BLEND);
|
||||
if(curFlags & DCFlag_DisableDepthMask)
|
||||
|
|
@ -910,7 +904,8 @@ void GL3_Draw3DBatchesNow()
|
|||
static qboolean drawStateEqual(const gl3drawCmd_t* a, const gl3drawCmd_t* b)
|
||||
{
|
||||
if( a->flags != b->flags || a->shaderIdx != b->shaderIdx
|
||||
|| a->texnum != b->texnum || a->lmtexnum != b->lmtexnum )
|
||||
|| a->texnum != b->texnum || a->lmtexnum != b->lmtexnum
|
||||
|| a->transModelMatIdx != b->transModelMatIdx )
|
||||
return false;
|
||||
|
||||
int flags = a->flags; // at this point we know the flags are identical
|
||||
|
|
@ -928,24 +923,19 @@ static qboolean drawStateEqual(const gl3drawCmd_t* a, const gl3drawCmd_t* b)
|
|||
return false;
|
||||
|
||||
if((flags & DCFlag_UseLmStyles) && !lmstylesEqual(a->styles, b->styles))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !(flags & DCFlag_IsIdentityMat) )
|
||||
{
|
||||
const float* atm = a->transModelMat.Elements[0];
|
||||
const float* btm = b->transModelMat.Elements[0];
|
||||
for(int i=0; i<16; ++i)
|
||||
{
|
||||
if(atm[i] != btm[i]) // TODO: tolerance?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GL3_SetDrawCmdTransMatrix(gl3drawCmd_t* drawCmd, hmm_mat4 mat)
|
||||
{
|
||||
int idx = da_count(transModelMats);
|
||||
da_add(transModelMats, mat);
|
||||
drawCmd->transModelMatIdx = idx;
|
||||
}
|
||||
|
||||
// assumes gl3state.v[ab]o3D are bound
|
||||
// buffers and draws gl3_3D_vtx_t vertices
|
||||
// drawMode is something like GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN or whatever
|
||||
|
|
@ -1033,7 +1023,7 @@ GL3_DrawBeam(entity_t *e)
|
|||
int i;
|
||||
enum { NUM_BEAM_SEGS = 6 };
|
||||
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(true);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
|
||||
vec3_t perpvec;
|
||||
vec3_t direction, normalized_direction;
|
||||
|
|
@ -1109,7 +1099,7 @@ GL3_DrawSpriteModel(entity_t *e, gl3model_t *currentmodel)
|
|||
dsprite_t *psprite;
|
||||
gl3image_t *skin;
|
||||
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(true);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
|
||||
/* don't even bother culling, because it's just
|
||||
a single polygon without a surface cache */
|
||||
|
|
@ -1180,7 +1170,7 @@ static void
|
|||
GL3_DrawNullModel(entity_t *currententity)
|
||||
{
|
||||
vec3_t shadelight;
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(true);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
|
||||
if(currententity->flags & RF_TRANSLUCENT)
|
||||
drawCmd.flags |= DCFlag_DisableDepthMask;
|
||||
|
|
@ -1194,7 +1184,7 @@ GL3_DrawNullModel(entity_t *currententity)
|
|||
GL3_LightPoint(currententity, currententity->origin, shadelight);
|
||||
}
|
||||
|
||||
GL3_RotateForEntity(currententity, &drawCmd, true);
|
||||
GL3_RotateForEntity(currententity, &drawCmd);
|
||||
|
||||
drawCmd.alpha = 1.0f;
|
||||
for(int i=0; i<3; ++i)
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ GL3_DrawGLPoly(msurface_t *fa, gl3drawCmd_t drawCmd)
|
|||
{
|
||||
glpoly_t *p = fa->polys;
|
||||
|
||||
|
||||
GL3_BufferAndDraw3D(p->vertices, p->numverts, GL_TRIANGLE_FAN, drawCmd);
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +295,7 @@ GL3_DrawAlphaSurfaces(void)
|
|||
msurface_t *s;
|
||||
|
||||
/* go back to the world matrix */
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(true);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
drawCmd.flags |= DCFlag_Blend;
|
||||
|
||||
for (s = gl3_alpha_surfaces; s != NULL; s = s->texturechain)
|
||||
|
|
@ -344,7 +343,7 @@ DrawTextureChains(entity_t *currententity)
|
|||
|
||||
c_visible_textures = 0;
|
||||
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(true);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
|
||||
for (i = 0, image = gl3textures; i < numgl3textures; i++, image++)
|
||||
{
|
||||
|
|
@ -477,7 +476,7 @@ GL3_DrawBrushModel(entity_t *e, gl3model_t *currentmodel)
|
|||
return;
|
||||
}
|
||||
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(false);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
if(e->flags & RF_TRANSLUCENT)
|
||||
drawCmd.flags |= DCFlag_DisableDepthMask;
|
||||
|
||||
|
|
@ -527,7 +526,7 @@ GL3_DrawBrushModel(entity_t *e, gl3model_t *currentmodel)
|
|||
|
||||
e->angles[0] = -e->angles[0];
|
||||
e->angles[2] = -e->angles[2];
|
||||
GL3_RotateForEntity(e, &drawCmd, true);
|
||||
GL3_RotateForEntity(e, &drawCmd);
|
||||
e->angles[0] = -e->angles[0];
|
||||
e->angles[2] = -e->angles[2];
|
||||
|
||||
|
|
|
|||
|
|
@ -253,8 +253,6 @@ GL3_EmitWaterPolys(msurface_t *fa, gl3drawCmd_t drawCmd)
|
|||
drawCmd.lightScaleForTurb = fa->texinfo->image->is_lava ? 1.0f : 0.5f;
|
||||
drawCmd.flags |= DCFlag_UseLightScaleForTurb;
|
||||
|
||||
|
||||
|
||||
GL3_SetDrawCmdShader(&drawCmd, &gl3state.si3Dturb);
|
||||
|
||||
for (bp = fa->polys; bp != NULL; bp = bp->next)
|
||||
|
|
@ -684,7 +682,7 @@ GL3_DrawSkyBox(void)
|
|||
}
|
||||
}
|
||||
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd(false);
|
||||
gl3drawCmd_t drawCmd = GL3_CreateDrawCmd();
|
||||
|
||||
// glPushMatrix();
|
||||
|
||||
|
|
@ -697,7 +695,8 @@ GL3_DrawSkyBox(void)
|
|||
hmm_vec3 rotAxis = HMM_Vec3(skyaxis[0], skyaxis[1], skyaxis[2]);
|
||||
modMVmat = HMM_MultiplyMat4(modMVmat, HMM_Rotate(r_newrefdef.time * skyrotate, rotAxis));
|
||||
}
|
||||
drawCmd.transModelMat = modMVmat;
|
||||
|
||||
GL3_SetDrawCmdTransMatrix(&drawCmd, modMVmat);
|
||||
|
||||
GL3_SetDrawCmdShader(&drawCmd, &gl3state.si3Dsky);
|
||||
|
||||
|
|
|
|||
|
|
@ -278,12 +278,13 @@ typedef struct
|
|||
|
||||
// drawcommands using gl3_3D_vtx_t, for batching
|
||||
typedef struct gl3drawCmd_s {
|
||||
hmm_mat4 transModelMat;
|
||||
|
||||
GLuint texnum;
|
||||
signed char lmtexnum;
|
||||
signed char shaderIdx;
|
||||
|
||||
// index into gl3_main.c transModelMats; 0 always is identity matrix
|
||||
unsigned short transModelMatIdx;
|
||||
|
||||
float scroll; // for gl3state.uni3DData.scroll
|
||||
float lightScaleForTurb; // for gl3state.uni3DData.lightScaleForTurb
|
||||
float alpha; // either part of color or for gl3state.uni3DData.alpha
|
||||
|
|
@ -305,20 +306,15 @@ enum gl3drawCmd_Flags {
|
|||
DCFlag_UseScroll = 16,
|
||||
DCFlag_UseLmStyles = 32,
|
||||
DCFlag_UseLightScaleForTurb = 64,
|
||||
DCFlag_IsIdentityMat = 128, // avoids comparing the matrix in many cases
|
||||
|
||||
// TODO: DCFlag_SameAsPrevious = 255 for "don't check, just merge into previous command"?
|
||||
};
|
||||
|
||||
// create an "empty" gl3drawCmd_t with sane defaults
|
||||
static inline gl3drawCmd_t
|
||||
GL3_CreateDrawCmd(qboolean identityTrans)
|
||||
GL3_CreateDrawCmd(void)
|
||||
{
|
||||
gl3drawCmd_t ret = {0};
|
||||
if(identityTrans) {
|
||||
ret.transModelMat = gl3_identityMat4;
|
||||
ret.flags = DCFlag_IsIdentityMat;
|
||||
}
|
||||
ret.alpha = 1.0f;
|
||||
ret.styles[0] = 255;
|
||||
ret.lmtexnum = -1;
|
||||
|
|
@ -468,9 +464,10 @@ GL3_BindEBO(GLuint ebo)
|
|||
|
||||
extern void GL3_BufferAndDraw3D(const gl3_3D_vtx_t* verts, int numVerts, GLenum drawMode, gl3drawCmd_t drawCmd);
|
||||
extern void GL3_Draw3DBatchesNow(void);
|
||||
extern void GL3_SetDrawCmdTransMatrix(gl3drawCmd_t* drawCmd, hmm_mat4 mat);
|
||||
|
||||
extern void GL3_RotateUni3DforEntity(entity_t *e);
|
||||
extern void GL3_RotateForEntity(entity_t *e, gl3drawCmd_t* drawCmd, qboolean replaceTransModelMat);
|
||||
extern void GL3_RotateForEntity(entity_t *e, gl3drawCmd_t* drawCmd);
|
||||
|
||||
// gl3_sdl.c
|
||||
extern int GL3_InitContext(void* win);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue