GL1 unified draw calls, 7

Changed "buffer" functions (vertex, single/mtex, color) to macros.
Macros eliminate the function call overhead, resulting in faster
execution times. Depending of the hardware, there might be a
performance increase of almost 10%.
This forced the buffer to be exposed as global.
Not worth doing this for 2D elements though.
This commit is contained in:
Jaime Moreira 2024-07-27 23:08:46 -04:00
parent 826f4816f6
commit 94c4bf2df7
7 changed files with 118 additions and 142 deletions

View file

@ -29,33 +29,20 @@
#include "header/local.h" #include "header/local.h"
#define MAX_VERTICES 16384 #define GLBUFFER_RESET vtx_ptr = idx_ptr = 0; gl_buf.vt = gl_buf.tx = gl_buf.cl = 0;
#define MAX_INDICES (MAX_VERTICES * 4)
typedef struct // 832k aprox. glbuffer_t gl_buf; // our drawing buffer, used globally
{
buffered_draw_t type;
GLfloat static GLushort vtx_ptr, idx_ptr; // pointers for array positions in gl_buf
vtx[MAX_VERTICES * 3], // vertexes
tex[MAX_TEXTURE_UNITS][MAX_VERTICES * 2], // texture coords
clr[MAX_VERTICES * 4]; // color components
GLushort
idx[MAX_INDICES], // indices
vtx_ptr, idx_ptr; // pointers for array positions
int texture[MAX_TEXTURE_UNITS];
int flags; // entity flags
float alpha;
} glbuffer_t;
glbuffer_t gl_buf;
GLuint vt, tx, cl; // indices for arrays in gl_buf
extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
void
R_ResetGLBuffer(void)
{
GLBUFFER_RESET
}
void void
R_ApplyGLBuffer(void) R_ApplyGLBuffer(void)
{ {
@ -64,7 +51,7 @@ R_ApplyGLBuffer(void)
qboolean texture, mtex, alpha, color, alias, texenv_set; qboolean texture, mtex, alpha, color, alias, texenv_set;
float fovy, dist; float fovy, dist;
if (gl_buf.vtx_ptr == 0 || gl_buf.idx_ptr == 0) if (vtx_ptr == 0 || idx_ptr == 0)
{ {
return; return;
} }
@ -224,7 +211,7 @@ R_ApplyGLBuffer(void)
} }
// All set, we can finally draw // All set, we can finally draw
glDrawElements(GL_TRIANGLES, gl_buf.idx_ptr, GL_UNSIGNED_SHORT, gl_buf.idx); glDrawElements(GL_TRIANGLES, idx_ptr, GL_UNSIGNED_SHORT, gl_buf.idx);
// ... and now, turn back everything as it was // ... and now, turn back everything as it was
if (color) if (color)
@ -277,7 +264,7 @@ R_ApplyGLBuffer(void)
} }
} }
gl_buf.vtx_ptr = gl_buf.idx_ptr = 0; GLBUFFER_RESET
} }
void void
@ -304,46 +291,46 @@ R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy,
{ {
static const GLushort idx_max = MAX_INDICES - 7; static const GLushort idx_max = MAX_INDICES - 7;
static const GLushort vtx_max = MAX_VERTICES - 5; static const GLushort vtx_max = MAX_VERTICES - 5;
unsigned int i;
if (gl_buf.idx_ptr > idx_max || gl_buf.vtx_ptr > vtx_max) if (idx_ptr > idx_max || vtx_ptr > vtx_max)
{ {
R_ApplyGLBuffer(); R_ApplyGLBuffer();
} }
i = gl_buf.vtx_ptr * 2; // vertex index
// "Quad" = 2-triangle GL_TRIANGLE_FAN // "Quad" = 2-triangle GL_TRIANGLE_FAN
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr; gl_buf.idx[idx_ptr] = vtx_ptr;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+1; gl_buf.idx[idx_ptr+1] = vtx_ptr+1;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+2; gl_buf.idx[idx_ptr+2] = vtx_ptr+2;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr; gl_buf.idx[idx_ptr+3] = vtx_ptr;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+2; gl_buf.idx[idx_ptr+4] = vtx_ptr+2;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+3; gl_buf.idx[idx_ptr+5] = vtx_ptr+3;
idx_ptr += 6;
// up left corner coords // up left corner coords
gl_buf.vtx[i] = ul_vx; gl_buf.vtx[gl_buf.vt] = ul_vx;
gl_buf.vtx[i+1] = ul_vy; gl_buf.vtx[gl_buf.vt+1] = ul_vy;
// up right // up right
gl_buf.vtx[i+2] = dr_vx; gl_buf.vtx[gl_buf.vt+2] = dr_vx;
gl_buf.vtx[i+3] = ul_vy; gl_buf.vtx[gl_buf.vt+3] = ul_vy;
// down right // down right
gl_buf.vtx[i+4] = dr_vx; gl_buf.vtx[gl_buf.vt+4] = dr_vx;
gl_buf.vtx[i+5] = dr_vy; gl_buf.vtx[gl_buf.vt+5] = dr_vy;
// and finally, down left // and finally, down left
gl_buf.vtx[i+6] = ul_vx; gl_buf.vtx[gl_buf.vt+6] = ul_vx;
gl_buf.vtx[i+7] = dr_vy; gl_buf.vtx[gl_buf.vt+7] = dr_vy;
gl_buf.tex[0][i] = ul_tx; gl_buf.tex[0][gl_buf.tx] = ul_tx;
gl_buf.tex[0][i+1] = ul_ty; gl_buf.tex[0][gl_buf.tx+1] = ul_ty;
gl_buf.tex[0][i+2] = dr_tx; gl_buf.tex[0][gl_buf.tx+2] = dr_tx;
gl_buf.tex[0][i+3] = ul_ty; gl_buf.tex[0][gl_buf.tx+3] = ul_ty;
gl_buf.tex[0][i+4] = dr_tx; gl_buf.tex[0][gl_buf.tx+4] = dr_tx;
gl_buf.tex[0][i+5] = dr_ty; gl_buf.tex[0][gl_buf.tx+5] = dr_ty;
gl_buf.tex[0][i+6] = ul_tx; gl_buf.tex[0][gl_buf.tx+6] = ul_tx;
gl_buf.tex[0][i+7] = dr_ty; gl_buf.tex[0][gl_buf.tx+7] = dr_ty;
gl_buf.vtx_ptr += 4; vtx_ptr += 4;
gl_buf.vt += 8;
gl_buf.tx += 8;
} }
/* /*
@ -354,8 +341,8 @@ R_SetBufferIndices(GLenum type, GLuint vertices_num)
{ {
int i; int i;
if ( gl_buf.vtx_ptr + vertices_num >= MAX_VERTICES || if ( vtx_ptr + vertices_num >= MAX_VERTICES ||
gl_buf.idx_ptr + ( (vertices_num - 2) * 3 ) >= MAX_INDICES ) idx_ptr + ( (vertices_num - 2) * 3 ) >= MAX_INDICES )
{ {
R_ApplyGLBuffer(); R_ApplyGLBuffer();
} }
@ -365,9 +352,10 @@ R_SetBufferIndices(GLenum type, GLuint vertices_num)
case GL_TRIANGLE_FAN: case GL_TRIANGLE_FAN:
for (i = 0; i < vertices_num-2; i++) for (i = 0; i < vertices_num-2; i++)
{ {
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr; gl_buf.idx[idx_ptr] = vtx_ptr;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1; gl_buf.idx[idx_ptr+1] = vtx_ptr+i+1;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2; gl_buf.idx[idx_ptr+2] = vtx_ptr+i+2;
idx_ptr += 3;
} }
break; break;
case GL_TRIANGLE_STRIP: case GL_TRIANGLE_STRIP:
@ -375,16 +363,17 @@ R_SetBufferIndices(GLenum type, GLuint vertices_num)
{ {
if (i % 2 == 0) if (i % 2 == 0)
{ {
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i; gl_buf.idx[idx_ptr] = vtx_ptr+i;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1; gl_buf.idx[idx_ptr+1] = vtx_ptr+i+1;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2; gl_buf.idx[idx_ptr+2] = vtx_ptr+i+2;
} }
else // backwards order else // backwards order
{ {
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+2; gl_buf.idx[idx_ptr] = vtx_ptr+i+2;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i+1; gl_buf.idx[idx_ptr+1] = vtx_ptr+i+1;
gl_buf.idx[gl_buf.idx_ptr++] = gl_buf.vtx_ptr+i; gl_buf.idx[idx_ptr+2] = vtx_ptr+i;
} }
idx_ptr += 3;
} }
break; break;
default: default:
@ -392,58 +381,6 @@ R_SetBufferIndices(GLenum type, GLuint vertices_num)
return; return;
} }
// These affect the functions that follow in this file // GLBUFFER_VERTEX() must be called as many times as vertices_num
vt = gl_buf.vtx_ptr * 3; // vertex index vtx_ptr += vertices_num;
tx = gl_buf.vtx_ptr * 2; // texcoord index
cl = gl_buf.vtx_ptr * 4; // color index
// R_BufferVertex() must be called as many times as vertices_num
gl_buf.vtx_ptr += vertices_num;
}
/*
* Adds a single vertex to buffer
*/
void
R_BufferVertex(GLfloat x, GLfloat y, GLfloat z)
{
gl_buf.vtx[vt++] = x;
gl_buf.vtx[vt++] = y;
gl_buf.vtx[vt++] = z;
}
/*
* Adds texture coordinates for color texture (no lightmap coords)
*/
void
R_BufferSingleTex(GLfloat s, GLfloat t)
{
// tx should be set before this is called, by R_SetBufferIndices
gl_buf.tex[0][tx++] = s;
gl_buf.tex[0][tx++] = t;
}
/*
* Adds texture coordinates for color and lightmap
*/
void
R_BufferMultiTex(GLfloat cs, GLfloat ct, GLfloat ls, GLfloat lt)
{
gl_buf.tex[0][tx] = cs;
gl_buf.tex[0][tx+1] = ct;
gl_buf.tex[1][tx] = ls;
gl_buf.tex[1][tx+1] = lt;
tx += 2;
}
/*
* Adds color components of vertex
*/
void
R_BufferColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
gl_buf.clr[cl++] = r;
gl_buf.clr[cl++] = g;
gl_buf.clr[cl++] = b;
gl_buf.clr[cl++] = a;
} }

