1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 02:52:10 +01:00

[hud] Added stat counters to the HUD

This commit is contained in:
Philip Rebohle 2018-04-03 14:49:13 +02:00
parent 3ed03f7a3d
commit fc3f45c082
11 changed files with 288 additions and 15 deletions

View File

@ -12,10 +12,17 @@ namespace dxvk {
} }
DxvkStatCounters DxvkStatCounters::diff(const DxvkStatCounters& other) const {
DxvkStatCounters result;
for (size_t i = 0; i < m_counters.size(); i++)
result.m_counters[i] = m_counters[i] - other.m_counters[i];
return result;
}
void DxvkStatCounters::merge(const DxvkStatCounters& other) { void DxvkStatCounters::merge(const DxvkStatCounters& other) {
for (size_t i = 0; i < m_counters.size(); i++) { for (size_t i = 0; i < m_counters.size(); i++)
m_counters[i] += other.m_counters[i]; m_counters[i] += other.m_counters[i];
}
} }

View File

@ -77,6 +77,15 @@ namespace dxvk {
m_counters[uint32_t(ctr)] = 0; m_counters[uint32_t(ctr)] = 0;
} }
/**
* \brief Computes difference
*
* Computes difference between counter values.
* \param [in] other Counters to subtract
* \returns Difference between counter sets
*/
DxvkStatCounters diff(const DxvkStatCounters& other) const;
/** /**
* \brief Merges counters * \brief Merges counters
* *

View File

@ -12,7 +12,8 @@ namespace dxvk::hud {
m_context (m_device->createContext()), m_context (m_device->createContext()),
m_textRenderer (m_device, m_context), m_textRenderer (m_device, m_context),
m_uniformBuffer (createUniformBuffer()), m_uniformBuffer (createUniformBuffer()),
m_hudDeviceInfo (device) { m_hudDeviceInfo (device),
m_hudStats (config.elements) {
this->setupConstantState(); this->setupConstantState();
} }
@ -31,6 +32,7 @@ namespace dxvk::hud {
} }
m_hudFps.update(); m_hudFps.update();
m_hudStats.update(m_device);
this->beginRenderPass(recreateFbo); this->beginRenderPass(recreateFbo);
this->updateUniformBuffer(); this->updateUniformBuffer();
@ -42,11 +44,9 @@ namespace dxvk::hud {
Rc<Hud> Hud::createHud(const Rc<DxvkDevice>& device) { Rc<Hud> Hud::createHud(const Rc<DxvkDevice>& device) {
HudConfig config(env::getEnvVar(L"DXVK_HUD")); HudConfig config(env::getEnvVar(L"DXVK_HUD"));
if (config.elements.isClear()) return !config.elements.isClear()
return nullptr; ? new Hud(device, config)
: nullptr;
// TODO implement configuration options for the HUD
return new Hud(device, config);
} }
@ -78,6 +78,9 @@ namespace dxvk::hud {
position = m_hudFps.renderText( position = m_hudFps.renderText(
m_context, m_textRenderer, position); m_context, m_textRenderer, position);
} }
position = m_hudStats.renderText(
m_context, m_textRenderer, position);
} }

View File

@ -8,6 +8,7 @@
#include "dxvk_hud_devinfo.h" #include "dxvk_hud_devinfo.h"
#include "dxvk_hud_fps.h" #include "dxvk_hud_fps.h"
#include "dxvk_hud_text.h" #include "dxvk_hud_text.h"
#include "dxvk_hud_stats.h"
namespace dxvk::hud { namespace dxvk::hud {
@ -83,6 +84,7 @@ namespace dxvk::hud {
HudDeviceInfo m_hudDeviceInfo; HudDeviceInfo m_hudDeviceInfo;
HudFps m_hudFps; HudFps m_hudFps;
HudStats m_hudStats;
void renderText(); void renderText();

View File

@ -1,10 +1,14 @@
#include "dxvk_hud_config.h" #include "dxvk_hud_config.h"
namespace dxvk { namespace dxvk::hud {
const std::unordered_map<std::string, HudElement> g_hudElements = {{ const std::unordered_map<std::string, HudElement> g_hudElements = {{
{ "devinfo", HudElement::DeviceInfo }, { "devinfo", HudElement::DeviceInfo },
{ "fps", HudElement::Framerate }, { "fps", HudElement::Framerate },
{ "drawcalls", HudElement::StatDrawCalls },
{ "submissions", HudElement::StatSubmissions },
{ "pipelines", HudElement::StatPipelines },
{ "memory", HudElement::StatMemory },
}}; }};

View File

@ -2,7 +2,7 @@
#include "../dxvk_include.h" #include "../dxvk_include.h"
namespace dxvk { namespace dxvk::hud {
/** /**
* \brief HUD element * \brief HUD element
@ -11,8 +11,12 @@ namespace dxvk {
* or disable HUD elements on demand. * or disable HUD elements on demand.
*/ */
enum class HudElement { enum class HudElement {
DeviceInfo = 0, DeviceInfo = 0,
Framerate = 1, Framerate = 1,
StatDrawCalls = 2,
StatSubmissions = 3,
StatPipelines = 4,
StatMemory = 5,
}; };
using HudElements = Flags<HudElement>; using HudElements = Flags<HudElement>;

