summaryrefslogtreecommitdiff
path: root/Runtime/GfxDevice/threaded/ThreadedTimerQuery.cpp
blob: 2b1731aba565d70f1709bbe2a86cd82f18ae9f3a (plain)
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
#include "UnityPrefix.h"
#if ENABLE_PROFILER
#include "ThreadedTimerQuery.h"
#include "GfxDeviceWorker.h"
#include "Runtime/Threads/ThreadUtility.h"
#include "Runtime/Threads/ThreadedStreamBuffer.h"
#include "Runtime/GfxDevice/threaded/GfxDeviceClient.h"
#include "Runtime/GfxDevice/threaded/GfxCommands.h"

ThreadedTimerQuery::ThreadedTimerQuery(GfxDeviceClient& device)
:	m_ClientDevice(device)
{
	m_ClientQuery = new ClientDeviceTimerQuery;
	DebugAssert(Thread::CurrentThreadIsMainThread());
	if (m_ClientDevice.IsSerializing())
	{
		ThreadedStreamBuffer& stream = *m_ClientDevice.GetCommandQueue();
		stream.WriteValueType<GfxCommand>(kGfxCmd_TimerQuery_Constructor);
		stream.WriteValueType<ClientDeviceTimerQuery*>(m_ClientQuery);
		GFXDEVICE_LOCKSTEP_CLIENT();
	}
	else
		m_ClientQuery->internalQuery = GetRealGfxDevice().CreateTimerQuery();
}

ThreadedTimerQuery::~ThreadedTimerQuery()
{
	DebugAssert(Thread::CurrentThreadIsMainThread());
	if (m_ClientDevice.IsSerializing())
	{
		ThreadedStreamBuffer& stream = *m_ClientDevice.GetCommandQueue();
		stream.WriteValueType<GfxCommand>(kGfxCmd_TimerQuery_Destructor);
		stream.WriteValueType<ClientDeviceTimerQuery*>(m_ClientQuery);
		GFXDEVICE_LOCKSTEP_CLIENT();
	}
	else
	{
		Assert(m_ClientQuery);
		GetRealGfxDevice().DeleteTimerQuery(m_ClientQuery->GetInternal());
		delete m_ClientQuery;
	}
	m_ClientQuery = NULL;
}

void ThreadedTimerQuery::Measure()
{
	DebugAssert(Thread::CurrentThreadIsMainThread());
	if (m_ClientDevice.IsSerializing())
	{
		ThreadedStreamBuffer& stream = *m_ClientDevice.GetCommandQueue();
		stream.WriteValueType<GfxCommand>(kGfxCmd_TimerQuery_Measure);
		stream.WriteValueType<ClientDeviceTimerQuery*>(m_ClientQuery);
		GFXDEVICE_LOCKSTEP_CLIENT();
	}
	else
		m_ClientQuery->GetInternal()->Measure();
}

ProfileTimeFormat ThreadedTimerQuery::GetElapsed(UInt32 flags)
{
	DebugAssert(Thread::CurrentThreadIsMainThread());
	if (m_ClientDevice.IsSerializing())
	{
		// See if we have the result already
		ProfileTimeFormat time = GetElapsedIfReady();
		if (time != kInvalidProfileTime)
			return time;

		// Request result from worker thread
		ThreadedStreamBuffer& stream = *m_ClientDevice.GetCommandQueue();
		stream.WriteValueType<GfxCommand>(kGfxCmd_TimerQuery_GetElapsed);
		stream.WriteValueType<ClientDeviceTimerQuery*>(m_ClientQuery);
		stream.WriteValueType<UInt32>(flags);
		if (flags & GfxTimerQuery::kWaitClientThread)
		{
			m_ClientDevice.SubmitCommands();
			m_ClientDevice.GetGfxDeviceWorker()->WaitForSignal();
		}
		GFXDEVICE_LOCKSTEP_CLIENT();
		return GetElapsedIfReady();
	}
	else
		return m_ClientQuery->GetInternal()->GetElapsed(flags);
}

ProfileTimeFormat ThreadedTimerQuery::GetElapsedIfReady()
{
	if (!m_ClientQuery->pending)
	{
		// Be careful since UInt64 isn't guaranteed atomic
		UnityMemoryBarrier();
		return m_ClientQuery->elapsed;
	}
	return kInvalidProfileTime;
}

void ThreadedTimerQuery::DoLockstep()
{
	m_ClientDevice.DoLockstep();
}

#endif