mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-01 07:24:12 +01:00
[d3d11] Wired up D3D11Query to backend
This commit is contained in:
parent
7ddd2500d1
commit
5334ff57bf
@ -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;
|
||||||
|
@ -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,29 @@ 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:
|
|
||||||
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
|
||||||
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
case D3D11_QUERY_OCCLUSION_PREDICATE:
|
||||||
|
m_query = new DxvkQuery(VK_QUERY_TYPE_OCCLUSION);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_TIMESTAMP:
|
||||||
|
m_query = new DxvkQuery(VK_QUERY_TYPE_TIMESTAMP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_TIMESTAMP_DISJOINT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D11_QUERY_PIPELINE_STATISTICS:
|
||||||
|
m_query = new DxvkQuery(VK_QUERY_TYPE_PIPELINE_STATISTICS);
|
||||||
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 +45,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 +103,112 @@ 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_TIMESTAMP: {
|
||||||
|
DxvkQueryRevision rev = { m_query, m_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;
|
Logger::info(str::format(m_desc.Query));
|
||||||
static UINT64 fakeTimestamp = 0;
|
if (m_desc.Query == D3D11_QUERY_EVENT) {
|
||||||
|
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->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: {
|
||||||
|
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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,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;
|
||||||
|
@ -113,7 +113,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
|
||||||
|
Loading…
Reference in New Issue
Block a user