View file

@ -46,9 +46,9 @@ R_RenderDlight(dlight_t *light)
vtx [ i ] = light->origin [ i ] - vpn [ i ] * rad; vtx [ i ] = light->origin [ i ] - vpn [ i ] * rad;
} }
R_BufferVertex( vtx[0], vtx[1], vtx[2] ); GLBUFFER_VERTEX( vtx[0], vtx[1], vtx[2] )
R_BufferColor( light->color[0] * 0.2, light->color[1] * 0.2, GLBUFFER_COLOR( light->color[0] * 0.2, light->color[1] * 0.2,
light->color[2] * 0.2, 1 ); light->color[2] * 0.2, 1 )
for ( i = 16; i >= 0; i-- ) for ( i = 16; i >= 0; i-- )
{ {
@ -60,8 +60,8 @@ R_RenderDlight(dlight_t *light)
+ vup [ j ] * sin( a ) * rad; + vup [ j ] * sin( a ) * rad;
} }
R_BufferVertex( vtx[0], vtx[1], vtx[2] ); GLBUFFER_VERTEX( vtx[0], vtx[1], vtx[2] )
R_BufferColor( 0, 0, 0, 1 ); GLBUFFER_COLOR( 0, 0, 0, 1 )
} }
} }

View file

@ -148,6 +148,8 @@ void LM_FreeLightmapBuffers(void);
void Scrap_Free(void); void Scrap_Free(void);
void Scrap_Init(void); void Scrap_Init(void);
extern void R_ResetGLBuffer(void);
void void
R_RotateForEntity(entity_t *e) R_RotateForEntity(entity_t *e)
{ {
@ -1641,6 +1643,7 @@ RI_Init(void)
Mod_Init(); Mod_Init();
R_InitParticleTexture(); R_InitParticleTexture();
Draw_InitLocal(); Draw_InitLocal();
R_ResetGLBuffer();
return true; return true;
} }

