mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +01:00
[dxvk] Added performance counter class
This commit is contained in:
parent
180667ba65
commit
23abc82aa0
@ -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");
|
||||
}
|
||||
|
@ -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
41
src/dxvk/dxvk_stats.cpp
Normal 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
108
src/dxvk/dxvk_stats.h
Normal 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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user