diff options
author | Philip Rebohle <philip.rebohle@tu-dortmund.de> | 2023-01-13 17:09:32 +0300 |
---|---|---|
committer | Philip Rebohle <philip.rebohle@tu-dortmund.de> | 2023-01-13 18:27:22 +0300 |
commit | ee66ede841ae5e29b6c0142c9a64b1b07c4fb216 (patch) | |
tree | 4de9f09abeb17af69ce025f8e23d7b0a6346e825 | |
parent | 80ff2f9ed4a6ec3df76be2816fe1f634110af337 (diff) |
[hud] Display approximate progress when compiling shadersworker-priority
-rw-r--r-- | src/dxvk/dxvk_device.cpp | 4 | ||||
-rw-r--r-- | src/dxvk/dxvk_pipemanager.cpp | 13 | ||||
-rw-r--r-- | src/dxvk/dxvk_pipemanager.h | 31 | ||||
-rw-r--r-- | src/dxvk/dxvk_stats.h | 3 | ||||
-rw-r--r-- | src/dxvk/hud/dxvk_hud_item.cpp | 49 | ||||
-rw-r--r-- | src/dxvk/hud/dxvk_hud_item.h | 13 |
6 files changed, 83 insertions, 30 deletions
diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index e059f901..54ef2821 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -188,12 +188,14 @@ namespace dxvk { DxvkStatCounters DxvkDevice::getStatCounters() { DxvkPipelineCount pipe = m_objects.pipelineManager().getPipelineCount(); + DxvkPipelineWorkerStats workers = m_objects.pipelineManager().getWorkerStats(); DxvkStatCounters result; result.setCtr(DxvkStatCounter::PipeCountGraphics, pipe.numGraphicsPipelines); result.setCtr(DxvkStatCounter::PipeCountLibrary, pipe.numGraphicsLibraries); 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()); std::lock_guard<sync::Spinlock> lock(m_statLock); diff --git a/src/dxvk/dxvk_pipemanager.cpp b/src/dxvk/dxvk_pipemanager.cpp index b6443975..40c20cf8 100644 --- a/src/dxvk/dxvk_pipemanager.cpp +++ b/src/dxvk/dxvk_pipemanager.cpp @@ -24,7 +24,7 @@ namespace dxvk { std::unique_lock lock(m_lock); this->startWorkers(); - m_pendingTasks += 1; + m_tasksTotal += 1; m_buckets[uint32_t(priority)].queue.emplace(library); notifyWorkers(priority); @@ -39,18 +39,13 @@ namespace dxvk { this->startWorkers(); pipeline->acquirePipeline(); - m_pendingTasks += 1; + m_tasksTotal += 1; m_buckets[uint32_t(priority)].queue.emplace(pipeline, state); notifyWorkers(priority); } - bool DxvkPipelineWorkers::isBusy() const { - return m_pendingTasks.load() != 0ull; - } - - void DxvkPipelineWorkers::stopWorkers() { { std::unique_lock lock(m_lock); @@ -164,12 +159,12 @@ namespace dxvk { if (entry.pipelineLibrary) { entry.pipelineLibrary->compilePipeline(); - m_pendingTasks -= 1; } else if (entry.graphicsPipeline) { entry.graphicsPipeline->compilePipeline(entry.graphicsState); entry.graphicsPipeline->releasePipeline(); - m_pendingTasks -= 1; } + + m_tasksCompleted += 1; } } diff --git a/src/dxvk/dxvk_pipemanager.h b/src/dxvk/dxvk_pipemanager.h index 033e37ee..36801aef 100644 --- a/src/dxvk/dxvk_pipemanager.h +++ b/src/dxvk/dxvk_pipemanager.h @@ -34,6 +34,11 @@ namespace dxvk { std::atomic<uint32_t> numComputePipelines = { 0u }; }; + struct DxvkPipelineWorkerStats { + uint64_t tasksCompleted; + uint64_t tasksTotal; + }; + /** * \brief Pipeline priority */ @@ -59,6 +64,19 @@ namespace dxvk { ~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 * * Asynchronously compiles a basic variant of @@ -83,12 +101,6 @@ namespace dxvk { DxvkPipelinePriority priority); /** - * \brief Checks whether workers are busy - * \returns \c true if there is unfinished work - */ - bool isBusy() const; - - /** * \brief Stops all worker threads * * Stops threads and waits for their current work @@ -121,7 +133,8 @@ namespace dxvk { 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; std::array<PipelineBucket, 3> m_buckets; @@ -242,8 +255,8 @@ namespace dxvk { * \brief Checks whether async compiler is busy * \returns \c true if shaders are being compiled */ - bool isCompilingShaders() const { - return m_workers.isBusy(); + DxvkPipelineWorkerStats getWorkerStats() const { + return m_workers.getStats(); } /** diff --git a/src/dxvk/dxvk_stats.h b/src/dxvk/dxvk_stats.h index 211570f5..91c83701 100644 --- a/src/dxvk/dxvk_stats.h +++ b/src/dxvk/dxvk_stats.h @@ -18,7 +18,8 @@ namespace dxvk { PipeCountGraphics, ///< Number of graphics pipelines PipeCountLibrary, ///< Number of graphics shader libraries 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 QueuePresentCount, ///< Number of present calls / frames GpuSyncCount, ///< Number of GPU synchronizations diff --git a/src/dxvk/hud/dxvk_hud_item.cpp b/src/dxvk/hud/dxvk_hud_item.cpp index 4b7b0ea5..40707d64 100644 --- a/src/dxvk/hud/dxvk_hud_item.cpp +++ b/src/dxvk/hud/dxvk_hud_item.cpp @@ -755,15 +755,36 @@ namespace dxvk::hud { void HudCompilerActivityItem::update(dxvk::high_resolution_clock::time_point time) { DxvkStatCounters counters = m_device->getStatCounters(); - bool doShow = counters.getCtr(DxvkStatCounter::PipeCompilerBusy); - if (!doShow) { - auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(time - m_timeShown); - doShow = elapsed.count() <= MinShowDuration; - } + m_tasksDone = counters.getCtr(DxvkStatCounter::PipeTasksDone); + m_tasksTotal = counters.getCtr(DxvkStatCounter::PipeTasksTotal); + + bool doShow = m_tasksDone < m_tasksTotal; - if (doShow && !m_show) + if (!doShow) + m_timeDone = time; + + if (!m_show) { 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; } @@ -773,13 +794,27 @@ namespace dxvk::hud { HudRenderer& renderer, HudPos position) { if (m_show) { + std::string string = "Compiling shaders..."; + + if (m_showPercentage) + string = str::format(string, " (", computePercentage(), "%)"); + renderer.drawText(16.0f, { position.x, renderer.surfaceSize().height / renderer.scale() - 20.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, - "Compiling shaders..."); + string); } 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)); + } + } diff --git a/src/dxvk/hud/dxvk_hud_item.h b/src/dxvk/hud/dxvk_hud_item.h index b91f4d71..18f75054 100644 --- a/src/dxvk/hud/dxvk_hud_item.h +++ b/src/dxvk/hud/dxvk_hud_item.h @@ -482,10 +482,17 @@ namespace dxvk::hud { Rc<DxvkDevice> m_device; - bool m_show = false; + bool m_show = false; + bool m_showPercentage = false; - dxvk::high_resolution_clock::time_point m_timeShown - = dxvk::high_resolution_clock::now(); + uint64_t m_tasksDone = 0ull; + 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; }; |