2017-12-29 22:20:31 +01:00
|
|
|
#include "d3d11_device.h"
|
|
|
|
#include "d3d11_query.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
D3D11Query::D3D11Query(
|
|
|
|
D3D11Device* device,
|
|
|
|
const D3D11_QUERY_DESC& desc)
|
2019-04-02 03:46:06 +02:00
|
|
|
: m_device(device), m_desc(desc),
|
2019-04-14 16:27:15 +02:00
|
|
|
m_state(D3D11_VK_QUERY_INITIAL),
|
2018-10-12 18:31:55 +02:00
|
|
|
m_d3d10(this, device->GetD3D10Interface()) {
|
2018-11-16 23:54:44 +01:00
|
|
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
|
|
|
|
2018-02-18 22:34:23 +01:00
|
|
|
switch (m_desc.Query) {
|
2018-01-24 21:28:43 -08:00
|
|
|
case D3D11_QUERY_EVENT:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_event[0] = dxvkDevice->createGpuEvent();
|
2018-02-18 22:34:23 +01:00
|
|
|
break;
|
|
|
|
|
2018-01-13 23:35:33 -08:00
|
|
|
case D3D11_QUERY_OCCLUSION:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-02-19 11:27:14 +01:00
|
|
|
VK_QUERY_TYPE_OCCLUSION,
|
2018-11-17 10:48:18 +01:00
|
|
|
VK_QUERY_CONTROL_PRECISE_BIT, 0);
|
2018-02-19 11:27:14 +01:00
|
|
|
break;
|
|
|
|
|
2018-02-18 22:34:23 +01:00
|
|
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-11-17 10:48:18 +01:00
|
|
|
VK_QUERY_TYPE_OCCLUSION, 0, 0);
|
2018-02-18 22:34:23 +01:00
|
|
|
break;
|
|
|
|
|
2018-01-22 21:39:54 -08:00
|
|
|
case D3D11_QUERY_TIMESTAMP:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-11-17 10:48:18 +01:00
|
|
|
VK_QUERY_TYPE_TIMESTAMP, 0, 0);
|
2018-02-18 22:34:23 +01:00
|
|
|
break;
|
|
|
|
|
2018-01-22 21:39:54 -08:00
|
|
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
2019-06-16 17:00:38 +02:00
|
|
|
for (uint32_t i = 0; i < 2; i++) {
|
|
|
|
m_query[i] = dxvkDevice->createGpuQuery(
|
|
|
|
VK_QUERY_TYPE_TIMESTAMP, 0, 0);
|
|
|
|
}
|
2018-01-13 23:35:33 -08:00
|
|
|
break;
|
2018-02-18 22:34:23 +01:00
|
|
|
|
|
|
|
case D3D11_QUERY_PIPELINE_STATISTICS:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-11-17 10:48:18 +01:00
|
|
|
VK_QUERY_TYPE_PIPELINE_STATISTICS, 0, 0);
|
2018-02-18 22:34:23 +01:00
|
|
|
break;
|
|
|
|
|
2018-08-31 16:10:55 +02:00
|
|
|
case D3D11_QUERY_SO_STATISTICS:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM0:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0:
|
|
|
|
// FIXME it is technically incorrect to map
|
|
|
|
// SO_OVERFLOW_PREDICATE to the first stream,
|
|
|
|
// but this is good enough for D3D10 behaviour
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-08-31 16:10:55 +02:00
|
|
|
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM1:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-08-31 16:10:55 +02:00
|
|
|
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM2:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-08-31 16:10:55 +02:00
|
|
|
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM3:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3:
|
2019-06-16 16:53:11 +02:00
|
|
|
m_query[0] = dxvkDevice->createGpuQuery(
|
2018-08-31 16:10:55 +02:00
|
|
|
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT, 0, 3);
|
|
|
|
break;
|
|
|
|
|
2018-01-13 23:35:33 -08:00
|
|
|
default:
|
2018-02-18 22:34:23 +01:00
|
|
|
throw DxvkError(str::format("D3D11: Unhandled query type: ", desc.Query));
|
2018-01-13 23:35:33 -08:00
|
|
|
}
|
2017-12-29 22:20:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D11Query::~D3D11Query() {
|
2019-03-23 23:33:01 +01:00
|
|
|
if (m_predicate.defined())
|
|
|
|
m_device->FreePredicateSlice(m_predicate);
|
2017-12-29 22:20:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Query::QueryInterface(REFIID riid, void** ppvObject) {
|
2019-02-10 07:01:01 +00:00
|
|
|
if (ppvObject == nullptr)
|
|
|
|
return E_POINTER;
|
|
|
|
|
2018-04-02 12:52:02 +02:00
|
|
|
*ppvObject = nullptr;
|
2017-12-29 22:20:31 +01:00
|
|
|
|
2018-04-02 12:52:02 +02:00
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceChild)
|
|
|
|
|| riid == __uuidof(ID3D11Asynchronous)
|
|
|
|
|| riid == __uuidof(ID3D11Query)) {
|
|
|
|
*ppvObject = ref(this);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2018-08-12 00:20:17 +02:00
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|
|
|| riid == __uuidof(ID3D10DeviceChild)
|
|
|
|
|| riid == __uuidof(ID3D10Asynchronous)
|
|
|
|
|| riid == __uuidof(ID3D10Query)) {
|
|
|
|
*ppvObject = ref(&m_d3d10);
|
2018-04-02 12:52:02 +02:00
|
|
|
return S_OK;
|
|
|
|
}
|
2018-02-18 22:34:23 +01:00
|
|
|
|
2018-08-12 00:20:17 +02:00
|
|
|
if (m_desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE) {
|
2018-08-16 00:13:40 +02:00
|
|
|
if (riid == __uuidof(ID3D11Predicate)) {
|
2018-08-12 00:20:17 +02:00
|
|
|
*ppvObject = ref(this);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D10Predicate)) {
|
|
|
|
*ppvObject = ref(&m_d3d10);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-29 22:20:31 +01:00
|
|
|
Logger::warn("D3D11Query: Unknown interface query");
|
2018-03-12 14:05:43 +03:00
|
|
|
Logger::warn(str::format(riid));
|
2017-12-29 22:20:31 +01:00
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STDMETHODCALLTYPE D3D11Query::GetDevice(ID3D11Device **ppDevice) {
|
|
|
|
*ppDevice = ref(m_device);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UINT STDMETHODCALLTYPE D3D11Query::GetDataSize() {
|
|
|
|
switch (m_desc.Query) {
|
|
|
|
case D3D11_QUERY_EVENT:
|
|
|
|
return sizeof(BOOL);
|
|
|
|
|
|
|
|
case D3D11_QUERY_OCCLUSION:
|
|
|
|
return sizeof(UINT64);
|
|
|
|
|
|
|
|
case D3D11_QUERY_TIMESTAMP:
|
|
|
|
return sizeof(UINT64);
|
|
|
|
|
|
|
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
|
|
|
return sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT);
|
|
|
|
|
|
|
|
case D3D11_QUERY_PIPELINE_STATISTICS:
|
|
|
|
return sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS);
|
|
|
|
|
|
|
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
|
|
|
return sizeof(BOOL);
|
|
|
|
|
|
|
|
case D3D11_QUERY_SO_STATISTICS:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM0:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM1:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM2:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM3:
|
|
|
|
return sizeof(D3D11_QUERY_DATA_SO_STATISTICS);
|
|
|
|
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3:
|
|
|
|
return sizeof(BOOL);
|
|
|
|
}
|
|
|
|
|
|
|
|
Logger::err("D3D11Query: Failed to query data size");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STDMETHODCALLTYPE D3D11Query::GetDesc(D3D11_QUERY_DESC *pDesc) {
|
|
|
|
*pDesc = m_desc;
|
|
|
|
}
|
|
|
|
|
2018-01-01 20:59:54 +01:00
|
|
|
|
2018-11-17 10:48:18 +01:00
|
|
|
void D3D11Query::Begin(DxvkContext* ctx) {
|
2019-04-14 16:27:15 +02:00
|
|
|
if (unlikely(m_state == D3D11_VK_QUERY_BEGUN))
|
|
|
|
return;
|
|
|
|
|
2018-11-17 10:48:18 +01:00
|
|
|
switch (m_desc.Query) {
|
|
|
|
case D3D11_QUERY_EVENT:
|
|
|
|
case D3D11_QUERY_TIMESTAMP:
|
2019-06-16 17:00:38 +02:00
|
|
|
break;
|
|
|
|
|
2018-11-17 10:48:18 +01:00
|
|
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
2019-06-16 17:00:38 +02:00
|
|
|
ctx->writeTimestamp(m_query[1]);
|
2018-11-17 10:48:18 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-06-16 16:53:11 +02:00
|
|
|
ctx->beginQuery(m_query[0]);
|
2018-02-18 22:34:23 +01:00
|
|
|
}
|
2019-04-14 16:27:15 +02:00
|
|
|
|
|
|
|
m_state = D3D11_VK_QUERY_BEGUN;
|
2018-02-18 22:34:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D11Query::End(DxvkContext* ctx) {
|
2018-01-01 20:59:54 +01:00
|
|
|
switch (m_desc.Query) {
|
2018-11-17 10:48:18 +01:00
|
|
|
case D3D11_QUERY_EVENT:
|
2019-06-16 16:53:11 +02:00
|
|
|
ctx->signalGpuEvent(m_event[0]);
|
2018-11-17 10:48:18 +01:00
|
|
|
break;
|
2018-02-18 22:57:45 +01:00
|
|
|
|
2018-11-17 10:48:18 +01:00
|
|
|
case D3D11_QUERY_TIMESTAMP:
|
|
|
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
2019-06-16 17:00:38 +02:00
|
|
|
ctx->writeTimestamp(m_query[0]);
|
2018-02-18 22:34:23 +01:00
|
|
|
break;
|
2018-11-17 10:48:18 +01:00
|
|
|
|
|
|
|
default:
|
2019-04-14 16:27:15 +02:00
|
|
|
if (unlikely(m_state != D3D11_VK_QUERY_BEGUN))
|
|
|
|
return;
|
|
|
|
|
2019-06-16 16:53:11 +02:00
|
|
|
ctx->endQuery(m_query[0]);
|
2018-02-18 22:34:23 +01:00
|
|
|
}
|
2019-03-23 23:33:01 +01:00
|
|
|
|
|
|
|
if (m_predicate.defined())
|
2019-06-16 16:53:11 +02:00
|
|
|
ctx->writePredicate(m_predicate, m_query[0]);
|
2019-04-14 16:27:15 +02:00
|
|
|
|
|
|
|
m_state = D3D11_VK_QUERY_ENDED;
|
2018-02-18 22:34:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11Query::GetData(
|
|
|
|
void* pData,
|
|
|
|
UINT GetDataFlags) {
|
|
|
|
if (m_desc.Query == D3D11_QUERY_EVENT) {
|
2019-06-16 16:53:11 +02:00
|
|
|
DxvkGpuEventStatus status = m_event[0]->test();
|
2018-11-16 23:54:44 +01:00
|
|
|
|
|
|
|
if (status == DxvkGpuEventStatus::Invalid)
|
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
|
|
|
|
bool signaled = status == DxvkGpuEventStatus::Signaled;
|
|
|
|
|
2018-02-26 14:33:27 +01:00
|
|
|
if (pData != nullptr)
|
|
|
|
*static_cast<BOOL*>(pData) = signaled;
|
|
|
|
|
|
|
|
return signaled ? S_OK : S_FALSE;
|
2018-02-18 22:34:23 +01:00
|
|
|
} else {
|
2019-06-16 16:53:11 +02:00
|
|
|
std::array<DxvkQueryData, MaxGpuQueries> queryData = { };
|
2018-02-26 14:33:27 +01:00
|
|
|
|
2019-06-16 16:53:11 +02:00
|
|
|
for (uint32_t i = 0; i < MaxGpuQueries && m_query[i] != nullptr; i++) {
|
|
|
|
DxvkGpuQueryStatus status = m_query[i]->getData(queryData[i]);
|
2018-09-10 23:07:51 +02:00
|
|
|
|
2018-11-17 10:48:18 +01:00
|
|
|
if (status == DxvkGpuQueryStatus::Invalid
|
|
|
|
|| status == DxvkGpuQueryStatus::Failed)
|
2018-09-10 23:07:51 +02:00
|
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
|
2018-11-17 10:48:18 +01:00
|
|
|
if (status == DxvkGpuQueryStatus::Pending)
|
2018-09-10 23:07:51 +02:00
|
|
|
return S_FALSE;
|
|
|
|
}
|
2018-02-18 22:34:23 +01:00
|
|
|
|
|
|
|
if (pData == nullptr)
|
2018-01-01 20:59:54 +01:00
|
|
|
return S_OK;
|
2018-02-18 22:34:23 +01:00
|
|
|
|
|
|
|
switch (m_desc.Query) {
|
|
|
|
case D3D11_QUERY_OCCLUSION:
|
2019-06-16 16:53:11 +02:00
|
|
|
*static_cast<UINT64*>(pData) = queryData[0].occlusion.samplesPassed;
|
2018-02-18 22:34:23 +01:00
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
2019-06-16 16:53:11 +02:00
|
|
|
*static_cast<BOOL*>(pData) = queryData[0].occlusion.samplesPassed != 0;
|
2018-02-18 22:34:23 +01:00
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
case D3D11_QUERY_TIMESTAMP:
|
2019-06-16 16:53:11 +02:00
|
|
|
*static_cast<UINT64*>(pData) = queryData[0].timestamp.time;
|
2018-02-18 22:34:23 +01:00
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
case D3D11_QUERY_TIMESTAMP_DISJOINT: {
|
|
|
|
auto data = static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData);
|
2018-06-13 14:29:58 +02:00
|
|
|
data->Frequency = GetTimestampQueryFrequency();
|
2019-06-16 17:00:38 +02:00
|
|
|
data->Disjoint = queryData[0].timestamp.time < queryData[1].timestamp.time;
|
2018-02-18 22:34:23 +01:00
|
|
|
} return S_OK;
|
2018-01-01 20:59:54 +01:00
|
|
|
|
2018-02-18 22:34:23 +01:00
|
|
|
case D3D11_QUERY_PIPELINE_STATISTICS: {
|
|
|
|
auto data = static_cast<D3D11_QUERY_DATA_PIPELINE_STATISTICS*>(pData);
|
2019-06-16 16:53:11 +02:00
|
|
|
data->IAVertices = queryData[0].statistic.iaVertices;
|
|
|
|
data->IAPrimitives = queryData[0].statistic.iaPrimitives;
|
|
|
|
data->VSInvocations = queryData[0].statistic.vsInvocations;
|
|
|
|
data->GSInvocations = queryData[0].statistic.gsInvocations;
|
|
|
|
data->GSPrimitives = queryData[0].statistic.gsPrimitives;
|
|
|
|
data->CInvocations = queryData[0].statistic.clipInvocations;
|
|
|
|
data->CPrimitives = queryData[0].statistic.clipPrimitives;
|
|
|
|
data->PSInvocations = queryData[0].statistic.fsInvocations;
|
|
|
|
data->HSInvocations = queryData[0].statistic.tcsPatches;
|
|
|
|
data->DSInvocations = queryData[0].statistic.tesInvocations;
|
|
|
|
data->CSInvocations = queryData[0].statistic.csInvocations;
|
2018-02-18 22:34:23 +01:00
|
|
|
} return S_OK;
|
2018-08-31 16:10:55 +02:00
|
|
|
|
|
|
|
case D3D11_QUERY_SO_STATISTICS:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM0:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM1:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM2:
|
|
|
|
case D3D11_QUERY_SO_STATISTICS_STREAM3: {
|
|
|
|
auto data = static_cast<D3D11_QUERY_DATA_SO_STATISTICS*>(pData);
|
2019-06-16 16:53:11 +02:00
|
|
|
data->NumPrimitivesWritten = queryData[0].xfbStream.primitivesWritten;
|
|
|
|
data->PrimitivesStorageNeeded = queryData[0].xfbStream.primitivesNeeded;
|
2018-08-31 16:10:55 +02:00
|
|
|
} return S_OK;
|
2018-02-18 22:34:23 +01:00
|
|
|
|
2018-08-31 16:10:55 +02:00
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2:
|
|
|
|
case D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3: {
|
|
|
|
auto data = static_cast<BOOL*>(pData);
|
2019-06-16 16:53:11 +02:00
|
|
|
*data = queryData[0].xfbStream.primitivesNeeded
|
|
|
|
> queryData[0].xfbStream.primitivesWritten;
|
2018-08-31 16:10:55 +02:00
|
|
|
} return S_OK;
|
|
|
|
|
2018-02-18 22:34:23 +01:00
|
|
|
default:
|
|
|
|
Logger::err(str::format("D3D11: Unhandled query type in GetData: ", m_desc.Query));
|
|
|
|
return E_INVALIDARG;
|
|
|
|
}
|
2018-01-01 20:59:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-13 14:29:58 +02:00
|
|
|
|
2019-04-02 03:46:06 +02:00
|
|
|
DxvkBufferSlice D3D11Query::GetPredicate(DxvkContext* ctx) {
|
|
|
|
std::lock_guard<sync::Spinlock> lock(m_predicateLock);
|
|
|
|
|
2019-04-14 14:26:56 +02:00
|
|
|
if (unlikely(m_desc.Query != D3D11_QUERY_OCCLUSION_PREDICATE))
|
|
|
|
return DxvkBufferSlice();
|
|
|
|
|
2019-04-14 16:27:15 +02:00
|
|
|
if (unlikely(m_state != D3D11_VK_QUERY_ENDED))
|
|
|
|
return DxvkBufferSlice();
|
|
|
|
|
2019-04-02 03:46:06 +02:00
|
|
|
if (unlikely(!m_predicate.defined())) {
|
|
|
|
m_predicate = m_device->AllocPredicateSlice();
|
2019-06-16 16:53:11 +02:00
|
|
|
ctx->writePredicate(m_predicate, m_query[0]);
|
2019-04-02 03:46:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return m_predicate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-13 14:29:58 +02:00
|
|
|
UINT64 D3D11Query::GetTimestampQueryFrequency() const {
|
|
|
|
Rc<DxvkDevice> device = m_device->GetDXVKDevice();
|
|
|
|
Rc<DxvkAdapter> adapter = device->adapter();
|
|
|
|
|
|
|
|
VkPhysicalDeviceLimits limits = adapter->deviceProperties().limits;
|
|
|
|
return uint64_t(1'000'000'000.0f / limits.timestampPeriod);
|
|
|
|
}
|
|
|
|
|
2017-12-29 22:20:31 +01:00
|
|
|
}
|