From 139b916e465b09d49d8324ba521d653ea8b1230a Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 6 Jul 2021 00:12:20 +0000 Subject: [PATCH] Make scenecache less... flickery. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5953 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_main.c | 2 +- engine/client/r_surf.c | 76 ++++++++++++++++++++++++++++------------ engine/client/render.h | 2 +- engine/client/renderer.c | 2 +- engine/gl/gl_model.c | 4 +++ engine/gl/gl_shadow.c | 2 +- engine/server/sv_ccmds.c | 2 ++ 7 files changed, 63 insertions(+), 27 deletions(-) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 9143000c1..872b2ebff 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1799,7 +1799,7 @@ void CL_ClearState (qboolean gamestart) CL_ClearParseState(); CL_ClearTEnts(); CL_ClearCustomTEnts(); - Surf_ClearLightmaps(); + Surf_ClearSceneCache(); #ifdef HEXEN2 T_FreeInfoStrings(); #endif diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 6bf17f330..586fcd47d 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -3384,6 +3384,8 @@ static void Surf_SimpleWorld_Q3BSP(struct webostate_s *es, qbyte *pvs) } if (eb->inefficient) { //slow path that needs to create a single ram-backed mesh + + //FIXME: for portal/refract surfaces, track surfaces for refract pvs info if (eb->maxverts < eb->m.numvertexes + mesh->numvertexes) { //FIXME: pre-allocate @@ -3426,11 +3428,12 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b) struct webostate_s *es = ctx; qbyte *pvs; + int sortid; + batch_t *batch; + qboolean inefficient; + if (!es->numbatches) { - int sortid; - batch_t *batch; - es->numbatches = es->wmodel->numbatches; for (i = 0; i < es->numbatches; i++) @@ -3445,19 +3448,6 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b) memset(&es->batches[i].m, 0, sizeof(es->batches[i].m)); memset(&es->batches[i].vbo, 0, sizeof(es->batches[i].vbo)); } - - //set to 2 to reveal the inefficient surfaces... - if (r_temporalscenecache.ival < 2) - for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) - for (batch = currentmodel->batches[sortid]; batch != NULL; batch = batch->next) - { -#if MAXRLIGHTMAPS > 1 - if (batch->lmlightstyle[1] != INVALID_LIGHTSTYLE || batch->vtlightstyle[1] != INVALID_VLIGHTSTYLE) - continue; //not supported here, show fallback shader instead (would work but with screwed lighting, we prefer a better-defined result). -#endif - if (!batch->shader || batch->shader->flags & SHADER_NEEDSARRAYS) - es->batches[batch->user.bmodel.ebobatch].inefficient = true; - } } else { @@ -3469,6 +3459,43 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b) } } + //set to 2 to reveal the inefficient surfaces... + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = es->wmodel->batches[sortid]; batch != NULL; batch = batch->next) + { + inefficient = false; + if (r_temporalscenecache.ival < 2) + { +#if MAXRLIGHTMAPS > 1 + if (batch->lmlightstyle[1] != INVALID_LIGHTSTYLE || batch->vtlightstyle[1] != INVALID_VLIGHTSTYLE) + continue; //not supported here, show fallback shader instead (would work but with screwed lighting, we prefer a better-defined result). +#endif + if (!batch->shader) + inefficient = true; + else if (batch->shader->flags & SHADER_NEEDSARRAYS) + inefficient = true; + } + if (es->batches[batch->user.bmodel.ebobatch].inefficient != inefficient) + { + es->batches[batch->user.bmodel.ebobatch].inefficient = inefficient; + if (!inefficient) + { + if (es->batches[i].inefficient) + { + BZ_Free(es->batches[i].m.xyz_array); + BZ_Free(es->batches[i].m.st_array); + BZ_Free(es->batches[i].m.lmst_array[0]); + BZ_Free(es->batches[i].m.normals_array); + BZ_Free(es->batches[i].m.snormals_array); + BZ_Free(es->batches[i].m.tnormals_array); + } + BZ_Free(es->batches[i].idxbuffer); + + memset(&es->batches[i], 0, sizeof(es->batches[i])); + } + } + } + //maybe we should just use fatpvs instead, and wait for completion when outside? if (r_novis.ival) { @@ -3554,23 +3581,26 @@ void Surf_DrawWorld (void) r_temporalscenecache.ival = sc; r_temporalscenecache.modified = true; } + if (r_temporalscenecache.modified || r_dynamic.modified) { r_dynamic.modified = false; r_temporalscenecache.modified = false; Sh_CheckSettings(); //fiddle with r_dynamic vs r_shadow_realtime_dlight. - } - if (!r_temporalscenecache.ival) - { - r_dynamic.ival = r_dynamic.value; - webo_blocklightmapupdates = false; + COM_WorkerPartialSync(webogenerating, &webogeneratingstate, true); while (webostates) { void *webostate = webostates; webostates = webostates->next; R_DestroyWorldEBO(webostate); } + webo_blocklightmapupdates = false; + } + + if (!r_temporalscenecache.ival) + { + r_dynamic.ival = r_dynamic.value; } else if (!r_refdef.recurse && currentmodel->type == mod_brush) { @@ -3673,7 +3703,7 @@ void Surf_DrawWorld (void) if (kill->lastvalid < cls.framecount-5 && kill->wmodel == currentmodel && kill != webostate) { //this one looks old... kill it. if (webogenerating) - R_DestroyWorldEBO(webogenerating); //can't use more than one! + R_DestroyWorldEBO(webogenerating); //can't use more than one, tidy up stale ones webogenerating = kill; *link = kill->next; } @@ -4486,7 +4516,7 @@ void Surf_BuildModelLightmaps (model_t *m) m->lightmaps.first = newfirst; } -void Surf_ClearLightmaps(void) +void Surf_ClearSceneCache(void) { #ifdef THREADEDWORLD while(webogenerating) diff --git a/engine/client/render.h b/engine/client/render.h index 9720c560e..c797052f0 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -358,7 +358,7 @@ void Surf_WipeStains(void); void Surf_DeInit(void); void Surf_Clear(struct model_s *mod); void Surf_BuildLightmaps(void); //enables Surf_BuildModelLightmaps, calls it for each bsp. -void Surf_ClearLightmaps(void); //stops Surf_BuildModelLightmaps from working. +void Surf_ClearSceneCache(void); //stops Surf_BuildModelLightmaps from working. void Surf_BuildModelLightmaps (struct model_s *m); //rebuild lightmaps for a single bsp. beware of submodels. void Surf_RenderDynamicLightmaps (struct msurface_s *fa); void Surf_RenderAmbientLightmaps (struct msurface_s *fa, int ambient); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index c22de51e7..5714c50cf 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -1439,7 +1439,7 @@ void R_ShutdownRenderer(qboolean devicetoo) if (host_basepal) BZ_Free(host_basepal); host_basepal = NULL; - Surf_ClearLightmaps(); + Surf_ClearSceneCache(); RQ_Shutdown(); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 851fe0fa8..2e527f672 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -303,6 +303,7 @@ void Mod_RebuildLightmaps (void) } } +#ifdef HAVE_CLIENT void Mod_ResortShaders(void) { //called when some shader changed its sort key. @@ -332,7 +333,10 @@ void Mod_ResortShaders(void) } } } + + Surf_ClearSceneCache(); //make sure their caches are updated. } +#endif const char *Mod_GetEntitiesString(model_t *mod) { diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 6fe49d069..c52e3b7f4 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -3914,7 +3914,7 @@ void Sh_CheckSettings(void) } r_dynamic.ival = r_dynamic.value; - if (canshadowless && r_dynamic.value && !r_shadow_realtime_dlight.ival && (r_temporalscenecache.ival || (cl.worldmodel && cl.worldmodel->fromgame == fg_quake3))) + if (canshadowless && r_dynamic.value && !r_shadow_realtime_dlight.ival && (r_temporalscenecache.ival))// || (cl.worldmodel && cl.worldmodel->fromgame == fg_quake3))) { r_shadow_realtime_dlight.ival = 1; r_shadow_realtime_dlight_shadows.ival = 0; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index c0a085d4f..12d5f82c1 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -3266,6 +3266,8 @@ void SV_InitOperatorCommands (void) Cmd_AddCommandAD ("mapedit", SV_Map_f, SV_Map_c, "Loads the named map without any gamecode active."); #ifdef Q3SERVER Cmd_AddCommandAD ("spmap", SV_Map_f, SV_Map_c, NULL); + Cmd_AddCommandAD ("spdevmap", SV_Map_f, SV_Map_c, NULL); + Cmd_AddCommandAD ("devmap", SV_Map_f, SV_Map_c, NULL); #endif Cmd_AddCommandAD ("gamemap", SV_Map_f, SV_Map_c, NULL); Cmd_AddCommandAD ("changelevel", SV_Map_f, SV_Map_c, NULL);