[dxvk] Added performance counter class

This commit is contained in:
Philip Rebohle 2017-12-12 10:29:17 +01:00
parent 180667ba65
commit 23abc82aa0
5 changed files with 170 additions and 2 deletions

View File

@ -101,6 +101,8 @@ namespace dxvk {
Rc<DxvkBuffer> DxvkDevice::createBuffer(
const DxvkBufferCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
m_statCounters.increment(DxvkStat::ResBufferCreations, 1);
return new DxvkBuffer(m_vkd,
createInfo, *m_memory, memoryType);
}
@ -116,6 +118,8 @@ namespace dxvk {
Rc<DxvkImage> DxvkDevice::createImage(
const DxvkImageCreateInfo& createInfo,
VkMemoryPropertyFlags memoryType) {
m_statCounters.increment(DxvkStat::ResImageCreations, 1);
return new DxvkImage(m_vkd,
createInfo, *m_memory, memoryType);
}
@ -200,11 +204,14 @@ namespace dxvk {
// FIXME this must go away once the ring buffer is implemented
m_recycledCommandLists.returnObject(commandList);
m_statCounters.increment(DxvkStat::DevQueueSubmissions, 1);
return fence;
}
void DxvkDevice::waitForIdle() const {
void DxvkDevice::waitForIdle() {
m_statCounters.increment(DxvkStat::DevSynchronizations, 1);
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
throw DxvkError("DxvkDevice::waitForIdle: Operation failed");
}

View File

@ -13,6 +13,7 @@
#include "dxvk_renderpass.h"
#include "dxvk_sampler.h"
#include "dxvk_shader.h"
#include "dxvk_stats.h"
#include "dxvk_swapchain.h"
#include "dxvk_sync.h"
@ -255,7 +256,15 @@ namespace dxvk {
* used to ensure that resources that were previously
* used by the GPU can be safely destroyed.
*/
void waitForIdle() const;
void waitForIdle();
/**
* \brief Retrieves stat counters
* \returns Stat counters
*/
DxvkStatCounters queryCounters() const {
return m_statCounters;
}
private:
@ -274,6 +283,8 @@ namespace dxvk {
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
DxvkRecycler<DxvkStagingBuffer, 4> m_recycledStagingBuffers;
DxvkStatCounters m_statCounters;
};
}

41
src/dxvk/dxvk_stats.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "dxvk_stats.h"
namespace dxvk {
DxvkStatCounters:: DxvkStatCounters() { }
DxvkStatCounters::~DxvkStatCounters() { }
DxvkStatCounters::DxvkStatCounters(const DxvkStatCounters& other) {
for (size_t i = 0; i < m_counters.size(); i++)
m_counters.at(i) = other.m_counters.at(i).load();
}
DxvkStatCounters& DxvkStatCounters::operator = (const DxvkStatCounters& other) {
for (size_t i = 0; i < m_counters.size(); i++)
m_counters.at(i) = other.m_counters.at(i).load();
return *this;
}
DxvkStatCounters DxvkStatCounters::delta(const DxvkStatCounters& oldState) const {
DxvkStatCounters result;
for (size_t i = 0; i < m_counters.size(); i++)
result.m_counters.at(i) = m_counters.at(i) - oldState.m_counters.at(i);;
return result;
}
void DxvkStatCounters::addCounters(const DxvkStatCounters& counters) {
for (size_t i = 0; i < m_counters.size(); i++)
m_counters.at(i) += counters.m_counters.at(i);
}
void DxvkStatCounters::clear() {
for (size_t i = 0; i < m_counters.size(); i++)
m_counters.at(i) = 0;
}
}

108
src/dxvk/dxvk_stats.h Normal file
View File

@ -0,0 +1,108 @@
#pragma once
#include <atomic>
#include <array>
#include "dxvk_include.h"
namespace dxvk {
/**
* \brief Statistics counter
*/
enum class DxvkStat : uint32_t {
CtxDescriptorUpdates, ///< # of descriptor set writes
CtxDrawCalls, ///< # of vkCmdDraw/vkCmdDrawIndexed
CtxDispatchCalls, ///< # of vkCmdDispatch
CtxFramebufferBinds, ///< # of render pass begin/end
CtxPipelineBinds, ///< # of vkCmdBindPipeline
DevQueueSubmissions, ///< # of vkQueueSubmit
DevQueuePresents, ///< # of vkQueuePresentKHR (aka frames)
DevSynchronizations, ///< # of vkDeviceWaitIdle
ResBufferCreations, ///< # of buffer creations
ResBufferUpdates, ///< # of unmapped buffer updates
ResImageCreations, ///< # of image creations
ResImageUpdates, ///< # of unmapped image updates
// Do not remove
MaxCounterId
};
/**
* \brief Device statistics
*
* Stores a bunch of counters that may be useful
* for performance evaluation and optimization.
*/
class DxvkStatCounters {
public:
DxvkStatCounters();
~DxvkStatCounters();
DxvkStatCounters(
const DxvkStatCounters& other);
DxvkStatCounters& operator = (const DxvkStatCounters& other);
/**
* \brief Increments a counter by a given value
*
* \param [in] counter The counter to increment
* \param [in] amount Number to add to the counter
*/
void increment(DxvkStat counter, uint32_t amount) {
m_counters.at(counterId(counter)) += amount;
}
/**
* \brief Returns a counter
*
* \param [in] counter The counter to retrieve
* \returns Current value of the counter
*/
uint32_t get(DxvkStat counter) const {
return m_counters.at(counterId(counter));
}
/**
* \brief Computes delta to a previous state
*
* \param [in] oldState previous state
* \returns Difference to previous state
*/
DxvkStatCounters delta(
const DxvkStatCounters& oldState) const;
/**
* \brief Adds counters from another source
*
* Adds each counter from the source operand to the
* corresponding counter in this set. Useful to merge
* context counters and device counters.
* \param [in] counters Counters to add
*/
void addCounters(
const DxvkStatCounters& counters);
/**
* \brief Clears counters
*
* Should be used to clear per-context counters.
* Do not clear the global device counters.
*/
void clear();
private:
std::array<std::atomic<uint32_t>,
static_cast<uint32_t>(DxvkStat::MaxCounterId)> m_counters;
static size_t counterId(DxvkStat counter) {
return static_cast<uint32_t>(counter);
}
};
}

View File

@ -23,6 +23,7 @@ dxvk_src = files([
'dxvk_sampler.cpp',
'dxvk_shader.cpp',
'dxvk_staging.cpp',
'dxvk_stats.cpp',
'dxvk_surface.cpp',
'dxvk_swapchain.cpp',
'dxvk_sync.cpp',