View file

@ -169,11 +169,11 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
index_xyz = order[2]; index_xyz = order[2];
order += 3; order += 3;
R_BufferVertex(s_lerped[index_xyz][0], GLBUFFER_VERTEX(s_lerped[index_xyz][0],
s_lerped[index_xyz][1], s_lerped[index_xyz][2]); s_lerped[index_xyz][1], s_lerped[index_xyz][2])
R_BufferColor(shadelight[0], shadelight[1], GLBUFFER_COLOR(shadelight[0], shadelight[1],
shadelight[2], alpha); shadelight[2], alpha)
} }
while (--count); while (--count);
} }
@ -191,13 +191,13 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
/* normals and vertexes come from the frame list */ /* normals and vertexes come from the frame list */
l = shadedots[verts[index_xyz].lightnormalindex]; l = shadedots[verts[index_xyz].lightnormalindex];
R_BufferVertex(s_lerped[index_xyz][0], GLBUFFER_VERTEX(s_lerped[index_xyz][0],
s_lerped[index_xyz][1], s_lerped[index_xyz][2]); s_lerped[index_xyz][1], s_lerped[index_xyz][2])
R_BufferSingleTex(tex[0], tex[1]); GLBUFFER_SINGLETEX(tex[0], tex[1])
R_BufferColor(l * shadelight[0], l * shadelight[1], GLBUFFER_COLOR(l * shadelight[0], l * shadelight[1],
l * shadelight[2], alpha); l * shadelight[2], alpha)
} }
while (--count); while (--count);
} }
@ -255,7 +255,7 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
point[1] -= shadevector[1] * (point[2] + lheight); point[1] -= shadevector[1] * (point[2] + lheight);
point[2] = height; point[2] = height;
R_BufferVertex( point[0], point[1], point[2] ); GLBUFFER_VERTEX( point[0], point[1], point[2] )
order += 3; order += 3;
} }

