summaryrefslogtreecommitdiff
path: root/materialsystem/shaderapidx9/recording.cpp
blob: 4d2344ad15739938b42f8c69979b7292a7db4dba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//========= 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 <stdio.h>

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

#ifdef RECORDING

//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------

static CUtlVector<unsigned char> 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