mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
feat: add an in-game performance panel (#1090)
Add in-game performance panel Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
committed by
GitHub
parent
415387f00d
commit
6aa3846fb2
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <vk_mem_alloc.h>
|
||||
@@ -99,6 +100,14 @@ struct GraphicContext {
|
||||
[[nodiscard]] bool CanReportMemoryUsage() const noexcept { return memory_budget_ext_enabled; }
|
||||
[[nodiscard]] uint64_t GetDeviceMemoryUsage() const;
|
||||
[[nodiscard]] uint64_t GetTotalMemoryBudget() const;
|
||||
|
||||
struct HeapUsage {
|
||||
uint64_t usage = 0; // Whole process, as reported by VK_EXT_memory_budget.
|
||||
uint64_t budget = 0;
|
||||
uint32_t allocations = 0;
|
||||
bool device_local = false;
|
||||
};
|
||||
[[nodiscard]] uint32_t GetHeapUsage(std::span<HeapUsage, VK_MAX_MEMORY_HEAPS> heaps) const;
|
||||
[[nodiscard]] bool CreateImage(const vk::ImageCreateInfo& info, VulkanImage& image);
|
||||
void DeleteImage(VulkanImage& image);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/profiler.h"
|
||||
#include "graphics/guest_gpu/graphicsRun.h"
|
||||
@@ -177,6 +178,7 @@ bool BufferCache::DownloadBufferMemory(Buffer& buffer, uint64_t vaddr, uint64_t
|
||||
if (copies.empty()) {
|
||||
return false;
|
||||
}
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::BufferDownloadBytes, total_size);
|
||||
|
||||
auto [mapped, offset] = m_download_buffer.Map(total_size, 64);
|
||||
std::unique_ptr<Buffer> temporary;
|
||||
@@ -467,6 +469,7 @@ vk::Buffer BufferCache::UploadCopies(Buffer& buffer, std::span<vk::BufferCopy> c
|
||||
if (copies.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::BufferUploadBytes, total_size);
|
||||
|
||||
const auto source = UploadMemory(m_graphics, m_scheduler, m_staging_buffer, total_size, 4,
|
||||
vk::BufferUsageFlagBits::eTransferSrc, [&](uint8_t* mapped, uint64_t base_offset) {
|
||||
@@ -658,6 +661,7 @@ void BufferCache::RunGarbageCollector() {
|
||||
} else {
|
||||
m_memory_tracker.UntrackMemory(buffer.CpuAddress(), buffer.Size());
|
||||
DeleteBuffer(id);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::BufferEvictions);
|
||||
}
|
||||
return ++retire_count == limit;
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/profiler.h"
|
||||
@@ -954,6 +955,7 @@ void TextureCache::UploadImage(Image& image, Buffer& source, uint64_t source_off
|
||||
const auto linear = m_tiler.Detile(source.Handle(), source_offset, info);
|
||||
const auto copies = info.BufferCopies(linear.offset);
|
||||
destination.Upload(copies, linear.buffer, linear.offset, linear.size);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::TextureUploadBytes, linear.size);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -999,6 +1001,7 @@ void TextureCache::UploadImage(Image& image, Buffer& source, uint64_t source_off
|
||||
copies[0].imageExtent = info.extent;
|
||||
}
|
||||
destination.Upload(copies, linear.buffer, linear.offset, linear.size);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::TextureUploadBytes, linear.size);
|
||||
}
|
||||
|
||||
void TextureCache::InitializeImage(ImageId id) {
|
||||
@@ -1774,6 +1777,7 @@ bool TextureCache::DownloadImageMemory(ImageId id) {
|
||||
download.Flush(offset, range.size);
|
||||
|
||||
DownloadImage(image, download, offset, range.size, image.info.resources.levels);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::TextureDownloadBytes, range.size);
|
||||
vk::BufferMemoryBarrier barrier {};
|
||||
barrier.srcAccessMask = vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eTransferWrite |
|
||||
vk::AccessFlagBits::eShaderWrite;
|
||||
@@ -1943,6 +1947,7 @@ void TextureCache::RunGarbageCollector() {
|
||||
}
|
||||
}
|
||||
FreeImage(id);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::TextureEvictions);
|
||||
if (m_total_used_memory < m_critical_gc_memory && aggressive) {
|
||||
deletions >>= 2;
|
||||
aggressive = false;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "graphics/host_gpu/renderer/commandScheduler.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
|
||||
@@ -373,6 +374,7 @@ uint64_t CommandScheduler::Submit(SubmitInfo submit) {
|
||||
|
||||
result = graphics.queue.submit(1, &submit_info, nullptr);
|
||||
}
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::QueueSubmits);
|
||||
|
||||
if (result != vk::Result::eSuccess) {
|
||||
ReportVulkanFatal("vkQueueSubmit", result, tick, m_command.m_debug_op,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "graphics/host_gpu/renderer/masterSemaphore.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
|
||||
namespace Libs::Graphics {
|
||||
@@ -49,6 +50,8 @@ void MasterSemaphore::Wait(uint64_t tick) {
|
||||
wait_info.pSemaphores = &m_semaphore;
|
||||
wait_info.pValues = &tick;
|
||||
|
||||
Common::DebugCounters::ScopedTimer timer(Common::DebugCounters::Counter::GpuWaits,
|
||||
Common::DebugCounters::Counter::GpuWaitNs);
|
||||
const auto result = m_graphics.device.waitSemaphores(&wait_info, UINT64_MAX);
|
||||
EXIT_NOT_IMPLEMENTED(result != vk::Result::eSuccess);
|
||||
Refresh();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "graphics/host_gpu/renderer/pipeline/pipelineCache.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/file.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -24,6 +25,7 @@
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fmt/format.h>
|
||||
@@ -299,6 +301,9 @@ struct PipelineCache::ProgramCache {
|
||||
ShaderRecompiler::IR::ResourceSpecialization specialization,
|
||||
uint32_t push_data_start_dword,
|
||||
std::span<const uint32_t> function_code) {
|
||||
Common::DebugCounters::ScopedTimer timer(Common::DebugCounters::Counter::ShadersCompiled,
|
||||
Common::DebugCounters::Counter::ShaderCompileNs,
|
||||
Common::DebugCounters::Peak::ShaderCompileNs);
|
||||
auto result = ShaderRecompiler::CompileProgram(std::move(translated), options,
|
||||
specialization, push_data_start_dword);
|
||||
if (!ValidateShaderSpirv(options.dump_label, options.shader_hash, result.spirv,
|
||||
@@ -993,8 +998,13 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
|
||||
auto cached = std::make_unique<Pipeline>();
|
||||
LogPipelineTrace("CreatePipelineInternal begin", vs_id, ps_id);
|
||||
CreatePipelineInternal(m_graphics, *cached, rendering, key.vertex_input, vertex_info,
|
||||
ps_input_info, programs, static_params, m_driver_cache);
|
||||
{
|
||||
Common::DebugCounters::ScopedTimer timer(Common::DebugCounters::Counter::PipelinesCreated,
|
||||
Common::DebugCounters::Counter::PipelineCreateNs,
|
||||
Common::DebugCounters::Peak::PipelineCreateNs);
|
||||
CreatePipelineInternal(m_graphics, *cached, rendering, key.vertex_input, vertex_info,
|
||||
ps_input_info, programs, static_params, m_driver_cache);
|
||||
}
|
||||
LogPipelineTrace("CreatePipelineInternal done", vs_id, ps_id);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline == nullptr);
|
||||
@@ -1024,7 +1034,13 @@ PipelineCache::GetComputePipeline(const ShaderComputeInputInfo& input_info,
|
||||
}
|
||||
|
||||
auto cached = std::make_unique<Pipeline>();
|
||||
CreatePipelineInternal(m_graphics, *cached, input_info, compute_program.module, m_driver_cache);
|
||||
{
|
||||
Common::DebugCounters::ScopedTimer timer(Common::DebugCounters::Counter::PipelinesCreated,
|
||||
Common::DebugCounters::Counter::PipelineCreateNs,
|
||||
Common::DebugCounters::Peak::PipelineCreateNs);
|
||||
CreatePipelineInternal(m_graphics, *cached, input_info, compute_program.module,
|
||||
m_driver_cache);
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(cached->pipeline_layout == nullptr);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/file.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -432,6 +433,7 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, CommandBuffer& buffer,
|
||||
|
||||
vk_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.pipeline);
|
||||
vk_buffer.dispatch(thread_group_x, thread_group_y, thread_group_z);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::Dispatches);
|
||||
|
||||
// The removed host fence also ordered read-only dispatches before later writers.
|
||||
ShaderAccessBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader);
|
||||
@@ -501,6 +503,7 @@ void RenderExecutor::DispatchIndirect(uint64_t submit_id, CommandBuffer& buffer,
|
||||
1, &barrier, 0, nullptr, 0, nullptr);
|
||||
vk_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.pipeline);
|
||||
vk_buffer.dispatchIndirect(args_buffer->Handle(), args_offset);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::Dispatches);
|
||||
ShaderAccessBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader);
|
||||
ResetBindings();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/debugCounters.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/file.h"
|
||||
#include "common/logging/log.h"
|
||||
@@ -1233,6 +1234,8 @@ void RenderExecutor::ExecutePreparedDraw(uint64_t submit_id, CommandBuffer& buff
|
||||
} else {
|
||||
EmitDrawPrimitives(ucfg, vk_buffer, draw, emit);
|
||||
}
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::Draws);
|
||||
Common::DebugCounters::Add(Common::DebugCounters::Counter::DrawInstances, draw.instance_count);
|
||||
|
||||
if (!draw.IsIndexed()) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x600u);
|
||||
|
||||
@@ -97,6 +97,24 @@ uint64_t GraphicContext::GetDeviceMemoryUsage() const {
|
||||
return usage;
|
||||
}
|
||||
|
||||
uint32_t GraphicContext::GetHeapUsage(std::span<HeapUsage, VK_MAX_MEMORY_HEAPS> heaps) const {
|
||||
if (allocator == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
VmaBudget budgets[VK_MAX_MEMORY_HEAPS] {};
|
||||
vmaGetHeapBudgets(allocator, budgets);
|
||||
const auto count = physical_device_memory_properties.memoryHeapCount;
|
||||
for (uint32_t heap = 0; heap < count; heap++) {
|
||||
const auto& properties = physical_device_memory_properties.memoryHeaps[heap];
|
||||
heaps[heap] = {.usage = budgets[heap].usage,
|
||||
.budget = budgets[heap].budget,
|
||||
.allocations = budgets[heap].statistics.allocationCount,
|
||||
.device_local = static_cast<bool>(properties.flags &
|
||||
vk::MemoryHeapFlagBits::eDeviceLocal)};
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
uint64_t GraphicContext::GetTotalMemoryBudget() const {
|
||||
if (allocator == nullptr) {
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user