View file

@ -69,8 +69,8 @@ R_DrawGLPoly(msurface_t *fa)
for ( i = 0; i < nv; i++, v += VERTEXSIZE ) for ( i = 0; i < nv; i++, v += VERTEXSIZE )
{ {
R_BufferVertex(v[0], v[1], v[2]); GLBUFFER_VERTEX( v[0], v[1], v[2] )
R_BufferSingleTex(v[3] + scroll, v[4]); GLBUFFER_SINGLETEX( v[3] + scroll, v[4] )
} }
} }
@ -594,8 +594,8 @@ R_RenderLightmappedPoly(entity_t *currententity, msurface_t *surf)
for (i = 0; i < nv; i++, v += VERTEXSIZE) for (i = 0; i < nv; i++, v += VERTEXSIZE)
{ {
R_BufferVertex( v[0], v[1], v[2] ); GLBUFFER_VERTEX( v[0], v[1], v[2] )
R_BufferMultiTex( v[3] + scroll, v[4], v[5], v[6] ); GLBUFFER_MULTITEX( v[3] + scroll, v[4], v[5], v[6] )
} }
} }

View file

@ -310,8 +310,8 @@ R_EmitWaterPolys(msurface_t *fa)
s = os + r_turbsin [ (int) ( ( ot * 0.125 + rdt ) * TURBSCALE ) & 255 ] + scroll; s = os + r_turbsin [ (int) ( ( ot * 0.125 + rdt ) * TURBSCALE ) & 255 ] + scroll;
t = ot + r_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ]; t = ot + r_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ];
R_BufferVertex( v[0], v[1], v[2] ); GLBUFFER_VERTEX( v[0], v[1], v[2] )
R_BufferSingleTex( s * ( 1.0 / 64 ), t * ( 1.0 / 64 ) ); GLBUFFER_SINGLETEX( s * ( 1.0 / 64 ), t * ( 1.0 / 64 ) )
} }
} }
} }

View file

