Commit fa3d6784 authored by Dino Bollinger's avatar Dino Bollinger Committed by Richard Gobeille
Browse files

Engine: Save voxmodels in texcache to reduce startup delay in Polymost

parent b51e7acb
......@@ -77,6 +77,9 @@ extern void texcache_setupmemcache(void);
extern void texcache_checkgarbage(void);
extern void texcache_setupindex(void);
extern voxmodel_t* voxcache_fetchvoxmodel(const char* const cacheid);
extern void voxcache_writevoxmodel(const char* const cacheid, voxmodel_t* vm);
#endif
#ifdef __cplusplus
......
......@@ -896,4 +896,103 @@ void texcache_setupmemcache(void)
}
}
// ---------------------------------------
// Voxel 2 Poly Disk Caching
// ---------------------------------------
#define INITVARS_VOXSIZES(_vs, _is, _ts, _total) do {\
_vs = 5 * 4 * ((size_t)vm->qcnt) * sizeof(GLfloat);\
_is = 3 * 2 * ((size_t)vm->qcnt) * sizeof(GLuint);\
_ts = ((size_t)vm->mytexx) * ((size_t)vm->mytexy) * sizeof(int32_t);\
_total = _vs + _is + _ts;\
} while(0);
struct voxcachedat_t {
int32_t qcnt, mytexx, mytexy;
int32_t compressed_size;
};
voxmodel_t* voxcache_fetchvoxmodel(const char* const cacheid)
{
if (!texcache_enabled()) return NULL;
int32_t i = hash_find(&texcache.hashes, cacheid);
if (i < 0 || !texcache.entries[i])
return NULL; // didn't find it
voxcachedat_t voxd = {};
size_t vertexsize, indexsize, mytexsize, totalsize;
voxmodel_t* vm = (voxmodel_t*)Xmalloc(sizeof(voxmodel_t));
texcache.dataFilePos = texcache.entries[i]->offset;
texcache_readdata(&voxd, sizeof(voxd));
vm->mytexx = voxd.mytexx;
vm->mytexy = voxd.mytexy;
vm->qcnt = voxd.qcnt;
INITVARS_VOXSIZES(vertexsize, indexsize, mytexsize, totalsize);
char* compressed_data = (char*)Xmalloc(voxd.compressed_size);
texcache_readdata(compressed_data, voxd.compressed_size);
char* decompressed_data = (char*)Xmalloc(totalsize);
auto bytes = LZ4_decompress_safe(compressed_data, decompressed_data, voxd.compressed_size, totalsize);
Xfree(compressed_data);
UNREFERENCED_PARAMETER(bytes);
Bassert(bytes > 0);
vm->vertex = (GLfloat*)Xmalloc(vertexsize);
Bmemcpy(vm->vertex, decompressed_data, vertexsize);
vm->index = (GLuint*)Xmalloc(indexsize);
Bmemcpy(vm->index, &decompressed_data[vertexsize], indexsize);
vm->mytex = (int32_t*)Xmalloc(mytexsize);
Bmemcpy(vm->mytex, &decompressed_data[vertexsize + indexsize], mytexsize);
Xfree(decompressed_data);
return vm;
}
void voxcache_writevoxmodel(const char* const cacheid, voxmodel_t* vm)
{
if (!vm || !texcache_enabled()) return;
size_t vertexsize, indexsize, mytexsize, totalsize;
voxcachedat_t vxdat = { vm->qcnt, vm->mytexx, vm->mytexy, 0 };
INITVARS_VOXSIZES(vertexsize, indexsize, mytexsize, totalsize);
char* srcdata = (char*)Xmalloc(totalsize);
Bmemcpy(srcdata, vm->vertex, vertexsize);
Bmemcpy(&srcdata[vertexsize], vm->index, indexsize);
Bmemcpy(&srcdata[vertexsize + indexsize], vm->mytex, mytexsize);
int const max_compressed_size = LZ4_compressBound(totalsize);
char* targetdata = (char*) Xmalloc(max_compressed_size);
int32_t const actual_compressed_size = LZ4_compress_default((const char*)srcdata, targetdata, totalsize, max_compressed_size);
Xfree(srcdata);
Bassert(actual_compressed_size > 0);
vxdat.compressed_size = actual_compressed_size;
targetdata = (char*)Xrealloc(targetdata, actual_compressed_size);
buildvfs_fseek_end(texcache.dataFilePtr);
size_t const offset = buildvfs_ftell(texcache.dataFilePtr);
if (buildvfs_fwrite(&vxdat, sizeof(voxcachedat_t), 1, texcache.dataFilePtr) != 1)
goto vxstore_failure;
if (buildvfs_fwrite(targetdata, actual_compressed_size, 1, texcache.dataFilePtr) != 1)
goto vxstore_failure;
texcache_postwritetex(cacheid, offset);
Xfree(targetdata);
return;
vxstore_failure:
LOG_F(ERROR, "voxcache mystery error");
texcache.current->offset = 0;
Xfree(texcache.current->name);
Xfree(targetdata);
}
#endif
......@@ -17,7 +17,6 @@
#include "texcache.h"
#include "vfs.h"
//For loading/conversion only
static vec3_t voxsiz;
static int32_t yzsiz, *vbit = 0; //vbit: 1 bit per voxel: 0=air,1=solid
......@@ -976,17 +975,34 @@ voxmodel_t *voxload(const char *filnam)
//else if (!Bstrcasecmp(&filnam[i],".vxl")) { ret = loadvxl(filnam); is8bit = 0; }
else return NULL;
voxmodel_t *const vm = (ret >= 0) ? vox2poly() : NULL;
if (vm)
voxmodel_t* vm = NULL;
if (ret >= 0)
{
vm->mdnum = 1; //VOXel model id
vm->scale = vm->bscale = 1.f;
vm->siz.x = voxsiz.x; vm->siz.y = voxsiz.y; vm->siz.z = voxsiz.z;
vm->piv.x = voxpiv.x; vm->piv.y = voxpiv.y; vm->piv.z = voxpiv.z;
vm->is8bit = is8bit;
// file presence is guaranteed
buildvfs_kfd filh = kopen4load(filnam, 0);
int32_t const filelen = kfilelength(filh);
kclose(filh);
char voxcacheid[BMAX_PATH];
texcache_calcid(voxcacheid, filnam, filelen, -1, -1);
vm->texid = (uint32_t *)Xcalloc(MAXPALOOKUPS, sizeof(uint32_t));
// static variable 'gvox' is normally defined by 'vox2poly' -- do same here for safety
if (!(gvox = vm = voxcache_fetchvoxmodel(voxcacheid)))
{
vm = vox2poly();
voxcache_writevoxmodel(voxcacheid, vm);
}
if (vm)
{
vm->mdnum = 1; //VOXel model id
vm->scale = vm->bscale = 1.f;
vm->siz.x = voxsiz.x; vm->siz.y = voxsiz.y; vm->siz.z = voxsiz.z;
vm->piv.x = voxpiv.x; vm->piv.y = voxpiv.y; vm->piv.z = voxpiv.z;
vm->is8bit = is8bit;
vm->texid = (uint32_t*)Xcalloc(MAXPALOOKUPS, sizeof(uint32_t));
}
}
DO_FREE_AND_NULL(shcntmal);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment