aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 23:07:49 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 23:07:49 -0400
commit571f9b58eb8a9c102a91a5d26cd32ebae4330232 (patch)
tree989c5032c268044452d7ad7c324b147c964227e9 /src/video_core/renderer_vulkan
parent808039e5806dc841a30ef7d887462635860ae291 (diff)
nx2: GPU-thread zone timers and an in-process sampling profiler
EDEN_NX2_GPU_PROFILE=1 times the GPU thread's stages (command parsing, macros, draw setup by step, compute, texture uploads) and logs each one's share of every second. EDEN_NX2_SAMPLE=<thread names> (Windows) pauses the named threads about 600 times a second for EDEN_NX2_SAMPLE_SECONDS, walks their stacks and writes per-function counts plus folded stacks (EDEN_NX2_SAMPLE_OUT).
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp109
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp30
2 files changed, 94 insertions, 45 deletions
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 172ee4dcaa..f737ad9f70 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -29,6 +29,7 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "common/settings.h"
+#include "video_core/nx2_profile.h"
#if defined(_MSC_VER) && defined(NDEBUG)
#define LAMBDA_FORCEINLINE [[msvc::forceinline]]
@@ -355,7 +356,11 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
views.reserve(num_image_elements);
samplers.reserve(num_textures);
- texture_cache.SynchronizeDescriptors(false);
+ namespace Profile = VideoCommon::Nx2Profile;
+ {
+ Profile::Scope scope{Profile::Zone::SyncDescriptors};
+ texture_cache.SynchronizeDescriptors(false);
+ }
buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes);
@@ -432,24 +437,31 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
return true;
}};
- if constexpr (Spec::enabled_stages[0]) {
- config_stage(0);
- }
- if constexpr (Spec::enabled_stages[1]) {
- config_stage(1);
- }
- if constexpr (Spec::enabled_stages[2]) {
- config_stage(2);
- }
- if constexpr (Spec::enabled_stages[3]) {
- config_stage(3);
- }
- if constexpr (Spec::enabled_stages[4]) {
- config_stage(4);
+ {
+ Profile::Scope scope{Profile::Zone::ReadHandles};
+ if constexpr (Spec::enabled_stages[0]) {
+ config_stage(0);
+ }
+ if constexpr (Spec::enabled_stages[1]) {
+ config_stage(1);
+ }
+ if constexpr (Spec::enabled_stages[2]) {
+ config_stage(2);
+ }
+ if constexpr (Spec::enabled_stages[3]) {
+ config_stage(3);
+ }
+ if constexpr (Spec::enabled_stages[4]) {
+ config_stage(4);
+ }
}
ASSERT(views.size() == num_image_elements);
ASSERT(samplers.size() == num_textures);
- texture_cache.FillImageViews(std::span(views.data(), views.size()), false, Spec::has_images);
+ {
+ Profile::Scope scope{Profile::Zone::FillImageViews};
+ texture_cache.FillImageViews(std::span(views.data(), views.size()), false,
+ Spec::has_images);
+ }
VideoCommon::ImageViewInOut* texture_buffer_it{views.data()};
const auto bind_stage_info{[&](size_t stage) LAMBDA_FORCEINLINE {
@@ -493,39 +505,54 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
texture_buffer_it += Shader::NumDescriptors(info.image_descriptors);
}
}};
- if constexpr (Spec::enabled_stages[0]) {
- bind_stage_info(0);
- }
- if constexpr (Spec::enabled_stages[1]) {
- bind_stage_info(1);
- }
- if constexpr (Spec::enabled_stages[2]) {
- bind_stage_info(2);
- }
- if constexpr (Spec::enabled_stages[3]) {
- bind_stage_info(3);
- }
- if constexpr (Spec::enabled_stages[4]) {
- bind_stage_info(4);
+ {
+ Profile::Scope scope{Profile::Zone::TextureBuffers};
+ if constexpr (Spec::enabled_stages[0]) {
+ bind_stage_info(0);
+ }
+ if constexpr (Spec::enabled_stages[1]) {
+ bind_stage_info(1);
+ }
+ if constexpr (Spec::enabled_stages[2]) {
+ bind_stage_info(2);
+ }
+ if constexpr (Spec::enabled_stages[3]) {
+ bind_stage_info(3);
+ }
+ if constexpr (Spec::enabled_stages[4]) {
+ bind_stage_info(4);
+ }
}
if (regs.transform_feedback_enabled != 0) {
scheduler.RequestOutsideRenderPassOperationContext();
}
- buffer_cache.UpdateGraphicsBuffers(is_indexed);
- buffer_cache.BindHostGeometryBuffers(is_indexed);
+ {
+ Profile::Scope scope{Profile::Zone::UpdateBuffers};
+ buffer_cache.UpdateGraphicsBuffers(is_indexed);
+ buffer_cache.BindHostGeometryBuffers(is_indexed);
+ }
- guest_descriptor_queue.Acquire(scheduler, num_descriptor_entries, uses_descriptor_buffer);
+ {
+ Profile::Scope scope{Profile::Zone::DescriptorAcquire};
+ guest_descriptor_queue.Acquire(scheduler, num_descriptor_entries, uses_descriptor_buffer);
+ }
RescalingPushConstant rescaling;
RenderAreaPushConstant render_area;
const VideoCommon::SamplerId* samplers_it{samplers.data()};
const VideoCommon::ImageViewInOut* views_it{views.data()};
const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
- buffer_cache.BindHostStageBuffers(stage);
- PushImageDescriptors(texture_cache, guest_descriptor_queue, stage_infos[stage], rescaling,
- samplers_it, views_it);
+ {
+ Profile::Scope scope{Profile::Zone::BindStageBuffers};
+ buffer_cache.BindHostStageBuffers(stage);
+ }
+ {
+ Profile::Scope scope{Profile::Zone::PushDescriptors};
+ PushImageDescriptors(texture_cache, guest_descriptor_queue, stage_infos[stage],
+ rescaling, samplers_it, views_it);
+ }
const auto& info{stage_infos[stage]};
if (info.uses_render_area) {
render_area.uses_render_area = true;
@@ -555,12 +582,16 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
buffer_cache.runtime.PostCopyBarrier();
buffer_cache.any_buffer_uploaded = false;
}
- texture_cache.UpdateRenderTargets(false);
- texture_cache.CheckFeedbackLoop(std::span<const VideoCommon::ImageViewInOut>{views.data(),
- views.size()});
+ {
+ Profile::Scope scope{Profile::Zone::RenderTargets};
+ texture_cache.UpdateRenderTargets(false);
+ texture_cache.CheckFeedbackLoop(
+ std::span<const VideoCommon::ImageViewInOut>{views.data(), views.size()});
+ }
if (IsBuilt() && !pipeline) {
return false;
}
+ Profile::Scope scope{Profile::Zone::ConfigureDraw};
return ConfigureDraw(rescaling, render_area);
}
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 609ac12fb4..decfb0d136 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -49,6 +49,7 @@
#include "video_core/texture_cache/texture_cache_base.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
+#include "video_core/nx2_profile.h"
namespace Vulkan {
@@ -253,8 +254,12 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
LOG_DEBUG(HW_GPU, "Native graphics draw failed; refusing submission completion");
}
};
- FlushWork();
- gpu_memory->FlushCaching();
+ namespace Profile = VideoCommon::Nx2Profile;
+ {
+ Profile::Scope scope{Profile::Zone::FlushWork};
+ FlushWork();
+ gpu_memory->FlushCaching();
+ }
const auto report_failure = [&](std::string_view reason) {
static std::set<std::tuple<u64, u64, std::string_view>> seen;
@@ -266,7 +271,10 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
regs.rt[0].Address(), regs.rt[0].width, regs.rt[0].height);
}
};
- GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()};
+ GraphicsPipeline* const pipeline{[&] {
+ Profile::Scope scope{Profile::Zone::PipelineLookup};
+ return pipeline_cache.CurrentGraphicsPipeline();
+ }()};
if (!pipeline) {
report_failure("no pipeline");
return;
@@ -274,17 +282,23 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
// update engine as channel may be different.
pipeline->SetEngine(maxwell3d, gpu_memory);
- if (!pipeline->Configure(is_indexed)) {
+ if (Profile::Scope scope{Profile::Zone::Configure}; !pipeline->Configure(is_indexed)) {
report_failure("configure failed");
return;
}
- UpdateDynamicStates();
+ {
+ Profile::Scope scope{Profile::Zone::DynamicState};
+ UpdateDynamicStates();
+ }
query_cache.NotifySegment(true);
HandleTransformFeedback();
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, maxwell3d->regs.zpass_pixel_count_enable);
- draw_func();
+ {
+ Profile::Scope scope{Profile::Zone::DrawRecord};
+ draw_func();
+ }
submitted = true;
static u32 native_capture_count{};
if (maxwell3d->GetNativeMacroEngine().native_turing &&
@@ -412,6 +426,7 @@ void TraceWindowTarget(const Tegra::Engines::Maxwell3D& maxwell3d, Tegra::Memory
} // Anonymous namespace
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
+ VideoCommon::Nx2Profile::Scope profile_scope{VideoCommon::Nx2Profile::Zone::Draw};
TraceWindowTarget(*maxwell3d, *gpu_memory, is_indexed ? "draw-indexed" : "draw",
is_indexed ? maxwell3d->draw_manager.draw_state.index_buffer.count
: maxwell3d->draw_manager.draw_state.vertex_buffer.count);
@@ -554,6 +569,7 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
}
void RasterizerVulkan::DrawIndirect() {
+ VideoCommon::Nx2Profile::Scope profile_scope{VideoCommon::Nx2Profile::Zone::Draw};
const auto& params = maxwell3d->draw_manager.indirect_state;
buffer_cache.SetDrawIndirect(&params);
PrepareDraw(params.is_indexed, [this, &params] {
@@ -659,6 +675,7 @@ void RasterizerVulkan::DrawTexture() {
}
void RasterizerVulkan::Clear(u32 layer_count) {
+ VideoCommon::Nx2Profile::Scope profile_scope{VideoCommon::Nx2Profile::Zone::Clear};
if (Tegra::Engines::g_nx2_trace_draws_after_upscale > 0) {
const auto& regs = maxwell3d->regs;
LOG_INFO(HW_GPU, "after upscale: clear rt0 {:#x} {}x{} fmt {:#x} surface {:#x} colour {} {} {} {}",
@@ -852,6 +869,7 @@ void RasterizerVulkan::Clear(u32 layer_count) {
}
void RasterizerVulkan::DispatchCompute() {
+ VideoCommon::Nx2Profile::Scope profile_scope{VideoCommon::Nx2Profile::Zone::Compute};
FlushWork();
gpu_memory->FlushCaching();