- backend update from GZDoom.

* GC fix
* better sound range check
* UE model loader license change.
This commit is contained in:
Christoph Oelckers 2022-01-11 17:20:48 +01:00
parent e5dad53f6d
commit 44e64a6a12
8 changed files with 92 additions and 72 deletions

View file

@ -388,7 +388,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
FVector3 pos, vel;
FRolloffInfo *rolloff;
if (sound_id <= 0 || volume <= 0 || nosfx || !SoundEnabled() || blockNewSounds)
if (sound_id <= 0 || volume <= 0 || nosfx || !SoundEnabled() || blockNewSounds || (unsigned)sound_id >= S_sfx.Size())
return NULL;
// prevent crashes.

View file

@ -1,21 +1,25 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2018 Marisa Kirisame
// All rights reserved.
// Copyright (c) 2018-2022 Marisa Kirisame, UnSX Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//--------------------------------------------------------------------------
//

View file

@ -229,7 +229,6 @@ DObject::DObject ()
ObjNext = GC::Root;
GCNext = nullptr;
GC::Root = this;
GC::AllocCount++;
}
DObject::DObject (PClass *inClass)
@ -239,7 +238,6 @@ DObject::DObject (PClass *inClass)
ObjNext = GC::Root;
GCNext = nullptr;
GC::Root = this;
GC::AllocCount++;
}
//==========================================================================
@ -277,7 +275,6 @@ DObject::~DObject ()
void DObject::Release()
{
if (GC::AllocCount > 0) GC::AllocCount--;
DObject **probe;
// Unlink this object from the GC list.

View file

@ -3,7 +3,7 @@
** The garbage collector. Based largely on Lua's.
**
**---------------------------------------------------------------------------
** Copyright 2008 Randy Heit
** Copyright 2008-2022 Marisa Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -82,13 +82,19 @@
** infinity, where each step performs a full collection.) You can also
** change this value dynamically.
*/
#define DEFAULT_GCMUL 400 // GC runs 'quadruple the speed' of memory allocation
#define DEFAULT_GCMUL 200 // GC runs 'double the speed' of memory allocation
// Number of sectors to mark for each step.
// Minimum step size
#define GCSTEPSIZE (sizeof(DObject) * 16)
#define GCSTEPSIZE 1024u
// Maximum number of elements to sweep in a single step
#define GCSWEEPMAX 40
#define GCSWEEPCOST 10
// Cost of sweeping one element (the size of a small object divided by
// some adjust for the sweep speed)
#define GCSWEEPCOST (sizeof(DObject) / 4)
// Cost of calling of one destructor
#define GCFINALIZECOST 100
// TYPES -------------------------------------------------------------------
@ -99,6 +105,8 @@
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static size_t CalcStepSize();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -108,7 +116,6 @@ namespace GC
size_t AllocBytes;
size_t Threshold;
size_t Estimate;
size_t AllocCount;
DObject *Gray;
DObject *Root;
DObject *SoftRoots;
@ -118,11 +125,15 @@ EGCState State = GCS_Pause;
int Pause = DEFAULT_GCPAUSE;
int StepMul = DEFAULT_GCMUL;
int StepCount;
size_t Dept;
uint64_t CheckTime;
bool FinalGC;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static int LastCollectTime; // Time last time collector finished
static size_t LastCollectAlloc; // Memory allocation when collector finished
static size_t MinStepSize; // Cover at least this much memory per step
// CODE --------------------------------------------------------------------
//==========================================================================
@ -161,8 +172,8 @@ size_t PropagateMark()
//
// SweepList
//
// Runs a limited sweep on a list, returning the location where to resume
// the sweep at next time. (FIXME: Horrible Engrish in this description.)
// Runs a limited sweep on a list, returning the position in the list just
// after the last object swept.
//
//==========================================================================
@ -254,6 +265,26 @@ void MarkArray(DObject **obj, size_t count)
}
}
//==========================================================================
//
// CalcStepSize
//
// Decide how big a step should be based, depending on how long it took to
// allocate up to the threshold from the amount left after the previous
// collection.
//
//==========================================================================
static size_t CalcStepSize()
{
int time_passed = CheckTime - LastCollectTime;
auto alloc = min(LastCollectAlloc, Estimate);
size_t bytes_gained = AllocBytes > alloc ? AllocBytes - alloc : 0;
return (StepMul > 0 && time_passed > 0)
? std::max<size_t>(GCSTEPSIZE, bytes_gained / time_passed * StepMul / 100)
: std::numeric_limits<size_t>::max() / 2; // no limit
}
//==========================================================================
//
// MarkRoot
@ -310,6 +341,10 @@ static void Atomic()
SweepPos = &Root;
State = GCS_Sweep;
Estimate = AllocBytes;
// Now that we are about to start a sweep, establish a baseline minimum
// step size for how much memory we want to sweep each CheckGC().
MinStepSize = CalcStepSize();
}
//==========================================================================
@ -354,7 +389,8 @@ static size_t SingleStep()
case GCS_Finalize:
State = GCS_Pause; // end collection
Dept = 0;
LastCollectAlloc = AllocBytes;
LastCollectTime = CheckTime;
return 0;
default:
@ -374,29 +410,26 @@ static size_t SingleStep()
void Step()
{
size_t lim = (GCSTEPSIZE/100) * StepMul;
size_t olim;
if (lim == 0)
{
lim = (~(size_t)0) / 2; // no limit
}
Dept += AllocBytes - Threshold;
// We recalculate a step size in case the rate of allocation went up
// since we started sweeping because we don't want to fall behind.
// However, we also don't want to go slower than what was decided upon
// when the sweep began if the rate of allocation has slowed.
size_t lim = max(CalcStepSize(), MinStepSize);
do
{
olim = lim;
lim -= SingleStep();
} while (olim > lim && State != GCS_Pause);
if (State != GCS_Pause)
{
if (Dept < GCSTEPSIZE)
size_t done = SingleStep();
if (done < lim)
{
Threshold = AllocBytes + GCSTEPSIZE; // - lim/StepMul
lim -= done;
}
else
{
Dept -= GCSTEPSIZE;
Threshold = AllocBytes;
lim = 0;
}
} while (lim && State != GCS_Pause);
if (State != GCS_Pause)
{
Threshold = AllocBytes;
}
else
{
@ -571,16 +604,13 @@ ADD_STAT(gc)
" Sweep ",
"Finalize " };
FString out;
out.Format("[%s] Alloc:%6zuK Thresh:%6zuK Est:%6zuK Steps: %d",
out.Format("[%s] Alloc:%6zuK Thresh:%6zuK Est:%6zuK Steps: %d %zuK",
StateStrings[GC::State],
(GC::AllocBytes + 1023) >> 10,
(GC::Threshold + 1023) >> 10,
(GC::Estimate + 1023) >> 10,
GC::StepCount);
if (GC::State != GC::GCS_Pause)
{
out.AppendFormat(" %zuK", (GC::Dept + 1023) >> 10);
}
GC::StepCount,
(GC::MinStepSize + 1023) >> 10);
return out;
}