@ -53,6 +53,10 @@
#define MAX_TEXTURE_UNITS 2 #define MAX_TEXTURE_UNITS 2
#define GL_LIGHTMAP_FORMAT GL_RGBA #define GL_LIGHTMAP_FORMAT GL_RGBA
// GL buffer definitions
#define MAX_VERTICES 16384
#define MAX_INDICES (MAX_VERTICES * 4)
/* up / down */ /* up / down */
#define PITCH 0 #define PITCH 0
@ -118,10 +122,29 @@ typedef enum
buf_shadow buf_shadow
} buffered_draw_t; } buffered_draw_t;
typedef struct // 832k aprox.
{
buffered_draw_t type;
GLfloat
vtx[MAX_VERTICES * 3], // vertexes
tex[MAX_TEXTURE_UNITS][MAX_VERTICES * 2], // texture coords
clr[MAX_VERTICES * 4]; // color components
GLushort idx[MAX_INDICES]; // indices for the draw call
GLuint vt, tx, cl; // indices for GLfloat arrays above
int texture[MAX_TEXTURE_UNITS];
int flags; // entity flags
float alpha;
} glbuffer_t;
#include "model.h" #include "model.h"
void R_SetDefaultState(void); void R_SetDefaultState(void);
extern glbuffer_t gl_buf;
extern float gldepthmin, gldepthmax; extern float gldepthmin, gldepthmax;
extern image_t gltextures[MAX_GLTEXTURES]; extern image_t gltextures[MAX_GLTEXTURES];
@ -291,15 +314,28 @@ void R_TextureAlphaMode(char *string);
void R_TextureSolidMode(char *string); void R_TextureSolidMode(char *string);
int Scrap_AllocBlock(int w, int h, int *x, int *y); int Scrap_AllocBlock(int w, int h, int *x, int *y);
// GL buffer operations
#define GLBUFFER_VERTEX(X, Y, Z) \
gl_buf.vtx[gl_buf.vt] = X; gl_buf.vtx[gl_buf.vt+1] = Y; \
gl_buf.vtx[gl_buf.vt+2] = Z; gl_buf.vt += 3;
#define GLBUFFER_SINGLETEX(S, T) \
gl_buf.tex[0][gl_buf.tx] = S; gl_buf.tex[0][gl_buf.tx+1] = T; gl_buf.tx += 2;
#define GLBUFFER_MULTITEX(CS, CT, LS, LT) \
gl_buf.tex[0][gl_buf.tx] = CS; gl_buf.tex[0][gl_buf.tx+1] = CT; \
gl_buf.tex[1][gl_buf.tx] = LS; gl_buf.tex[1][gl_buf.tx+1] = LT; gl_buf.tx += 2;
#define GLBUFFER_COLOR(R, G, B, A) \
gl_buf.clr[gl_buf.cl] = R; gl_buf.clr[gl_buf.cl+1] = G; \
gl_buf.clr[gl_buf.cl+2] = B; gl_buf.clr[gl_buf.cl+3] = A; gl_buf.cl += 4;
void R_ApplyGLBuffer(void); void R_ApplyGLBuffer(void);
void R_UpdateGLBuffer(buffered_draw_t type, int colortex, int lighttex, int flags, float alpha); void R_UpdateGLBuffer(buffered_draw_t type, int colortex, int lighttex, int flags, float alpha);
void R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy, void R_Buffer2DQuad(GLfloat ul_vx, GLfloat ul_vy, GLfloat dr_vx, GLfloat dr_vy,
GLfloat ul_tx, GLfloat ul_ty, GLfloat dr_tx, GLfloat dr_ty); GLfloat ul_tx, GLfloat ul_ty, GLfloat dr_tx, GLfloat dr_ty);
void R_SetBufferIndices(GLenum type, GLuint vertices_num); void R_SetBufferIndices(GLenum type, GLuint vertices_num);
void R_BufferVertex(GLfloat x, GLfloat y, GLfloat z);
void R_BufferSingleTex(GLfloat s, GLfloat t);
void R_BufferMultiTex(GLfloat cs, GLfloat ct, GLfloat ls, GLfloat lt);
void R_BufferColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
#ifdef DEBUG #ifdef DEBUG
void glCheckError_(const char *file, const char *function, int line); void glCheckError_(const char *file, const char *function, int line);