1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-11-30 22:24:15 +01:00

[d3d11] Wired up D3D11Query to backend

This commit is contained in:
Philip Rebohle 2018-02-18 22:34:23 +01:00
parent 7ddd2500d1
commit 5334ff57bf
6 changed files with 203 additions and 48 deletions

View File

@ -150,12 +150,40 @@ namespace dxvk {
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) {
// 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;
}
// 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,
// so we have to find out what we are actually dealing with
Com<ID3D11Query> query;

View File

@ -1086,9 +1086,19 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11Device::CreateQuery(
const D3D11_QUERY_DESC* pQueryDesc,
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)
return S_FALSE;
try {
*ppQuery = ref(new D3D11Query(this, *pQueryDesc));
return S_OK;
@ -1102,8 +1112,19 @@ namespace dxvk {
HRESULT STDMETHODCALLTYPE D3D11Device::CreatePredicate(
const D3D11_QUERY_DESC* pPredicateDesc,
ID3D11Predicate** ppPredicate) {
Logger::err("D3D11Device::CreatePredicate: Not implemented");
return E_NOTIMPL;
if (pPredicateDesc->Query != D3D11_QUERY_OCCLUSION_PREDICATE)
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;
}
}

View File

@ -7,19 +7,29 @@ namespace dxvk {
D3D11Device* device,
const D3D11_QUERY_DESC& desc)
: m_device(device), m_desc(desc) {
switch (desc.Query) {
// Other query types are currently unsupported
switch (m_desc.Query) {
case D3D11_QUERY_EVENT:
case D3D11_QUERY_OCCLUSION:
case D3D11_QUERY_TIMESTAMP:
case D3D11_QUERY_TIMESTAMP_DISJOINT:
case D3D11_QUERY_OCCLUSION_PREDICATE:
m_event = new DxvkEvent();
break;
case D3D11_QUERY_OCCLUSION:
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;
default:
static bool errorShown = false;
if (!std::exchange(errorShown, true))
Logger::warn(str::format("D3D11Query: Unsupported query type ", desc.Query));
throw DxvkError(str::format("D3D11: Unhandled query type: ", desc.Query));
}
}
@ -35,6 +45,9 @@ namespace dxvk {
COM_QUERY_IFACE(riid, ppvObject, ID3D11Asynchronous);
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");
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(
void* pData,
UINT GetDataFlags) {
static bool errorShown = false;
static UINT64 fakeTimestamp = 0;
if (!std::exchange(errorShown, true))
Logger::warn("D3D11Query::GetData: Stub");
if (pData == nullptr)
return S_OK;
switch (m_desc.Query) {
case D3D11_QUERY_EVENT:
*static_cast<BOOL*>(pData) = TRUE;
return S_OK;
case D3D11_QUERY_OCCLUSION:
*static_cast<UINT64*>(pData) = 1;
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;
case D3D11_QUERY_OCCLUSION_PREDICATE:
*static_cast<BOOL*>(pData) = TRUE;
Logger::info(str::format(m_desc.Query));
if (m_desc.Query == D3D11_QUERY_EVENT) {
const bool signaled = m_event->getStatus() == DxvkEventStatus::Signaled;
if (pData != nullptr)
*static_cast<BOOL*>(pData) = signaled;
return signaled ? S_OK : S_FALSE;
} else {
DxvkQueryData queryData = {};
if (m_query->getData(queryData) != DxvkQueryStatus::Available)
return S_FALSE;
if (pData == nullptr)
return S_OK;
switch (m_desc.Query) {
case D3D11_QUERY_OCCLUSION:
*static_cast<UINT64*>(pData) = queryData.occlusion.samplesPassed;
return S_OK;
default: return E_INVALIDARG;
case D3D11_QUERY_OCCLUSION_PREDICATE:
*static_cast<BOOL*>(pData) = queryData.occlusion.samplesPassed != 0;
return S_OK;
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;
}
}
}

View File

@ -2,9 +2,12 @@
#include "d3d11_device_child.h"
#include "../dxvk/dxvk_event.h"
#include "../dxvk/dxvk_query.h"
namespace dxvk {
class D3D11Query : public D3D11DeviceChild<ID3D11Query> {
class D3D11Query : public D3D11DeviceChild<ID3D11Predicate> {
public:
@ -26,6 +29,16 @@ namespace dxvk {
void STDMETHODCALLTYPE GetDesc(
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(
void* pData,
UINT GetDataFlags);
@ -35,6 +48,11 @@ namespace dxvk {
D3D11Device* const m_device;
D3D11_QUERY_DESC m_desc;
Rc<DxvkQuery> m_query = nullptr;
Rc<DxvkEvent> m_event = nullptr;
uint32_t m_revision = 0;
};
}

View File

@ -13,7 +13,7 @@ namespace dxvk {
}
uint32_t DxvkQuery::invalidate() {
uint32_t DxvkQuery::reset() {
std::unique_lock<std::mutex> lock(m_mutex);
m_status = DxvkQueryStatus::Reset;

View File

@ -113,7 +113,7 @@ namespace dxvk {
* will take the revision number as an argument.
* \returns The new query revision number
*/
uint32_t invalidate();
uint32_t reset();
/**
* \brief Retrieves query data