Skip to content

Commit de128ba

Browse files
committed
Squashed commit of the following:
commit 8f8f51cadfd80d618c388a368b118cb95a3c4e5b Author: DoubleStyx <79298541+DoubleStyx@users.noreply.github.com> Date: Mon Jun 15 18:46:04 2026 -0500 Unify debug HUD diagnostics under Stats commit 3d45205eb860473f645bad3c8476f474903ba5e8 Author: DoubleStyx <79298541+DoubleStyx@users.noreply.github.com> Date: Mon Jun 15 15:28:17 2026 -0500 Expand debug HUD renderer diagnostics
1 parent 03b605a commit de128ba

37 files changed

Lines changed: 1775 additions & 65 deletions

crates/renderide/src/backend/debug_hud_bundle.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::diagnostics::{
88
DebugHud, DebugHudInput, DebugHudOverlayContext, FrameDiagnosticsSnapshot,
99
FrameTimingHudSnapshot, RendererInfoSnapshot, SceneTransformsSnapshot, TextureDebugSnapshot,
1010
};
11+
use crate::hud_contract::WorldMeshViewHudStats;
1112
use crate::hud_contract::{DebugHudEncodeError, PerViewHudConfig, PerViewHudOutputs};
1213
use crate::world_mesh::{WorldMeshDrawStateRow, WorldMeshDrawStats};
1314

@@ -19,8 +20,10 @@ pub struct DebugHudBundle {
1920
want_capture_mouse: bool,
2021
want_capture_keyboard: bool,
2122
last_world_mesh_draw_stats: WorldMeshDrawStats,
23+
last_world_mesh_view_stats: Vec<WorldMeshViewHudStats>,
2224
last_world_mesh_draw_state_rows: Vec<WorldMeshDrawStateRow>,
2325
per_view_config: PerViewHudConfig,
26+
capture_graph_command_diagnostics: bool,
2427
current_view_texture_2d_asset_ids: BTreeSet<i32>,
2528
}
2629

