From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- utils/remoteshadercompile/remoteshadercompile.cpp | 316 ++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 utils/remoteshadercompile/remoteshadercompile.cpp (limited to 'utils/remoteshadercompile/remoteshadercompile.cpp') diff --git a/utils/remoteshadercompile/remoteshadercompile.cpp b/utils/remoteshadercompile/remoteshadercompile.cpp new file mode 100644 index 0000000..81438a1 --- /dev/null +++ b/utils/remoteshadercompile/remoteshadercompile.cpp @@ -0,0 +1,316 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Defines the entry point for the console application +// +//=============================================================================== + +//#include +//#include +#include +#include +#include +#include "tier1/utlvector.h" +#include "tier0/icommandline.h" +#include "tier2/tier2.h" +#include "tier2/fileutils.h" +#include "../../dx9sdk/include/d3d9.h" +#include "../../dx9sdk/include/d3dx9.h" + +#define DEFAULT_PORT "20000" +#define DEFAULT_SEND_BUF_LEN 40000 +#define DEFAULT_RECV_BUF_LEN 40000 + +char g_pPathBase[MAX_PATH]; +bool g_bPrintDisassembly; + +// This guy just spins and compiles when a command comes in from the game +void ServerThread( void * ) +{ + WSADATA wsaData; + if( WSAStartup( 0x101, &wsaData ) != 0 ) + return; + + struct addrinfo *result = NULL, hints; + + ZeroMemory( &hints, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + + // Resolve the server address and port + int nResult = getaddrinfo( NULL, DEFAULT_PORT, &hints, &result ); + if ( nResult != 0 ) + { + printf( "getaddrinfo failed: %d\n", nResult ); + WSACleanup(); + return; + } + + // Create a SOCKET for connecting to server + SOCKET ListenSocket = socket( result->ai_family, result->ai_socktype, result->ai_protocol ); + if (ListenSocket == INVALID_SOCKET) { + printf("socket failed: %ld\n", WSAGetLastError()); + freeaddrinfo(result); + WSACleanup(); + return; + } + + // Setup the TCP listening socket + nResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen ); + if (nResult == SOCKET_ERROR) + { + printf("bind failed: %d\n", WSAGetLastError()); + freeaddrinfo(result); + closesocket(ListenSocket); + WSACleanup(); + return; + } + + freeaddrinfo(result); + + + nResult = listen( ListenSocket, SOMAXCONN ); + if ( nResult == SOCKET_ERROR ) + { + printf( "listen failed: %d\n", WSAGetLastError() ); + closesocket( ListenSocket ); + WSACleanup(); + return; + } + + printf( "Waiting for initial connection...\n" ); + + // Accept a client socket + SOCKET ClientSocket = accept( ListenSocket, NULL, NULL ); + if ( ClientSocket == INVALID_SOCKET ) + { + printf( "accept failed: %d\n", WSAGetLastError() ); + closesocket( ListenSocket ); + WSACleanup(); + return; + } + + // First connection + printf( "Game connected\n" ); + + char pRecbuf[DEFAULT_RECV_BUF_LEN]; // Text in command file from game + uint32 pSendbuf[DEFAULT_SEND_BUF_LEN]; // Error string or binary shader blob in reply + + while ( true ) + { + nResult = recv( ClientSocket, pRecbuf, DEFAULT_RECV_BUF_LEN, 0 ); + + if ( nResult > 0 ) + { + char *pShaderFilename = strtok ( pRecbuf, "\n"); + char pFullFilename[MAX_PATH]; + + // If we took in a path on the commandline, we concatenate the incoming filenames with it + if ( V_strlen( g_pPathBase ) > 0 ) + { + V_strncpy( pFullFilename, g_pPathBase, MAX_PATH ); // base path + V_strncat( pFullFilename, pShaderFilename, MAX_PATH ); + pShaderFilename = pFullFilename; + } + char *pShaderModel = strtok ( NULL, "\n"); + int nSendBufLen = 0; + + // Only try to compile if we have a recognized profile + if ( !stricmp( pShaderModel, "vs_2_0" ) || !stricmp( pShaderModel, "ps_2_0" ) || !stricmp( pShaderModel, "ps_2_b" ) ) + { + char *pNumMacros = strtok ( NULL, "\n"); + int nNumMacros = atoi( pNumMacros ); + + // Read macros from the command file + CUtlVector macros; + D3DXMACRO macro; + for ( int i=0; iGetBufferPointer(), pErrorMessages->GetBufferSize() ); // Null-terminated string + printf("%s\n", (const char*)(pSendbuf + 1 )); + nSendBufLen = pErrorMessages->GetBufferSize() + 4; // account for uint32 at front of the buffer + } + else + { + ((uint8*)(pSendbuf+1))[0] = '?'; + ((uint8*)(pSendbuf+1))[1] = '\0'; + nSendBufLen = 2 + 4; // account for uint32 at front of the buffer + } + + + } + else // Success! + { +// printf( "Compiled %s\n", pShaderFilename ); + pSendbuf[0] = pShader->GetBufferSize(); + memcpy( pSendbuf+1, pShader->GetBufferPointer(), pShader->GetBufferSize() ); + nSendBufLen = pShader->GetBufferSize() + 4; // account for uint32 at front of the buffer + + if ( g_bPrintDisassembly ) + { + printf( "Filename: %s\n", pShaderFilename ); + printf( "Shader model: %s\n", pShaderModel ); + printf( "Macros: " ); + for ( int i = 0; i < nNumMacros - 1; i++ ) + printf( " %s\n", macros[i].Name ); + LPD3DXBUFFER pDisassembly = NULL; + D3DXDisassembleShader( (const DWORD*)pShader->GetBufferPointer(), FALSE, "", &pDisassembly ); + if ( pDisassembly ) + { + printf( "Disassembled shader:\n"); + puts( (const char*)pDisassembly->GetBufferPointer() ); + printf("\n"); + + pDisassembly->Release(); + } + } + } + + if (pErrorMessages) + { + pErrorMessages->Release(); + } + + if (pShader) + { + pShader->Release(); + } + + // Purge the macro buffer + macros.RemoveMultipleFromTail( nNumMacros ); + } + else // Not a supported shader profile + { + pSendbuf[0] = 0; + char *pCharSendbuff = (char *) (pSendbuf+1); + V_snprintf( pCharSendbuff, DEFAULT_SEND_BUF_LEN, "Unsupported shader profile: %s\n", pShaderModel ); + nSendBufLen = strlen( pCharSendbuff ) + 4; // account for uint32 at front of the buffer + } + + // Send the compiled shader back to the game + int nSendResult = send( ClientSocket, (const char *)pSendbuf, nSendBufLen, 0 ); + if ( nSendResult == SOCKET_ERROR ) + { + printf( "send failed: %d\n", WSAGetLastError() ); + closesocket( ClientSocket ); + WSACleanup(); + return; + } + } + else // We had a game talking to us but it went away + { + printf( "Game went away, waiting for new connection...\n" ); + + // Block again waiting to accept a connection + ClientSocket = accept( ListenSocket, NULL, NULL ); + + printf( "Game connected\n" ); + + if ( ClientSocket == INVALID_SOCKET ) + { + printf( "accept failed: %d\n", WSAGetLastError() ); + Assert( 0 ); + closesocket( ListenSocket ); + WSACleanup(); + return; + } + } + } + + nResult = shutdown( ClientSocket, SD_SEND ); + if ( nResult == SOCKET_ERROR ) + { + printf("shutdown failed: %d\n", WSAGetLastError()); + closesocket( ClientSocket ); + WSACleanup(); + return; + } + + // cleanup + closesocket( ClientSocket ); + WSACleanup(); +} + + +void CheckPath( char *pPath ) +{ + int len = V_strlen( pPath ); + + // If we don't have a path separator at the end of the path, put one there + if ( ( pPath[len-1] != '\\' ) && ( pPath[len-1] != '/' ) ) + { + V_strncat( pPath, CORRECT_PATH_SEPARATOR_S, MAX_PATH ); + } +} + + +int main(int argc, char* argv[]) +{ + if ( argc < 2 ) + { + printf( "============================================================\n" ); + printf( " Please provide full path to shader directory. For example:\n" ); + printf( " U:\\piston\\staging\\src\\materialsystem\\stdshaders\\ \n"); + printf( "============================================================\n" ); + printf( " remoteshadercompiler will now exit!!! \n" ); + printf( "============================================================\n" ); + return 0; + } + + printf( "========================================================\n"); + printf( "Remote shader compiler is running. Press ESCAPE to exit\n" ); + printf( "========================================================\n"); + + // If we have a path specified on the commandline, we expect + // that the remote machine is going to send base filenames only + // and that we'll want to strcat this path onto the filename from the worker. + // + // For example, if you have your shader source on your Windows machine, you can use something like this: + // + // U:\piston\staging\src\materialsystem\stdshaders\ + // + strcpy( g_pPathBase, argv[1] ); + + if ( argc == 3 ) + { + g_bPrintDisassembly = true; + } + + CheckPath( g_pPathBase ); + + // Kick off compile server thread + _beginthread( ServerThread, 0, NULL ); + + // Spin until escape + while( _getch() != 27 ) + ; + + return 0; +} -- cgit v1.2.3