Skip to content

Commit 0e71fb1

Browse files
committed
engine: load worldspawn separately from other map data
1 parent 33d476e commit 0e71fb1

File tree

10 files changed

+109
-76
lines changed

10 files changed

+109
-76
lines changed

src/dummygame/cgame.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ class LoadMapCmd : public Cmd::StaticCmd
155155
// the renderer starts (though there is no way to get it back later)
156156
refdef.gradingWeights[0] = 1.0f;
157157

158-
trap_R_LoadWorldMap(("maps/" + args.Argv(2) + ".bsp").c_str());
158+
trap_R_LoadWorldSpawn(("maps/" + args.Argv(2)).c_str());
159+
trap_R_LoadWorldData();
159160

160161
// This is done by EndRegistration but there is no way to invoke that
161162
bool reflection;

src/engine/client/cg_msgdef.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ enum cgameImport_t
159159
CG_R_GETSHADERNAMEFROMHANDLE,
160160
CG_R_SCISSOR_ENABLE,
161161
CG_R_SCISSOR_SET,
162-
CG_R_LOADWORLDMAP,
162+
CG_R_LOADWORLDSPAWN,
163+
CG_R_LOADWORLDDATA,
163164
CG_R_REGISTERMODEL,
164165
CG_R_REGISTERSKIN,
165166
CG_R_REGISTERSHADER,
@@ -301,8 +302,16 @@ namespace Render {
301302
IPC::Message<IPC::Id<VM::QVM, CG_R_GETSHADERNAMEFROMHANDLE>, int>,
302303
IPC::Reply<std::string>
303304
>;
304-
// TODO is it really async?
305-
using LoadWorldMapMsg = IPC::Message<IPC::Id<VM::QVM, CG_R_LOADWORLDMAP>, std::string>;
305+
// It better be sync even if it doesn't return anything.
306+
using LoadWorldSpawnMsg = IPC::SyncMessage<
307+
IPC::Message<IPC::Id<VM::QVM, CG_R_LOADWORLDSPAWN>, std::string>,
308+
IPC::Reply<bool>
309+
>;
310+
// It better be sync even if it doesn't return anything.
311+
using LoadWorldDataMsg = IPC::SyncMessage<
312+
IPC::Message<IPC::Id<VM::QVM, CG_R_LOADWORLDDATA>>,
313+
IPC::Reply<bool>
314+
>;
306315
using RegisterModelMsg = IPC::SyncMessage<
307316
IPC::Message<IPC::Id<VM::QVM, CG_R_REGISTERMODEL>, std::string>,
308317
IPC::Reply<int>

src/engine/client/cl_cgame.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,10 +1185,18 @@ void CGameVM::QVMSyscall(int syscallNum, Util::Reader& reader, IPC::Channel& cha
11851185
});
11861186
break;
11871187

