summaryrefslogtreecommitdiff
path: root/utils/texturecompile/texturecompile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/texturecompile/texturecompile.cpp')
-rw-r--r--utils/texturecompile/texturecompile.cpp775
1 files changed, 775 insertions, 0 deletions
diff --git a/utils/texturecompile/texturecompile.cpp b/utils/texturecompile/texturecompile.cpp
new file mode 100644
index 0000000..03c003b
--- /dev/null
+++ b/utils/texturecompile/texturecompile.cpp
@@ -0,0 +1,775 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// vmpi_bareshell.cpp : Defines the entry point for the console application.
+//
+
+#include <windows.h>
+#include <conio.h>
+#include <process.h>
+#include "vmpi.h"
+#include "filesystem.h"
+#include "vmpi_filesystem.h"
+#include "vmpi_distribute_work.h"
+#include "vmpi_tools_shared.h"
+#include "cmdlib.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlbuffer.h"
+#include "tier1/utllinkedlist.h"
+#include "tier1/utlstringmap.h"
+#include "tier0/icommandline.h"
+#include "tier1/strtools.h"
+#include "threads.h"
+#include "tier0/dbg.h"
+#include "interface.h"
+#include "ilaunchabledll.h"
+#include <direct.h>
+#include "io.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define STARTWORK_PACKETID 5
+#define WORKUNIT_PACKETID 6
+#define ERRMSG_PACKETID 7
+#define TEXTUREHADERROR_PACKETID 8
+#define MACHINE_NAME 9
+
+#define TEXTURES_PER_WORKUNIT 1
+
+#ifdef _DEBUG
+//#define DEBUGFP
+#endif
+
+const char *g_pGameDir = NULL;
+const char *g_pTextureOutputDir = NULL;
+char g_WorkerTempPath[MAX_PATH];
+char g_ExeDir[MAX_PATH];
+CUtlVector<char *> g_CompileCommands;
+int g_nTexturesPerWorkUnit = 0;
+#ifdef DEBUGFP
+FILE *g_WorkerDebugFp = NULL;
+#endif
+bool g_bGotStartWorkPacket = false;
+double g_flStartTime;
+bool g_bVerbose = false;
+
+struct TextureInfo_t
+{
+};
+
+void Texture_ParseTextureInfoFromCompileCommands( int nCompileCommandID, TextureInfo_t &shaderInfo );
+void Worker_GetSourceFiles( int iWorkUnit );
+
+void Worker_GetLocalCopyOfTextureSource( const char *pVtfName );
+
+// g_ByteCode["shadername"][shadercombo][bytecodeoffset]
+//typedef CUtlVector<CUtlBuffer> VectorOfBuffers_t;
+
+//CUtlStringMap<TextureInfo_t> g_TextureToTextureInfo;
+
+typedef CUtlVector<char> CharVector_t;
+
+struct SourceTargetPair_t
+{
+ char *pSrcName;
+ char *pTargetName;
+};
+
+CUtlVector<SourceTargetPair_t> g_SourceTargetPairs;
+
+CUtlStringMap<bool> g_Master_TextureHadError;
+
+CDispatchReg g_DistributeWorkReg( WORKUNIT_PACKETID, DistributeWorkDispatch );
+
+unsigned long VMPI_Stats_GetJobWorkerID( void )
+{
+ return 0;
+}
+
+
+bool StartWorkDispatch( MessageBuffer *pBuf, int iSource, int iPacketID )
+{
+ g_bGotStartWorkPacket = true;
+ return true;
+}
+
+CDispatchReg g_StartWorkReg( STARTWORK_PACKETID, StartWorkDispatch );
+
+bool ErrMsgDispatch( MessageBuffer *pBuf, int iSource, int iPacketID )
+{
+ static CUtlStringMap<bool> errorMessages;
+ if( !errorMessages.Defined( pBuf->data + 1 ) )
+ {
+ errorMessages[pBuf->data + 1] = true;
+ fprintf( stderr, "ERROR: %s\n", pBuf->data + 1 );
+ }
+ return true;
+}
+
+CDispatchReg g_ErrMsgReg( ERRMSG_PACKETID, ErrMsgDispatch );
+
+bool TextureHadErrorDispatch( MessageBuffer *pBuf, int iSource, int iPacketID )
+{
+ g_Master_TextureHadError[pBuf->data+1] = true;
+ return true;
+}
+
+CDispatchReg g_TextureHadErrorReg( TEXTUREHADERROR_PACKETID, TextureHadErrorDispatch );
+
+void DebugOut( const char *pMsg, ... )
+{
+ char msg[2048];
+ va_list marker;
+ va_start( marker, pMsg );
+ _vsnprintf( msg, sizeof( msg ), pMsg, marker );
+ va_end( marker );
+
+ if (g_bVerbose)
+ {
+ Msg( "%s", msg );
+ }
+
+#ifdef DEBUGFP
+ fprintf( g_WorkerDebugFp, "%s", msg );
+ fflush( g_WorkerDebugFp );
+#endif
+}
+
+
+// Worker should implement this so it will quit nicely when the master disconnects.
+void MyDisconnectHandler( int procID, const char *pReason )
+{
+ // If we're a worker, then it's a fatal error if we lose the connection to the master.
+ if ( !g_bMPIMaster )
+ {
+ Msg( "Master disconnected.\n ");
+ DebugOut( "Master disconnected.\n" );
+ TerminateProcess( GetCurrentProcess(), 1 );
+ }
+}
+
+
+// pBuf is ready to read the results written to the buffer in ProcessWorkUnitFn.
+// work is done. .master gets it back this way.
+// compiled code in pBuf
+void Master_ReceiveWorkUnitFn( uint64 iWorkUnit, MessageBuffer *pBuf, int iWorker )
+{
+ DebugOut( "Master_ReceiveWorkUnitFn\n" );
+ int textureStart = iWorkUnit * g_nTexturesPerWorkUnit;
+ int textureEnd = textureStart + g_nTexturesPerWorkUnit;
+ textureEnd = min( g_CompileCommands.Count(), textureEnd );
+ int i;
+ for( i = textureStart; i < textureEnd; i++ )
+ {
+ int len;
+ pBuf->read( &len, sizeof( len ) );
+ if( len == 0 )
+ {
+ continue;
+ }
+ CUtlBuffer fileData;
+ fileData.EnsureCapacity( len );
+ pBuf->read( fileData.Base(), len );
+
+ Warning( "%s\n", g_CompileCommands[i] );
+ FILE *fp;
+ fp = fopen( g_CompileCommands[i], "wb" );
+ if ( !fp )
+ Error( "Can't open %s for writing.\n", g_CompileCommands[i] );
+ fwrite( fileData.Base(), 1, len, fp );
+ fclose( fp );
+ }
+}
+
+// same as "system", but doesn't pop up a window
+void MySystem( char *pCommand )
+{
+ FILE *batFp = fopen( "temp.bat", "w" );
+ fprintf( batFp, "%s\n", pCommand );
+ fclose( batFp );
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ // Start the child process.
+ if( !CreateProcess( NULL, // No module name (use command line).
+ "temp.bat", // Command line.
+ NULL, // Process handle not inheritable.
+ NULL, // Thread handle not inheritable.
+ FALSE, // Set handle inheritance to FALSE.
+ IDLE_PRIORITY_CLASS | CREATE_NO_WINDOW, // No creation flags.
+ NULL, // Use parent's environment block.
+ g_WorkerTempPath, // Use parent's starting directory.
+ &si, // Pointer to STARTUPINFO structure.
+ &pi ) // Pointer to PROCESS_INFORMATION structure.
+ )
+ {
+ Error( "CreateProcess failed." );
+ Assert( 0 );
+ }
+
+ // Wait until child process exits.
+ WaitForSingleObject( pi.hProcess, INFINITE );
+
+ // Close process and thread handles.
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+}
+
+void VTFNameToTGAName( const char *pSrcName, char *pDstName )
+{
+ pDstName[0] = '\0';
+ const char *pMaterials = Q_stristr( pSrcName, "materials" );
+ Assert( pMaterials );
+ if( pMaterials )
+ {
+ Q_strncpy( pDstName, pSrcName, pMaterials - pSrcName + 1 );
+ }
+ Q_strcat( pDstName, "materialsrc", MAX_PATH );
+ Q_strcat( pDstName, pMaterials + strlen( "materials" ), MAX_PATH );
+ Q_StripExtension( pDstName, pDstName, strlen( pDstName ) );
+ Q_strcat( pDstName, ".tga", MAX_PATH );
+}
+
+// You must append data to pBuf with the work unit results.
+void Worker_ProcessWorkUnitFn( int iThread, uint64 iWorkUnit, MessageBuffer *pBuf )
+{
+ DebugOut( "Worker_ProcessWorkUnitFn textures/workunit=%d\n", g_nTexturesPerWorkUnit );
+ Worker_GetSourceFiles( iWorkUnit );
+ int textureStart = iWorkUnit * g_nTexturesPerWorkUnit;
+ int textureEnd = textureStart + g_nTexturesPerWorkUnit;
+ textureEnd = min( g_CompileCommands.Count(), textureEnd );
+
+ int i;
+ for( i = textureStart; i < textureEnd; i++ )
+ {
+ DebugOut( "texture to compile: \"%s\"\n", g_CompileCommands[i] );
+ char cmdline[1024];
+ char tganame[1024];
+ VTFNameToTGAName( g_CompileCommands[i], tganame );
+ sprintf( cmdline, "vtex -allowdebug -vproject \"%s%s\" -mkdir -nopause \"%s%s\"", g_WorkerTempPath, g_pGameDir + 3, g_WorkerTempPath, tganame + 3 ); // hack hack
+ DebugOut( cmdline );
+ DebugOut( "\n" );
+// MySystem( cmdline );
+ system( cmdline );
+
+ char localVTFName[1024];
+ sprintf( localVTFName, "%s%s", g_WorkerTempPath, g_CompileCommands[i] + 3 );
+ DebugOut( "local: \"%s\"\n", localVTFName );
+
+ FILE *fp = fopen( localVTFName, "rb" );
+ if( fp )
+ {
+ // Send the compiled shader to the master
+ fseek( fp, 0, SEEK_END );
+ int len = ftell( fp );
+ fseek( fp, 0, SEEK_SET );
+ CUtlBuffer buf;
+ buf.EnsureCapacity( len );
+ int nBytesRead = fread( buf.Base(), 1, len, fp );
+ fclose( fp );
+ buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead );
+
+ pBuf->write( &len, sizeof( len ) );
+ pBuf->write( buf.Base(), len );
+ }
+ else
+ {
+// static CUtlStringMap<bool> m_FileAlreadyFailed;
+//
+// if( !m_FileAlreadyFailed.Defined( g_CompileCommands[i] ) )
+// {
+// m_FileAlreadyFailed[g_CompileCommands[i]] = true;
+// CUtlVector<char> fileNameBuf;
+// fileNameBuf.AddToTail( ( char )TEXTUREHADERROR_PACKETID );
+// int len = strlen( g_CompileCommands[i] );
+// fileNameBuf.AddMultipleToTail( len + 1, g_CompileCommands[i] );
+// VMPI_SendData( fileNameBuf.Base(), fileNameBuf.Count(), VMPI_MASTER_ID );
+// }
+
+ // Write zero to signify that we didn't do anything here.
+ int len = 0;
+ pBuf->write( &len, sizeof( len ) );
+ }
+ VMPI_HandleSocketErrors();
+ }
+}
+
+void MakeDirHier( const char *pPath )
+{
+ char temp[1024];
+ Q_strncpy( temp, pPath, 1024 );
+ int i;
+ for( i = 0; i < strlen( temp ); i++ )
+ {
+ if( temp[i] == '/' || temp[i] == '\\' )
+ {
+ temp[i] = '\0';
+// DebugOut( "mkdir( %s )\n", temp );
+ mkdir( temp );
+ temp[i] = '\\';
+ }
+ }
+// DebugOut( "mkdir( %s )\n", temp );
+ mkdir( temp );
+}
+
+void Worker_ReadFilesToCopy( void )
+{
+ // Create virtual files for all of the stuff that we need to compile the shader
+ // make sure and prefix the file name so that it doesn't find it locally.
+ char filename[1024];
+ sprintf( filename, "%s\\filestocopy.txt", g_pGameDir );
+ DebugOut( "using \"%s\" as filestocopy\n", filename );
+ char buf[1024];
+ FileHandle_t fp = g_pFileSystem->Open( filename, "r" );
+ if( fp == FILESYSTEM_INVALID_HANDLE )
+ {
+ fprintf( stderr, "Can't open uniquefilestocopy.txt!\n" );
+ exit( -1 );
+ }
+
+ while( CmdLib_FGets( buf, sizeof( buf ), fp ) )
+ {
+ // get rid of the newline if there is one.
+ int len = strlen( buf );
+ if( buf[len-1] == 0xd || buf[len-1] == 0xa )
+ {
+ buf[len-1] = '\0';
+ }
+// DebugOut( "buf: %s\n", buf );
+
+ char *pStar = Q_stristr( buf, "*" );
+ Assert( pStar );
+ if( !pStar )
+ {
+ continue;
+ }
+
+ *pStar = '\0';
+ char *pVtfName = buf;
+ char *pSrcName = pStar + 1;
+
+ SourceTargetPair_t &pair = g_SourceTargetPairs[g_SourceTargetPairs.AddToTail()];
+ pair.pSrcName = strdup( pSrcName );
+ pair.pTargetName = strdup( pVtfName );
+ }
+ g_pFileSystem->Close( fp );
+}
+
+void Worker_GetSourceFiles( int iWorkUnit )
+{
+ DebugOut( "Worker_GetSourceFiles( %d )\n", iWorkUnit );
+ int textureStart = iWorkUnit * g_nTexturesPerWorkUnit;
+ int textureEnd = textureStart + g_nTexturesPerWorkUnit;
+ textureEnd = min( g_CompileCommands.Count(), textureEnd );
+ int i;
+ for( i = textureStart; i < textureEnd; i++ )
+ {
+ Worker_GetLocalCopyOfTextureSource( g_CompileCommands[i] );
+ }
+}
+
+void Worker_GetFileFromMaster( const char *pFileName )
+{
+ DebugOut( "Worker_GetFileFromMaster: \"%s\"\n", pFileName );
+ FileHandle_t fp2 = g_pFileSystem->Open( pFileName, "rb" );
+ bool bZeroLength = false;
+ if( fp2 == FILESYSTEM_INVALID_HANDLE )
+ {
+ bZeroLength = true;
+ Warning( "zero length file: \"%s\"\n", pFileName );
+ // make a zero length file hack hack hack
+// continue;
+ }
+ CUtlVector<char> fileBuf;
+ int fileLen = 0;
+ if( !bZeroLength )
+ {
+// printf( "getting local copy of file: \"%s\"\n", pFileName );
+ fileLen = g_pFileSystem->Size( fp2 );
+ fileBuf.SetCount( fileLen );
+ g_pFileSystem->Read( fileBuf.Base(), fileLen, fp2 );
+ g_pFileSystem->Close( fp2 );
+ }
+
+ // create the dir that the file needs to go into.
+ char path[1024];
+ char filename[1024];
+ sprintf( path, "%s%s", g_WorkerTempPath, pFileName + 3 ); // dear lord . .skip the u:\ BUG BUG BUG
+// printf( "creating \"%s\"\n", path );
+ Q_StripFilename( path );
+ MakeDirHier( path );
+
+ sprintf( filename, "%s%s", g_WorkerTempPath, pFileName + 3 ); // dear lord . .skip the u:\ BUG BUG BUG
+// printf( "creating \"%s\"\n", pFileName );
+
+ FILE *fp3 = fopen( filename, "wb" );
+ if( !fp3 )
+ {
+ Error( "Couldn't open \"%s\"\n", filename );
+ }
+ if( !bZeroLength )
+ {
+ fwrite( fileBuf.Base(), 1, fileLen, fp3 );
+ }
+ fclose( fp3 );
+}
+
+void Worker_GetLocalCopyOfTextureSource( const char *pVtfName )
+{
+ int i;
+ for( i = 0; i < g_SourceTargetPairs.Count(); i++ )
+ {
+// DebugOut( "comparing: \"%s\" \"%s\"\n", pVtfName, g_SourceTargetPairs[i].pTargetName );
+ if( Q_stricmp( pVtfName, g_SourceTargetPairs[i].pTargetName ) == 0 )
+ {
+// DebugOut( "MATCH!\n" );
+ Worker_GetFileFromMaster( g_SourceTargetPairs[i].pSrcName );
+ }
+ }
+}
+
+void Worker_GetLocalCopyOfBinary( const char *pFilename )
+{
+ CUtlBuffer fileBuf;
+ char tmpFilename[MAX_PATH];
+ sprintf( tmpFilename, "%s\\%s", g_ExeDir, pFilename );
+ printf( "trying to open: %s\n", tmpFilename );
+
+ FILE *fp = fopen( tmpFilename, "rb" );
+ if( !fp )
+ {
+ Assert( 0 );
+ fprintf( stderr, "Can't open %s!\n", pFilename );
+ exit( -1 );
+ }
+ fseek( fp, 0, SEEK_END );
+ int fileLen = ftell( fp );
+ fseek( fp, 0, SEEK_SET );
+ fileBuf.EnsureCapacity( fileLen );
+ int nBytesRead = fread( fileBuf.Base(), 1, fileLen, fp );
+ fclose( fp );
+ fileBuf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead );
+
+ char newFilename[MAX_PATH];
+ sprintf( newFilename, "%s%s", g_WorkerTempPath, pFilename );
+
+ DebugOut( "this is fucked \"%s\"\n", newFilename );
+ FILE *fp2 = fopen( newFilename, "wb" );
+ if( !fp2 )
+ {
+ Assert( 0 );
+ fprintf( stderr, "Can't open %s!\n", newFilename );
+ exit( -1 );
+ }
+ fwrite( fileBuf.Base(), 1, fileLen, fp2 );
+ fclose( fp2 );
+}
+
+void Worker_GetLocalCopyOfBinaries( void )
+{
+ Worker_GetLocalCopyOfBinary( "vtex.exe" );
+ Worker_GetLocalCopyOfBinary( "vtex_dll.dll" );
+ Worker_GetLocalCopyOfBinary( "vstdlib.dll" );
+ Worker_GetLocalCopyOfBinary( "tier0.dll" );
+}
+
+void Shared_ParseListOfCompileCommands( void )
+{
+ char buf[1024];
+
+ char fileListFileName[1024];
+ sprintf( fileListFileName, "%s\\texturelist.txt", g_pGameDir );
+ FileHandle_t fp = g_pFileSystem->Open( fileListFileName, "r" );
+ if( fp == FILESYSTEM_INVALID_HANDLE )
+ {
+ DebugOut( "Can't open %s!\n", fileListFileName );
+ fprintf( stderr, "Can't open %s!\n", fileListFileName );
+ exit( -1 );
+ }
+ while( CmdLib_FGets( buf, 1023, fp ) )
+ {
+ char *pNewString = new char[ strlen( buf ) + 1 ];
+ strcpy( pNewString, buf );
+ pNewString[strlen( pNewString ) - 2] = '\0'; // This is some hacky shit right here.
+ int newID = g_CompileCommands.AddToTail();
+ g_CompileCommands[newID] = pNewString;
+ }
+ g_pFileSystem->Close( fp );
+
+// printf( "%d compiles\n", g_CompileCommands.Count() );
+ DebugOut( "%d compiles\n", g_CompileCommands.Count() );
+}
+
+void SetupPaths( int argc, char **argv )
+{
+ GetTempPath( sizeof( g_WorkerTempPath ), g_WorkerTempPath );
+ strcat( g_WorkerTempPath, "texturecompiletemp\\" );
+ char tmp[MAX_PATH];
+ sprintf( tmp, "rd /s /q \"%s\"", g_WorkerTempPath );
+ system( tmp );
+ _mkdir( g_WorkerTempPath );
+// printf( "g_WorkerTempPath: \"%s\"\n", g_WorkerTempPath );
+
+ CommandLine()->CreateCmdLine( argc, argv );
+ g_pGameDir = CommandLine()->ParmValue( "-gamedir", "" );
+ strcpy( g_ExeDir, argv[0] );
+ Q_StripFilename( g_ExeDir );
+ Q_FixSlashes( g_ExeDir );
+// printf( "exedir: \"%s\"\n", g_ExeDir );
+
+ g_pTextureOutputDir = CommandLine()->ParmValue( "-textureoutputdir", "" );
+// printf( "shaderoutputdir: \"%s\"\n", g_pShaderOutputDir );
+
+ g_bVerbose = CommandLine()->FindParm("-verbose") != 0;
+}
+
+void SetupDebugFile( void )
+{
+#ifdef DEBUGFP
+ const char *pComputerName = getenv( "COMPUTERNAME" );
+ char filename[MAX_PATH];
+ sprintf( filename, "\\\\fileserver\\user\\gary\\debug\\%s.txt", pComputerName );
+ g_WorkerDebugFp = fopen( filename, "w" );
+ Assert( g_WorkerDebugFp );
+ DebugOut( "opened debug file\n" );
+#endif
+}
+
+void WriteTexture( const char *pTextureName )
+{
+#if 0
+ CUtlVector<CUtlBuffer> &byteCodeArray = g_ByteCode[pShaderName];
+ const ShaderInfo_t &shaderInfo = g_ShaderToShaderInfo[pShaderName];
+// printf( "%s : %d combos centroid mask: 0x%x numDynamicCombos: %d flags: 0x%x\n",
+// pShaderName, shaderInfo.m_nTotalShaderCombos,
+// shaderInfo.m_CentroidMask, shaderInfo.m_nDynamicCombos, shaderInfo.m_Flags );
+ CUtlBuffer header;
+ CUtlBuffer body;
+ header.PutInt( SHADER_VCS_VERSION_NUMBER ); // version
+ header.PutInt( shaderInfo.m_nTotalShaderCombos );
+ header.PutInt( shaderInfo.m_nDynamicCombos );
+ header.PutUnsignedInt( shaderInfo.m_Flags );
+ header.PutUnsignedInt( shaderInfo.m_CentroidMask );
+
+ int headerSize = sizeof( int ) * 5;
+ int directorySize = sizeof( int ) * 2 * shaderInfo.m_nTotalShaderCombos;
+ int bodyOffset = headerSize + directorySize;
+ int nCombo;
+ for( nCombo = 0; nCombo < shaderInfo.m_nTotalShaderCombos; nCombo++ )
+ {
+ CUtlBuffer &byteCode = byteCodeArray[nCombo];
+ if( byteCode.TellPut() == 0 )
+ {
+ // This is a skipped combo.
+ header.PutInt( -1 );
+ header.PutInt( 0 );
+ }
+ else
+ {
+ header.PutInt( body.TellPut() + bodyOffset );
+ header.PutInt( byteCode.TellPut() );
+ body.Put( byteCode.Base(), byteCode.TellPut() );
+ }
+ }
+
+ char filename[MAX_PATH];
+ char filename2[MAX_PATH];
+// strcpy( filename2, g_pShaderOutputDir );
+ strcpy( filename2, g_pShaderPath );
+ strcat( filename2, "\\shaders\\fxc" );
+
+ struct _stat buf;
+ if( _stat( filename2, &buf ) == -1 )
+ {
+ printf( "mkdir %s\n", filename2 );
+ // doh. . need to make the directory that the vcs file is going to go into.
+ _mkdir( filename2 );
+ }
+
+ strcat( filename2, "\\" );
+ strcpy( filename, pShaderName );
+ char *dot = strstr( filename, "." );
+ if( dot )
+ {
+ *dot = '\0';
+ }
+ strcat( filename, ".vcs" );
+ strcat( filename2, filename );
+ if( _stat( filename2, &buf ) != -1 )
+ {
+ // The file exists, let's see if it's writable.
+ if( !( buf.st_mode & _S_IWRITE ) )
+ {
+ // It isn't writable. . we'd better change it's permissions (or check it out possibly).
+ printf( "Warning: making %s writable!\n", filename2 );
+ _chmod( filename2, _S_IREAD | _S_IWRITE );
+ }
+ }
+ FILE *fp = fopen( filename2, "wb" );
+ if( !fp )
+ {
+ printf( "Can't open %s\n", filename2 );
+ return;
+ }
+ printf( "writing %s\n", filename );
+ fwrite( header.Base(), 1, headerSize + directorySize, fp );
+ fwrite( body.Base(), 1, body.TellPut(), fp );
+ fclose( fp );
+#endif
+}
+
+void TouchFile( const char *path )
+{
+ Warning( "TouchFile: %s\n", path );
+ char dir[MAX_PATH];
+ Q_strcpy( dir, path );
+ Q_StripFilename( dir );
+ MakeDirHier( dir );
+ FILE *fp = fopen( path, "wb" );
+ fclose( fp );
+}
+
+int TextureCompile_Main( int argc, char* argv[] )
+{
+ InstallSpewFunction();
+ g_bSuppressPrintfOutput = false;
+ g_flStartTime = Plat_FloatTime();
+
+ SetupDebugFile();
+ numthreads = 1; // holy shit batman!
+ SetupPaths( argc, argv );
+
+ // Master, start accepting connections.
+ // Worker, make a connection.
+ DebugOut( "Before VMPI_Init\n" );
+ g_bSuppressPrintfOutput = true;
+ VMPIRunMode mode = VMPI_RUN_NETWORKED;
+ if ( !VMPI_Init( argc, argv, "dependency_info_texturecompile.txt", MyDisconnectHandler, mode ) )
+ {
+ g_bSuppressPrintfOutput = false;
+ DebugOut( "MPI_Init failed.\n" );
+ Error( "MPI_Init failed." );
+ }
+ g_bSuppressPrintfOutput = false;
+
+ DebugOut( "After VMPI_Init\n" );
+
+ int maxFileSystemMemoryUsageBytes = 50000000;
+ CmdLib_InitFileSystem( ".", maxFileSystemMemoryUsageBytes );
+
+ DebugOut( "After VMPI_FileSystem_Init\n" );
+ Shared_ParseListOfCompileCommands();
+ DebugOut( "After Shared_ParseListOfCompileCommands\n" );
+
+ // 4-ish work units per machine
+ g_nTexturesPerWorkUnit = TEXTURES_PER_WORKUNIT;
+ int nWorkUnits = g_CompileCommands.Count() / g_nTexturesPerWorkUnit + 1;
+
+// printf( "nWorkUnits: %d\n", nWorkUnits );
+// printf( "g_nShadersPerWorkUnit: %d\n", g_nShadersPerWorkUnit );
+
+ DebugOut( "Before conditional\n" );
+ if ( g_bMPIMaster )
+ {
+ // Send all of the workers the complete list of work to do.
+ DebugOut( "Before STARTWORK_PACKETID\n" );
+
+ char packetID = STARTWORK_PACKETID;
+ VMPI_SendData( &packetID, sizeof( packetID ), VMPI_PERSISTENT );
+
+ // nWorkUnits is how many work units. . .1000 is good.
+ // The work unit number impies which combo to do.
+ DebugOut( "Before DistributeWork\n" );
+ DistributeWork( nWorkUnits, WORKUNIT_PACKETID, NULL, Master_ReceiveWorkUnitFn );
+ }
+ else
+ {
+ // wait until we get a packet from the master to start doing stuff.
+ MessageBuffer buf;
+ DebugOut( "Before VMPI_DispatchUntil\n" );
+ while ( !g_bGotStartWorkPacket )
+ {
+ VMPI_DispatchNextMessage();
+ }
+ DebugOut( "after VMPI_DispatchUntil\n" );
+
+ Worker_ReadFilesToCopy();
+// Worker_GetSourceFiles();
+// DebugOut( "Before Worker_GetLocalCopyOfShaders\n" );
+// Worker_GetLocalCopyOfTextureSource();
+// DebugOut( "Before Worker_GetLocalCopyOfBinaries\n" );
+ DebugOut( "Before _chdir\n" );
+ _chdir( g_WorkerTempPath );
+
+ // DIE DIE KILL KILL AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ char path[MAX_PATH];
+ sprintf( path, "%s%s\\bin\\server.dll", g_WorkerTempPath, g_pGameDir + 3 ); // hack hack
+ TouchFile( path );
+ sprintf( path, "%s%s\\bin\\client.dll", g_WorkerTempPath, g_pGameDir + 3 );// hack hack
+ TouchFile( path );
+
+ Worker_GetLocalCopyOfBinaries();
+
+ // nWorkUnits is how many work units. . .1000 is good.
+ // The work unit number impies which combo to do.
+ DebugOut( "Before DistributeWork\n" );
+
+ DistributeWork( nWorkUnits, WORKUNIT_PACKETID, Worker_ProcessWorkUnitFn, NULL );
+ }
+
+ DebugOut( "Before VMPI_Finalize\n" );
+ g_bSuppressPrintfOutput = true;
+ VMPI_FileSystem_Term();
+ VMPI_Finalize();
+ g_bSuppressPrintfOutput = false;
+
+ if( g_bMPIMaster )
+ {
+/*
+ printf( "\n" );
+ int nStrings = g_ByteCode.GetNumStrings();
+ int i;
+ for( i = 0; i < nStrings; i++ )
+ {
+ if( g_Master_TextureHadError.Defined( g_ByteCode.String( i ) ) )
+ {
+ printf( "FAILED: \"%s\"\n", g_ByteCode.String( i ) );
+ }
+ else
+ {
+// printf( "\"%s\" succeeded!\n", g_ByteCode.String( i ) );
+ WriteTexture( g_ByteCode.String( i ) );
+ }
+ }
+
+ double end = Plat_FloatTime();
+
+ char str[512];
+ GetHourMinuteSecondsString( (int)( end - g_flStartTime ), str, sizeof( str ) );
+ Msg( "%s elapsed\n", str );
+*/
+ }
+ return 0;
+}
+
+class CTextureCompileDLL : public ILaunchableDLL
+{
+ int main( int argc, char **argv );
+};
+
+int CTextureCompileDLL::main( int argc, char **argv )
+{
+ return TextureCompile_Main( argc, argv );
+}
+
+EXPOSE_SINGLE_INTERFACE( CTextureCompileDLL, ILaunchableDLL, LAUNCHABLE_DLL_INTERFACE_VERSION );