1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-12 13:08:50 +01:00

[hud] Display approximate progress when compiling shaders

This commit is contained in:
Philip Rebohle 2023-01-13 15:09:32 +01:00
parent c978e62ec8
commit 3a84838ac4
6 changed files with 83 additions and 30 deletions

View File

@ -188,12 +188,14 @@ namespace dxvk {
DxvkStatCounters DxvkDevice::getStatCounters() { DxvkStatCounters DxvkDevice::getStatCounters() {
DxvkPipelineCount pipe = m_objects.pipelineManager().getPipelineCount(); DxvkPipelineCount pipe = m_objects.pipelineManager().getPipelineCount();
DxvkPipelineWorkerStats workers = m_objects.pipelineManager().getWorkerStats();
DxvkStatCounters result; DxvkStatCounters result;
result.setCtr(DxvkStatCounter::PipeCountGraphics, pipe.numGraphicsPipelines); result.setCtr(DxvkStatCounter::PipeCountGraphics, pipe.numGraphicsPipelines);
result.setCtr(DxvkStatCounter::PipeCountLibrary, pipe.numGraphicsLibraries); result.setCtr(DxvkStatCounter::PipeCountLibrary, pipe.numGraphicsLibraries);
result.setCtr(DxvkStatCounter::PipeCountCompute, pipe.numComputePipelines); result.setCtr(DxvkStatCounter::PipeCountCompute, pipe.numComputePipelines);
result.setCtr(DxvkStatCounter::PipeCompilerBusy, m_objects.pipelineManager().isCompilingShaders()); result.setCtr(DxvkStatCounter::PipeTasksDone, workers.tasksCompleted);
result.setCtr(DxvkStatCounter::PipeTasksTotal, workers.tasksTotal);
result.setCtr(DxvkStatCounter::GpuIdleTicks, m_submissionQueue.gpuIdleTicks()); result.setCtr(DxvkStatCounter::GpuIdleTicks, m_submissionQueue.gpuIdleTicks());
std::lock_guard<sync::Spinlock> lock(m_statLock); std::lock_guard<sync::Spinlock> lock(m_statLock);

View File

@ -24,7 +24,7 @@ namespace dxvk {
std::unique_lock lock(m_lock); std::unique_lock lock(m_lock);
this->startWorkers(); this->startWorkers();
m_pendingTasks += 1; m_tasksTotal += 1;
m_buckets[uint32_t(priority)].queue.emplace(library); m_buckets[uint32_t(priority)].queue.emplace(library);
notifyWorkers(priority); notifyWorkers(priority);
@ -39,18 +39,13 @@ namespace dxvk {
this->startWorkers(); this->startWorkers();
pipeline->acquirePipeline(); pipeline->acquirePipeline();
m_pendingTasks += 1; m_tasksTotal += 1;
m_buckets[uint32_t(priority)].queue.emplace(pipeline, state); m_buckets[uint32_t(priority)].queue.emplace(pipeline, state);
notifyWorkers(priority); notifyWorkers(priority);
} }
bool DxvkPipelineWorkers::isBusy() const {
return m_pendingTasks.load() != 0ull;
}
void DxvkPipelineWorkers::stopWorkers() { void DxvkPipelineWorkers::stopWorkers() {
{ std::unique_lock lock(m_lock); { std::unique_lock lock(m_lock);
@ -164,12 +159,12 @@ namespace dxvk {
if (entry.pipelineLibrary) { if (entry.pipelineLibrary) {
entry.pipelineLibrary->compilePipeline(); entry.pipelineLibrary->compilePipeline();
m_pendingTasks -= 1;
} else if (entry.graphicsPipeline) { } else if (entry.graphicsPipeline) {
entry.graphicsPipeline->compilePipeline(entry.graphicsState); entry.graphicsPipeline->compilePipeline(entry.graphicsState);
entry.graphicsPipeline->releasePipeline(); entry.graphicsPipeline->releasePipeline();
m_pendingTasks -= 1;
} }
m_tasksCompleted += 1;
} }
} }

View File

@ -34,6 +34,11 @@ namespace dxvk {
std::atomic<uint32_t> numComputePipelines = { 0u }; std::atomic<uint32_t> numComputePipelines = { 0u };
}; };
struct DxvkPipelineWorkerStats {
uint64_t tasksCompleted;
uint64_t tasksTotal;
};
/** /**
* \brief Pipeline priority * \brief Pipeline priority
*/ */
@ -58,6 +63,19 @@ namespace dxvk {
~DxvkPipelineWorkers(); ~DxvkPipelineWorkers();
/**
* \brief Queries worker statistics
*
* The returned result may be immediately out of date.
* \returns Worker statistics
*/
DxvkPipelineWorkerStats getStats() const {
DxvkPipelineWorkerStats result;
result.tasksCompleted = m_tasksCompleted.load(std::memory_order_acquire);
result.tasksTotal = m_tasksTotal.load(std::memory_order_relaxed);
return result;
}
/** /**
* \brief Compiles a pipeline library * \brief Compiles a pipeline library
* *
@ -82,12 +100,6 @@ namespace dxvk {
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
DxvkPipelinePriority priority); DxvkPipelinePriority priority);
/**
* \brief Checks whether workers are busy
* \returns \c true if there is unfinished work
*/
bool isBusy() const;
/** /**
* \brief Stops all worker threads * \brief Stops all worker threads
* *
@ -121,7 +133,8 @@ namespace dxvk {
DxvkDevice* m_device; DxvkDevice* m_device;
std::atomic<uint64_t> m_pendingTasks = { 0ull }; std::atomic<uint64_t> m_tasksTotal = { 0ull };
std::atomic<uint64_t> m_tasksCompleted = { 0ull };
dxvk::mutex m_lock; dxvk::mutex m_lock;
std::array<PipelineBucket, 3> m_buckets; std::array<PipelineBucket, 3> m_buckets;
@ -242,8 +255,8 @@ namespace dxvk {
* \brief Checks whether async compiler is busy * \brief Checks whether async compiler is busy
* \returns \c true if shaders are being compiled * \returns \c true if shaders are being compiled
*/ */
bool isCompilingShaders() const { DxvkPipelineWorkerStats getWorkerStats() const {
return m_workers.isBusy(); return m_workers.getStats();
} }
/** /**

View File

@ -18,7 +18,8 @@ namespace dxvk {
PipeCountGraphics, ///< Number of graphics pipelines PipeCountGraphics, ///< Number of graphics pipelines
PipeCountLibrary, ///< Number of graphics shader libraries PipeCountLibrary, ///< Number of graphics shader libraries
PipeCountCompute, ///< Number of compute pipelines PipeCountCompute, ///< Number of compute pipelines
PipeCompilerBusy, ///< Boolean indicating compiler activity PipeTasksDone, ///< Boolean indicating compiler activity
PipeTasksTotal, ///< Boolean indicating compiler activity
QueueSubmitCount, ///< Number of command buffer submissions QueueSubmitCount, ///< Number of command buffer submissions
QueuePresentCount, ///< Number of present calls / frames QueuePresentCount, ///< Number of present calls / frames
GpuSyncCount, ///< Number of GPU synchronizations GpuSyncCount, ///< Number of GPU synchronizations

View File

@ -755,15 +755,36 @@ namespace dxvk::hud {
void HudCompilerActivityItem::update(dxvk::high_resolution_clock::time_point time) { void HudCompilerActivityItem::update(dxvk::high_resolution_clock::time_point time) {
DxvkStatCounters counters = m_device->getStatCounters(); DxvkStatCounters counters = m_device->getStatCounters();
bool doShow = counters.getCtr(DxvkStatCounter::PipeCompilerBusy);
if (!doShow) { m_tasksDone = counters.getCtr(DxvkStatCounter::PipeTasksDone);
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(time - m_timeShown); m_tasksTotal = counters.getCtr(DxvkStatCounter::PipeTasksTotal);
doShow = elapsed.count() <= MinShowDuration;
}
if (doShow && !m_show) bool doShow = m_tasksDone < m_tasksTotal;
if (!doShow)
m_timeDone = time;
if (!m_show) {
m_timeShown = time; m_timeShown = time;
m_showPercentage = false;
} else {
auto durationShown = std::chrono::duration_cast<std::chrono::milliseconds>(time - m_timeShown);
auto durationWorking = std::chrono::duration_cast<std::chrono::milliseconds>(time - m_timeDone);
if (!doShow) {
m_offset = m_tasksTotal;
// Ensure the item stays up long enough to be legible
doShow = durationShown.count() <= MinShowDuration;
}
if (!m_showPercentage) {
// Don't show percentage if it's just going to be stuck at 99%
// because the workers are not being fed tasks fast enough
m_showPercentage = durationWorking.count() >= (MinShowDuration / 5)
&& (computePercentage() < 50);
}
}
m_show = doShow; m_show = doShow;
} }
@ -773,13 +794,27 @@ namespace dxvk::hud {
HudRenderer& renderer, HudRenderer& renderer,
HudPos position) { HudPos position) {
if (m_show) { if (m_show) {
std::string string = "Compiling shaders...";
if (m_showPercentage)
string = str::format(string, " (", computePercentage(), "%)");
renderer.drawText(16.0f, renderer.drawText(16.0f,
{ position.x, renderer.surfaceSize().height / renderer.scale() - 20.0f }, { position.x, renderer.surfaceSize().height / renderer.scale() - 20.0f },
{ 1.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f },
"Compiling shaders..."); string);
} }
return position; return position;
} }
uint32_t HudCompilerActivityItem::computePercentage() const {
if (m_offset == m_tasksTotal)
return 100;
return (uint32_t(m_tasksDone - m_offset) * 100)
/ (uint32_t(m_tasksTotal - m_offset));
}
} }

View File

@ -482,10 +482,17 @@ namespace dxvk::hud {
Rc<DxvkDevice> m_device; Rc<DxvkDevice> m_device;
bool m_show = false; bool m_show = false;
bool m_showPercentage = false;
dxvk::high_resolution_clock::time_point m_timeShown uint64_t m_tasksDone = 0ull;
= dxvk::high_resolution_clock::now(); uint64_t m_tasksTotal = 0ull;
uint64_t m_offset = 0ull;
dxvk::high_resolution_clock::time_point m_timeShown = dxvk::high_resolution_clock::now();
dxvk::high_resolution_clock::time_point m_timeDone = dxvk::high_resolution_clock::now();
uint32_t computePercentage() const;
}; };