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:
parent
c978e62ec8
commit
3a84838ac4
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user