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() {
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);

View File

@ -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;
}
}

View File

@ -34,6 +34,11 @@ namespace dxvk {
std::atomic<uint32_t> numComputePipelines = { 0u };
};
struct DxvkPipelineWorkerStats {
uint64_t tasksCompleted;
uint64_t tasksTotal;
};
/**
* \brief Pipeline priority
*/
@ -58,6 +63,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
*
@ -82,12 +100,6 @@ namespace dxvk {
const DxvkGraphicsPipelineStateInfo& state,
DxvkPipelinePriority priority);
/**
* \brief Checks whether workers are busy
* \returns \c true if there is unfinished work
*/
bool isBusy() const;
/**
* \brief Stops all worker threads
*
@ -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();
}
/**

View File

@ -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

View File

@ -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);
if (doShow && !m_show)
bool doShow = m_tasksDone < m_tasksTotal;
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));
}
}

View File

@ -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;
};