mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 19:24:12 +01:00
[dxvk] Implemented more query and query pool methods
This commit is contained in:
parent
5beae25bdf
commit
54cfdbdc51
@ -47,24 +47,44 @@ namespace dxvk {
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
DxvkContextFlag::CpDirtyPipelineState,
|
||||
DxvkContextFlag::CpDirtyResources);
|
||||
|
||||
// Restart queries that were active during
|
||||
// the last command buffer submission.
|
||||
this->beginActiveQueries();
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkCommandList> DxvkContext::endRecording() {
|
||||
this->renderPassEnd();
|
||||
this->endActiveQueries();
|
||||
|
||||
m_cmd->endRecording();
|
||||
return std::exchange(m_cmd, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::beginQuery(const Rc<DxvkQuery>& query) {
|
||||
// TODO implement
|
||||
void DxvkContext::beginQuery(const DxvkQueryRevision& query) {
|
||||
DxvkQueryHandle handle; // TODO = allocateQuery(...)
|
||||
|
||||
m_cmd->cmdBeginQuery(
|
||||
handle.queryPool,
|
||||
handle.queryId,
|
||||
0);
|
||||
|
||||
query.query->beginRecording(query.revision);
|
||||
this->insertActiveQuery(query);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::endQuery(const Rc<DxvkQuery>& query) {
|
||||
// TODO implement
|
||||
void DxvkContext::endQuery(const DxvkQueryRevision& query) {
|
||||
DxvkQueryHandle handle = query.query->getHandle();
|
||||
|
||||
m_cmd->cmdEndQuery(
|
||||
handle.queryPool,
|
||||
handle.queryId);
|
||||
|
||||
query.query->endRecording(query.revision);
|
||||
this->eraseActiveQuery(query);
|
||||
}
|
||||
|
||||
|
||||
@ -1581,4 +1601,51 @@ namespace dxvk {
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::resetQueryPool(const Rc<DxvkQueryPool>& pool) {
|
||||
this->renderPassEnd();
|
||||
|
||||
m_cmd->cmdResetQueryPool(
|
||||
pool->handle(), 0,
|
||||
pool->queryCount());
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::beginActiveQueries() {
|
||||
for (const DxvkQueryRevision& query : m_activeQueries) {
|
||||
DxvkQueryHandle handle; // TODO = allocateQuery(...)
|
||||
|
||||
m_cmd->cmdBeginQuery(
|
||||
handle.queryPool,
|
||||
handle.queryId,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::endActiveQueries() {
|
||||
for (const DxvkQueryRevision& query : m_activeQueries) {
|
||||
DxvkQueryHandle handle = query.query->getHandle();
|
||||
|
||||
m_cmd->cmdEndQuery(
|
||||
handle.queryPool,
|
||||
handle.queryId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::insertActiveQuery(const DxvkQueryRevision& query) {
|
||||
m_activeQueries.push_back(query);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::eraseActiveQuery(const DxvkQueryRevision& query) {
|
||||
for (auto i = m_activeQueries.begin(); i != m_activeQueries.end(); i++) {
|
||||
if (i->query == query.query && i->revision == query.revision) {
|
||||
m_activeQueries.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_context_state.h"
|
||||
#include "dxvk_data.h"
|
||||
#include "dxvk_query.h"
|
||||
#include "dxvk_query_pool.h"
|
||||
#include "dxvk_util.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -49,19 +49,18 @@ namespace dxvk {
|
||||
Rc<DxvkCommandList> endRecording();
|
||||
|
||||
/**
|
||||
* \brief Begins gathering query data
|
||||
* \brief Begins generating query data
|
||||
* \param [in] query The query to end
|
||||
*/
|
||||
void beginQuery(
|
||||
const Rc<DxvkQuery>& query);
|
||||
const DxvkQueryRevision& query);
|
||||
|
||||
/**
|
||||
* \brief Ends gathering query data
|
||||
*
|
||||
* \brief Ends generating query data
|
||||
* \param [in] query The query to end
|
||||
*/
|
||||
void endQuery(
|
||||
const Rc<DxvkQuery>& query);
|
||||
const DxvkQueryRevision& query);
|
||||
|
||||
/**
|
||||
* \brief Sets framebuffer
|
||||
@ -555,6 +554,8 @@ namespace dxvk {
|
||||
VkPipeline m_gpActivePipeline = VK_NULL_HANDLE;
|
||||
VkPipeline m_cpActivePipeline = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<DxvkQueryRevision> m_activeQueries;
|
||||
|
||||
std::array<DxvkShaderResourceSlot, MaxNumResourceSlots> m_rc;
|
||||
std::array<DxvkDescriptorInfo, MaxNumActiveBindings> m_descInfos;
|
||||
std::array<VkWriteDescriptorSet, MaxNumActiveBindings> m_descWrites;
|
||||
@ -594,6 +595,19 @@ namespace dxvk {
|
||||
|
||||
void commitComputeBarriers();
|
||||
|
||||
void resetQueryPool(
|
||||
const Rc<DxvkQueryPool>& pool);
|
||||
|
||||
void beginActiveQueries();
|
||||
|
||||
void endActiveQueries();
|
||||
|
||||
void insertActiveQuery(
|
||||
const DxvkQueryRevision& query);
|
||||
|
||||
void eraseActiveQuery(
|
||||
const DxvkQueryRevision& query);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -145,6 +145,12 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkQueryPool> DxvkDevice::createQueryPool(
|
||||
VkQueryType queryType) {
|
||||
return new DxvkQueryPool(m_vkd, queryType);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkSampler> DxvkDevice::createSampler(
|
||||
const DxvkSamplerCreateInfo& createInfo) {
|
||||
return new DxvkSampler(m_vkd, createInfo);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "dxvk_pipecache.h"
|
||||
#include "dxvk_pipemanager.h"
|
||||
#include "dxvk_queue.h"
|
||||
#include "dxvk_query_pool.h"
|
||||
#include "dxvk_recycler.h"
|
||||
#include "dxvk_renderpass.h"
|
||||
#include "dxvk_sampler.h"
|
||||
@ -206,6 +207,13 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image,
|
||||
const DxvkImageViewCreateInfo& createInfo);
|
||||
|
||||
/**
|
||||
* \brief Creates a query pool
|
||||
* \param [in] queryType Query type
|
||||
*/
|
||||
Rc<DxvkQueryPool> createQueryPool(
|
||||
VkQueryType queryType);
|
||||
|
||||
/**
|
||||
* \brief Creates a sampler object
|
||||
*
|
||||
|
@ -13,7 +13,7 @@ namespace dxvk {
|
||||
MaxNumResourceSlots = 1096,
|
||||
MaxNumActiveBindings = 128,
|
||||
MaxNumQueuedCommandBuffers = 8,
|
||||
MaxNumQueryCountPerPool = 16,
|
||||
MaxNumQueryCountPerPool = 128,
|
||||
MaxVertexBindingStride = 2048,
|
||||
MaxPushConstantSize = 128,
|
||||
};
|
||||
|
@ -36,6 +36,11 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkQueryHandle DxvkQuery::getHandle() {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
|
||||
void DxvkQuery::beginRecording(uint32_t revision) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
@ -47,16 +52,28 @@ namespace dxvk {
|
||||
void DxvkQuery::endRecording(uint32_t revision) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_revision == revision)
|
||||
m_status = DxvkQueryStatus::Pending;
|
||||
if (m_revision == revision) {
|
||||
if (m_queryIndex < m_queryCount) {
|
||||
m_status = DxvkQueryStatus::Pending;
|
||||
} else {
|
||||
m_status = DxvkQueryStatus::Available;
|
||||
m_signal.notify_all();
|
||||
}
|
||||
|
||||
m_handle = DxvkQueryHandle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkQuery::associateQuery(uint32_t revision) {
|
||||
void DxvkQuery::associateQuery(uint32_t revision, DxvkQueryHandle handle) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_revision == revision)
|
||||
m_queryCount += 1;
|
||||
|
||||
// Assign the handle either way as this
|
||||
// will be used by the DXVK context.
|
||||
m_handle = handle;
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,6 +71,17 @@ namespace dxvk {
|
||||
DxvkQueryStatisticData statistic;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Query entry
|
||||
*
|
||||
* Stores the pool handle and the
|
||||
* index of a single Vulkan query.
|
||||
*/
|
||||
struct DxvkQueryHandle {
|
||||
VkQueryPool queryPool = VK_NULL_HANDLE;
|
||||
uint32_t queryId = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Query object
|
||||
*
|
||||
@ -105,6 +116,12 @@ namespace dxvk {
|
||||
DxvkQueryStatus getData(
|
||||
DxvkQueryData& data);
|
||||
|
||||
/**
|
||||
* \brief Gets current query handle
|
||||
* \returns The current query handle
|
||||
*/
|
||||
DxvkQueryHandle getHandle();
|
||||
|
||||
/**
|
||||
* \brief Begins recording the query
|
||||
*
|
||||
@ -127,8 +144,11 @@ namespace dxvk {
|
||||
* The internal query count is used to determine
|
||||
* when the query data is actually available.
|
||||
* \param [in] revision Query version ID
|
||||
* \param [in] handle The query handle
|
||||
*/
|
||||
void associateQuery(uint32_t revision);
|
||||
void associateQuery(
|
||||
uint32_t revision,
|
||||
DxvkQueryHandle handle);
|
||||
|
||||
/**
|
||||
* \brief Updates query data
|
||||
@ -151,6 +171,7 @@ namespace dxvk {
|
||||
|
||||
DxvkQueryStatus m_status = DxvkQueryStatus::Reset;
|
||||
DxvkQueryData m_data = {};
|
||||
DxvkQueryHandle m_handle;
|
||||
|
||||
uint32_t m_queryIndex = 0;
|
||||
uint32_t m_queryCount = 0;
|
||||
@ -158,4 +179,15 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Query revision
|
||||
*
|
||||
* Stores the query object and the
|
||||
* version ID for query operations.
|
||||
*/
|
||||
struct DxvkQueryRevision {
|
||||
Rc<DxvkQuery> query;
|
||||
uint32_t revision;
|
||||
};
|
||||
|
||||
}
|
@ -3,15 +3,73 @@
|
||||
namespace dxvk {
|
||||
|
||||
DxvkQueryPool::DxvkQueryPool(
|
||||
const Rc<vk::DeviceFn>& fn,
|
||||
VkQueryType queryType,
|
||||
uint32_t queryCount) {
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
VkQueryType queryType)
|
||||
: m_vkd(vkd), m_queryType(queryType) {
|
||||
VkQueryPoolCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.queryType = queryType;
|
||||
info.queryCount = MaxNumQueryCountPerPool;
|
||||
info.pipelineStatistics = 0;
|
||||
|
||||
if (queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) {
|
||||
info.pipelineStatistics
|
||||
= VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT
|
||||
| VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;
|
||||
}
|
||||
|
||||
if (m_vkd->vkCreateQueryPool(m_vkd->device(), &info, nullptr, &m_queryPool) != VK_SUCCESS)
|
||||
Logger::err("DxvkQueryPool: Failed to create query pool");
|
||||
}
|
||||
|
||||
|
||||
DxvkQueryPool::~DxvkQueryPool() {
|
||||
m_vkd->vkDestroyQueryPool(
|
||||
m_vkd->device(), m_queryPool, nullptr);
|
||||
}
|
||||
|
||||
|
||||
DxvkQueryHandle DxvkQueryPool::allocQuery(const DxvkQueryRevision& query) {
|
||||
const DxvkQueryHandle result = { m_queryPool, m_queryId };
|
||||
|
||||
query.query->associateQuery(query.revision, result);
|
||||
m_queries.at(m_queryId) = query;
|
||||
m_queryId += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
VkResult DxvkQueryPool::getData(
|
||||
uint32_t queryIndex,
|
||||
uint32_t queryCount) {
|
||||
std::array<DxvkQueryData, MaxNumQueryCountPerPool> results;
|
||||
|
||||
const VkResult status = m_vkd->vkGetQueryPoolResults(
|
||||
m_vkd->device(), m_queryPool, queryIndex, queryCount,
|
||||
sizeof(DxvkQueryData) * MaxNumQueryCountPerPool,
|
||||
results.data(), sizeof(DxvkQueryData),
|
||||
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
|
||||
if (status != VK_SUCCESS)
|
||||
return status;
|
||||
|
||||
for (uint32_t i = 0; i < queryCount; i++) {
|
||||
const DxvkQueryRevision& query = m_queries.at(queryIndex + i);
|
||||
query.query->updateData(query.revision, results.at(i));
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
@ -16,18 +16,56 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkQueryPool(
|
||||
const Rc<vk::DeviceFn>& fn,
|
||||
VkQueryType queryType,
|
||||
uint32_t queryCount);
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
VkQueryType queryType);
|
||||
|
||||
~DxvkQueryPool();
|
||||
|
||||
/**
|
||||
* \brief Query pool handle
|
||||
* \returns Query pool handle
|
||||
*/
|
||||
VkQueryPool handle() const {
|
||||
return m_queryPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Query count
|
||||
* \returns Query count
|
||||
*/
|
||||
uint32_t queryCount() const {
|
||||
return MaxNumQueryCountPerPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates a Vulkan query
|
||||
*
|
||||
* \param [in] revision Query revision
|
||||
* \returns The query ID and pool handle
|
||||
*/
|
||||
DxvkQueryHandle allocQuery(
|
||||
const DxvkQueryRevision& revision);
|
||||
|
||||
/**
|
||||
* \brief Writes back data for a range of queries
|
||||
*
|
||||
* \param [in] queryIndex First query in the range
|
||||
* \param [in] queryCount Number of queries
|
||||
* \returns Query result status
|
||||
*/
|
||||
VkResult getData(
|
||||
uint32_t queryIndex,
|
||||
uint32_t queryCount);
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
VkQueryPool m_queryPool = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<Rc<DxvkQuery>> m_queries;
|
||||
VkQueryType m_queryType;
|
||||
VkQueryPool m_queryPool = VK_NULL_HANDLE;
|
||||
|
||||
std::array<DxvkQueryRevision, MaxNumQueryCountPerPool> m_queries;
|
||||
uint32_t m_queryId = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -115,14 +115,6 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct RcHash {
|
||||
size_t operator () (const Rc<T>& rc) const {
|
||||
return std::hash<T*>()(rc.ptr());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
Loading…
Reference in New Issue
Block a user