View File

@ -41,7 +41,7 @@ namespace dxvk::hud {
{ 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f },
m_fpsString); m_fpsString);
return HudPos { position.x, position.y + 20 }; return HudPos { position.x, position.y + 24 };
} }
} }

View File

@ -0,0 +1,168 @@
#include "dxvk_hud_stats.h"
namespace dxvk::hud {
HudStats::HudStats(HudElements elements)
: m_elements(filterElements(elements)) { }
HudStats::~HudStats() {
}
void HudStats::update(const Rc<DxvkDevice>& device) {
if (m_elements.isClear())
return;
// For some counters, we'll display the absolute value,
// for others, the average counter increment per frame.
DxvkStatCounters nextCounters = device->getStatCounters();
m_diffCounters = nextCounters.diff(m_prevCounters);
m_prevCounters = nextCounters;
}
HudPos HudStats::renderText(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position) {
if (m_elements.test(HudElement::StatSubmissions))
position = this->printSubmissionStats(context, renderer, position);
if (m_elements.test(HudElement::StatDrawCalls))
position = this->printDrawCallStats(context, renderer, position);
if (m_elements.test(HudElement::StatPipelines))
position = this->printPipelineStats(context, renderer, position);
if (m_elements.test(HudElement::StatMemory))
position = this->printMemoryStats(context, renderer, position);
return position;
}
HudPos HudStats::printDrawCallStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position) {
const uint64_t frameCount = std::max(m_diffCounters.getCtr(DxvkStatCounter::QueuePresentCount), 1u);
const uint64_t gpCalls = m_diffCounters.getCtr(DxvkStatCounter::CmdDrawCalls) / frameCount;
const uint64_t cpCalls = m_diffCounters.getCtr(DxvkStatCounter::CmdDispatchCalls) / frameCount;
const uint64_t rpCalls = m_diffCounters.getCtr(DxvkStatCounter::CmdRenderPassCount) / frameCount;
const std::string strDrawCalls = str::format("Draw calls: ", gpCalls);
const std::string strDispatchCalls = str::format("Dispatch calls: ", cpCalls);
const std::string strRenderPasses = str::format("Render passes: ", rpCalls);
renderer.drawText(context, 16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strDrawCalls);
renderer.drawText(context, 16.0f,
{ position.x, position.y + 20.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strDispatchCalls);
renderer.drawText(context, 16.0f,
{ position.x, position.y + 40.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strRenderPasses);
return { position.x, position.y + 64 };
}
HudPos HudStats::printSubmissionStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position) {
const uint64_t frameCount = std::max(m_diffCounters.getCtr(DxvkStatCounter::QueuePresentCount), 1u);
const uint64_t numSubmits = m_diffCounters.getCtr(DxvkStatCounter::QueueSubmitCount) / frameCount;
const std::string strSubmissions = str::format("Queue submissions: ", numSubmits);
renderer.drawText(context, 16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strSubmissions);
return { position.x, position.y + 24.0f };
}
HudPos HudStats::printPipelineStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position) {
constexpr uint64_t kib = 1024;
constexpr uint64_t mib = 1024 * 1024;
const uint64_t gpCount = m_prevCounters.getCtr(DxvkStatCounter::PipeCountGraphics);
const uint64_t cpCount = m_prevCounters.getCtr(DxvkStatCounter::PipeCountCompute);
const uint64_t pcSize = m_prevCounters.getCtr(DxvkStatCounter::PipeCacheSize);
const std::string strGpCount = str::format("Graphics pipelines: ", gpCount);
const std::string strCpCount = str::format("Compute pipelines: ", cpCount);
const std::string strPcSize = str::format("Pipeline cache: ", pcSize >= mib
? str::format(pcSize / mib, ".", ((10 * pcSize) / mib) % 10, " MB")
: str::format(pcSize / kib, " kB"));
renderer.drawText(context, 16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strGpCount);
renderer.drawText(context, 16.0f,
{ position.x, position.y + 20.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strCpCount);
renderer.drawText(context, 16.0f,
{ position.x, position.y + 40.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strPcSize);
return { position.x, position.y + 64.0f };
}
HudPos HudStats::printMemoryStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position) {
constexpr uint64_t mib = 1024 * 1024;
const uint64_t memAllocated = m_prevCounters.getCtr(DxvkStatCounter::MemoryAllocated);
const uint64_t memUsed = m_prevCounters.getCtr(DxvkStatCounter::MemoryUsed);
const std::string strMemAllocated = str::format("Memory allocated: ", memAllocated / mib, " MB");
const std::string strMemUsed = str::format("Memory used: ", memUsed / mib, " MB");
renderer.drawText(context, 16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strMemAllocated);
renderer.drawText(context, 16.0f,
{ position.x, position.y + 20.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strMemUsed);
return { position.x, position.y + 44.0f };
}
HudElements HudStats::filterElements(HudElements elements) {
return elements & HudElements(
HudElement::StatDrawCalls,
HudElement::StatSubmissions,
HudElement::StatPipelines,
HudElement::StatMemory);
}
}

View File

@ -0,0 +1,63 @@
#pragma once
#include "../dxvk_stats.h"
#include "dxvk_hud_config.h"
#include "dxvk_hud_text.h"
namespace dxvk::hud {
/**
* \brief Statistics display for the HUD
*
* Displays some stat counters for the device
* if enabled. Certain groups of counters can
* be enabled inidividually.
*/
class HudStats {
public:
HudStats(HudElements elements);
~HudStats();
void update(
const Rc<DxvkDevice>& device);
HudPos renderText(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position);
private:
const HudElements m_elements;
DxvkStatCounters m_prevCounters;
DxvkStatCounters m_diffCounters;
HudPos printDrawCallStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position);
HudPos printSubmissionStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position);
HudPos printPipelineStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position);
HudPos printMemoryStats(
const Rc<DxvkContext>& context,
HudTextRenderer& renderer,
HudPos position);
static HudElements filterElements(HudElements elements);
};
}

View File

@ -52,6 +52,7 @@ dxvk_src = files([
'hud/dxvk_hud_devinfo.cpp', 'hud/dxvk_hud_devinfo.cpp',
'hud/dxvk_hud_font.cpp', 'hud/dxvk_hud_font.cpp',
'hud/dxvk_hud_fps.cpp', 'hud/dxvk_hud_fps.cpp',
'hud/dxvk_hud_stats.cpp',
'hud/dxvk_hud_text.cpp', 'hud/dxvk_hud_text.cpp',
'vulkan/dxvk_vulkan_extensions.cpp', 'vulkan/dxvk_vulkan_extensions.cpp',

View File

@ -68,6 +68,18 @@ namespace dxvk {
return m_bits; return m_bits;
} }
Flags operator & (const Flags& other) const {
return Flags(m_bits & other.m_bits);
}
Flags operator | (const Flags& other) const {
return Flags(m_bits | other.m_bits);
}
Flags operator ^ (const Flags& other) const {
return Flags(m_bits ^ other.m_bits);
}
private: private:
IntType m_bits = 0; IntType m_bits = 0;