Merge branch 'optimize-precip-think' into 'master'

Optimize precipitation by eliminating the thinker entirely

See merge request KartKrew/Kart!1157
This commit is contained in:
Oni 2023-04-09 05:31:31 +00:00
commit d6d8cf548a
8 changed files with 84 additions and 52 deletions

View file

@ -5082,6 +5082,12 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// uncapped/interpolation
interpmobjstate_t interp = {0};
// okay... this is a hack, but weather isn't networked, so it should be ok
if (!P_PrecipThinker(thing))
{
return;
}
// do interpolation
if (R_UsingFrameInterpolation() && !paused)
{
@ -5181,13 +5187,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->precip = true;
vis->bbox = false;
// okay... this is a hack, but weather isn't networked, so it should be ok
if (!(thing->precipflags & PCF_THUNK))
{
P_PrecipThinker(thing);
thing->precipflags |= PCF_THUNK;
}
}
#endif

View file

@ -51,7 +51,7 @@ precise_t ps_playerthink_time = 0;
precise_t ps_botticcmd_time = 0;
precise_t ps_thinkertime = 0;
precise_t ps_thlist_times[NUM_THINKERLISTS];
precise_t ps_thlist_times[NUM_ACTIVETHINKERLISTS];
precise_t ps_acs_time = 0;
int ps_checkposition_calls = 0;
@ -367,7 +367,6 @@ static void M_DrawTickStats(void)
{"main ", "Main: ", &ps_thlist_times[THINK_MAIN]},
{"mobjs ", "Mobjs: ", &ps_thlist_times[THINK_MOBJ]},
{"dynslop", "Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE]},
{"precip ", "Precipitation: ", &ps_thlist_times[THINK_PRECIP]},
{0}
};

View file

@ -72,7 +72,13 @@ typedef enum
THINK_MAIN,
THINK_MOBJ,
THINK_DYNSLOPE,
THINK_PRECIP,
// Lists after this may exist but they do not call an
// action in P_RunThinkers
NUM_ACTIVETHINKERLISTS,
THINK_PRECIP = NUM_ACTIVETHINKERLISTS,
NUM_THINKERLISTS
} thinklistnum_t; /**< Thinker lists. */
extern thinker_t thlist[];
@ -80,6 +86,7 @@ extern thinker_t thlist[];
void P_InitThinkers(void);
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker);
void P_RemoveThinker(thinker_t *thinker);
void P_UnlinkThinker(thinker_t *thinker);
//
// P_USER

View file

@ -546,7 +546,7 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state)
if (state == S_NULL)
{ // Remove mobj
P_RemovePrecipMobj(mobj);
P_FreePrecipMobj(mobj);
return false;
}
st = &states[state];
@ -4174,25 +4174,33 @@ void P_RecalcPrecipInSector(sector_t *sector)
//
// P_NullPrecipThinker
//
// For "Blank" precipitation
// Just the identification of a precip thinker. The thinker
// should never actually be called!
//
void P_NullPrecipThinker(precipmobj_t *mobj)
{
//(void)mobj;
mobj->precipflags &= ~PCF_THUNK;
R_ResetPrecipitationMobjInterpolationState(mobj);
(void)mobj;
I_Assert("P_NullPrecipThinker should not be called" == 0);
}
void P_PrecipThinker(precipmobj_t *mobj)
boolean P_PrecipThinker(precipmobj_t *mobj)
{
boolean flip = (mobj->precipflags & PCF_FLIP);
if (mobj->lastThink == leveltime)
return true; // already thinked this tick
mobj->lastThink = leveltime;
R_ResetPrecipitationMobjInterpolationState(mobj);
P_CycleStateAnimation((mobj_t *)mobj);
if (mobj->state == &states[S_RAINRETURN])
{
// Reset to ceiling!
P_SetPrecipMobjState(mobj, mobj->info->spawnstate);
if (!P_SetPrecipMobjState(mobj, mobj->info->spawnstate))
return false;
mobj->z = (flip) ? (mobj->floorz) : (mobj->ceilingz);
mobj->momz = FixedMul(-mobj->info->speed, mapobjectscale);
mobj->precipflags &= ~PCF_SPLASH;
@ -4213,20 +4221,23 @@ void P_PrecipThinker(precipmobj_t *mobj)
// HACK: sprite changes are 1 tic late, so you would see splashes on the ceiling if not for this state.
// We need to use the settings from the previous state, since some of those are NOT 1 tic late.
INT32 frame = (mobj->frame & ~FF_FRAMEMASK);
P_SetPrecipMobjState(mobj, S_RAINRETURN);
if (!P_SetPrecipMobjState(mobj, S_RAINRETURN))
return false;
mobj->frame = frame;
return;
return true;
}
else
{
if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate))
return;
return false;
}
}
}
if (mobj->precipflags & PCF_SPLASH)
return;
return true;
mobj->z += mobj->momz;
@ -4240,12 +4251,16 @@ void P_PrecipThinker(precipmobj_t *mobj)
}
else
{
P_SetPrecipMobjState(mobj, mobj->info->deathstate);
if (!P_SetPrecipMobjState(mobj, mobj->info->deathstate))
return false;
mobj->z = (flip) ? (mobj->ceilingz) : (mobj->floorz);
mobj->precipflags |= PCF_SPLASH;
R_ResetPrecipitationMobjInterpolationState(mobj);
}
}
return true;
}
static void P_RingThinker(mobj_t *mobj)
@ -11253,7 +11268,7 @@ boolean P_MobjWasRemoved(mobj_t *mobj)
return true;
}
void P_RemovePrecipMobj(precipmobj_t *mobj)
void P_FreePrecipMobj(precipmobj_t *mobj)
{
// unlink from sector and block lists
P_UnsetPrecipThingPosition(mobj);
@ -11265,7 +11280,9 @@ void P_RemovePrecipMobj(precipmobj_t *mobj)
}
// free block
P_RemoveThinker((thinker_t *)mobj);
// Precipmobjs don't actually think using their thinker,
// so the free cannot be delayed.
P_UnlinkThinker((thinker_t*)mobj);
}
// Clearing out stuff for savegames
@ -11301,12 +11318,7 @@ void P_RemoveSavegameMobj(mobj_t *mobj)
// free block
// Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers
{
thinker_t *thinker = (thinker_t *)mobj;
thinker_t *next = thinker->next;
(next->prev = thinker->prev)->next = next;
Z_Free(thinker);
}
P_UnlinkThinker((thinker_t*)mobj);
}
static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};

