1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-12 04:08:52 +01:00

Merge branch 'queries'

This commit is contained in:
Philip Rebohle 2018-02-20 11:32:57 +01:00
commit be4ccc1260
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
20 changed files with 434 additions and 94 deletions

View File

@ -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

View File

@ -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;

View File

@ -41,21 +41,23 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() { void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
m_parent->FlushInitContext(); if (m_csChunk->commandCount() != 0) {
m_drawCount = 0; m_parent->FlushInitContext();
m_drawCount = 0;
// Add commands to flush the threaded // Add commands to flush the threaded
// context, then flush the command list // context, then flush the command list
EmitCs([dev = m_device] (DxvkContext* ctx) { EmitCs([dev = m_device] (DxvkContext* ctx) {
dev->submitCommandList( dev->submitCommandList(
ctx->endRecording(), ctx->endRecording(),
nullptr, nullptr); nullptr, nullptr);
ctx->beginRecording( ctx->beginRecording(
dev->createCommandList()); dev->createCommandList());
}); });
FlushCsChunk(); FlushCsChunk();
}
} }

View File

@ -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;
}
} }

View File

@ -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 (pData == nullptr) if (m_query != nullptr
return S_OK; && m_query->getData(queryData) != DxvkQueryStatus::Available)
return S_FALSE;
switch (m_desc.Query) { if (pData == nullptr)
case D3D11_QUERY_EVENT:
*static_cast<BOOL*>(pData) = TRUE;
return S_OK; return S_OK;
case D3D11_QUERY_OCCLUSION: switch (m_desc.Query) {
*static_cast<UINT64*>(pData) = 1; case D3D11_QUERY_OCCLUSION:
return S_OK; *static_cast<UINT64*>(pData) = queryData.occlusion.samplesPassed;
return S_OK;
case D3D11_QUERY_TIMESTAMP: case D3D11_QUERY_OCCLUSION_PREDICATE:
*static_cast<UINT64*>(pData) = fakeTimestamp++; *static_cast<BOOL*>(pData) = queryData.occlusion.samplesPassed != 0;
return S_OK; return S_OK;
case D3D11_QUERY_TIMESTAMP_DISJOINT: case D3D11_QUERY_TIMESTAMP:
static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData)->Frequency = 1000; *static_cast<UINT64*>(pData) = queryData.timestamp.time;
static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData)->Disjoint = FALSE; return S_OK;
return S_OK;
case D3D11_QUERY_OCCLUSION_PREDICATE: case D3D11_QUERY_TIMESTAMP_DISJOINT: {
*static_cast<BOOL*>(pData) = TRUE; // FIXME return correct frequency
return S_OK; auto data = static_cast<D3D11_QUERY_DATA_TIMESTAMP_DISJOINT*>(pData);
data->Frequency = 1000;
data->Disjoint = FALSE;
} return S_OK;
default: return E_INVALIDARG; 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 "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;
}; };
} }

View File

@ -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;
}; };

View File

@ -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);
} }
} }

View File

@ -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

View File

@ -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();
}
} }

View File

@ -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
@ -46,12 +48,22 @@ 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;
};
} }

View 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();
}
}

View 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;
};
}

View File

@ -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();
}
} }
} }

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <condition_variable>
#include <mutex> #include <mutex>
#include "dxvk_limits.h" #include "dxvk_limits.h"
@ -78,8 +77,9 @@ namespace dxvk {
* index of a single Vulkan query. * index of a single Vulkan query.
*/ */
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
@ -172,10 +185,10 @@ 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 = {};

View File

@ -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();
} }
} }

View File

@ -9,8 +9,6 @@ namespace dxvk {
/** /**
* \brief Query range * \brief Query range
*
*
*/ */
struct DxvkQueryRange { struct DxvkQueryRange {
Rc<DxvkQueryPool> queryPool; Rc<DxvkQueryPool> queryPool;

View File

@ -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);
} }
} }

View File

@ -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',

View File

@ -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;
}; };