1188-
case CG_R_LOADWORLDMAP:
1189-
IPC::HandleMsg<Render::LoadWorldMapMsg>(channel, std::move(reader), [this] (const std::string& mapName) {
1188+
case CG_R_LOADWORLDSPAWN:
1189+
IPC::HandleMsg<Render::LoadWorldSpawnMsg>(channel, std::move(reader), [this] (const std::string& mapName, bool &done) {
11901190
re.SetWorldVisData(CM_ClusterPVS(-1));
1191-
re.LoadWorld(mapName.c_str());
1191+
re.LoadWorldSpawn(mapName);
1192+
done = true;
1193+
});
1194+
break;
1195+
1196+
case CG_R_LOADWORLDDATA:
1197+
IPC::HandleMsg<Render::LoadWorldDataMsg>(channel, std::move(reader), [this] (bool &done) {
1198+
re.LoadWorldData();
1199+
done = true;
11921200
});
11931201
break;
11941202

src/engine/null/null_renderer.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ void RE_GlyphChar( fontInfo_t *font, int, glyphInfo_t *glyph )
7575
RE_Glyph( font, nullptr, glyph );
7676
}
7777
void RE_UnregisterFont( fontInfo_t* ) { }
78-
void RE_LoadWorldMap( const char * ) { }
78+
void RE_LoadWorldSpawn( const std::string ) { }
79+
void RE_LoadWorldData() { }
7980
void RE_SetWorldVisData( const byte * ) { }
8081
void RE_EndRegistration() { }
8182
void RE_ClearScene() { }
@@ -208,7 +209,8 @@ refexport_t *GetRefAPI( int, refimport_t* )
208209
re.Glyph = RE_Glyph;
209210
re.GlyphChar = RE_GlyphChar;
210211
re.UnregisterFont = RE_UnregisterFont;
211-
re.LoadWorld = RE_LoadWorldMap;
212+
re.LoadWorldSpawn = RE_LoadWorldSpawn;
213+
re.LoadWorldData = RE_LoadWorldData;
212214
re.SetWorldVisData = RE_SetWorldVisData;
213215
re.EndRegistration = RE_EndRegistration;
214216

src/engine/renderer/tr_bsp.cpp

Lines changed: 63 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3131
========================================================
3232
Loads and prepares a map file for scene rendering.
3333
34-
A single entry point:
35-
RE_LoadWorldMap(const char *name);
34+
Two entry points, to be called in this order:
35+
RE_LoadWorldSpawn(const std::string worldName);
36+
RE_LoadWorldData();
3637
========================================================
3738
*/
3839

@@ -411,11 +412,11 @@ static void LoadRGBEToBytes( const char *name, byte **ldrImage, int *width, int
411412
Z_Free( hdrImage );
412413
}
413414

414-
static std::vector<std::string> R_LoadExternalLightmaps( const char *mapName )
415+
static std::vector<std::string> R_LoadExternalLightmaps( std::string worldName )
415416
{
416417
const char *const extensions[] {".png", ".tga", ".webp", ".crn", ".jpg", ".jpeg"};
417418
std::vector<std::string> files[ ARRAY_LEN( extensions ) ];
418-
for ( const std::string& filename : FS::PakPath::ListFiles( mapName ) ) {
419+
for ( const std::string& filename : FS::PakPath::ListFiles( worldName ) ) {
419420
for ( size_t i = 0; i < ARRAY_LEN( extensions ); i++ )
420421
{
421422
if ( Str::IsISuffix( extensions[ i ], filename ) )
@@ -440,7 +441,7 @@ static std::vector<std::string> R_LoadExternalLightmaps( const char *mapName )
440441
R_LoadLightmaps
441442
===============
442443
*/
443-
static void R_LoadLightmaps( lump_t *l, const char *bspName )
444+
static void R_LoadLightmaps( lump_t *l, std::string worldName )
444445
{
445446
tr.worldLightMapping = r_precomputedLighting->integer && tr.lightMode == lightMode_t::MAP;
446447

@@ -454,11 +455,6 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
454455
int len = l->filelen;
455456
if ( !len )
456457
{
457-
char mapName[ MAX_QPATH ];
458-
459-
Q_strncpyz( mapName, bspName, sizeof( mapName ) );
460-
COM_StripExtension3( mapName, mapName, sizeof( mapName ) );
461-
462458
if ( tr.worldHDR_RGBE )
463459
{
464460
// we are about to upload textures
@@ -469,7 +465,7 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
469465
byte *ldrImage;
470466

471467
std::vector<std::string> hdrFiles;
472-
for ( const std::string& filename : FS::PakPath::ListFiles( mapName ) )
468+
for ( const std::string& filename : FS::PakPath::ListFiles( worldName ) )
473469
{
474470
if ( Str::IsISuffix( ".hdr", filename ) )
475471
{
@@ -487,17 +483,17 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
487483

488484
for ( const std::string& filename : hdrFiles )
489485
{
490-
Log::Debug("...loading external lightmap as RGB8 LDR '%s/%s'", mapName, filename );
486+
Log::Debug("...loading external lightmap as RGB8 LDR '%s/%s'", worldName, filename );
491487

492488
width = height = 0;
493-
LoadRGBEToBytes( va( "%s/%s", mapName, filename.c_str() ), &ldrImage, &width, &height );
489+
LoadRGBEToBytes( va( "%s/%s", worldName.c_str(), filename.c_str() ), &ldrImage, &width, &height );
494490

495491
imageParams_t imageParams = {};
496492
imageParams.bits = IF_NOPICMIP | IF_LIGHTMAP;
497493
imageParams.filterType = filterType_t::FT_DEFAULT;
498494
imageParams.wrapType = wrapTypeEnum_t::WT_CLAMP;
499495

500-
auto image = R_CreateImage( va( "%s/%s", mapName, filename.c_str() ), (const byte **)&ldrImage, width, height, 1, imageParams );
496+
auto image = R_CreateImage( va( "%s/%s", worldName.c_str(), filename.c_str() ), (const byte **)&ldrImage, width, height, 1, imageParams );
501497

502498
tr.lightmaps.push_back( image );
503499

@@ -506,7 +502,7 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
506502

507503
if (tr.worldDeluxeMapping) {
508504
// load deluxemaps
509-
std::vector<std::string> lightmapFiles = R_LoadExternalLightmaps(mapName);
505+
std::vector<std::string> lightmapFiles = R_LoadExternalLightmaps( worldName );
510506
if (lightmapFiles.empty()) {
511507
Log::Warn("no lightmap files found");
512508
tr.worldLightMapping = false;
@@ -517,21 +513,21 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
517513
Log::Debug("...loading %i deluxemaps", lightmapFiles.size());
518514

519515
for (const std::string& filename : lightmapFiles) {
520-
Log::Debug("...loading external lightmap '%s/%s'", mapName, filename);
516+
Log::Debug("...loading external lightmap '%s/%s'", worldName.c_str(), filename);
521517

522518
imageParams_t imageParams = {};
523519
imageParams.bits = IF_NOPICMIP | IF_NORMALMAP;
524520
imageParams.filterType = filterType_t::FT_DEFAULT;
525521
imageParams.wrapType = wrapTypeEnum_t::WT_CLAMP;
526522

527-
auto image = R_FindImageFile(va("%s/%s", mapName, filename.c_str()), imageParams);
523+
auto image = R_FindImageFile(va("%s/%s", worldName.c_str(), filename.c_str()), imageParams);
528524
tr.deluxemaps.push_back(image);
529525
}
530526
}
531527
}
532528
else
533529
{
534-
std::vector<std::string> lightmapFiles = R_LoadExternalLightmaps(mapName);
530+
std::vector<std::string> lightmapFiles = R_LoadExternalLightmaps( worldName );
535531
if (lightmapFiles.empty()) {
536532
Log::Warn("no lightmap files found");
537533
tr.worldLightMapping = false;
@@ -545,15 +541,15 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
545541
R_SyncRenderThread();
546542

547543
for (size_t i = 0; i < lightmapFiles.size(); i++) {
548-
Log::Debug("...loading external lightmap '%s/%s'", mapName, lightmapFiles[i]);
544+
Log::Debug("...loading external lightmap '%s/%s'", worldName.c_str(), lightmapFiles[i]);
549545

550546
if (!tr.worldDeluxeMapping || i % 2 == 0) {
551547
imageParams_t imageParams = {};
552548
imageParams.bits = IF_NOPICMIP | IF_LIGHTMAP;
553549
imageParams.filterType = filterType_t::FT_LINEAR;
554550
imageParams.wrapType = wrapTypeEnum_t::WT_CLAMP;
555551

556-
auto image = R_FindImageFile(va("%s/%s", mapName, lightmapFiles[i].c_str()), imageParams);
552+
auto image = R_FindImageFile(va("%s/%s", worldName.c_str(), lightmapFiles[i].c_str()), imageParams);
557553
tr.lightmaps.push_back(image);
558554
}
559555
else if (tr.worldDeluxeMapping)
@@ -563,7 +559,7 @@ static void R_LoadLightmaps( lump_t *l, const char *bspName )
563559
imageParams.filterType = filterType_t::FT_LINEAR;
564560
imageParams.wrapType = wrapTypeEnum_t::WT_CLAMP;
565561

566-
auto image = R_FindImageFile(va("%s/%s", mapName, lightmapFiles[i].c_str()), imageParams);
562+
auto image = R_FindImageFile(va("%s/%s", worldName.c_str(), lightmapFiles[i].c_str()), imageParams);
567563
tr.deluxemaps.push_back( image );
568564
}
569565
}
@@ -4465,25 +4461,24 @@ static void SetWorldLight() {
44654461
}
44664462
}
44674463

4468-
/*
4469-
=================
4470-
RE_LoadWorldMap
4464+
std::string worldName;
4465+
std::string bspBuffer;
4466+
dheader_t *bspHeader;
4467+
byte *bspStartMarker;
44714468

4472-
Called directly from cgame
4473-
=================
4474-
*/
4475-
void RE_LoadWorldMap( const char *name )
4469+
// Called directly from cgame.
4470+
void RE_LoadWorldSpawn( const std::string name )
44764471
{
4477-
int i;
4478-
dheader_t *header;
4479-
byte *startMarker;
4472+
worldName = name;
4473+
4474+
Log::Debug("----- RE_LoadWorldSpawn( %s ) -----", worldName );
44804475

44814476
if ( tr.worldMapLoaded )
44824477
{
44834478
Sys::Drop( "ERROR: attempted to redundantly load world map" );
44844479
}
44854480

4486-
Log::Debug("----- RE_LoadWorldMap( %s ) -----", name );
4481+
tr.worldMapLoaded = true;
44874482

44884483
// set default sun direction to be used if it isn't
44894484
// overridden by a shader
@@ -4493,17 +4488,19 @@ void RE_LoadWorldMap( const char *name )
44934488

44944489
VectorNormalize( tr.sunDirection );
44954490

4496-
tr.worldMapLoaded = true;
4491+
std::string bspName = name + ".bsp";
44974492

44984493
// load it
44994494
std::error_code err;
4500-
std::string buffer = FS::PakPath::ReadFile( name, err );
4495+
bspBuffer = FS::PakPath::ReadFile( bspName, err );
45014496

45024497
if ( err )
45034498
{
4504-
Sys::Drop( "RE_LoadWorldMap: %s not found", name );
4499+
Sys::Drop( "RE_LoadWorldSpawn: %s not found", bspName );
45054500
}
45064501

4502+
Log::Debug( "Loading %s…", bspName );
4503+
45074504
// clear tr.world so if the level fails to load, the next
45084505
// try will not look at the partially loaded version
45094506
tr.world = nullptr;
@@ -4514,45 +4511,45 @@ void RE_LoadWorldMap( const char *name )
45144511
tr.worldDeluxeMapping = false; // set by R_LoadEntities
45154512
tr.worldHDR_RGBE = false; // set by R_LoadEntities
45164513
tr.mapOverBrightBits = r_overbrightDefaultExponent.Get(); // maybe set by R_LoadEntities
4517-
tr.overbrightBits = std::min( tr.mapOverBrightBits, r_overbrightBits.Get() ); // set by RE_LoadWorldMap
4518-
tr.mapLightFactor = 1.0f; // set by RE_LoadWorldMap
4519-
tr.identityLight = 1.0f; // set by RE_LoadWorldMap
4514+
tr.overbrightBits = std::min( tr.mapOverBrightBits, r_overbrightBits.Get() ); // set by RE_LoadWorldSpawn
4515+
tr.mapLightFactor = 1.0f; // set by RE_LoadWorldSpawn
4516+
tr.identityLight = 1.0f; // set by RE_LoadWorldSpawn
45204517

45214518
s_worldData = {};
4522-
Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) );
4519+
Q_strncpyz( s_worldData.name, bspName.c_str(), sizeof( s_worldData.name ) );
45234520

45244521
Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) );
45254522
COM_StripExtension3( s_worldData.baseName, s_worldData.baseName, sizeof( s_worldData.baseName ) );
45264523
tr.loadingMap = s_worldData.baseName;
45274524

4528-
startMarker = (byte*) ri.Hunk_Alloc( 0, ha_pref::h_low );
4525+
bspStartMarker = (byte*) ri.Hunk_Alloc( 0, ha_pref::h_low );
45294526

4530-
header = ( dheader_t * ) buffer.data();
4531-
fileBase = ( byte * ) header;
4527+
bspHeader = ( dheader_t * ) bspBuffer.data();
4528+
fileBase = ( byte * ) bspHeader;
45324529

4533-
i = LittleLong( header->version );
4530+
int i = LittleLong( bspHeader->version );
45344531

45354532
if ( i != BSP_VERSION && i != BSP_VERSION_Q3 )
45364533
{
4537-
Sys::Drop( "RE_LoadWorldMap: %s has wrong version number (%i should be %i for ET or %i for Q3)",
4538-
name, i, BSP_VERSION, BSP_VERSION_Q3 );
4534+
Sys::Drop( "RE_LoadWorldSpawn: %s has wrong version number (%i should be %i for ET or %i for Q3)",
4535+
bspName, i, BSP_VERSION, BSP_VERSION_Q3 );
45394536
}
45404537

45414538
// swap all the lumps
45424539
for ( unsigned j = 0; j < sizeof( dheader_t ) / 4; j++ )
45434540
{
4544-
( ( int * ) header ) [ j ] = LittleLong( ( ( int * ) header ) [ j ] );
4541+
( ( int * ) bspHeader ) [ j ] = LittleLong( ( ( int * ) bspHeader ) [ j ] );
45454542
}
45464543

45474544
if ( glConfig2.reflectionMappingAvailable ) {
45484545
// TODO: Take into account potential shader changes
4549-
headerString = Str::Format( "%i %i %i %i %i", header->lumps[LUMP_PLANES].filelen, header->lumps[LUMP_NODES].filelen,
4550-
header->lumps[LUMP_LEAFS].filelen, header->lumps[LUMP_BRUSHES].filelen, header->lumps[LUMP_SURFACES].filelen );
4546+
headerString = Str::Format( "%i %i %i %i %i", bspHeader->lumps[LUMP_PLANES].filelen, bspHeader->lumps[LUMP_NODES].filelen,
4547+
bspHeader->lumps[LUMP_LEAFS].filelen, bspHeader->lumps[LUMP_BRUSHES].filelen, bspHeader->lumps[LUMP_SURFACES].filelen );
45514548
}
45524549

45534550
// load into heap
45544551

4555-
std::string externalEntitiesFileName = FS::Path::StripExtension( name ) + ".ent";
4552+
std::string externalEntitiesFileName = worldName + ".ent";
45564553
std::string externalEntities = FS::PakPath::ReadFile( externalEntitiesFileName, err );
45574554
if ( err )
45584555
{
@@ -4563,31 +4560,36 @@ void RE_LoadWorldMap( const char *name )
45634560
}
45644561
externalEntities = "";
45654562
}
4566-
R_LoadEntities( &header->lumps[ LUMP_ENTITIES ], externalEntities );
4563+
R_LoadEntities( &bspHeader->lumps[ LUMP_ENTITIES ], externalEntities );
45674564

45684565
// Now we can set this after checking a possible worldspawn value for mapOverbrightBits
45694566
tr.overbrightBits = std::min( tr.mapOverBrightBits, r_overbrightBits.Get() );
4567+
}
45704568

4571-
R_LoadShaders( &header->lumps[ LUMP_SHADERS ] );
4569+
// Called directly from cgame.
4570+
// Should be called after RE_LoadWorldSpawn().
4571+
void RE_LoadWorldData()
4572+
{
4573+
R_LoadShaders( &bspHeader->lumps[ LUMP_SHADERS ] );
45724574

4573-
R_LoadLightmaps( &header->lumps[ LUMP_LIGHTMAPS ], name );
4575+
R_LoadLightmaps( &bspHeader->lumps[ LUMP_LIGHTMAPS ], worldName );
45744576

4575-
R_LoadPlanes( &header->lumps[ LUMP_PLANES ] );
4577+
R_LoadPlanes( &bspHeader->lumps[ LUMP_PLANES ] );
45764578

4577-
R_LoadSurfaces( &header->lumps[ LUMP_SURFACES ], &header->lumps[ LUMP_DRAWVERTS ], &header->lumps[ LUMP_DRAWINDEXES ] );
4579+
R_LoadSurfaces( &bspHeader->lumps[ LUMP_SURFACES ], &bspHeader->lumps[ LUMP_DRAWVERTS ], &bspHeader->lumps[ LUMP_DRAWINDEXES ] );
45784580

4579-
R_LoadMarksurfaces( &header->lumps[ LUMP_LEAFSURFACES ] );
4581+
R_LoadMarksurfaces( &bspHeader->lumps[ LUMP_LEAFSURFACES ] );
45804582

4581-
R_LoadNodesAndLeafs( &header->lumps[ LUMP_NODES ], &header->lumps[ LUMP_LEAFS ] );
4583+
R_LoadNodesAndLeafs( &bspHeader->lumps[ LUMP_NODES ], &bspHeader->lumps[ LUMP_LEAFS ] );
45824584

4583-
R_LoadSubmodels( &header->lumps[ LUMP_MODELS ] );
4585+
R_LoadSubmodels( &bspHeader->lumps[ LUMP_MODELS ] );
45844586

45854587
// moved fog lump loading here, so fogs can be tagged with a model num
4586-
R_LoadFogs( &header->lumps[ LUMP_FOGS ], &header->lumps[ LUMP_BRUSHES ], &header->lumps[ LUMP_BRUSHSIDES ] );
4588+
R_LoadFogs( &bspHeader->lumps[ LUMP_FOGS ], &bspHeader->lumps[ LUMP_BRUSHES ], &bspHeader->lumps[ LUMP_BRUSHSIDES ] );
45874589

4588-
R_LoadVisibility( &header->lumps[ LUMP_VISIBILITY ] );
4590+
R_LoadVisibility( &bspHeader->lumps[ LUMP_VISIBILITY ] );
45894591

4590-
R_LoadLightGrid( &header->lumps[ LUMP_LIGHTGRID ] );
4592+
R_LoadLightGrid( &bspHeader->lumps[ LUMP_LIGHTGRID ] );
45914593

45924594
// create a static vbo for the world
45934595
// Do SetWorldLight() before R_CreateWorldVBO(), because the latter will use the world light values to generate materials
@@ -4600,7 +4602,7 @@ void RE_LoadWorldMap( const char *name )
46004602
FinishSkybox();
46014603
}
46024604

4603-
s_worldData.dataSize = ( byte * ) ri.Hunk_Alloc( 0, ha_pref::h_low ) - startMarker;
4605+
s_worldData.dataSize = ( byte * ) ri.Hunk_Alloc( 0, ha_pref::h_low ) - bspStartMarker;
46044606
// only set tr.world now that we know the entire level has loaded properly
46054607
tr.world = &s_worldData;
46064608

0 commit comments

Comments
 (0)