1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00
OpenDX/src/dxvk/hud/dxvk_hud_item.cpp

350 lines
8.7 KiB
C++
Raw Normal View History

#include "dxvk_hud_item.h"
#include <version.h>
namespace dxvk::hud {
HudItem::~HudItem() {
}
void HudItem::update(dxvk::high_resolution_clock::time_point time) {
// Do nothing by default. Some items won't need this.
}
HudItemSet::HudItemSet() {
std::string configStr = env::getEnvVar("DXVK_HUD");
if (configStr == "full") {
// Just enable everything
m_enableFull = true;
} else if (configStr == "1") {
m_enabled.insert("devinfo");
m_enabled.insert("fps");
} else {
std::string::size_type pos = 0;
std::string::size_type end = 0;
while (pos < configStr.size()) {
end = configStr.find(',', pos);
if (end == std::string::npos)
end = configStr.size();
m_enabled.insert(configStr.substr(pos, end - pos));
pos = end + 1;
}
}
}
HudItemSet::~HudItemSet() {
}
void HudItemSet::update() {
auto time = dxvk::high_resolution_clock::now();
for (const auto& item : m_items)
item->update(time);
}
void HudItemSet::render(HudRenderer& renderer) {
HudPos position = { 8.0f, 8.0f };
for (const auto& item : m_items)
position = item->render(renderer, position);
}
HudPos HudVersionItem::render(
HudRenderer& renderer,
HudPos position) {
position.y += 16.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
"DXVK " DXVK_VERSION);
position.y += 8.0f;
return position;
}
HudClientApiItem::HudClientApiItem(const Rc<DxvkDevice>& device)
: m_device(device) {
}
HudClientApiItem::~HudClientApiItem() {
}
HudPos HudClientApiItem::render(
HudRenderer& renderer,
HudPos position) {
position.y += 16.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
m_device->clientApi());
position.y += 8.0f;
return position;
}
HudDeviceInfoItem::HudDeviceInfoItem(const Rc<DxvkDevice>& device) {
VkPhysicalDeviceProperties props = device->adapter()->deviceProperties();
m_deviceName = props.deviceName;
m_driverVer = str::format("Driver: ",
VK_VERSION_MAJOR(props.driverVersion), ".",
VK_VERSION_MINOR(props.driverVersion), ".",
VK_VERSION_PATCH(props.driverVersion));
m_vulkanVer = str::format("Vulkan: ",
VK_VERSION_MAJOR(props.apiVersion), ".",
VK_VERSION_MINOR(props.apiVersion), ".",
VK_VERSION_PATCH(props.apiVersion));
}
HudDeviceInfoItem::~HudDeviceInfoItem() {
}
HudPos HudDeviceInfoItem::render(
HudRenderer& renderer,
HudPos position) {
position.y += 16.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
m_deviceName);
position.y += 24.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
m_driverVer);
position.y += 20.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
m_vulkanVer);
position.y += 8.0f;
return position;
}
HudFpsItem::HudFpsItem() { }
HudFpsItem::~HudFpsItem() { }
void HudFpsItem::update(dxvk::high_resolution_clock::time_point time) {
m_frameCount += 1;
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(time - m_lastUpdate);
if (elapsed.count() >= UpdateInterval) {
int64_t fps = (10'000'000ll * m_frameCount) / elapsed.count();
m_frameRate = str::format("FPS: ", fps / 10, ".", fps % 10);
m_frameCount = 0;
m_lastUpdate = time;
}
}
HudPos HudFpsItem::render(
HudRenderer& renderer,
HudPos position) {
position.y += 16.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
m_frameRate);
position.y += 8.0f;
return position;
}
HudFrameTimeItem::HudFrameTimeItem() { }
HudFrameTimeItem::~HudFrameTimeItem() { }
void HudFrameTimeItem::update(dxvk::high_resolution_clock::time_point time) {
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(time - m_lastUpdate);
m_dataPoints[m_dataPointId] = float(elapsed.count());
m_dataPointId = (m_dataPointId + 1) % NumDataPoints;
m_lastUpdate = time;
}
HudPos HudFrameTimeItem::render(
HudRenderer& renderer,
HudPos position) {
std::array<HudLineVertex, NumDataPoints * 2> vData;
position.y += 40.0f;
// 60 FPS = optimal, 10 FPS = worst
const float targetUs = 16'666.6f;
const float minUs = 5'000.0f;
const float maxUs = 100'000.0f;
// Ten times the maximum/minimum number
// of milliseconds for a single frame
uint32_t minMs = 0xFFFFFFFFu;
uint32_t maxMs = 0x00000000u;
// Paint the time points
for (uint32_t i = 0; i < NumDataPoints; i++) {
float us = m_dataPoints[(m_dataPointId + i) % NumDataPoints];
minMs = std::min(minMs, uint32_t(us / 100.0f));
maxMs = std::max(maxMs, uint32_t(us / 100.0f));
float r = std::min(std::max(-1.0f + us / targetUs, 0.0f), 1.0f);
float g = std::min(std::max( 3.0f - us / targetUs, 0.0f), 1.0f);
float l = std::sqrt(r * r + g * g);
HudNormColor color = {
uint8_t(255.0f * (r / l)),
uint8_t(255.0f * (g / l)),
uint8_t(0), uint8_t(255) };
float x = position.x + float(i);
float y = position.y;
float hVal = std::log2(std::max((us - minUs) / targetUs + 1.0f, 1.0f))
/ std::log2((maxUs - minUs) / targetUs);
float h = std::min(std::max(40.0f * hVal, 2.0f), 40.0f);
vData[2 * i + 0] = HudLineVertex { { x, y }, color };
vData[2 * i + 1] = HudLineVertex { { x, y - h }, color };
}
renderer.drawLines(vData.size(), vData.data());
// Paint min/max frame times in the entire window
position.y += 20.0f;
renderer.drawText(14.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
str::format("min: ", minMs / 10, ".", minMs % 10));
renderer.drawText(14.0f,
{ position.x + 150.0f, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
str::format("max: ", maxMs / 10, ".", maxMs % 10));
position.y += 2.0f;
return position;
}
HudSubmissionStatsItem::HudSubmissionStatsItem(const Rc<DxvkDevice>& device)
: m_device(device) {
}
HudSubmissionStatsItem::~HudSubmissionStatsItem() {
}
void HudSubmissionStatsItem::update(dxvk::high_resolution_clock::time_point time) {
DxvkStatCounters counters = m_device->getStatCounters();
uint32_t currCounter = counters.getCtr(DxvkStatCounter::QueueSubmitCount);
m_diffCounter = currCounter - m_prevCounter;
m_prevCounter = currCounter;
}
HudPos HudSubmissionStatsItem::render(
HudRenderer& renderer,
HudPos position) {
position.y += 16.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
str::format("Queue submissions: ", m_diffCounter));
position.y += 8.0f;
return position;
}
HudDrawCallStatsItem::HudDrawCallStatsItem(const Rc<DxvkDevice>& device)
: m_device(device) {
}
HudDrawCallStatsItem::~HudDrawCallStatsItem() {
}
void HudDrawCallStatsItem::update(dxvk::high_resolution_clock::time_point time) {
DxvkStatCounters counters = m_device->getStatCounters();
m_diffCounters = counters.diff(m_prevCounters);
m_prevCounters = counters;
}
HudPos HudDrawCallStatsItem::render(
HudRenderer& renderer,
HudPos position) {
uint64_t gpCalls = m_diffCounters.getCtr(DxvkStatCounter::CmdDrawCalls);
uint64_t cpCalls = m_diffCounters.getCtr(DxvkStatCounter::CmdDispatchCalls);
uint64_t rpCalls = m_diffCounters.getCtr(DxvkStatCounter::CmdRenderPassCount);
std::string strDrawCalls = str::format("Draw calls: ", gpCalls);
std::string strDispatchCalls = str::format("Dispatch calls: ", cpCalls);
std::string strRenderPasses = str::format("Render passes: ", rpCalls);
position.y += 16.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strDrawCalls);
position.y += 20.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strDispatchCalls);
position.y += 20.0f;
renderer.drawText(16.0f,
{ position.x, position.y },
{ 1.0f, 1.0f, 1.0f, 1.0f },
strRenderPasses);
position.y += 8.0f;
return position;
}
}