Improve VM memory usage by avoiding fragmentation in sound shaders and prop

data. Games can enable dynamic memory allocation by setting SOUNDSHADER_DYNAMIC
and PROPDATA_DYNAMIC in their progs.src
This commit is contained in:
Marco Cawthorne 2021-11-15 03:46:59 +01:00
parent 0085403c95
commit 58734ec4d2
Signed by: eukara
GPG key ID: C196CD8BA993248A
2 changed files with 72 additions and 9 deletions

View file

@ -14,6 +14,22 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
#define PROPDATA_DYNAMIC
Your game can define PRODATA_DYNAMIC in its progs.src if you want an unpredictable amount of prop data.
Other than that, you can increase the value of PROPDATA_MAX.
We switched to up-front allocation because QCLIB fragments memory like hell as there's
no real garbage collector to speak of
*/
#ifndef PROPDATA_DYNAMIC
#ifndef PROPDATA_MAX
#define PROPDATA_MAX 128
#endif
#endif
void
PropData_Shutdown(void)
{
@ -182,14 +198,23 @@ PropData_ForModel(string modelname)
}
/* check if it's already cached */
for (int i = 0; i < g_propdata_count; i++) {
if (modelname == g_propdata[i].name) {
return i;
}
{
int cache;
cache = (int)hash_get(g_hashpropdata, modelname);
if (cache >= 0)
return cache;
}
g_propdata_count++;
#ifdef PROPDATA_DYNAMIC
g_propdata = (propdata_t *)memrealloc(g_propdata, sizeof(propdata_t), index, g_propdata_count);
#else
if (g_propdata_count >= PROPDATA_MAX) {
error(sprintf("PropData_ForModel: Reached PROPDATA_MAX (%d)\n", PROPDATA_MAX));
}
#endif
/* Defaults go here */
@ -364,7 +389,6 @@ PropData_Init(void)
}
/* Defaults go here */
fh = fopen("scripts/propdata.txt", FILE_READ);
if (fh < 0) {
print("^1[PROPDATA] Can't find propdata.txt\n");
@ -376,9 +400,17 @@ PropData_Init(void)
PropData_CountLine(line);
}
#ifdef PROPDATA_DYNAMIC
/* alocate our stuff */
g_propdata = (propdata_t *)memalloc(sizeof(propdata_t) * g_propdata_count);
g_breakmodel = (breakmodel_t *)memalloc(sizeof(breakmodel_t) * g_breakmodel_count);
#else
/* alocate our stuff */
g_propdata = (propdata_t *)memalloc(sizeof(propdata_t) * PROPDATA_MAX);
g_breakmodel = (breakmodel_t *)memalloc(sizeof(breakmodel_t) * PROPDATA_MAX);
print(sprintf("PropData_Init: Allocated %d bytes for prop data\n", sizeof(propdata_t) * PROPDATA_MAX));
print(sprintf("PropData_Init: Allocated %d bytes for breakmodels\n", sizeof(breakmodel_t) * PROPDATA_MAX));
#endif
fseek(fh, 0);

View file

@ -14,6 +14,22 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SOUNDSHADER_DYNAMIC
#ifndef SOUNDSHADER_MAX
#define SOUNDSHADER_MAX 512
#endif
#endif
/*
#define SOUNDSHADER_DYNAMIC
Your game can define PRODATA_DYNAMIC in its progs.src if you want an unpredictable amount of prop data.
Other than that, you can increase the value of PROPDATA_MAX.
We switched to up-front allocation because QCLIB fragments memory like hell as there's
no real garbage collector to speak of
*/
void
Sound_Shutdown(void)
{
@ -30,6 +46,11 @@ Sound_Init(void)
{
/* make sure it's all reset */
Sound_Shutdown();
#ifndef PROPDATA_DYNAMIC
g_sounds = (snd_t *)memalloc(sizeof(snd_t) * SOUNDSHADER_MAX);
print(sprintf("Sound_Init: Allocated %d bytes\n", sizeof(snd_t) * SOUNDSHADER_MAX));
#endif
}
void
@ -235,15 +256,25 @@ Sound_Precache(string shader)
}
/* check if it's already cached */
for (int i = 0; i < g_sounds_count; i++) {
if (shader == g_sounds[i].name) {
dprint("[SOUND] Shader already precached.\n");
return i;
{
int cache;
cache = (int)hash_get(g_hashsounds, shader, -1);
if (cache >= 0) {
dprint(sprintf("^1Sound_Precache: shader %s already precached\n", shader));
return cache;
}
}
g_sounds_count++;
#ifdef PROPDATA_DYNAMIC
g_sounds = (snd_t *)memrealloc(g_sounds, sizeof(snd_t), index, g_sounds_count);
#else
if (g_sounds_count >= SOUNDSHADER_MAX) {
error(sprintf("Sound_Precache: Reached SOUNDSHADER_MAX (%d)\n", SOUNDSHADER_MAX));
}
#endif
g_sounds[index].volume = 1.0f;
g_sounds[index].dist_max = 1000;