View file

@ -43,9 +43,6 @@ namespace GC
// Number of bytes currently allocated through M_Malloc/M_Realloc.
extern size_t AllocBytes;
// Number of allocated objects since last CheckGC call.
extern size_t AllocCount;
// Amount of memory to allocate before triggering a collection.
extern size_t Threshold;
@ -73,6 +70,9 @@ namespace GC
// Is this the final collection just before exit?
extern bool FinalGC;
// Counts the number of times CheckGC has been called.
extern uint64_t CheckTime;
// Current white value for known-dead objects.
static inline uint32_t OtherWhite()
{
@ -108,15 +108,11 @@ namespace GC
}
// Check if it's time to collect, and do a collection step if it is.
static inline bool CheckGC()
static inline void CheckGC()
{
AllocCount = 0;
CheckTime++;
if (AllocBytes >= Threshold)
{
Step();
return true;
}
return false;
}
// Forces a collection to start now.
@ -184,6 +180,13 @@ class TObjPtr
DObject *o;
};
public:
TObjPtr() = default;
TObjPtr(const TObjPtr<T> &q) = default;
TObjPtr(T q) noexcept
: pp(q)
{
}
T operator=(T q)
{
pp = q;

View file

@ -121,7 +121,6 @@ CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N
Printf("Changing the video backend requires a restart for " GAMENAME ".\n");
}
//CVAR(Int, vid_renderer, 1, 0) // for some stupid mods which threw caution out of the window...
CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL)
{

View file

@ -352,7 +352,7 @@ void DStatusBarCore::SetScale()
int horz = HorizontalResolution;
int vert = VerticalResolution;
double refaspect = horz / double(vert);
double screenaspect = ActiveRatio(w, h);
double screenaspect = w / double(h);
if ((horz == 320 && vert == 200) || (horz == 640 && vert == 400))
{

View file

@ -373,19 +373,6 @@ static void GameTicker()
break;
}
GC::CheckGC();
// Do some more aggressive GC maintenance when the game ticker is inactive.
if ((gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) || paused)
{
size_t ac = max<size_t>(10, GC::AllocCount);
for (size_t cnt = 0; cnt < ac; cnt++)
{
if (!GC::CheckGC()) break;
}
}
}