From 5ad6c0e8577478422c10d7ae79fb61b88ac5ae85 Mon Sep 17 00:00:00 2001 From: cloudwalk Date: Sat, 14 Nov 2020 16:26:31 +0000 Subject: [PATCH] gl_draw, model_shared: Refactor vertex adding. Add faster codepath that skips hash function for drawing lines. Modest improvement in netgraph performance. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@13044 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_screen.c | 12 +++---- clvm_cmds.c | 2 +- draw.h | 2 +- gl_draw.c | 21 +++++++++--- model_shared.c | 87 ++++++++++++++++++++++++++++++++------------------ model_shared.h | 2 ++ r_stats.c | 2 +- 7 files changed, 83 insertions(+), 45 deletions(-) diff --git a/cl_screen.c b/cl_screen.c index 186342d1..5b97ccb6 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -285,12 +285,12 @@ static void SCR_DrawNetGraph_DrawGraph (int graphx, int graphy, int graphwidth, b = g[(j+1)%NETGRAPH_PACKETS]; if (a[0] < 0.0f || b[0] > 1.0f || b[0] < a[0]) continue; - DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[2], graphx + graphwidth * b[0], graphy + graphheight * b[2], 1.0f, 1.0f, 1.0f, 1.0f, 0); - DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[1], graphx + graphwidth * b[0], graphy + graphheight * b[1], 1.0f, 0.0f, 0.0f, 1.0f, 0); - DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[5], graphx + graphwidth * b[0], graphy + graphheight * b[5], 0.0f, 1.0f, 0.0f, 1.0f, 0); - DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[4], graphx + graphwidth * b[0], graphy + graphheight * b[4], 1.0f, 1.0f, 1.0f, 1.0f, 0); - DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[3], graphx + graphwidth * b[0], graphy + graphheight * b[3], 1.0f, 0.5f, 0.0f, 1.0f, 0); - DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[6], graphx + graphwidth * b[0], graphy + graphheight * b[6], 0.0f, 0.0f, 1.0f, 1.0f, 0); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[2], graphx + graphwidth * b[0], graphy + graphheight * b[2], 1.0f, 1.0f, 1.0f, 1.0f, 0, true); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[1], graphx + graphwidth * b[0], graphy + graphheight * b[1], 1.0f, 0.0f, 0.0f, 1.0f, 0, true); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[5], graphx + graphwidth * b[0], graphy + graphheight * b[5], 0.0f, 1.0f, 0.0f, 1.0f, 0, true); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[4], graphx + graphwidth * b[0], graphy + graphheight * b[4], 1.0f, 1.0f, 1.0f, 1.0f, 0, true); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[3], graphx + graphwidth * b[0], graphy + graphheight * b[3], 1.0f, 0.5f, 0.0f, 1.0f, 0, true); + DrawQ_Line(1, graphx + graphwidth * a[0], graphy + graphheight * a[6], graphx + graphwidth * b[0], graphy + graphheight * b[6], 0.0f, 0.0f, 1.0f, 1.0f, 0, true); } x = graphx; y = graphy + graphheight; diff --git a/clvm_cmds.c b/clvm_cmds.c index adf20144..7f2dffbe 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -1215,7 +1215,7 @@ void VM_drawline (prvm_prog_t *prog) rgb = PRVM_G_VECTOR(OFS_PARM3); alpha = PRVM_G_FLOAT(OFS_PARM4); flags = (int)PRVM_G_FLOAT(OFS_PARM5); - DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags); + DrawQ_Line(width, c1[0], c1[1], c2[0], c2[1], rgb[0], rgb[1], rgb[2], alpha, flags, false); } /* diff --git a/draw.h b/draw.h index 381dd35e..e06f19aa 100644 --- a/draw.h +++ b/draw.h @@ -174,7 +174,7 @@ void DrawQ_SetClipArea(float x, float y, float width, float height); // reset the clipping area void DrawQ_ResetClipArea(void); // draw a line -void DrawQ_Line(float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags); +void DrawQ_Line(float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags, qbool fast); const char *Draw_GetPicName(cachepic_t *pic); int Draw_GetPicWidth(cachepic_t *pic); diff --git a/gl_draw.c b/gl_draw.c index 2211f261..3de01e19 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -1404,7 +1404,7 @@ void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); } -void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags) +void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags, qbool fast) { model_t *mod = CL_Mesh_UI(); msurface_t *surf; @@ -1422,10 +1422,21 @@ void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, f offsety = 0; } surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true); - e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); - e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); - e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); - e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + if (fast) + { + Mod_Mesh_CheckResize_Vertex(mod, surf); + e0 = Mod_Mesh_AddVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e1 = Mod_Mesh_AddVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e2 = Mod_Mesh_AddVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e3 = Mod_Mesh_AddVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + } + else + { + e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha); + } Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2); Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3); } diff --git a/model_shared.c b/model_shared.c index 5c69dd23..55b4673e 100644 --- a/model_shared.c +++ b/model_shared.c @@ -4506,10 +4506,31 @@ msurface_t *Mod_Mesh_AddSurface(model_t *mod, texture_t *tex, qbool batchwithpre return surf; } -int Mod_Mesh_IndexForVertex(model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a) +static void Mod_Mesh_RebuildHashTable(model_t *mod, msurface_t *surf) { int hashindex, h, vnum, mask; surfmesh_t *mesh = &mod->surfmesh; + + // rebuild the hash table + mesh->num_vertexhashsize = 4 * mesh->max_vertices; + mesh->num_vertexhashsize &= ~(mesh->num_vertexhashsize - 1); // round down to pow2 + mesh->data_vertexhash = (int *)Mem_Realloc(mod->mempool, mesh->data_vertexhash, mesh->num_vertexhashsize * sizeof(*mesh->data_vertexhash)); + memset(mesh->data_vertexhash, -1, mesh->num_vertexhashsize * sizeof(*mesh->data_vertexhash)); + mask = mod->surfmesh.num_vertexhashsize - 1; + // no need to hash the vertices for the entire model, the latest surface will suffice. + for (vnum = surf ? surf->num_firstvertex : 0; vnum < mesh->num_vertices; vnum++) + { + // this uses prime numbers intentionally for computing the hash + hashindex = (unsigned int)(mesh->data_vertex3f[vnum * 3 + 0] * 2003 + mesh->data_vertex3f[vnum * 3 + 1] * 4001 + mesh->data_vertex3f[vnum * 3 + 2] * 7919 + mesh->data_normal3f[vnum * 3 + 0] * 4097 + mesh->data_normal3f[vnum * 3 + 1] * 257 + mesh->data_normal3f[vnum * 3 + 2] * 17) & mask; + for (h = hashindex; mesh->data_vertexhash[h] >= 0; h = (h + 1) & mask) + ; // just iterate until we find the terminator + mesh->data_vertexhash[h] = vnum; + } +} + +void Mod_Mesh_CheckResize_Vertex(model_t *mod, msurface_t *surf) +{ + surfmesh_t *mesh = &mod->surfmesh; if (mesh->max_vertices == mesh->num_vertices) { mesh->max_vertices = max(mesh->num_vertices * 2, 256); @@ -4520,36 +4541,15 @@ int Mod_Mesh_IndexForVertex(model_t *mod, msurface_t *surf, float x, float y, fl mesh->data_texcoordtexture2f = (float *)Mem_Realloc(mod->mempool, mesh->data_texcoordtexture2f, mesh->max_vertices * sizeof(float[2])); mesh->data_texcoordlightmap2f = (float *)Mem_Realloc(mod->mempool, mesh->data_texcoordlightmap2f, mesh->max_vertices * sizeof(float[2])); mesh->data_lightmapcolor4f = (float *)Mem_Realloc(mod->mempool, mesh->data_lightmapcolor4f, mesh->max_vertices * sizeof(float[4])); - // rebuild the hash table - mesh->num_vertexhashsize = 4 * mesh->max_vertices; - mesh->num_vertexhashsize &= ~(mesh->num_vertexhashsize - 1); // round down to pow2 - mesh->data_vertexhash = (int *)Mem_Realloc(mod->mempool, mesh->data_vertexhash, mesh->num_vertexhashsize * sizeof(*mesh->data_vertexhash)); - memset(mesh->data_vertexhash, -1, mesh->num_vertexhashsize * sizeof(*mesh->data_vertexhash)); - mask = mod->surfmesh.num_vertexhashsize - 1; - // no need to hash the vertices for the entire model, the latest surface will suffice. - for (vnum = surf ? surf->num_firstvertex : 0; vnum < mesh->num_vertices; vnum++) - { - // this uses prime numbers intentionally for computing the hash - hashindex = (unsigned int)(mesh->data_vertex3f[vnum * 3 + 0] * 2003 + mesh->data_vertex3f[vnum * 3 + 1] * 4001 + mesh->data_vertex3f[vnum * 3 + 2] * 7919 + mesh->data_normal3f[vnum * 3 + 0] * 4097 + mesh->data_normal3f[vnum * 3 + 1] * 257 + mesh->data_normal3f[vnum * 3 + 2] * 17) & mask; - for (h = hashindex; mesh->data_vertexhash[h] >= 0; h = (h + 1) & mask) - ; // just iterate until we find the terminator - mesh->data_vertexhash[h] = vnum; - } - } - mask = mod->surfmesh.num_vertexhashsize - 1; - // this uses prime numbers intentionally for computing the hash - hashindex = (unsigned int)(x * 2003 + y * 4001 + z * 7919 + nx * 4097 + ny * 257 + nz * 17) & mask; - // when possible find an identical vertex within the same surface and return it - for(h = hashindex;(vnum = mesh->data_vertexhash[h]) >= 0;h = (h + 1) & mask) - { - if (vnum >= surf->num_firstvertex - && mesh->data_vertex3f[vnum * 3 + 0] == x && mesh->data_vertex3f[vnum * 3 + 1] == y && mesh->data_vertex3f[vnum * 3 + 2] == z - && mesh->data_normal3f[vnum * 3 + 0] == nx && mesh->data_normal3f[vnum * 3 + 1] == ny && mesh->data_normal3f[vnum * 3 + 2] == nz - && mesh->data_texcoordtexture2f[vnum * 2 + 0] == s && mesh->data_texcoordtexture2f[vnum * 2 + 1] == t - && mesh->data_texcoordlightmap2f[vnum * 2 + 0] == u && mesh->data_texcoordlightmap2f[vnum * 2 + 1] == v - && mesh->data_lightmapcolor4f[vnum * 4 + 0] == r && mesh->data_lightmapcolor4f[vnum * 4 + 1] == g && mesh->data_lightmapcolor4f[vnum * 4 + 2] == b && mesh->data_lightmapcolor4f[vnum * 4 + 3] == a) - return vnum; + Mod_Mesh_RebuildHashTable(mod, surf); } +} + +int Mod_Mesh_AddVertex(model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a) +{ + int vnum; + surfmesh_t *mesh = &mod->surfmesh; + // add the new vertex vnum = mesh->num_vertices++; if (surf->num_vertices > 0) @@ -4567,7 +4567,6 @@ int Mod_Mesh_IndexForVertex(model_t *mod, msurface_t *surf, float x, float y, fl VectorSet(surf->maxs, x, y, z); } surf->num_vertices = mesh->num_vertices - surf->num_firstvertex; - mesh->data_vertexhash[h] = vnum; mesh->data_vertex3f[vnum * 3 + 0] = x; mesh->data_vertex3f[vnum * 3 + 1] = y; mesh->data_vertex3f[vnum * 3 + 2] = z; @@ -4585,6 +4584,32 @@ int Mod_Mesh_IndexForVertex(model_t *mod, msurface_t *surf, float x, float y, fl return vnum; } +int Mod_Mesh_IndexForVertex(model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a) +{ + int hashindex, h, vnum, mask; + surfmesh_t *mesh = &mod->surfmesh; + + Mod_Mesh_CheckResize_Vertex(mod, surf); + + mask = mod->surfmesh.num_vertexhashsize - 1; + // this uses prime numbers intentionally for computing the hash + hashindex = (unsigned int)(x * 2003 + y * 4001 + z * 7919 + nx * 4097 + ny * 257 + nz * 17) & mask; + // when possible find an identical vertex within the same surface and return it + for(h = hashindex;(vnum = mesh->data_vertexhash[h]) >= 0;h = (h + 1) & mask) + { + if (vnum >= surf->num_firstvertex + && mesh->data_vertex3f[vnum * 3 + 0] == x && mesh->data_vertex3f[vnum * 3 + 1] == y && mesh->data_vertex3f[vnum * 3 + 2] == z + && mesh->data_normal3f[vnum * 3 + 0] == nx && mesh->data_normal3f[vnum * 3 + 1] == ny && mesh->data_normal3f[vnum * 3 + 2] == nz + && mesh->data_texcoordtexture2f[vnum * 2 + 0] == s && mesh->data_texcoordtexture2f[vnum * 2 + 1] == t + && mesh->data_texcoordlightmap2f[vnum * 2 + 0] == u && mesh->data_texcoordlightmap2f[vnum * 2 + 1] == v + && mesh->data_lightmapcolor4f[vnum * 4 + 0] == r && mesh->data_lightmapcolor4f[vnum * 4 + 1] == g && mesh->data_lightmapcolor4f[vnum * 4 + 2] == b && mesh->data_lightmapcolor4f[vnum * 4 + 3] == a) + return vnum; + } + vnum = Mod_Mesh_AddVertex(mod, surf, x, y, z, nx, ny, nz, s, t, u, v, r, g, b, a); + mesh->data_vertexhash[h] = vnum; + return vnum; +} + void Mod_Mesh_AddTriangle(model_t *mod, msurface_t *surf, int e0, int e1, int e2) { surfmesh_t *mesh = &mod->surfmesh; diff --git a/model_shared.h b/model_shared.h index 0e477789..6b0530a8 100644 --- a/model_shared.h +++ b/model_shared.h @@ -698,6 +698,8 @@ void Mod_Mesh_Destroy(model_t *mod); void Mod_Mesh_Reset(model_t *mod); texture_t *Mod_Mesh_GetTexture(model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int defaultmaterialflags); msurface_t *Mod_Mesh_AddSurface(model_t *mod, texture_t *tex, qbool batchwithprevioussurface); +void Mod_Mesh_CheckResize_Vertex(model_t *mod, msurface_t *surf); +int Mod_Mesh_AddVertex(model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a); int Mod_Mesh_IndexForVertex(model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a); void Mod_Mesh_AddTriangle(model_t *mod, msurface_t *surf, int e0, int e1, int e2); void Mod_Mesh_Validate(model_t *mod); diff --git a/r_stats.c b/r_stats.c index 6dfc7938..edb4625f 100644 --- a/r_stats.c +++ b/r_stats.c @@ -504,7 +504,7 @@ void R_TimeReport_EndFrame(void) i++; x2 = max(x, x + width - sum * scalex); y2 = y + height - (data[index] - range_min) * scaley; - DrawQ_Line(1, x1, y1, x2, y2, r_speeds_graph_colors[color][0], r_speeds_graph_colors[color][1], r_speeds_graph_colors[color][2], r_speeds_graph_colors[color][3], 0); + DrawQ_Line(1, x1, y1, x2, y2, r_speeds_graph_colors[color][0], r_speeds_graph_colors[color][1], r_speeds_graph_colors[color][2], r_speeds_graph_colors[color][3], 0, true); } } } -- 2.39.2