void CmdLib_FPrintf( FileHandle_t hFile, const char *pFormat, ... ) { static CUtlVector<char> buf; if ( buf.Count() == 0 ) buf.SetCount( 1024 ); va_list marker; va_start( marker, pFormat ); while ( 1 ) { int ret = Q_vsnprintf( buf.Base(), buf.Count(), pFormat, marker ); if ( ret >= 0 ) { // Write the string. g_pFileSystem->Write( buf.Base(), ret, hFile ); break; } else { // Make the buffer larger. int newSize = buf.Count() * 2; buf.SetCount( newSize ); if ( buf.Count() != newSize ) { Error( "CmdLib_FPrintf: can't allocate space for text." ); } } } va_end( marker ); }
//----------------------------------------------------------------------------- // For every specular surface that wasn't referenced by some env_cubemap, call Cubemap_CreateTexInfo. //----------------------------------------------------------------------------- void Cubemap_AttachDefaultCubemapToSpecularSides( void ) { Cubemap_ResetCubemapSideData(); Cubemap_InitCubemapSideData(); CUtlVector<entitySideList_t> sideList; sideList.SetCount( num_entities ); int i; for ( i = 0; i < num_entities; i++ ) { sideList[i].firstBrushSide = 0; sideList[i].brushSideCount = 0; } for ( i = 0; i < nummapbrushes; i++ ) { sideList[mapbrushes[i].entitynum].brushSideCount += mapbrushes[i].numsides; } int curSide = 0; for ( i = 0; i < num_entities; i++ ) { sideList[i].firstBrushSide = curSide; curSide += sideList[i].brushSideCount; } int currentEntity = 0; for ( int iSide = 0; iSide < nummapbrushsides; ++iSide ) { side_t *pSide = &brushsides[iSide]; if ( !SideHasCubemapAndWasntManuallyReferenced( iSide ) ) continue; while ( currentEntity < num_entities-1 && iSide > sideList[currentEntity].firstBrushSide + sideList[currentEntity].brushSideCount ) { currentEntity++; } int iCubemap = Cubemap_FindClosestCubemap( entities[currentEntity].origin, pSide ); if ( iCubemap == -1 ) continue; #ifdef DEBUG if ( pSide->pMapDisp ) { Assert( pSide->texinfo == pSide->pMapDisp->face.texinfo ); } #endif pSide->texinfo = Cubemap_CreateTexInfo( pSide->texinfo, g_CubemapSamples[iCubemap].origin ); if ( pSide->pMapDisp ) { pSide->pMapDisp->face.texinfo = pSide->texinfo; } } }
//----------------------------------------------------------------------------- // For every specular surface that wasn't referenced by some env_cubemap, call Cubemap_CreateTexInfo. //----------------------------------------------------------------------------- void Cubemap_AttachDefaultCubemapToSpecularSides( void ) { Cubemap_ResetCubemapSideData(); Cubemap_InitCubemapSideData(); // build a mapping from side to entity id so that we can get the entity origin CUtlVector<int> sideToEntityIndex; sideToEntityIndex.SetCount(g_MainMap->nummapbrushsides); int i; for ( i = 0; i < g_MainMap->nummapbrushsides; i++ ) { sideToEntityIndex[i] = -1; } for ( i = 0; i < g_MainMap->nummapbrushes; i++ ) { int entityIndex = g_MainMap->mapbrushes[i].entitynum; for ( int j = 0; j < g_MainMap->mapbrushes[i].numsides; j++ ) { side_t *side = &g_MainMap->mapbrushes[i].original_sides[j]; int sideIndex = side - g_MainMap->brushsides; sideToEntityIndex[sideIndex] = entityIndex; } } for ( int iSide = 0; iSide < g_MainMap->nummapbrushsides; ++iSide ) { side_t *pSide = &g_MainMap->brushsides[iSide]; if ( !SideHasCubemapAndWasntManuallyReferenced( iSide ) ) continue; int currentEntity = sideToEntityIndex[iSide]; int iCubemap = Cubemap_FindClosestCubemap( g_MainMap->entities[currentEntity].origin, pSide ); if ( iCubemap == -1 ) continue; #ifdef DEBUG if ( pSide->pMapDisp ) { Assert( pSide->texinfo == pSide->pMapDisp->face.texinfo ); } #endif pSide->texinfo = Cubemap_CreateTexInfo( pSide->texinfo, g_CubemapSamples[iCubemap].origin ); if ( pSide->pMapDisp ) { pSide->pMapDisp->face.texinfo = pSide->texinfo; } } }
void WorldVertexTransitionFixup( void ) { CUtlVector<entitySideList_t> sideList; sideList.SetCount( g_MainMap->num_entities ); int i; for ( i = 0; i < g_MainMap->num_entities; i++ ) { sideList[i].firstBrushSide = 0; sideList[i].brushSideCount = 0; } for ( i = 0; i < g_MainMap->nummapbrushes; i++ ) { sideList[g_MainMap->mapbrushes[i].entitynum].brushSideCount += g_MainMap->mapbrushes[i].numsides; } int curSide = 0; for ( i = 0; i < g_MainMap->num_entities; i++ ) { sideList[i].firstBrushSide = curSide; curSide += sideList[i].brushSideCount; } int currentEntity = 0; for ( int iSide = 0; iSide < g_MainMap->nummapbrushsides; ++iSide ) { side_t *pSide = &g_MainMap->brushsides[iSide]; // skip displacments if ( pSide->pMapDisp ) continue; if( pSide->texinfo < 0 ) continue; const char *pShaderName = GetShaderNameForTexInfo( pSide->texinfo ); if ( !pShaderName || !Q_stristr( pShaderName, "worldvertextransition" ) ) { continue; } while ( currentEntity < g_MainMap->num_entities-1 && iSide > sideList[currentEntity].firstBrushSide + sideList[currentEntity].brushSideCount ) { currentEntity++; } pSide->texinfo = CreateBrushVersionOfWorldVertexTransitionMaterial( pSide->texinfo ); } }
void RecvData( CUtlVector<unsigned char> &recvBuf ) { #if defined( USE_MPI ) MPI_Status stat; MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat); recvBuf.SetCount( stat.count ); MPI_Recv( recvBuf.Base(), stat.count, MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &stat); #else if ( !g_pSocket->Recv( recvBuf, 50000 ) ) { g_pSocket->Release(); g_pSocket = NULL; } #endif }
// need to do this so that if we are building HDR data, the LDR data is intact, and vice versa.s void UnserializeDetailPropLighting( int lumpID, int lumpVersion, CUtlVector<DetailPropLightstylesLump_t> &lumpData ) { GameLumpHandle_t handle = g_GameLumps.GetGameLumpHandle( lumpID ); if( handle == g_GameLumps.InvalidGameLump() ) { return; } if (g_GameLumps.GetGameLumpVersion(handle) != lumpVersion) return; // Unserialize CUtlBuffer buf( g_GameLumps.GetGameLump(handle), g_GameLumps.GameLumpSize( handle ), CUtlBuffer::READ_ONLY ); int count = buf.GetInt(); if( !count ) { return; } lumpData.SetCount( count ); int lightsize = lumpData.Size() * sizeof(DetailPropLightstylesLump_t); buf.Get( lumpData.Base(), lightsize ); }
void ComputePerLeafAmbientLighting() { // Figure out which lights should go in the per-leaf ambient cubes. int nInAmbientCube = 0; int nSurfaceLights = 0; for ( int i=0; i < *pNumworldlights; i++ ) { dworldlight_t *wl = &dworldlights[i]; if ( IsLeafAmbientSurfaceLight( wl ) ) wl->flags |= DWL_FLAGS_INAMBIENTCUBE; else wl->flags &= ~DWL_FLAGS_INAMBIENTCUBE; if ( wl->type == emit_surface ) ++nSurfaceLights; if ( wl->flags & DWL_FLAGS_INAMBIENTCUBE ) ++nInAmbientCube; } Msg( "%d of %d (%d%% of) surface lights went in leaf ambient cubes.\n", nInAmbientCube, nSurfaceLights, nSurfaceLights ? ((nInAmbientCube*100) / nSurfaceLights) : 0 ); g_LeafAmbientSamples.SetCount(numleafs); if ( g_bUseMPI ) { // Distribute the work among the workers. VMPI_SetCurrentStage( "ComputeLeafAmbientLighting" ); DistributeWork( numleafs, VMPI_DISTRIBUTEWORK_PACKETID, VMPI_ProcessLeafAmbient, VMPI_ReceiveLeafAmbientResults ); } else { RunThreadsOn(numleafs, true, ThreadComputeLeafAmbient); } // now write out the data Msg("Writing leaf ambient..."); g_pLeafAmbientIndex->RemoveAll(); g_pLeafAmbientLighting->RemoveAll(); g_pLeafAmbientIndex->SetCount( numleafs ); g_pLeafAmbientLighting->EnsureCapacity( numleafs*4 ); for ( int leafID = 0; leafID < numleafs; leafID++ ) { const CUtlVector<ambientsample_t> &list = g_LeafAmbientSamples[leafID]; g_pLeafAmbientIndex->Element(leafID).ambientSampleCount = list.Count(); if ( !list.Count() ) { g_pLeafAmbientIndex->Element(leafID).firstAmbientSample = 0; } else { g_pLeafAmbientIndex->Element(leafID).firstAmbientSample = g_pLeafAmbientLighting->Count(); // compute the samples in disk format. Encode the positions in 8-bits using leaf bounds fractions for ( int i = 0; i < list.Count(); i++ ) { int outIndex = g_pLeafAmbientLighting->AddToTail(); dleafambientlighting_t &light = g_pLeafAmbientLighting->Element(outIndex); light.x = Fixed8Fraction( list[i].pos.x, dleafs[leafID].mins[0], dleafs[leafID].maxs[0] ); light.y = Fixed8Fraction( list[i].pos.y, dleafs[leafID].mins[1], dleafs[leafID].maxs[1] ); light.z = Fixed8Fraction( list[i].pos.z, dleafs[leafID].mins[2], dleafs[leafID].maxs[2] ); light.pad = 0; for ( int side = 0; side < 6; side++ ) { VectorToColorRGBExp32( list[i].cube[side], light.cube.m_Color[side] ); } } } } for ( int i = 0; i < numleafs; i++ ) { // UNDONE: Do this dynamically in the engine instead. This will allow us to sample across leaf // boundaries always which should improve the quality of lighting in general if ( g_pLeafAmbientIndex->Element(i).ambientSampleCount == 0 ) { if ( !(dleafs[i].contents & CONTENTS_SOLID) ) { Msg("Bad leaf ambient for leaf %d\n", i ); } int refLeaf = NearestNeighborWithLight(i); g_pLeafAmbientIndex->Element(i).ambientSampleCount = 0; g_pLeafAmbientIndex->Element(i).firstAmbientSample = refLeaf; } } Msg("done\n"); }
// Returns time it took to finish the work. double DistributeWork( uint64 nWorkUnits, // how many work units to dole out char cPacketID, ProcessWorkUnitFn processFn, // workers implement this to process a work unit and send results back ReceiveWorkUnitFn receiveFn // the master implements this to receive a work unit ) { ++g_iCurDSInfo; if ( g_iCurDSInfo == 0 ) { // Register our disconnect handler so we can deal with it if clients bail out. if ( g_bMPIMaster ) { VMPI_AddDisconnectHandler( VMPI_DistributeWork_DisconnectHandler ); } } else if ( g_iCurDSInfo >= MAX_DW_CALLS ) { Error( "DistributeWork: called more than %d times.\n", MAX_DW_CALLS ); } CDSInfo *pInfo = &g_DSInfo; pInfo->m_cPacketID = cPacketID; pInfo->m_nWorkUnits = nWorkUnits; // Make all the workers wait until the master is ready. PreDistributeWorkSync( pInfo ); g_nWUs = nWorkUnits; g_nCompletedWUs = 0ull; g_nDuplicatedWUs = 0ull; // Setup stats info. double flMPIStartTime = Plat_FloatTime(); g_wuCountByProcess.SetCount( 512 ); memset( g_wuCountByProcess.Base(), 0, sizeof( int ) * g_wuCountByProcess.Count() ); unsigned long nBytesSentStart = g_nBytesSent; unsigned long nBytesReceivedStart = g_nBytesReceived; unsigned long nMessagesSentStart = g_nMessagesSent; unsigned long nMessagesReceivedStart = g_nMessagesReceived; EWorkUnitDistributor eWorkUnitDistributor = VMPI_GetActiveWorkUnitDistributor(); if ( g_bMPIMaster ) { Assert( !g_pCurDistributorMaster ); g_pCurDistributorMaster = ( eWorkUnitDistributor == k_eWorkUnitDistributor_SDK ? CreateWUDistributor_SDKMaster() : CreateWUDistributor_DefaultMaster() ); DistributeWork_Master( pInfo, processFn, receiveFn ); g_pCurDistributorMaster->Release(); g_pCurDistributorMaster = NULL; } else { Assert( !g_pCurDistributorWorker ); g_pCurDistributorWorker = ( eWorkUnitDistributor == k_eWorkUnitDistributor_SDK ? CreateWUDistributor_SDKWorker() : CreateWUDistributor_DefaultWorker() ); DistributeWork_Worker( pInfo, processFn ); g_pCurDistributorWorker->Release(); g_pCurDistributorWorker = NULL; } double flTimeSpent = Plat_FloatTime() - flMPIStartTime; ShowMPIStats( flTimeSpent, g_nBytesSent - nBytesSentStart, g_nBytesReceived - nBytesReceivedStart, g_nMessagesSent - nMessagesSentStart, g_nMessagesReceived - nMessagesReceivedStart ); // Mark that the threads aren't working on anything at the moment. for ( int i=0; i < ARRAYSIZE( g_ThreadWUs ); i++ ) g_ThreadWUs[i] = ~0ull; return flTimeSpent; }
int main( int argc, char* argv[] ) { if ( argc < 2 ) { return PrintUsage(); } const char *pClientOrServer = argv[1]; const char *pIP = NULL; bool bClient = false; if ( stricmp( pClientOrServer, "-client" ) == 0 ) { if ( argc < 3 ) { return PrintUsage(); } bClient = true; pIP = argv[2]; } CUtlVector<unsigned char> recvBuf; if ( bClient ) { DoClientConnect( pIP ); // Ok, now start blasting packets of different sizes and measure how long it takes to get an ack back. int nIterations = 30; for ( int size=350; size <= 350000; size += 512 ) { CUtlVector<unsigned char> buf; buf.SetCount( size ); double flTotalRoundTripTime = 0; CFastTimer throughputTimer; throughputTimer.Start(); for ( int i=0; i < nIterations; i++ ) { for ( int z=0; z < size; z++ ) buf[z] = (char)rand(); SendData( buf.Base(), buf.Count() ); CFastTimer timer; timer.Start(); RecvData( recvBuf ); timer.End(); // Make sure we got the same data back. assert( recvBuf.Count() == buf.Count() ); for ( z=0; z < size; z++ ) { assert( recvBuf[z] == buf[z] ); } //if ( i % 100 == 0 ) // printf( "%05d\n", i ); printf( "%d\n", i ); flTotalRoundTripTime += timer.GetDuration().GetMillisecondsF(); } throughputTimer.End(); double flTotalSeconds = throughputTimer.GetDuration().GetSeconds(); double flAvgRoundTripTime = flTotalRoundTripTime / nIterations; printf( "%d: %.2f ms per roundtrip (%d bytes/sec) sec: %.2f megs: %.2f\n", size, flAvgRoundTripTime, (int)((size*nIterations)/flTotalSeconds), flTotalSeconds, (double)(size*nIterations) / (1024*1024) ); } // Send an 'end' message to the server. int val = -1; SendData( &val, sizeof( val ) ); } else { // Wait for a connection. DoServerConnect(); // Wait for packets and ack them. while ( 1 ) { RecvData( recvBuf ); if ( !g_pSocket ) break; if ( recvBuf.Count() < 4 ) { assert( false ); } SendData( recvBuf.Base(), recvBuf.Count() ); } } return 0; }
//----------------------------------------------------------------------------- // Purpose: Loads data from buffer //----------------------------------------------------------------------------- bool TFReportedStats_t::LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer ) { // read the version lump of beginning of file and verify version bool bGotEndTag = false; unsigned short iLump = 0; unsigned short iLumpCount = 0; if ( !CBaseGameStats::GetLumpHeader( MAX_LUMP_COUNT, LoadBuffer, iLump, iLumpCount ) ) return false; if ( iLump != TFSTATS_LUMP_VERSION ) { Msg( "Didn't find version header. Expected lump type TFSTATS_LUMP_VERSION, got lump type %d. Skipping file.\n", iLump ); return false; } TF_Gamestats_Version_t versionLump; CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( versionLump ), &versionLump ); if ( versionLump.m_iMagic != TF_GAMESTATS_MAGIC ) { Msg( "Incorrect magic # in version header. Expected %x, got %x. Skipping file.\n", TF_GAMESTATS_MAGIC, versionLump.m_iMagic ); return false; } if ( versionLump.m_iVersion != TF_GAMESTATS_FILE_VERSION ) { Msg( "Mismatched file version. Expected file version %d, got %d. Skipping file.\n", TF_GAMESTATS_FILE_VERSION, versionLump.m_iVersion ); return false; } // read all the lumps in the file while( CBaseGameStats::GetLumpHeader( MAX_LUMP_COUNT, LoadBuffer, iLump, iLumpCount ) ) { switch ( iLump ) { case TFSTATS_LUMP_MAPHEADER: { TF_Gamestats_LevelStats_t::LevelHeader_t header; CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( TF_Gamestats_LevelStats_t::LevelHeader_t ), &header ); // quick sanity check on some data -- we get some stat files that start out OK but are corrupted later in the file if ( ( header.m_iRoundsPlayed < 0 ) || ( header.m_iTotalTime < 0 ) || ( header.m_iRoundsPlayed > 1000 ) ) return false; // if there's no interesting data, skip this file. (Need to have server not send it in this case.) if ( header.m_iTotalTime == 0 ) return false; m_pCurrentGame = FindOrAddMapStats( header.m_szMapName ); if ( m_pCurrentGame ) { m_pCurrentGame->m_Header = header; } break; } case TFSTATS_LUMP_MAPDEATH: { CUtlVector<TF_Gamestats_LevelStats_t::PlayerDeathsLump_t> playerDeaths; playerDeaths.SetCount( iLumpCount ); CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( TF_Gamestats_LevelStats_t::PlayerDeathsLump_t ), static_cast<void*>( playerDeaths.Base() ) ); if ( m_pCurrentGame ) { m_pCurrentGame->m_aPlayerDeaths = playerDeaths; } break; } case TFSTATS_LUMP_MAPDAMAGE: { CUtlVector<TF_Gamestats_LevelStats_t::PlayerDamageLump_t> playerDamage; playerDamage.SetCount( iLumpCount ); CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( TF_Gamestats_LevelStats_t::PlayerDamageLump_t ), static_cast<void*>( playerDamage.Base() ) ); if ( m_pCurrentGame ) { m_pCurrentGame->m_aPlayerDamage = playerDamage; } break; } case TFSTATS_LUMP_CLASS: { Assert( m_pCurrentGame ); Assert ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aClassStats ) ); if ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aClassStats ) ) { CBaseGameStats::LoadLump( LoadBuffer, ARRAYSIZE( m_pCurrentGame->m_aClassStats ), sizeof( m_pCurrentGame->m_aClassStats[0] ), m_pCurrentGame->m_aClassStats ); // quick sanity check on some data -- we get some stat files that start out OK but are corrupted later in the file for ( int i = 0; i < ARRAYSIZE( m_pCurrentGame->m_aClassStats ); i++ ) { TF_Gamestats_ClassStats_t &classStats = m_pCurrentGame->m_aClassStats[i]; if ( ( classStats.iSpawns < 0 ) || ( classStats.iSpawns > 10000 ) || ( classStats.iTotalTime < 0 ) || ( classStats.iTotalTime > 36000 * 20 ) || ( classStats.iKills < 0 ) || ( classStats.iKills > 10000 ) ) { return false; } } } else { // mismatched lump size, possibly from different build, don't know how it interpret it, just skip over it return false; } break; } case TFSTATS_LUMP_WEAPON: { Assert( m_pCurrentGame ); Assert ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aWeaponStats ) ); if ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aWeaponStats ) ) { CBaseGameStats::LoadLump( LoadBuffer, ARRAYSIZE( m_pCurrentGame->m_aWeaponStats ), sizeof( m_pCurrentGame->m_aWeaponStats[0] ), m_pCurrentGame->m_aWeaponStats ); // quick sanity check on some data -- we get some stat files that start out OK but are corrupted later in the file if ( ( m_pCurrentGame->m_aWeaponStats[TF_WEAPON_MEDIGUN].iShotsFired < 0 ) || ( m_pCurrentGame->m_aWeaponStats[TF_WEAPON_MEDIGUN].iShotsFired > 100000 ) || ( m_pCurrentGame->m_aWeaponStats[TF_WEAPON_FLAMETHROWER_ROCKET].iShotsFired != 0 ) ) // check that unused weapon has 0 shots { return false; } } else { // mismatched lump size, possibly from different build, don't know how it interpret it, just skip over it return false; } break; } case TFSTATS_LUMP_ENDTAG: { // check that end tag is valid -- should be version lump again TF_Gamestats_Version_t versionLump; CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( versionLump ), &versionLump ); if ( versionLump.m_iMagic != TF_GAMESTATS_MAGIC ) { Msg( "Incorrect magic # in version header. Expected %x, got %x. Skipping file.\n", TF_GAMESTATS_MAGIC, versionLump.m_iMagic ); return false; } if ( versionLump.m_iVersion != TF_GAMESTATS_FILE_VERSION ) { Msg( "Mismatched file version. Expected file version %d, got %d. Skipping file.\n", TF_GAMESTATS_FILE_VERSION, versionLump.m_iVersion ); return false; } bGotEndTag = true; break; } } } return bGotEndTag; }