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(
|
Rc<DxvkBuffer> DxvkDevice::createBuffer(
|
||||||
const DxvkBufferCreateInfo& createInfo,
|
const DxvkBufferCreateInfo& createInfo,
|
||||||
VkMemoryPropertyFlags memoryType) {
|
VkMemoryPropertyFlags memoryType) {
|
||||||
|
m_statCounters.increment(DxvkStat::ResBufferCreations, 1);
|
||||||
|
|
||||||
return new DxvkBuffer(m_vkd,
|
return new DxvkBuffer(m_vkd,
|
||||||
createInfo, *m_memory, memoryType);
|
createInfo, *m_memory, memoryType);
|
||||||
}
|
}
|
||||||
@ -116,6 +118,8 @@ namespace dxvk {
|
|||||||
Rc<DxvkImage> DxvkDevice::createImage(
|
Rc<DxvkImage> DxvkDevice::createImage(
|
||||||
const DxvkImageCreateInfo& createInfo,
|
const DxvkImageCreateInfo& createInfo,
|
||||||
VkMemoryPropertyFlags memoryType) {
|
VkMemoryPropertyFlags memoryType) {
|
||||||
|
m_statCounters.increment(DxvkStat::ResImageCreations, 1);
|
||||||
|
|
||||||
return new DxvkImage(m_vkd,
|
return new DxvkImage(m_vkd,
|
||||||
createInfo, *m_memory, memoryType);
|
createInfo, *m_memory, memoryType);
|
||||||
}
|
}
|
||||||
@ -200,11 +204,14 @@ namespace dxvk {
|
|||||||
|
|
||||||
// FIXME this must go away once the ring buffer is implemented
|
// FIXME this must go away once the ring buffer is implemented
|
||||||
m_recycledCommandLists.returnObject(commandList);
|
m_recycledCommandLists.returnObject(commandList);
|
||||||
|
m_statCounters.increment(DxvkStat::DevQueueSubmissions, 1);
|
||||||
return fence;
|
return fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkDevice::waitForIdle() const {
|
void DxvkDevice::waitForIdle() {
|
||||||
|
m_statCounters.increment(DxvkStat::DevSynchronizations, 1);
|
||||||
|
|
||||||
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
|
if (m_vkd->vkDeviceWaitIdle(m_vkd->device()) != VK_SUCCESS)
|
||||||
throw DxvkError("DxvkDevice::waitForIdle: Operation failed");
|
throw DxvkError("DxvkDevice::waitForIdle: Operation failed");
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "dxvk_renderpass.h"
|
#include "dxvk_renderpass.h"
|
||||||
#include "dxvk_sampler.h"
|
#include "dxvk_sampler.h"
|
||||||
#include "dxvk_shader.h"
|
#include "dxvk_shader.h"
|
||||||
|
#include "dxvk_stats.h"
|
||||||
#include "dxvk_swapchain.h"
|
#include "dxvk_swapchain.h"
|
||||||
#include "dxvk_sync.h"
|
#include "dxvk_sync.h"
|
||||||
|
|
||||||
@ -255,7 +256,15 @@ namespace dxvk {
|
|||||||
* used to ensure that resources that were previously
|
* used to ensure that resources that were previously
|
||||||
* used by the GPU can be safely destroyed.
|
* 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:
|
private:
|
||||||
|
|
||||||
@ -274,6 +283,8 @@ namespace dxvk {
|
|||||||
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
|
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
|
||||||
DxvkRecycler<DxvkStagingBuffer, 4> m_recycledStagingBuffers;
|
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_sampler.cpp',
|
||||||
'dxvk_shader.cpp',
|
'dxvk_shader.cpp',
|
||||||
'dxvk_staging.cpp',
|
'dxvk_staging.cpp',
|
||||||
|
'dxvk_stats.cpp',
|
||||||
'dxvk_surface.cpp',
|
'dxvk_surface.cpp',
|
||||||
'dxvk_swapchain.cpp',
|
'dxvk_swapchain.cpp',
|
||||||
'dxvk_sync.cpp',
|
'dxvk_sync.cpp',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user