Files
FlaxEngine/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTimerQueryDX11.cpp
2021-01-05 02:13:15 +01:00

132 lines
3.0 KiB
C++

// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#if GRAPHICS_API_DIRECTX11
#include "GPUTimerQueryDX11.h"
GPUTimerQueryDX11::GPUTimerQueryDX11(GPUDeviceDX11* device)
: GPUResourceDX11<GPUTimerQuery>(device, String::Empty)
{
D3D11_QUERY_DESC queryDesc;
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
queryDesc.MiscFlags = 0;
HRESULT hr = device->GetDevice()->CreateQuery(&queryDesc, &_disjointQuery);
if (hr != S_OK)
{
LOG(Fatal, "Failed to create a timer query.");
}
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
hr = device->GetDevice()->CreateQuery(&queryDesc, &_beginQuery);
if (hr != S_OK)
{
LOG(Fatal, "Failed to create a timer query.");
}
hr = device->GetDevice()->CreateQuery(&queryDesc, &_endQuery);
if (hr != S_OK)
{
LOG(Fatal, "Failed to create a timer query.");
}
// Set non-zero mem usage (fake)
_memoryUsage = sizeof(D3D11_QUERY_DESC) * 3;
}
GPUTimerQueryDX11::~GPUTimerQueryDX11()
{
if (_beginQuery)
_beginQuery->Release();
if (_endQuery)
_endQuery->Release();
if (_disjointQuery)
_disjointQuery->Release();
}
void GPUTimerQueryDX11::OnReleaseGPU()
{
SAFE_RELEASE(_beginQuery);
SAFE_RELEASE(_endQuery);
SAFE_RELEASE(_disjointQuery);
}
ID3D11Resource* GPUTimerQueryDX11::GetResource()
{
return nullptr;
}
void GPUTimerQueryDX11::Begin()
{
auto context = _device->GetIM();
context->Begin(_disjointQuery);
context->End(_beginQuery);
_endCalled = false;
}
void GPUTimerQueryDX11::End()
{
if (_endCalled)
return;
auto context = _device->GetIM();
context->End(_endQuery);
context->End(_disjointQuery);
_endCalled = true;
_finalized = false;
}
bool GPUTimerQueryDX11::HasResult()
{
if (!_endCalled)
return false;
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
return _device->GetIM()->GetData(_disjointQuery, &disjointData, sizeof(disjointData), 0) == S_OK;
}
float GPUTimerQueryDX11::GetResult()
{
if (!_finalized)
{
#if BUILD_DEBUG
ASSERT(HasResult());
#endif
UINT64 timeStart, timeEnd;
auto context = _device->GetIM();
context->GetData(_beginQuery, &timeStart, sizeof(timeStart), 0);
context->GetData(_endQuery, &timeEnd, sizeof(timeEnd), 0);
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
context->GetData(_disjointQuery, &disjointData, sizeof(disjointData), 0);
if (disjointData.Disjoint == FALSE)
{
const UINT64 delta = timeEnd - timeStart;
_timeDelta = (float)(((double)delta / (double)disjointData.Frequency) * 1000.0);
}
else
{
_timeDelta = 0.0f;
#if !BUILD_RELEASE
static bool SingleShotLog = false;
if (!SingleShotLog)
{
SingleShotLog = true;
LOG(Warning, "Unreliable GPU timer query detected.");
}
#endif
}
_finalized = true;
}
return _timeDelta;
}
#endif