mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-13 07:08:50 +01:00
[hud] Display approximate progress when compiling shaders
This commit is contained in:
parent
c978e62ec8
commit
3a84838ac4
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
m_tasksDone = counters.getCtr(DxvkStatCounter::PipeTasksDone);
|
||||
m_tasksTotal = counters.getCtr(DxvkStatCounter::PipeTasksTotal);
|
||||
|
||||
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) {
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(time - m_timeShown);
|
||||
doShow = elapsed.count() <= MinShowDuration;
|
||||
m_offset = m_tasksTotal;
|
||||
|
||||
// Ensure the item stays up long enough to be legible
|
||||
doShow = durationShown.count() <= MinShowDuration;
|
||||
}
|
||||
|
||||
if (doShow && !m_show)
|
||||
m_timeShown = time;
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -483,9 +483,16 @@ namespace dxvk::hud {
|
||||
Rc<DxvkDevice> m_device;
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user