Skip to content

Commit da30355

Browse files
committed
Merge master into renderer cycle decoupling
2 parents c8f109c + 7a0ecc9 commit da30355

41 files changed

Lines changed: 692 additions & 176 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/renderide/src/app/driver.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ pub(crate) struct AppDriver {
5050
pub(in crate::app::driver) frame_clock: FrameClock,
5151
/// Open Tracy span that attributes the winit wait gap to `app::about_to_wait`.
5252
pub(in crate::app::driver) about_to_wait_span: crate::profiling::DeferredCpuSpan,
53+
/// Whether the last completed tick queued an HMD projection layer for compositor pacing.
54+
pub(in crate::app::driver) hmd_compositor_paced_last_frame: bool,
5355
pub(in crate::app::driver) external_shutdown: Option<ExternalShutdownCoordinator>,
5456
pub(in crate::app::driver) main_heartbeat: Option<crate::diagnostics::Heartbeat>,
5557
/// RAII guard suppressing main-thread watchdog hang reports for the duration of the
@@ -88,6 +90,7 @@ impl AppDriver {
8890
cursor_output_tracking: CursorOutputTracking::default(),
8991
frame_clock: FrameClock::default(),
9092
about_to_wait_span: crate::profiling::DeferredCpuSpan::default(),
93+
hmd_compositor_paced_last_frame: false,
9194
external_shutdown,
9295
main_heartbeat,
9396
shutdown_watchdog_pause: None,

crates/renderide/src/app/driver/events.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl ApplicationHandler for AppDriver {
173173
let plan = plan_redraw(RedrawInputs {
174174
has_window: self.target.is_some(),
175175
exit_requested: self.exit_is_requested(),
176-
vr_active: self.runtime.vr_active(),
176+
hmd_compositor_paced: self.hmd_compositor_paced_last_frame,
177177
vsync,
178178
window_has_keyboard_focus: self.input.window_focused,
179179
foreground_fps_cap: frame_pacing_caps.foreground_fps_cap,

crates/renderide/src/app/driver/frame.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ impl AppDriver {
141141
event_loop: &dyn ActiveEventLoop,
142142
frame_start: Instant,
143143
) -> FrameTickOutcome {
144+
self.hmd_compositor_paced_last_frame = false;
144145
self.frame_tick_prologue(frame_start);
145146
self.poll_ipc_and_window();
146147
if self.check_external_shutdown(event_loop) {
@@ -229,6 +230,7 @@ impl AppDriver {
229230
};
230231
self.runtime.note_frame_render_attempted();
231232
let hmd_projection_ended = render_outcome.hmd_projection_ended;
233+
self.hmd_compositor_paced_last_frame = hmd_projection_ended;
232234
if self.handle_gpu_device_loss_request(event_loop) {
233235
if !hmd_projection_ended {
234236
self.queue_empty_openxr_frame_if_needed(xr_tick);

crates/renderide/src/app/redraw_plan.rs

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ pub(crate) struct RedrawInputs {
3333
pub(crate) has_window: bool,
3434
/// Whether the app has already requested event-loop exit.
3535
pub(crate) exit_requested: bool,
36-
/// Whether VR pacing owns frame cadence.
37-
pub(crate) vr_active: bool,
36+
/// Whether HMD compositor pacing owns frame cadence for the next redraw.
37+
pub(crate) hmd_compositor_paced: bool,
3838
/// Swapchain VSync mode. `On` lets FIFO presentation own desktop cadence.
3939
pub(crate) vsync: VsyncMode,
4040
/// Whether winit reports that the renderer window currently has keyboard focus.
@@ -80,7 +80,7 @@ pub(crate) fn plan_redraw(inputs: RedrawInputs) -> RedrawPlan {
8080
};
8181
}
8282

83-
if inputs.vr_active || inputs.vsync == VsyncMode::On {
83+
if inputs.hmd_compositor_paced || inputs.vsync == VsyncMode::On {
8484
return RedrawPlan {
8585
decision: RedrawDecision::RedrawNow,
8686
fps_cap: 0,
@@ -159,7 +159,7 @@ mod tests {
159159
let plan = plan_redraw(RedrawInputs {
160160
has_window: true,
161161
exit_requested: false,
162-
vr_active: false,
162+
hmd_compositor_paced: false,
163163
vsync: VsyncMode::Off,
164164
window_has_keyboard_focus: true,
165165
foreground_fps_cap: 60,
@@ -179,7 +179,7 @@ mod tests {
179179
let plan = plan_redraw(RedrawInputs {
180180
has_window: true,
181181
exit_requested: false,
182-
vr_active: false,
182+
hmd_compositor_paced: false,
183183
vsync: VsyncMode::Off,
184184
window_has_keyboard_focus: false,
185185
foreground_fps_cap: 60,
@@ -203,7 +203,7 @@ mod tests {
203203
let plan = plan_redraw(RedrawInputs {
204204
has_window: true,
205205
exit_requested: false,
206-
vr_active: false,
206+
hmd_compositor_paced: false,
207207
vsync: VsyncMode::Off,
208208
window_has_keyboard_focus: true,
209209
foreground_fps_cap: 30,
@@ -218,13 +218,13 @@ mod tests {
218218
}
219219

220220
#[test]
221-
fn redraw_plan_redraws_immediately_when_uncapped_or_vr() {
221+
fn redraw_plan_redraws_immediately_when_uncapped_or_hmd_paced() {
222222
let now = Instant::now();
223223
assert_eq!(
224224
plan_redraw(RedrawInputs {
225225
has_window: true,
226226
exit_requested: false,
227-
vr_active: false,
227+
hmd_compositor_paced: false,
228228
vsync: VsyncMode::Off,
229229
window_has_keyboard_focus: true,
230230
foreground_fps_cap: 0,
@@ -235,21 +235,41 @@ mod tests {
235235
.decision,
236236
RedrawDecision::RedrawNow
237237
);
238-
assert_eq!(
239-
plan_redraw(RedrawInputs {
240-
has_window: true,
241-
exit_requested: false,
242-
vr_active: true,
243-
vsync: VsyncMode::Off,
244-
window_has_keyboard_focus: true,
245-
foreground_fps_cap: 60,
246-
background_fps_cap: 15,
247-
last_frame_start: Some(now),
248-
now,
249-
})
250-
.decision,
251-
RedrawDecision::RedrawNow
252-
);
238+
let hmd_paced = plan_redraw(RedrawInputs {
239+
has_window: true,
240+
exit_requested: false,
241+
hmd_compositor_paced: true,
242+
vsync: VsyncMode::Off,
243+
window_has_keyboard_focus: true,
244+
foreground_fps_cap: 60,
245+
background_fps_cap: 15,
246+
last_frame_start: Some(now),
247+
now,
248+
});
249+
assert_eq!(hmd_paced.decision, RedrawDecision::RedrawNow);
250+
assert_eq!(hmd_paced.fps_cap, 0);
251+
assert_eq!(hmd_paced.wait_ms, 0.0);
252+
}
253+
254+
#[test]
255+
fn redraw_plan_caps_non_hmd_frames_even_after_xr_session_exists() {
256+
let t0 = Instant::now();
257+
let now = t0 + Duration::from_millis(1);
258+
let plan = plan_redraw(RedrawInputs {
259+
has_window: true,
260+
exit_requested: false,
261+
hmd_compositor_paced: false,
262+
vsync: VsyncMode::Off,
263+
window_has_keyboard_focus: true,
264+
foreground_fps_cap: 60,
265+
background_fps_cap: 15,
266+
last_frame_start: Some(t0),
267+
now,
268+
});
269+
270+
assert_eq!(plan.fps_cap, 60);
271+
assert!(matches!(plan.decision, RedrawDecision::WaitUntil(_)));
272+
assert!(plan.wait_ms > 0.0);
253273
}
254274

255275
#[test]
@@ -260,7 +280,7 @@ mod tests {
260280
let plan = plan_redraw(RedrawInputs {
261281
has_window: true,
262282
exit_requested: false,
263-
vr_active: false,
283+
hmd_compositor_paced: false,
264284
vsync: VsyncMode::On,
265285
window_has_keyboard_focus,
266286
foreground_fps_cap: 60,
@@ -281,7 +301,7 @@ mod tests {
281301
plan_redraw(RedrawInputs {
282302
has_window: false,
283303
exit_requested: false,
284-
vr_active: false,
304+
hmd_compositor_paced: false,
285305
vsync: VsyncMode::Off,
286306
window_has_keyboard_focus: true,
287307
foreground_fps_cap: 60,
@@ -296,7 +316,7 @@ mod tests {
296316
plan_redraw(RedrawInputs {
297317
has_window: true,
298318
exit_requested: true,
299-
vr_active: true,
319+
hmd_compositor_paced: true,
300320
vsync: VsyncMode::Off,
301321
window_has_keyboard_focus: true,
302322
foreground_fps_cap: 60,

crates/renderide/src/backend/asset_transfers/integrator/drain.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ fn submit_mesh_upload_flush(
193193
.submit(crate::gpu::driver_thread::SubmitBatch {
194194
submit_kind: crate::gpu::driver_thread::DriverSubmitKind::BackgroundGpuWork,
195195
command_buffers: vec![command_buffer],
196+
retained_resources: crate::gpu::GpuRetainedResources::new(),
196197
surface_texture: None,
197198
on_submitted_work_done,
198199
frame_timing: None,

crates/renderide/src/backend/facade.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,13 @@ impl RenderBackend {
564564
let command_recording_mode = self.command_recording_mode();
565565
let wall_frame_time_ms = self.debug_frame_time_ms();
566566
let skin_weight_mode = self.skin_weight_mode();
567-
let (transient_pool, history_registry, upload_arena, latest_upload_stats) =
568-
self.graph_state.execution_resources_mut();
567+
let (
568+
transient_pool,
569+
history_registry,
570+
upload_arena,
571+
latest_upload_stats,
572+
pending_transient_releases,
573+
) = self.graph_state.execution_resources_mut();
569574
let (frame_resources, mesh_preprocess, mesh_deform_scratch, skin_cache) =
570575
self.frame_services.graph_access_slices();
571576
BackendGraphAccess {
@@ -581,6 +586,7 @@ impl RenderBackend {
581586
history_registry,
582587
upload_arena,
583588
latest_upload_stats,
589+
pending_transient_releases,
584590
debug_hud: self.diagnostics.bundle_mut(),
585591
scene_color_format,
586592
gpu_limits,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl RenderBackend {
6262
}
6363
}
6464
}
65+
self.graph_state.release_completed_transient_submits(gpu);
6566
self.graph_state.history_registry_mut().advance_frame();
6667
debug_assert_eq!(
6768
requirements,

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::passes::post_processing::settings_slots::{
2121
use crate::render_graph::TransientPool;
2222
use crate::render_graph::blackboard::Blackboard;
2323
use crate::render_graph::compiled::FrameView;
24+
use crate::render_graph::context::GraphResolvedResources;
2425
use crate::render_graph::execution_backend::{
2526
GraphExecutionBackend, GraphFrameParamsSplit, GraphViewBlackboardPreparer,
2627
};
@@ -30,6 +31,7 @@ use super::super::debug_hud_bundle::DebugHudBundle;
3031
use super::super::{
3132
FrameResourceManager, HistoryRegistry, WorldMeshDrawPlanSlot, WorldMeshOverlayDrawPlanSlot,
3233
};
34+
use super::graph_state::PendingTransientRelease;
3335

3436
/// Live post-processing parameters seeded into per-view blackboards.
3537
#[derive(Clone, Copy, Debug, Default)]
@@ -74,6 +76,8 @@ pub(crate) struct BackendGraphAccess<'a> {
7476
pub(crate) upload_arena: &'a mut PersistentUploadArena,
7577
/// Latest frame-upload stats published for diagnostics.
7678
pub(crate) latest_upload_stats: &'a mut FrameUploadBatchStats,
79+
/// Resolved transient resource sets waiting on driver submit before pool release.
80+
pub(super) pending_transient_releases: &'a mut Vec<PendingTransientRelease>,
7781
/// Debug HUD state and encoder.
7882
pub(crate) debug_hud: &'a mut DebugHudBundle,
7983
/// Scene-color format snapshot selected before graph execution borrows backend fields.
@@ -137,6 +141,18 @@ impl<'a> BackendGraphAccess<'a> {
137141
self.transient_pool
138142
}
139143

144+
/// Schedules resolved transient resources for pool release once `token` has submitted.
145+
pub(crate) fn schedule_transient_release_after_submit(
146+
&mut self,
147+
token: crate::gpu::driver_thread::SubmitToken,
148+
resources: Vec<GraphResolvedResources>,
149+
) {
150+
if !resources.is_empty() {
151+
self.pending_transient_releases
152+
.push(PendingTransientRelease { token, resources });
153+
}
154+
}
155+
140156
/// Shared history registry for import resolution.
141157
pub(crate) fn history_registry(&self) -> &HistoryRegistry {
142158
self.history_registry
@@ -271,6 +287,14 @@ impl GraphExecutionBackend for BackendGraphAccess<'_> {
271287
BackendGraphAccess::transient_pool_mut(self)
272288
}
273289

290+
fn schedule_transient_release_after_submit(
291+
&mut self,
292+
token: crate::gpu::driver_thread::SubmitToken,
293+
resources: Vec<GraphResolvedResources>,
294+
) {
295+
BackendGraphAccess::schedule_transient_release_after_submit(self, token, resources);
296+
}
297+
274298
fn history_registry(&self) -> &HistoryRegistry {
275299
BackendGraphAccess::history_registry(self)
276300
}

0 commit comments

Comments
 (0)