Exemple #1
0
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;
	}
}