void CBaseGameStats_Driver::ResetData() { #ifdef GAME_DLL // on the server, if there is a gamestats data container registered (by a client in the same process), they're in charge of resetting it, nothing for us to do if ( engine->GetGamestatsData() != NULL ) return; #endif if ( m_pGamestatsData != NULL ) { delete m_pGamestatsData; m_pGamestatsData = NULL; } m_pGamestatsData = new CGamestatsData(); KeyValues *pKV = m_pGamestatsData->m_pKVData; pKV->SetInt( "version", GAMESTATS_VERSION ); pKV->SetString( "srcid", s_szPseudoUniqueID ); #ifdef CLIENT_DLL const CPUInformation &cpu = GetCPUInformation(); OverWriteCharsWeHate( cpu.m_szProcessorID ); pKV->SetString( "CPUID", cpu.m_szProcessorID ); pKV->SetFloat( "CPUGhz", cpu.m_Speed * ( 1.0 / 1.0e9 ) ); pKV->SetInt( "NumCores", cpu.m_nPhysicalProcessors ); MaterialAdapterInfo_t gpu; materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), gpu ); CMatRenderContextPtr pRenderContext( materials ); int dest_width,dest_height; pRenderContext->GetRenderTargetDimensions( dest_width, dest_height ); if ( gpu.m_pDriverName ) { OverWriteCharsWeHate( gpu.m_pDriverName ); } pKV->SetString( "GPUDrv", SafeString( gpu.m_pDriverName ) ); pKV->SetInt( "GPUVendor", gpu.m_VendorID ); pKV->SetInt( "GPUDeviceID", gpu.m_DeviceID ); pKV->SetString( "GPUDriverVersion", CFmtStr( "%d.%d", gpu.m_nDriverVersionHigh, gpu.m_nDriverVersionLow ) ); pKV->SetInt( "DxLvl", g_pMaterialSystemHardwareConfig->GetDXSupportLevel() ); pKV->SetInt( "Width", dest_width ); pKV->SetInt( "Height", dest_height ); engine->SetGamestatsData( m_pGamestatsData ); #endif }
FloatBitMap_t *FloatBitMap_t::ComputeSelfShadowedBumpmapFromHeightInAlphaChannel( float bump_scale, int nrays_to_trace_per_pixel, uint32 nOptionFlags ) const { // first, add all the triangles from the height map to the "world". // we will make multiple copies to handle wrapping int tcnt = 1; Vector * verts; Vector * normals; ComputeVertexPositionsAndNormals( bump_scale, & verts, & normals ); RayTracingEnvironment rtEnv; rtEnv.Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS; // save some ram if ( nrays_to_trace_per_pixel ) { rtEnv.MakeRoomForTriangles( ( 1 + 2 * NREPS_TILE ) * ( 1 + 2 * NREPS_TILE ) * 2 * Height * Width ); // now, add a whole mess of triangles to trace against for( int tilex =- NREPS_TILE; tilex <= NREPS_TILE; tilex++ ) for( int tiley =- NREPS_TILE; tiley <= NREPS_TILE; tiley++ ) { int min_x = 0; int max_x = Width - 1; int min_y = 0; int max_y = Height - 1; if ( tilex < 0 ) min_x = Width / 2; if ( tilex > 0 ) max_x = Width / 2; if ( tiley < 0 ) min_y = Height / 2; if ( tiley > 0 ) max_y = Height / 2; for( int y = min_y; y <= max_y; y++ ) for( int x = min_x; x <= max_x; x++ ) { Vector ofs( tilex * Width, tiley * Height, 0 ); int x1 = ( x + 1 ) % Width; int y1 = ( y + 1 ) % Height; Vector v0 = verts[x + y * Width]; Vector v1 = verts[x1 + y * Width]; Vector v2 = verts[x1 + y1 * Width]; Vector v3 = verts[x + y1 * Width]; v0.x = x; v0.y = y; v1.x = x + 1; v1.y = y; v2.x = x + 1; v2.y = y + 1; v3.x = x; v3.y = y + 1; v0 += ofs; v1 += ofs; v2 += ofs; v3 += ofs; rtEnv.AddTriangle( tcnt++, v0, v1, v2, Vector( 1, 1, 1 ) ); rtEnv.AddTriangle( tcnt++, v0, v3, v2, Vector( 1, 1, 1 ) ); } } //printf("added %d triangles\n",tcnt-1); ReportProgress("Creating kd-tree",0,0); rtEnv.SetupAccelerationStructure(); // ok, now we have built a structure for ray intersection. we will take advantage // of the SSE ray tracing code by intersecting rays as a batch. } // We need to calculate for each vertex (i.e. pixel) of the heightmap, how "much" of the world // it can see in each basis direction. we will do this by sampling a sphere of rays around the // vertex, and using dot-product weighting to measure the lighting contribution in each basis // direction. note that the surface normal is not used here. The surface normal will end up // being reflected in the result because of rays being blocked when they try to pass through // the planes of the triangles touching the vertex. // note that there is no reason inter-bounced lighting could not be folded into this // calculation. FloatBitMap_t * ret = new FloatBitMap_t( Width, Height ); Vector *trace_directions=new Vector[nrays_to_trace_per_pixel]; DirectionalSampler_t my_sphere_sampler; for( int r=0; r < nrays_to_trace_per_pixel; r++) { Vector trace_dir=my_sphere_sampler.NextValue(); // trace_dir=Vector(1,0,0); trace_dir.z=fabs(trace_dir.z); // upwards facing only trace_directions[ r ]= trace_dir; } volatile SSBumpCalculationContext ctxs[32]; ctxs[0].m_pRtEnv =& rtEnv; ctxs[0].ret_bm = ret; ctxs[0].src_bm = this; ctxs[0].nrays_to_trace_per_pixel = nrays_to_trace_per_pixel; ctxs[0].bump_scale = bump_scale; ctxs[0].trace_directions = trace_directions; ctxs[0].normals = normals; ctxs[0].min_y = 0; ctxs[0].max_y = Height - 1; ctxs[0].m_nOptionFlags = nOptionFlags; int nthreads = min( 32, GetCPUInformation().m_nPhysicalProcessors ); ThreadHandle_t waithandles[32]; int starty = 0; int ystep = Height / nthreads; for( int t = 0;t < nthreads; t++ ) { if ( t ) memcpy( (void * ) ( & ctxs[t] ), ( void * ) & ctxs[0], sizeof( ctxs[0] )); ctxs[t].thread_number = t; ctxs[t].min_y = starty; if ( t != nthreads - 1 ) ctxs[t].max_y = min( Height - 1, starty + ystep - 1 ); else ctxs[t].max_y = Height - 1; waithandles[t]= CreateSimpleThread( SSBumpCalculationThreadFN, ( SSBumpCalculationContext * ) & ctxs[t] ); starty += ystep; } for(int t=0;t<nthreads;t++) { ThreadJoin( waithandles[t] ); } if ( nOptionFlags & SSBUMP_MOD2X_DETAIL_TEXTURE ) { const float flOutputScale = 0.5 * ( 1.0 / .57735026 ); // normalize so that a flat normal yields 0.5 // scale output weights by color channel for( int nY = 0; nY < Height; nY++ ) for( int nX = 0; nX < Width; nX++ ) { float flScale = flOutputScale * (2.0/3.0) * ( Pixel( nX, nY, 0 ) + Pixel( nX, nY, 1 ) + Pixel( nX, nY, 2 ) ); ret->Pixel( nX, nY, 0 ) *= flScale; ret->Pixel( nX, nY, 1 ) *= flScale; ret->Pixel( nX, nY, 2 ) *= flScale; } } delete[] verts; delete[] trace_directions; delete[] normals; return ret; // destructor will clean up rtenv }
// get the string record for sending to the server. Contains perf data and hardware/software // info. Returns NULL if there isn't a good record to send (i.e. not enough data yet). // A successful Get() resets the stats char const *CStatsRecorder::GetPerfStatsString( int iType ) { switch ( iType ) { case PERFDATA_LEVEL: { if ( ! m_bBufferFull ) return NULL; float flAverageFrameRate = AverageStat( &StatsBufferRecord_t::m_flFrameRate ); float flMinFrameRate = MinStat( &StatsBufferRecord_t::m_flFrameRate ); float flMaxFrameRate = MaxStat( &StatsBufferRecord_t::m_flFrameRate ); const CPUInformation &cpu = GetCPUInformation(); MaterialAdapterInfo_t gpu; materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), gpu ); CMatRenderContextPtr pRenderContext( materials ); int dest_width,dest_height; pRenderContext->GetRenderTargetDimensions( dest_width, dest_height ); char szMap[MAX_PATH+1]=""; Q_FileBase( engine->GetLevelName(), szMap, ARRAYSIZE( szMap ) ); V_snprintf( s_cPerfString, sizeof( s_cPerfString ), "PERFDATA:AvgFps=%4.2f MinFps=%4.2f MaxFps=%4.2f CPUID=\"%s\" CPUGhz=%2.2f " "NumCores=%d GPUDrv=\"%s\" " "GPUVendor=%d GPUDeviceID=%d " "GPUDriverVersion=\"%d.%d\" DxLvl=%d " "Width=%d Height=%d MapName=%s", flAverageFrameRate, flMinFrameRate, flMaxFrameRate, cpu.m_szProcessorID, cpu.m_Speed * ( 1.0 / 1.0e9 ), cpu.m_nPhysicalProcessors, SafeString( gpu.m_pDriverName ), gpu.m_VendorID, gpu.m_DeviceID, gpu.m_nDriverVersionHigh, gpu.m_nDriverVersionLow, g_pMaterialSystemHardwareConfig->GetDXSupportLevel(), dest_width, dest_height, szMap ); // get rid of chars that we hate in vendor strings for( char *i = s_cPerfString; *i; i++ ) { if ( ( i[0]=='\n' ) || ( i[0]=='\r' ) || ( i[0]==';' ) ) i[0]=' '; } // clear buffer m_nWriteIndex = 0; m_bBufferFull = false; return s_cPerfString; } case PERFDATA_SHUTDOWN: V_snprintf( s_cPerfString, sizeof( s_cPerfString ), "PERFDATA:TotalLevelTime:%d NumLevels:%d", (int) m_flTotalTimeInLevels, m_iNumLevels ); return s_cPerfString; default: Assert( false ); return NULL; } }