@@ -40,8 +43,10 @@ impl DebugHudBundle {
4043
want_capture_mouse: false,
4144
want_capture_keyboard: false,
4245
last_world_mesh_draw_stats: WorldMeshDrawStats::default(),
46+
last_world_mesh_view_stats: Vec::new(),
4347
last_world_mesh_draw_state_rows: Vec::new(),
4448
per_view_config: PerViewHudConfig::default(),
49+
capture_graph_command_diagnostics: false,
4550
current_view_texture_2d_asset_ids: BTreeSet::new(),
4651
}
4752
}
@@ -71,6 +76,9 @@ impl DebugHudBundle {
7176
if !config.capture_world_mesh_draw_stats {
7277
self.last_world_mesh_draw_stats = WorldMeshDrawStats::default();
7378
}
79+
if !config.capture_world_mesh_view_stats {
80+
self.last_world_mesh_view_stats.clear();
81+
}
7482
if !config.capture_world_mesh_draw_state_rows {
7583
self.last_world_mesh_draw_state_rows.clear();
7684
}
@@ -85,6 +93,16 @@ impl DebugHudBundle {
8593
self.per_view_config
8694
}
8795

96+
/// Updates whether graph execution should publish HUD-formatted command diagnostics.
97+
pub(crate) fn set_capture_graph_command_diagnostics(&mut self, capture: bool) {
98+
self.capture_graph_command_diagnostics = capture;
99+
}
100+
101+
/// Returns whether graph execution should publish HUD-formatted command diagnostics.
102+
pub(crate) fn capture_graph_command_diagnostics(&self) -> bool {
103+
self.capture_graph_command_diagnostics
104+
}
105+
88106
/// Clears the current-view Texture2D id set before collecting this frame's submitted draws.
89107
pub(crate) fn clear_current_view_texture_2d_asset_ids(&mut self) {
90108
self.current_view_texture_2d_asset_ids.clear();
@@ -104,6 +122,9 @@ impl DebugHudBundle {
104122
if let Some(stats) = outputs.world_mesh_draw_stats.as_ref() {
105123
self.set_last_world_mesh_draw_stats(stats);
106124
}
125+
if let Some(view_stats) = outputs.world_mesh_view_stats.as_ref() {
126+
self.set_last_world_mesh_view_stats(view_stats.clone());
127+
}
107128
if let Some(rows) = outputs.world_mesh_draw_state_rows.clone() {
108129
self.set_last_world_mesh_draw_state_rows(rows);
109130
}
@@ -205,6 +226,22 @@ impl DebugHudBundle {
205226
self.last_world_mesh_draw_stats
206227
}
207228

229+
pub(crate) fn set_last_world_mesh_view_stats(&mut self, stats: WorldMeshViewHudStats) {
230+
if let Some(existing) = self
231+
.last_world_mesh_view_stats
232+
.iter_mut()
233+
.find(|existing| existing.view_id == stats.view_id)
234+
{
235+
*existing = stats;
236+
} else {
237+
self.last_world_mesh_view_stats.push(stats);
238+
}
239+
}
240+
241+
pub(crate) fn last_world_mesh_view_stats(&self) -> Vec<WorldMeshViewHudStats> {
242+
self.last_world_mesh_view_stats.clone()
243+
}
244+
208245
pub(crate) fn set_last_world_mesh_draw_state_rows(&mut self, rows: Vec<WorldMeshDrawStateRow>) {
209246
self.last_world_mesh_draw_state_rows = rows;
210247
}

crates/renderide/src/backend/facade.rs

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -466,26 +466,99 @@ impl RenderBackend {
466466
snapshot.last_world_mesh_draw_state_rows = self.last_world_mesh_draw_state_rows();
467467
}
468468

469-
if !interest.wants_stats() {
470-
return snapshot;
469+
if interest.wants_stats() {
470+
self.populate_stats_diagnostics_snapshot(&mut snapshot);
471471
}
472472

473+
if interest.wants_graph() {
474+
snapshot.command_encoding = self.graph_state.latest_command_encoding();
475+
}
476+
477+
if interest.wants_assets() {
478+
self.populate_asset_diagnostics_snapshot(&mut snapshot);
479+
}
480+
481+
if interest.wants_visibility() {
482+
self.populate_visibility_diagnostics_snapshot(&mut snapshot);
483+
}
484+
485+
snapshot
486+
}
487+
488+
fn populate_asset_diagnostics_snapshot(
489+
&self,
490+
snapshot: &mut crate::diagnostics::BackendDiagSnapshot,
491+
) {
492+
let asset_diagnostics = self.asset_transfers.diagnostic_snapshot();
493+
let worker_diagnostics = crate::assets::worker::diagnostic_snapshot();
494+
let material_diagnostics = self.materials.diagnostic_snapshot();
495+
496+
snapshot.texture_format_registration_count = self.texture_format_registration_count();
497+
snapshot.texture_mip0_ready_count = self.texture_mip0_ready_count();
498+
snapshot.texture_pool_resident_count = self.texture_pool().len();
499+
snapshot.render_texture_pool_len = self.render_texture_pool().len();
500+
snapshot.mesh_pool_entry_count = self.mesh_pool().len();
501+
snapshot.assets = crate::diagnostics::AssetDiagnosticsSnapshot {
502+
main_queued: asset_diagnostics.integrator.main_queued,
503+
high_priority_queued: asset_diagnostics.integrator.high_priority_queued,
504+
render_queued: asset_diagnostics.integrator.render_queued,
505+
normal_priority_queued: asset_diagnostics.integrator.normal_priority_queued,
506+
particle_queued: asset_diagnostics.integrator.particle_queued,
507+
total_queued: asset_diagnostics.integrator.total_queued,
508+
peak_queued: asset_diagnostics.integrator.peak_queued,
509+
pending_mesh_uploads: asset_diagnostics.pending_mesh_uploads,
510+
pending_texture_uploads: asset_diagnostics.pending_texture_uploads,
511+
pending_texture3d_uploads: asset_diagnostics.pending_texture3d_uploads,
512+
pending_cubemap_uploads: asset_diagnostics.pending_cubemap_uploads,
513+
pending_video_texture_loads: asset_diagnostics.pending_video_texture_loads,
514+
worker_queued: worker_diagnostics.queued,
515+
worker_running: worker_diagnostics.running,
516+
worker_max_queued: worker_diagnostics.max_queued,
517+
worker_spawned: worker_diagnostics.spawned,
518+
worker_completed: worker_diagnostics.completed,
519+
worker_inline_executed: worker_diagnostics.inline_executed,
520+
worker_saturated: worker_diagnostics.saturated,
521+
pending_material_batches: material_diagnostics.pending_material_batches,
522+
pending_shader_routes: material_diagnostics.pending_shader_routes,
523+
material_registry_attached: material_diagnostics.material_registry_attached,
524+
embedded_bind_attached: material_diagnostics.embedded_bind_attached,
525+
};
526+
}
527+
528+
fn populate_visibility_diagnostics_snapshot(
529+
&self,
530+
snapshot: &mut crate::diagnostics::BackendDiagSnapshot,
531+
) {
532+
snapshot.last_world_mesh_draw_stats = self.last_world_mesh_draw_stats();
533+
snapshot.last_world_mesh_view_stats = self.last_world_mesh_view_stats();
534+
snapshot.gpu_light_count = self.frame_services.frame_resources.frame_lights().len();
535+
snapshot.signed_scene_color_active = self.signed_scene_color_active();
536+
snapshot.lights = self.light_diagnostics_snapshot();
537+
}
538+
539+
fn populate_stats_diagnostics_snapshot(
540+
&self,
541+
snapshot: &mut crate::diagnostics::BackendDiagSnapshot,
542+
) {
473543
let store = self.material_property_store();
474544
let material_diagnostics = self.materials.diagnostic_snapshot();
475545
let graph_stats = self
476546
.graph_state
477547
.frame_graph_cache
478548
.compile_stats()
479549
.unwrap_or_default();
480-
snapshot = crate::diagnostics::BackendDiagSnapshot {
550+
let shader_routes = std::mem::take(&mut snapshot.shader_routes);
551+
let draw_state_rows = std::mem::take(&mut snapshot.last_world_mesh_draw_state_rows);
552+
*snapshot = crate::diagnostics::BackendDiagSnapshot {
481553
texture_format_registration_count: self.texture_format_registration_count(),
482554
texture_mip0_ready_count: self.texture_mip0_ready_count(),
483555
texture_pool_resident_count: self.texture_pool().len(),
484556
render_texture_pool_len: self.render_texture_pool().len(),
485557
mesh_pool_entry_count: self.mesh_pool().len(),
486-
shader_routes: snapshot.shader_routes,
558+
shader_routes,
487559
last_world_mesh_draw_stats: self.last_world_mesh_draw_stats(),
488-
last_world_mesh_draw_state_rows: snapshot.last_world_mesh_draw_state_rows,
560+
last_world_mesh_view_stats: Vec::new(),
561+
last_world_mesh_draw_state_rows: draw_state_rows,
489562
render_world_maintenance: self.draw_preparation.render_world_maintenance_stats(),
490563
world_mesh_command_cache: self.draw_preparation.command_cache_stats(),
491564
world_mesh_instance_plan_cache: self
@@ -509,8 +582,31 @@ impl RenderBackend {
509582
gpu_light_count: self.frame_services.frame_resources.frame_lights().len(),
510583
signed_scene_color_active: self.signed_scene_color_active(),
511584
upload_arena: self.graph_state.latest_upload_stats().into(),
585+
command_encoding: Default::default(),
586+
assets: Default::default(),
587+
lights: Default::default(),
512588
};
513-
snapshot
589+
}
590+
591+
fn light_diagnostics_snapshot(&self) -> crate::diagnostics::LightDiagnosticsSnapshot {
592+
let light_visibility = self.frame_services.frame_resources.light_visibility_stats();
593+
crate::diagnostics::LightDiagnosticsSnapshot {
594+
packed_default_lights: self.frame_services.frame_resources.frame_lights().len(),
595+
per_view_light_packs: self
596+
.frame_services
597+
.frame_resources
598+
.per_view_light_pack_count(),
599+
max_per_view_lights: self
600+
.frame_services
601+
.frame_resources
602+
.max_per_view_light_count(),
603+
signed_scene_color_active: self.signed_scene_color_active(),
604+
visibility_indexed_lights: light_visibility.indexed_lights,
605+
visibility_fallback_lights: light_visibility.fallback_lights,
606+
visibility_rejected_lights: light_visibility.rejected_lights,
607+
visibility_bvh_queries: light_visibility.bvh_queries,
608+
visibility_linear_queries: light_visibility.linear_queries,
609+
}
514610
}
515611

516612
/// Mutable render-graph transient resource pool.
@@ -569,6 +665,7 @@ impl RenderBackend {
569665
history_registry,
570666
upload_arena,
571667
latest_upload_stats,
668+
latest_command_encoding,
572669
pending_transient_releases,
573670
) = self.graph_state.execution_resources_mut();
574671
let (frame_resources, mesh_preprocess, mesh_deform_scratch, skin_cache) =
@@ -586,6 +683,7 @@ impl RenderBackend {
586683
history_registry,
587684
upload_arena,
588685
latest_upload_stats,
686+
latest_command_encoding,
589687
pending_transient_releases,
590688
debug_hud: self.diagnostics.bundle_mut(),
591689
scene_color_format,

crates/renderide/src/backend/facade/diagnostics.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::diagnostics::{
88
DebugHudInput, FrameDiagnosticsSnapshot, FrameTimingHudSnapshot, RendererInfoSnapshot,
99
SceneTransformsSnapshot, TextureDebugSnapshot,
1010
};
11+
use crate::hud_contract::WorldMeshViewHudStats;
1112
use crate::hud_contract::{DebugHudEncodeError, PerViewHudConfig};
1213
use crate::world_mesh::{WorldMeshDrawStateRow, WorldMeshDrawStats};
1314

@@ -56,6 +57,12 @@ impl BackendDiagnostics {
5657
self.debug_hud.set_per_view_config(config);
5758
}
5859

60+
/// Updates whether graph execution should publish HUD-formatted command diagnostics.
61+
pub(super) fn set_capture_graph_command_diagnostics(&mut self, capture: bool) {
62+
self.debug_hud
63+
.set_capture_graph_command_diagnostics(capture);
64+
}
65+
5966
/// Clears the current-view Texture2D set.
6067
pub(super) fn clear_current_view_texture_2d_asset_ids(&mut self) {
6168
self.debug_hud.clear_current_view_texture_2d_asset_ids();
@@ -144,6 +151,11 @@ impl BackendDiagnostics {
144151
self.debug_hud.last_world_mesh_draw_stats()
145152
}
146153

154+
/// Last per-view world-mesh draw stats captured by the HUD.
155+
pub(super) fn last_world_mesh_view_stats(&self) -> Vec<WorldMeshViewHudStats> {
156+
self.debug_hud.last_world_mesh_view_stats()
157+
}
158+
147159
/// Last world-mesh draw state rows captured by the HUD.
148160
pub(super) fn last_world_mesh_draw_state_rows(&self) -> Vec<WorldMeshDrawStateRow> {
149161
self.debug_hud.last_world_mesh_draw_state_rows()

crates/renderide/src/backend/facade/graph_access.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub(crate) struct BackendGraphAccess<'a> {
7676
pub(crate) upload_arena: &'a mut PersistentUploadArena,
7777
/// Latest frame-upload stats published for diagnostics.
7878
pub(crate) latest_upload_stats: &'a mut FrameUploadBatchStats,
79+
/// Latest graph command-recording stats published for diagnostics.
80+
pub(crate) latest_command_encoding: &'a mut crate::render_graph::CommandEncodingHudSnapshot,
7981
/// Resolved transient resource sets waiting on driver submit before pool release.
8082
pub(super) pending_transient_releases: &'a mut Vec<PendingTransientRelease>,
8183
/// Debug HUD state and encoder.
@@ -173,6 +175,14 @@ impl<'a> BackendGraphAccess<'a> {
173175
*self.latest_upload_stats = stats;
174176
}
175177

178+
/// Publishes graph command recording stats for diagnostics.
179+
pub(crate) fn record_command_encoding_diagnostics(
180+
&mut self,
181+
snapshot: crate::render_graph::CommandEncodingHudSnapshot,
182+
) {
183+
*self.latest_command_encoding = snapshot;
184+
}
185+
176186
/// Scene-color format snapshot selected for this graph frame.
177187
pub(crate) fn scene_color_format_wgpu(&self) -> wgpu::TextureFormat {
178188
self.scene_color_format
@@ -228,6 +238,11 @@ impl<'a> BackendGraphAccess<'a> {
228238
self.debug_hud.per_view_config()
229239
}
230240

241+
/// Whether graph execution should publish HUD-formatted command diagnostics.
242+
pub(crate) fn capture_graph_command_diagnostics(&self) -> bool {
243+
self.debug_hud.capture_graph_command_diagnostics()
244+
}
245+
231246
/// Whether the HUD will draw visible content this frame.
232247
pub(crate) fn debug_hud_has_visible_content(&self) -> bool {
233248
self.debug_hud.has_visible_content()
@@ -311,6 +326,17 @@ impl GraphExecutionBackend for BackendGraphAccess<'_> {
311326
BackendGraphAccess::record_frame_upload_stats(self, stats);
312327
}
313328

329+
fn record_command_encoding_diagnostics(
330+
&mut self,
331+
snapshot: crate::render_graph::CommandEncodingHudSnapshot,
332+
) {
333+
BackendGraphAccess::record_command_encoding_diagnostics(self, snapshot);
334+
}
335+
336+
fn capture_graph_command_diagnostics(&self) -> bool {
337+
BackendGraphAccess::capture_graph_command_diagnostics(self)
338+
}
339+
314340
fn scene_color_format_wgpu(&self) -> wgpu::TextureFormat {
315341
BackendGraphAccess::scene_color_format_wgpu(self)
316342
}

crates/renderide/src/backend/facade/graph_state.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub(super) struct RenderGraphState {
3333
upload_arena: PersistentUploadArena,
3434
/// Latest upload drain stats published by graph execution for diagnostics.
3535
latest_upload_stats: FrameUploadBatchStats,
36+
/// Latest command-recording stats published by graph execution for diagnostics.
37+
latest_command_encoding: crate::render_graph::CommandEncodingHudSnapshot,
3638
/// Transient resources recorded into queued submits but not yet reusable.
3739
pending_transient_releases: Vec<PendingTransientRelease>,
3840
/// Retained logical-view ownership for every backend cache that lives beyond one frame.
@@ -50,6 +52,7 @@ impl RenderGraphState {
5052
history_registry: HistoryRegistry::new(),
5153
upload_arena: PersistentUploadArena::new(),
5254
latest_upload_stats: FrameUploadBatchStats::default(),
55+
latest_command_encoding: crate::render_graph::CommandEncodingHudSnapshot::default(),
5356
pending_transient_releases: Vec::new(),
5457
view_resources: ViewResourceRegistry::new(),
5558
post_processing_resources: MainGraphPostProcessingResources::default(),
@@ -80,13 +83,15 @@ impl RenderGraphState {
8083
&mut HistoryRegistry,
8184
&mut PersistentUploadArena,
8285
&mut FrameUploadBatchStats,
86+
&mut crate::render_graph::CommandEncodingHudSnapshot,
8387
&mut Vec<PendingTransientRelease>,
8488
) {
8589
(
8690
&mut self.transient_pool,
8791
&mut self.history_registry,
8892
&mut self.upload_arena,
8993
&mut self.latest_upload_stats,
94+
&mut self.latest_command_encoding,
9095
&mut self.pending_transient_releases,
9196
)
9297
}
@@ -110,6 +115,13 @@ impl RenderGraphState {
110115
self.latest_upload_stats
111116
}
112117

118+
/// Latest command-recording stats published by graph execution.
119+
pub(super) fn latest_command_encoding(
120+
&self,
121+
) -> crate::render_graph::CommandEncodingHudSnapshot {
122+
self.latest_command_encoding.clone()
123+
}
124+
113125
/// Long-lived post-processing resources for main-graph rebuilds.
114126
pub(super) fn post_processing_resources(&self) -> &MainGraphPostProcessingResources {
115127
&self.post_processing_resources

0 commit comments

Comments
 (0)