View file

@ -493,6 +493,8 @@ struct precipmobj_t
INT32 tics; // state tic counter
state_t *state;
UINT32 flags; // flags from mobjinfo tables
tic_t lastThink;
};
struct actioncache_t
@ -540,9 +542,9 @@ void P_RemoveFloorSpriteSlope(mobj_t *mobj);
boolean P_BossTargetPlayer(mobj_t *actor, boolean closest);
boolean P_SupermanLook4Players(mobj_t *actor);
void P_DestroyRobots(void);
void P_PrecipThinker(precipmobj_t *mobj);
boolean P_PrecipThinker(precipmobj_t *mobj);
void P_NullPrecipThinker(precipmobj_t *mobj);
void P_RemovePrecipMobj(precipmobj_t *mobj);
void P_FreePrecipMobj(precipmobj_t *mobj);
void P_SetScale(mobj_t *mobj, fixed_t newscale);
void P_XYMovement(mobj_t *mo);
void P_RingXYMovement(mobj_t *mo);

View file

@ -1833,16 +1833,18 @@ void P_SwitchWeather(preciptype_t newWeather)
if (purge == true)
{
thinker_t *think;
thinker_t *next;
precipmobj_t *precipmobj;
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = next)
{
next = think->next;
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker
precipmobj = (precipmobj_t *)think;
P_RemovePrecipMobj(precipmobj);
P_FreePrecipMobj(precipmobj);
}
}
else if (swap != MT_NULL) // Rather than respawn all that crap, reuse it!

View file

@ -295,8 +295,6 @@ static thinker_t *currentthinker;
//
void P_RemoveThinkerDelayed(thinker_t *thinker)
{
thinker_t *next;
if (thinker->references != 0)
{
#ifdef PARANOIA
@ -327,15 +325,30 @@ void P_RemoveThinkerDelayed(thinker_t *thinker)
return;
}
/* Remove from main thinker list */
next = thinker->next;
R_DestroyLevelInterpolators(thinker);
/* Note that currentthinker is guaranteed to point to us,
* and since we're freeing our memory, we had better change that. So
* point it to thinker->prev, so the iterator will correctly move on to
* thinker->prev->next = thinker->next */
(next->prev = currentthinker = thinker->prev)->next = next;
currentthinker = thinker->prev;
R_DestroyLevelInterpolators(thinker);
/* Remove from main thinker list */
P_UnlinkThinker(thinker);
}
//
// P_UnlinkThinker()
//
// Actually removes thinker from the list and frees its memory.
//
void P_UnlinkThinker(thinker_t *thinker)
{
thinker_t *next = thinker->next;
I_Assert(thinker->references == 0);
(next->prev = thinker->prev)->next = next;
Z_Free(thinker);
}
@ -437,7 +450,7 @@ static void P_RunThinkers(void)
{
size_t i;
for (i = 0; i < NUM_THINKERLISTS; i++)
for (i = 0; i < NUM_ACTIVETHINKERLISTS; i++)
{
ps_thlist_times[i] = I_GetPreciseTime();
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)

View file

@ -2465,6 +2465,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// uncapped/interpolation
interpmobjstate_t interp = {0};
// okay... this is a hack, but weather isn't networked, so it should be ok
if (!P_PrecipThinker(thing))
{
return;
}
// do interpolation
if (R_UsingFrameInterpolation() && !paused)
{
@ -2554,7 +2560,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
if (thing->subsector->sector->cullheight)
{
if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt))
goto weatherthink;
return;
}
// Determine the blendmode and translucency value
@ -2565,7 +2571,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
trans = (thing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT;
if (trans >= NUMTRANSMAPS)
goto weatherthink; // cap
return; // cap
}
// store information in a vissprite
@ -2623,14 +2629,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// Fullbright
vis->colormap = colormaps;
weatherthink:
// okay... this is a hack, but weather isn't networked, so it should be ok
if (!(thing->precipflags & PCF_THUNK))
{
P_PrecipThinker(thing);
thing->precipflags |= PCF_THUNK;
}
}
// R_AddSprites