mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-11 19:24:11 +01:00
Merge branch 'queries'
This commit is contained in:
commit
be4ccc1260
@ -21,7 +21,7 @@ namespace dxvk {
|
|||||||
m_msState.sampleMask = 0; // Set during bind
|
m_msState.sampleMask = 0; // Set during bind
|
||||||
m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable;
|
m_msState.enableAlphaToCoverage = desc.AlphaToCoverageEnable;
|
||||||
m_msState.enableAlphaToOne = VK_FALSE;
|
m_msState.enableAlphaToOne = VK_FALSE;
|
||||||
m_msState.enableSampleShading = VK_TRUE;
|
m_msState.enableSampleShading = VK_FALSE;
|
||||||
m_msState.minSampleShading = 0.0f;
|
m_msState.minSampleShading = 0.0f;
|
||||||
|
|
||||||
// In 11_0, there is no logic op state. Later versions
|
// In 11_0, there is no logic op state. Later versions
|
||||||
|
@ -150,12 +150,40 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void STDMETHODCALLTYPE D3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync) {
|
void STDMETHODCALLTYPE D3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync) {
|
||||||
// Logger::err("D3D11DeviceContext::Begin: Not implemented");
|
Com<ID3D11Query> query;
|
||||||
|
|
||||||
|
if (SUCCEEDED(pAsync->QueryInterface(__uuidof(ID3D11Query), reinterpret_cast<void**>(&query)))) {
|
||||||
|
Com<D3D11Query> queryPtr = static_cast<D3D11Query*>(query.ptr());
|
||||||
|
|
||||||
|
if (queryPtr->HasBeginEnabled()) {
|
||||||
|
const uint32_t revision = queryPtr->Reset();
|
||||||
|
|
||||||
|
EmitCs([revision, queryPtr] (DxvkContext* ctx) {
|
||||||
|
queryPtr->Begin(ctx, revision);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void STDMETHODCALLTYPE D3D11DeviceContext::End(ID3D11Asynchronous *pAsync) {
|
void STDMETHODCALLTYPE D3D11DeviceContext::End(ID3D11Asynchronous *pAsync) {
|
||||||
// Logger::err("D3D11DeviceContext::End: Not implemented");
|
Com<ID3D11Query> query;
|
||||||
|
|
||||||
|
if (SUCCEEDED(pAsync->QueryInterface(__uuidof(ID3D11Query), reinterpret_cast<void**>(&query)))) {
|
||||||
|
Com<D3D11Query> queryPtr = static_cast<D3D11Query*>(query.ptr());
|
||||||
|
|
||||||
|
if (queryPtr->HasBeginEnabled()) {
|
||||||
|
EmitCs([queryPtr] (DxvkContext* ctx) {
|
||||||
|
queryPtr->End(ctx);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const uint32_t revision = queryPtr->Reset();
|
||||||
|
|
||||||
|
EmitCs([revision, queryPtr] (DxvkContext* ctx) {
|
||||||
|
queryPtr->Signal(ctx, revision);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -174,6 +202,10 @@ namespace dxvk {
|
|||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flush in order to make sure the query commands get dispatched
|
||||||
|
if ((GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH) == 0)
|
||||||
|
Flush();
|
||||||
|
|
||||||
// This method handles various different but incompatible interfaces,
|
// This method handles various different but incompatible interfaces,
|
||||||
// so we have to find out what we are actually dealing with
|
// so we have to find out what we are actually dealing with
|
||||||
Com<ID3D11Query> query;
|
Com<ID3D11Query> query;
|
||||||
|
@ -41,6 +41,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
|
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
|
||||||
|
if (m_csChunk->commandCount() != 0) {
|
||||||
m_parent->FlushInitContext();
|
m_parent->FlushInitContext();
|
||||||
m_drawCount = 0;
|
m_drawCount = 0;
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
FlushCsChunk();
|
FlushCsChunk();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void STDMETHODCALLTYPE D3D11ImmediateContext::ExecuteCommandList(
|
void STDMETHODCALLTYPE D3D11ImmediateContext::ExecuteCommandList(
|
||||||
|
@ -1086,6 +1086,16 @@ namespace dxvk {
|
|||||||
HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery(
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery(
|
||||||
const D3D11_QUERY_DESC* pQueryDesc,
|
const D3D11_QUERY_DESC* pQueryDesc,
|
||||||
ID3D11Query** ppQuery) {
|
ID3D11Query** ppQuery) {
|
||||||
|
if (pQueryDesc->Query != D3D11_QUERY_EVENT
|
||||||
|
&& pQueryDesc->Query != D3D11_QUERY_OCCLUSION
|
||||||
|
&& pQueryDesc->Query != D3D11_QUERY_TIMESTAMP
|
||||||
|
&& pQueryDesc->Query != D3D11_QUERY_TIMESTAMP_DISJOINT
|
||||||
|
&& pQueryDesc->Query != D3D11_QUERY_PIPELINE_STATISTICS
|
||||||
|
&& pQueryDesc->Query != D3D11_QUERY_OCCLUSION_PREDICATE) {
|
||||||
|
Logger::warn(str::format("D3D11Query: Unsupported query type ", pQueryDesc->Query));
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (ppQuery == nullptr)
|
if (ppQuery == nullptr)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
@ -1102,8 +1112,19 @@ namespace dxvk {
|
|||||||
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate(
|
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate(
|
||||||
const D3D11_QUERY_DESC* pPredicateDesc,
|
const D3D11_QUERY_DESC* pPredicateDesc,
|
||||||
ID3D11Predicate** ppPredicate) {
|
ID3D11Predicate** ppPredicate) {
|
||||||
Logger::err("D3D11Device::CreatePredicate: Not implemented");
|
if (pPredicateDesc->Query != D3D11_QUERY_OCCLUSION_PREDICATE)
|
||||||
return E_NOTIMPL;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (ppPredicate == nullptr)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
try {
|
||||||
|
*ppPredicate = ref(new D3D11Query(this, *pPredicateDesc));
|
||||||
|
return S_OK;
|
||||||
|
} catch (const DxvkError& e) {
|
||||||
|
Logger::err(e.message());
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,19 +7,37 @@ namespace dxvk {
|
|||||||
D3D11Device* device,
|
D3D11Device* device,
|
||||||
const D3D11_QUERY_DESC& desc)
|
const D3D11_QUERY_DESC& desc)
|
||||||
: m_device(device), m_desc(desc) {
|
: m_device(device), m_desc(desc) {
|
||||||
switch (desc.Query) {
|
switch (m_desc.Query) {
|
||||||
// Other query types are currently unsupported
|
|
||||||
case D3D11_QUERY_EVENT:
|
case D3D11_QUERY_EVENT:
|
||||||
|
m_event = new DxvkEvent();
|
||||||
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_OCCLUSION:
|
case D3D11_QUERY_OCCLUSION:
|
||||||
case D3D11_QUERY_TIMESTAMP:
|
m_query = new DxvkQuery(
|
||||||
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
VK_QUERY_TYPE_OCCLUSION,
|
||||||
|
VK_QUERY_CONTROL_PRECISE_BIT);
|
||||||
|
break;
|
||||||
|
|
||||||
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
||||||
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_OCCLUSION, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_TIMESTAMP:
|
||||||
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_TIMESTAMP, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_PIPELINE_STATISTICS:
|
||||||
|
m_query = new DxvkQuery(
|
||||||
|
VK_QUERY_TYPE_PIPELINE_STATISTICS, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
static bool errorShown = false;
|
throw DxvkError(str::format("D3D11: Unhandled query type: ", desc.Query));
|
||||||
if (!std::exchange(errorShown, true))
|
|
||||||
Logger::warn(str::format("D3D11Query: Unsupported query type ", desc.Query));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +53,9 @@ namespace dxvk {
|
|||||||
COM_QUERY_IFACE(riid, ppvObject, ID3D11Asynchronous);
|
COM_QUERY_IFACE(riid, ppvObject, ID3D11Asynchronous);
|
||||||
COM_QUERY_IFACE(riid, ppvObject, ID3D11Query);
|
COM_QUERY_IFACE(riid, ppvObject, ID3D11Query);
|
||||||
|
|
||||||
|
if (m_desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE)
|
||||||
|
COM_QUERY_IFACE(riid, ppvObject, ID3D11Predicate);
|
||||||
|
|
||||||
Logger::warn("D3D11Query: Unknown interface query");
|
Logger::warn("D3D11Query: Unknown interface query");
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
@ -90,41 +111,118 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t D3D11Query::Reset() {
|
||||||
|
if (m_query != nullptr)
|
||||||
|
return m_query->reset();
|
||||||
|
|
||||||
|
if (m_event != nullptr)
|
||||||
|
return m_event->reset();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool D3D11Query::HasBeginEnabled() const {
|
||||||
|
return m_desc.Query == D3D11_QUERY_OCCLUSION
|
||||||
|
|| m_desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE
|
||||||
|
|| m_desc.Query == D3D11_QUERY_PIPELINE_STATISTICS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11Query::Begin(DxvkContext* ctx, uint32_t revision) {
|
||||||
|
m_revision = revision;
|
||||||
|
|
||||||
|
if (m_query != nullptr) {
|
||||||
|
DxvkQueryRevision rev = { m_query, revision };
|
||||||
|
ctx->beginQuery(rev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11Query::End(DxvkContext* ctx) {
|
||||||
|
if (m_query != nullptr) {
|
||||||
|
DxvkQueryRevision rev = { m_query, m_revision };
|
||||||
|
ctx->endQuery(rev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11Query::Signal(DxvkContext* ctx, uint32_t revision) {
|
||||||
|
switch (m_desc.Query) {
|
||||||
|
case D3D11_QUERY_EVENT: {
|
||||||
|
DxvkEventRevision rev = { m_event, revision };
|
||||||
|
ctx->signalEvent(rev);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_TIMESTAMP: {
|
||||||
|
DxvkQueryRevision rev = { m_query, revision };
|
||||||
|
ctx->writeTimestamp(rev);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D11Query::GetData(
|
HRESULT STDMETHODCALLTYPE D3D11Query::GetData(
|
||||||
void* pData,
|
void* pData,
|
||||||
UINT GetDataFlags) {
|
UINT GetDataFlags) {
|
||||||
static bool errorShown = false;
|
if (m_desc.Query == D3D11_QUERY_EVENT) {
|
||||||
static UINT64 fakeTimestamp = 0;
|
const bool signaled = m_event->getStatus() == DxvkEventStatus::Signaled;
|
||||||
|
if (pData != nullptr)
|
||||||
|
*static_cast<BOOL*>(pData) = signaled;
|
||||||
|
|
||||||
if (!std::exchange(errorShown, true))
|
return signaled ? S_OK : S_FALSE;
|
||||||
Logger::warn("D3D11Query::GetData: Stub");
|
} else {
|
||||||
|
DxvkQueryData queryData = {};
|
||||||
|
|
||||||
|
if (m_query != nullptr
|
||||||
|
&& m_query->getData(queryData) != DxvkQueryStatus::Available)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
if (pData == nullptr)
|
if (pData == nullptr)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
switch (m_desc.Query) {
|
switch (m_desc.Query) {
|
||||||
case D3D11_QUERY_EVENT:
|
|
||||||
*static_cast<BOOL*>(pData) = TRUE;
|
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
case D3D11_QUERY_OCCLUSION:
|
case D3D11_QUERY_OCCLUSION:
|
||||||
*static_cast<UINT64*>(pData) = 1;
|
*static_cast<UINT64*>(pData) = queryData.occlusion.samplesPassed;
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
case D3D11_QUERY_TIMESTAMP:
|
|
||||||
*static_cast<UINT64*>(pData) = fakeTimestamp++;
|
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
|
||||||
static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData)->Frequency = 1000;
|
|
||||||
static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData)->Disjoint = FALSE;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
||||||
*static_cast<BOOL*>(pData) = TRUE;
|
*static_cast<BOOL*>(pData) = queryData.occlusion.samplesPassed != 0;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
default: return E_INVALIDARG;
|
case D3D11_QUERY_TIMESTAMP:
|
||||||
|
*static_cast<UINT64*>(pData) = queryData.timestamp.time;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case D3D11_QUERY_TIMESTAMP_DISJOINT: {
|
||||||
|
// FIXME return correct frequency
|
||||||
|
auto data = static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData);
|
||||||
|
data->Frequency = 1000;
|
||||||
|
data->Disjoint = FALSE;
|
||||||
|
} return S_OK;
|
||||||
|
|
||||||
|
case D3D11_QUERY_PIPELINE_STATISTICS: {
|
||||||
|
auto data = static_cast<D3D11_QUERY_DATA_PIPELINE_STATISTICS*>(pData);
|
||||||
|
data->IAVertices = queryData.statistic.iaVertices;
|
||||||
|
data->IAPrimitives = queryData.statistic.iaPrimitives;
|
||||||
|
data->VSInvocations = queryData.statistic.vsInvocations;
|
||||||
|
data->GSInvocations = queryData.statistic.gsInvocations;
|
||||||
|
data->GSPrimitives = queryData.statistic.gsPrimitives;
|
||||||
|
data->CInvocations = queryData.statistic.clipInvocations;
|
||||||
|
data->CPrimitives = queryData.statistic.clipPrimitives;
|
||||||
|
data->PSInvocations = queryData.statistic.fsInvocations;
|
||||||
|
data->HSInvocations = queryData.statistic.tcsPatches;
|
||||||
|
data->DSInvocations = queryData.statistic.tesInvocations;
|
||||||
|
data->CSInvocations = queryData.statistic.csInvocations;
|
||||||
|
} return S_OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger::err(str::format("D3D11: Unhandled query type in GetData: ", m_desc.Query));
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
#include "d3d11_device_child.h"
|
#include "d3d11_device_child.h"
|
||||||
|
|
||||||
|
#include "../dxvk/dxvk_event.h"
|
||||||
|
#include "../dxvk/dxvk_query.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class D3D11Query : public D3D11DeviceChild<ID3D11Query> {
|
class D3D11Query : public D3D11DeviceChild<ID3D11Predicate> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -26,6 +29,16 @@ namespace dxvk {
|
|||||||
void STDMETHODCALLTYPE GetDesc(
|
void STDMETHODCALLTYPE GetDesc(
|
||||||
D3D11_QUERY_DESC *pDesc) final;
|
D3D11_QUERY_DESC *pDesc) final;
|
||||||
|
|
||||||
|
uint32_t Reset();
|
||||||
|
|
||||||
|
bool HasBeginEnabled() const;
|
||||||
|
|
||||||
|
void Begin(DxvkContext* ctx, uint32_t revision);
|
||||||
|
|
||||||
|
void End(DxvkContext* ctx);
|
||||||
|
|
||||||
|
void Signal(DxvkContext* ctx, uint32_t revision);
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE GetData(
|
HRESULT STDMETHODCALLTYPE GetData(
|
||||||
void* pData,
|
void* pData,
|
||||||
UINT GetDataFlags);
|
UINT GetDataFlags);
|
||||||
@ -35,6 +48,11 @@ namespace dxvk {
|
|||||||
D3D11Device* const m_device;
|
D3D11Device* const m_device;
|
||||||
D3D11_QUERY_DESC m_desc;
|
D3D11_QUERY_DESC m_desc;
|
||||||
|
|
||||||
|
Rc<DxvkQuery> m_query = nullptr;
|
||||||
|
Rc<DxvkEvent> m_event = nullptr;
|
||||||
|
|
||||||
|
uint32_t m_revision = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "dxvk_binding.h"
|
#include "dxvk_binding.h"
|
||||||
#include "dxvk_descriptor.h"
|
#include "dxvk_descriptor.h"
|
||||||
|
#include "dxvk_event_tracker.h"
|
||||||
#include "dxvk_lifetime.h"
|
#include "dxvk_lifetime.h"
|
||||||
#include "dxvk_limits.h"
|
#include "dxvk_limits.h"
|
||||||
#include "dxvk_pipelayout.h"
|
#include "dxvk_pipelayout.h"
|
||||||
@ -85,12 +86,32 @@ namespace dxvk {
|
|||||||
m_queryTracker.trackQueryRange(std::move(queries));
|
m_queryTracker.trackQueryRange(std::move(queries));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds an event revision to track
|
||||||
|
*
|
||||||
|
* The event will be signaled after the command
|
||||||
|
* buffer has finished executing on the GPU.
|
||||||
|
*/
|
||||||
|
void trackEvent(const DxvkEventRevision& event) {
|
||||||
|
m_eventTracker.trackEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Signals tracked events
|
||||||
|
*
|
||||||
|
* Marks all tracked events as signaled. Call this after
|
||||||
|
* synchronizing with a fence for this command list.
|
||||||
|
*/
|
||||||
|
void signalEvents() {
|
||||||
|
m_eventTracker.signalEvents();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Writes back query results
|
* \brief Writes back query results
|
||||||
*
|
*
|
||||||
* Uses the query range to write back query data
|
* Writes back query data to all queries tracked by the
|
||||||
* after the command list has finished executing
|
* query range tracker. Call this after synchronizing
|
||||||
* on the GPU.
|
* with a fence for this command list.
|
||||||
*/
|
*/
|
||||||
void writeQueryData() {
|
void writeQueryData() {
|
||||||
m_queryTracker.writeQueryData();
|
m_queryTracker.writeQueryData();
|
||||||
@ -486,6 +507,7 @@ namespace dxvk {
|
|||||||
DxvkDescriptorAlloc m_descAlloc;
|
DxvkDescriptorAlloc m_descAlloc;
|
||||||
DxvkStagingAlloc m_stagingAlloc;
|
DxvkStagingAlloc m_stagingAlloc;
|
||||||
DxvkQueryTracker m_queryTracker;
|
DxvkQueryTracker m_queryTracker;
|
||||||
|
DxvkEventTracker m_eventTracker;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ namespace dxvk {
|
|||||||
m_cmd->cmdBeginQuery(
|
m_cmd->cmdBeginQuery(
|
||||||
handle.queryPool,
|
handle.queryPool,
|
||||||
handle.queryId,
|
handle.queryId,
|
||||||
0);
|
handle.flags);
|
||||||
|
|
||||||
query.query->beginRecording(query.revision);
|
query.query->beginRecording(query.revision);
|
||||||
this->insertActiveQuery(query);
|
this->insertActiveQuery(query);
|
||||||
@ -1201,6 +1201,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::signalEvent(const DxvkEventRevision& event) {
|
||||||
|
m_cmd->trackEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::writeTimestamp(const DxvkQueryRevision& query) {
|
void DxvkContext::writeTimestamp(const DxvkQueryRevision& query) {
|
||||||
DxvkQueryHandle handle = this->allocQuery(query);
|
DxvkQueryHandle handle = this->allocQuery(query);
|
||||||
|
|
||||||
@ -1631,7 +1636,7 @@ namespace dxvk {
|
|||||||
DxvkQueryHandle DxvkContext::allocQuery(const DxvkQueryRevision& query) {
|
DxvkQueryHandle DxvkContext::allocQuery(const DxvkQueryRevision& query) {
|
||||||
const VkQueryType queryType = query.query->type();
|
const VkQueryType queryType = query.query->type();
|
||||||
|
|
||||||
DxvkQueryHandle queryHandle = { VK_NULL_HANDLE, 0 };
|
DxvkQueryHandle queryHandle = DxvkQueryHandle();
|
||||||
Rc<DxvkQueryPool> queryPool = m_queryPools[queryType];
|
Rc<DxvkQueryPool> queryPool = m_queryPools[queryType];
|
||||||
|
|
||||||
if (queryPool != nullptr)
|
if (queryPool != nullptr)
|
||||||
@ -1676,7 +1681,7 @@ namespace dxvk {
|
|||||||
m_cmd->cmdBeginQuery(
|
m_cmd->cmdBeginQuery(
|
||||||
handle.queryPool,
|
handle.queryPool,
|
||||||
handle.queryId,
|
handle.queryId,
|
||||||
0);
|
handle.flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "dxvk_cmdlist.h"
|
#include "dxvk_cmdlist.h"
|
||||||
#include "dxvk_context_state.h"
|
#include "dxvk_context_state.h"
|
||||||
#include "dxvk_data.h"
|
#include "dxvk_data.h"
|
||||||
|
#include "dxvk_event.h"
|
||||||
|
#include "dxvk_query.h"
|
||||||
#include "dxvk_query_pool.h"
|
#include "dxvk_query_pool.h"
|
||||||
#include "dxvk_util.h"
|
#include "dxvk_util.h"
|
||||||
|
|
||||||
@ -542,6 +544,13 @@ namespace dxvk {
|
|||||||
uint32_t attachment,
|
uint32_t attachment,
|
||||||
const DxvkBlendMode& blendMode);
|
const DxvkBlendMode& blendMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Signals an event
|
||||||
|
* \param [in] event The event
|
||||||
|
*/
|
||||||
|
void signalEvent(
|
||||||
|
const DxvkEventRevision& event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Writes to a timestamp query
|
* \brief Writes to a timestamp query
|
||||||
* \param [in] query The timestamp query
|
* \param [in] query The timestamp query
|
||||||
|
@ -14,13 +14,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkEvent::signalEvent(uint32_t revision) {
|
void DxvkEvent::signal(uint32_t revision) {
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
if (m_revision == revision) {
|
if (m_revision == revision)
|
||||||
m_status = DxvkEventStatus::Signaled;
|
m_status = DxvkEventStatus::Signaled;
|
||||||
m_signal.notify_one();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "dxvk_include.h"
|
#include "dxvk_include.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Event status
|
||||||
|
*/
|
||||||
enum class DxvkEventStatus {
|
enum class DxvkEventStatus {
|
||||||
Reset = 0,
|
Reset = 0,
|
||||||
Signaled = 1,
|
Signaled = 1,
|
||||||
@ -36,7 +38,7 @@ namespace dxvk {
|
|||||||
* \brief Signals the event
|
* \brief Signals the event
|
||||||
* \param [in] revision The revision ID
|
* \param [in] revision The revision ID
|
||||||
*/
|
*/
|
||||||
void signalEvent(uint32_t revision);
|
void signal(uint32_t revision);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Queries event status
|
* \brief Queries event status
|
||||||
@ -47,11 +49,21 @@ namespace dxvk {
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::condition_variable m_signal;
|
|
||||||
|
|
||||||
DxvkEventStatus m_status = DxvkEventStatus::Reset;
|
DxvkEventStatus m_status = DxvkEventStatus::Reset;
|
||||||
uint32_t m_revision = 0;
|
uint32_t m_revision = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Event revision
|
||||||
|
*
|
||||||
|
* Stores the event object and the
|
||||||
|
* version ID for event operations.
|
||||||
|
*/
|
||||||
|
struct DxvkEventRevision {
|
||||||
|
Rc<DxvkEvent> event;
|
||||||
|
uint32_t revision;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
30
src/dxvk/dxvk_event_tracker.cpp
Normal file
30
src/dxvk/dxvk_event_tracker.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "dxvk_event_tracker.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
DxvkEventTracker::DxvkEventTracker() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkEventTracker::~DxvkEventTracker() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkEventTracker::trackEvent(const DxvkEventRevision& event) {
|
||||||
|
m_events.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkEventTracker::signalEvents() {
|
||||||
|
for (const DxvkEventRevision& event : m_events)
|
||||||
|
event.event->signal(event.revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkEventTracker::reset() {
|
||||||
|
m_events.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
src/dxvk/dxvk_event_tracker.h
Normal file
45
src/dxvk/dxvk_event_tracker.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxvk_event.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Event tracker
|
||||||
|
*/
|
||||||
|
class DxvkEventTracker {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxvkEventTracker();
|
||||||
|
~DxvkEventTracker();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds an event to track
|
||||||
|
* \param [in] event The event revision
|
||||||
|
*/
|
||||||
|
void trackEvent(const DxvkEventRevision& event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Signals tracked events
|
||||||
|
*
|
||||||
|
* Retrieves query data from the query pools
|
||||||
|
* and writes it back to the query objects.
|
||||||
|
*/
|
||||||
|
void signalEvents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Resets event tracker
|
||||||
|
*
|
||||||
|
* Releases all events from the tracker.
|
||||||
|
* Call this after signaling the events.
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector<DxvkEventRevision> m_events;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxvkQuery::DxvkQuery(VkQueryType type)
|
DxvkQuery::DxvkQuery(
|
||||||
: m_type(type) {
|
VkQueryType type,
|
||||||
|
VkQueryControlFlags flags)
|
||||||
|
: m_type(type), m_flags(flags) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,7 +15,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t DxvkQuery::invalidate() {
|
uint32_t DxvkQuery::reset() {
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
m_status = DxvkQueryStatus::Reset;
|
m_status = DxvkQueryStatus::Reset;
|
||||||
@ -57,7 +59,6 @@ namespace dxvk {
|
|||||||
m_status = DxvkQueryStatus::Pending;
|
m_status = DxvkQueryStatus::Pending;
|
||||||
} else {
|
} else {
|
||||||
m_status = DxvkQueryStatus::Available;
|
m_status = DxvkQueryStatus::Available;
|
||||||
m_signal.notify_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_handle = DxvkQueryHandle();
|
m_handle = DxvkQueryHandle();
|
||||||
@ -110,10 +111,8 @@ namespace dxvk {
|
|||||||
Logger::err(str::format("DxvkQuery: Unhandled query type: ", m_type));
|
Logger::err(str::format("DxvkQuery: Unhandled query type: ", m_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++m_queryIndex == m_queryCount && m_status == DxvkQueryStatus::Pending) {
|
if (++m_queryIndex == m_queryCount && m_status == DxvkQueryStatus::Pending)
|
||||||
m_status = DxvkQueryStatus::Available;
|
m_status = DxvkQueryStatus::Available;
|
||||||
m_signal.notify_all();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "dxvk_limits.h"
|
#include "dxvk_limits.h"
|
||||||
@ -80,6 +79,7 @@ namespace dxvk {
|
|||||||
struct DxvkQueryHandle {
|
struct DxvkQueryHandle {
|
||||||
VkQueryPool queryPool = VK_NULL_HANDLE;
|
VkQueryPool queryPool = VK_NULL_HANDLE;
|
||||||
uint32_t queryId = 0;
|
uint32_t queryId = 0;
|
||||||
|
VkQueryControlFlags flags = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +93,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkQuery(VkQueryType type);
|
DxvkQuery(
|
||||||
|
VkQueryType type,
|
||||||
|
VkQueryControlFlags flags);
|
||||||
~DxvkQuery();
|
~DxvkQuery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,6 +106,17 @@ namespace dxvk {
|
|||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Query control flags
|
||||||
|
*
|
||||||
|
* Flags that will be applied when
|
||||||
|
* calling \c vkCmdBeginQuery.
|
||||||
|
* \returns Query control flags
|
||||||
|
*/
|
||||||
|
VkQueryControlFlags flags() const {
|
||||||
|
return m_flags;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Resets the query object
|
* \brief Resets the query object
|
||||||
*
|
*
|
||||||
@ -113,7 +126,7 @@ namespace dxvk {
|
|||||||
* will take the revision number as an argument.
|
* will take the revision number as an argument.
|
||||||
* \returns The new query revision number
|
* \returns The new query revision number
|
||||||
*/
|
*/
|
||||||
uint32_t invalidate();
|
uint32_t reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves query data
|
* \brief Retrieves query data
|
||||||
@ -173,9 +186,9 @@ namespace dxvk {
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
const VkQueryType m_type;
|
const VkQueryType m_type;
|
||||||
|
const VkQueryControlFlags m_flags;
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::condition_variable m_signal;
|
|
||||||
|
|
||||||
DxvkQueryStatus m_status = DxvkQueryStatus::Reset;
|
DxvkQueryStatus m_status = DxvkQueryStatus::Reset;
|
||||||
DxvkQueryData m_data = {};
|
DxvkQueryData m_data = {};
|
||||||
|
@ -48,7 +48,10 @@ namespace dxvk {
|
|||||||
const uint32_t queryIndex = m_queryRangeOffset + m_queryRangeLength;
|
const uint32_t queryIndex = m_queryRangeOffset + m_queryRangeLength;
|
||||||
|
|
||||||
if (queryIndex < m_queryCount) {
|
if (queryIndex < m_queryCount) {
|
||||||
const DxvkQueryHandle result = { m_queryPool, queryIndex };
|
DxvkQueryHandle result;
|
||||||
|
result.queryPool = m_queryPool;
|
||||||
|
result.queryId = queryIndex;
|
||||||
|
result.flags = query.query->flags();
|
||||||
|
|
||||||
query.query->associateQuery(query.revision, result);
|
query.query->associateQuery(query.revision, result);
|
||||||
m_queries.at(queryIndex) = query;
|
m_queries.at(queryIndex) = query;
|
||||||
@ -56,7 +59,7 @@ namespace dxvk {
|
|||||||
m_queryRangeLength += 1;
|
m_queryRangeLength += 1;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return DxvkQueryHandle { VK_NULL_HANDLE, 0 };
|
return DxvkQueryHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Query range
|
* \brief Query range
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
struct DxvkQueryRange {
|
struct DxvkQueryRange {
|
||||||
Rc<DxvkQueryPool> queryPool;
|
Rc<DxvkQueryPool> queryPool;
|
||||||
|
@ -58,7 +58,9 @@ namespace dxvk {
|
|||||||
entry.fence->wait(std::numeric_limits<uint64_t>::max());
|
entry.fence->wait(std::numeric_limits<uint64_t>::max());
|
||||||
|
|
||||||
entry.cmdList->writeQueryData();
|
entry.cmdList->writeQueryData();
|
||||||
|
entry.cmdList->signalEvents();
|
||||||
entry.cmdList->reset();
|
entry.cmdList->reset();
|
||||||
|
|
||||||
m_device->recycleCommandList(entry.cmdList);
|
m_device->recycleCommandList(entry.cmdList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ dxvk_src = files([
|
|||||||
'dxvk_device.cpp',
|
'dxvk_device.cpp',
|
||||||
'dxvk_extensions.cpp',
|
'dxvk_extensions.cpp',
|
||||||
'dxvk_event.cpp',
|
'dxvk_event.cpp',
|
||||||
|
'dxvk_event_tracker.cpp',
|
||||||
'dxvk_format.cpp',
|
'dxvk_format.cpp',
|
||||||
'dxvk_framebuffer.cpp',
|
'dxvk_framebuffer.cpp',
|
||||||
'dxvk_graphics.cpp',
|
'dxvk_graphics.cpp',
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "../test_utils.h"
|
#include "../test_utils.h"
|
||||||
|
|
||||||
using namespace dxvk;
|
using namespace dxvk;
|
||||||
@ -242,6 +244,12 @@ public:
|
|||||||
&m_vertexFormat)))
|
&m_vertexFormat)))
|
||||||
throw DxvkError("Failed to create input layout");
|
throw DxvkError("Failed to create input layout");
|
||||||
|
|
||||||
|
D3D11_QUERY_DESC queryDesc;
|
||||||
|
queryDesc.Query = D3D11_QUERY_OCCLUSION;
|
||||||
|
queryDesc.MiscFlags = 0;
|
||||||
|
|
||||||
|
if (FAILED(m_device->CreateQuery(&queryDesc, &m_query)))
|
||||||
|
throw DxvkError("Failed to create occlusion query");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -275,11 +283,13 @@ public:
|
|||||||
UINT vsOffset = 0;
|
UINT vsOffset = 0;
|
||||||
|
|
||||||
// Test normal draws with base vertex
|
// Test normal draws with base vertex
|
||||||
|
m_context->Begin(m_query.ptr());
|
||||||
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
m_context->IASetInputLayout(m_vertexFormat.ptr());
|
m_context->IASetInputLayout(m_vertexFormat.ptr());
|
||||||
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
m_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &vsStride, &vsOffset);
|
||||||
m_context->Draw(3, 0);
|
m_context->Draw(3, 0);
|
||||||
m_context->Draw(3, 3);
|
m_context->Draw(3, 3);
|
||||||
|
m_context->End(m_query.ptr());
|
||||||
|
|
||||||
// Test instanced draws with base instance and base vertex
|
// Test instanced draws with base instance and base vertex
|
||||||
vsOffset = 6 * sizeof(Vertex);
|
vsOffset = 6 * sizeof(Vertex);
|
||||||
@ -302,6 +312,26 @@ public:
|
|||||||
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
m_context->OMSetRenderTargets(0, nullptr, nullptr);
|
||||||
|
|
||||||
m_swapChain->Present(0, 0);
|
m_swapChain->Present(0, 0);
|
||||||
|
|
||||||
|
// Test query results
|
||||||
|
while (true) {
|
||||||
|
UINT64 samplesPassed = 0;
|
||||||
|
|
||||||
|
UINT queryStatus = m_context->GetData(
|
||||||
|
m_query.ptr(), &samplesPassed, sizeof(samplesPassed),
|
||||||
|
D3D11_ASYNC_GETDATA_DONOTFLUSH);
|
||||||
|
|
||||||
|
if (queryStatus == S_OK) {
|
||||||
|
if (samplesPassed == 0)
|
||||||
|
std::cerr << "Occlusion query returned 0 samples" << std::endl;
|
||||||
|
break;
|
||||||
|
} else if (queryStatus == S_FALSE) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
} else {
|
||||||
|
std::cerr << "Occlusion query failed" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,6 +384,8 @@ private:
|
|||||||
Com<ID3D11VertexShader> m_vertexShader;
|
Com<ID3D11VertexShader> m_vertexShader;
|
||||||
Com<ID3D11PixelShader> m_pixelShader;
|
Com<ID3D11PixelShader> m_pixelShader;
|
||||||
|
|
||||||
|
Com<ID3D11Query> m_query;
|
||||||
|
|
||||||
D3D_FEATURE_LEVEL m_featureLevel;
|
D3D_FEATURE_LEVEL m_featureLevel;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user