//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #include "togl/rendermechanism.h" #include "recording.h" #include "shaderapi/ishaderutil.h" #include "materialsystem/imaterialsystem.h" #include "shaderapidx8_global.h" #include "utlvector.h" #include // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #ifdef RECORDING //----------------------------------------------------------------------------- // Globals //----------------------------------------------------------------------------- static CUtlVector g_pRecordingBuffer; static int g_ArgsRemaining = 0; static int g_CommandStartIdx = 0; //----------------------------------------------------------------------------- // Opens the recording file //----------------------------------------------------------------------------- static FILE* OpenRecordingFile() { #ifdef CRASH_RECORDING static FILE *fp = 0; #else FILE* fp = 0; #endif static bool g_CantOpenFile = false; static bool g_NeverOpened = true; if (!g_CantOpenFile) { #ifdef CRASH_RECORDING if( g_NeverOpened ) { fp = fopen( "shaderdx8.rec", "wbc" ); } #else fp = fopen( "shaderdx8.rec", g_NeverOpened ? "wb" : "ab" ); #endif if (!fp) { Warning("Unable to open recording file shaderdx8.rec!\n"); g_CantOpenFile = true; } g_NeverOpened = false; } return fp; } //----------------------------------------------------------------------------- // Writes to the recording file //----------------------------------------------------------------------------- #define COMMAND_BUFFER_SIZE 32768 static void WriteRecordingFile() { // Store the command size *(int*)&g_pRecordingBuffer[g_CommandStartIdx] = g_pRecordingBuffer.Size() - g_CommandStartIdx; #ifndef CRASH_RECORDING // When not crash recording, flush when buffer gets too big, // or when Present() is called if ((g_pRecordingBuffer.Size() < COMMAND_BUFFER_SIZE) && (g_pRecordingBuffer[g_CommandStartIdx+4] != DX8_PRESENT)) return; #endif FILE* fp = OpenRecordingFile(); if (fp) { // store the command size fwrite( g_pRecordingBuffer.Base(), 1, g_pRecordingBuffer.Size(), fp ); fflush( fp ); #ifndef CRASH_RECORDING fclose( fp ); #endif } g_pRecordingBuffer.RemoveAll(); } // Write the buffered crap out on shutdown. void FinishRecording() { #ifndef CRASH_RECORDING FILE* fp = OpenRecordingFile(); if (fp) { // store the command size fwrite( g_pRecordingBuffer.Base(), 1, g_pRecordingBuffer.Size(), fp ); fflush( fp ); } g_pRecordingBuffer.RemoveAll(); #endif } // set this to true in the debugger to actually record commands. static bool g_bDoRecord = true; //----------------------------------------------------------------------------- // Records a command //----------------------------------------------------------------------------- void RecordCommand( RecordingCommands_t cmd, int numargs ) { if( !g_bDoRecord ) { return; } Assert( g_ArgsRemaining == 0 ); g_CommandStartIdx = g_pRecordingBuffer.AddMultipleToTail( 6 ); // save space for the total command size g_pRecordingBuffer[g_CommandStartIdx+4] = cmd; g_pRecordingBuffer[g_CommandStartIdx+5] = numargs; g_ArgsRemaining = numargs; if (g_ArgsRemaining == 0) WriteRecordingFile(); } //----------------------------------------------------------------------------- // Records an argument for a command, flushes when the command is done //----------------------------------------------------------------------------- void RecordArgument( void const* pMemory, int size ) { if( !g_bDoRecord ) { return; } Assert( g_ArgsRemaining > 0 ); int tail = g_pRecordingBuffer.Size(); g_pRecordingBuffer.AddMultipleToTail( size ); memcpy( &g_pRecordingBuffer[tail], pMemory, size ); if (--g_ArgsRemaining == 0) WriteRecordingFile(); } #endif // RECORDING