Skip to content

Windows playback perf#1616

Merged
richiemcilroy merged 8 commits intomainfrom
windows-playback-perf
Feb 18, 2026
Merged

Windows playback perf#1616
richiemcilroy merged 8 commits intomainfrom
windows-playback-perf

Conversation

@richiemcilroy
Copy link
Member

Introduces several important changes to video frame handling, GPU diagnostics, and platform support, primarily focusing on improving NV12 frame processing and enhancing system diagnostics structures. The updates ensure consistent handling of strides in NV12 frame data across Rust and TypeScript code, expand GPU/system diagnostics for Windows, and introduce new dependencies and platform-specific improvements.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 18, 2026

Too many files changed for review. (137 files found, 100 file limit)

@richiemcilroy richiemcilroy merged commit e3f5b8b into main Feb 18, 2026
13 of 16 checks passed
Comment on lines +48 to +68
#[cfg(target_os = "windows")]
struct WindowsTimerResolution;

#[cfg(target_os = "windows")]
impl WindowsTimerResolution {
fn set_high_precision() -> Self {
unsafe {
windows::Win32::Media::timeBeginPeriod(1);
}
Self
}
}

#[cfg(target_os = "windows")]
impl Drop for WindowsTimerResolution {
fn drop(&mut self) {
unsafe {
windows::Win32::Media::timeEndPeriod(1);
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timeBeginPeriod/timeEndPeriod can fail, and timeEndPeriod should ideally only run if timeBeginPeriod succeeded. Tracking that state avoids making the global timer resolution worse if begin fails.

Suggested change
#[cfg(target_os = "windows")]
struct WindowsTimerResolution;
#[cfg(target_os = "windows")]
impl WindowsTimerResolution {
fn set_high_precision() -> Self {
unsafe {
windows::Win32::Media::timeBeginPeriod(1);
}
Self
}
}
#[cfg(target_os = "windows")]
impl Drop for WindowsTimerResolution {
fn drop(&mut self) {
unsafe {
windows::Win32::Media::timeEndPeriod(1);
}
}
}
#[cfg(target_os = "windows")]
struct WindowsTimerResolution {
enabled: bool,
}
#[cfg(target_os = "windows")]
impl WindowsTimerResolution {
fn set_high_precision() -> Self {
let enabled = unsafe { windows::Win32::Media::timeBeginPeriod(1) } == 0;
Self { enabled }
}
}
#[cfg(target_os = "windows")]
impl Drop for WindowsTimerResolution {
fn drop(&mut self) {
if self.enabled {
let _ = unsafe { windows::Win32::Media::timeEndPeriod(1) };
}
}
}

Comment on lines +181 to 183
if width == 0 || height == 0 {
return false;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NV12 is 4:2:0, so odd dimensions tend to produce subtle indexing issues (especially on the UV plane). Even if the stride is aligned, it’s safer to reject odd sizes here.

Suggested change
if width == 0 || height == 0 {
return false;
}
if width == 0 || height == 0 || !width.is_multiple_of(2) || !height.is_multiple_of(2) {
return false;
}

Comment on lines +181 to +186
let _ = self.tx.try_send(RendererMessage::RenderFrame {
segment_frames,
uniforms,
finished: finished_tx,
cursor,
})
.await;
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try_send dropping render requests is fine for perf, but swallowing Closed makes failures silent and hard to debug.

Suggested change
let _ = self.tx.try_send(RendererMessage::RenderFrame {
segment_frames,
uniforms,
finished: finished_tx,
cursor,
})
.await;
});
match self.tx.try_send(RendererMessage::RenderFrame {
segment_frames,
uniforms,
finished: finished_tx,
cursor,
}) {
Ok(()) => {}
Err(mpsc::error::TrySendError::Full(_)) => {}
Err(mpsc::error::TrySendError::Closed(_)) => {
tracing::warn!("Failed to send render request to renderer (channel closed)");
}
}

cache.clear();
last_decoded_frame = None;
}
pending_requests.sort_by_key(|r| r.frame);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor perf nit: sort_by_key is stable and a bit heavier than needed here. sort_unstable_by_key should be fine since you only need ordering by frame.

Suggested change
pending_requests.sort_by_key(|r| r.frame);
pending_requests.sort_unstable_by_key(|r| r.frame);

let cached = CachedFrame {
number: frame_number,
_texture: mf_frame.textures.nv12.texture.clone(),
_shared_handle: Some(mf_frame.textures.nv12.handle),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if mf_frame.textures.nv12.handle can ever be NULL, storing it as Some(NULL) makes it easy to accidentally treat as valid later.

Suggested change
_shared_handle: Some(mf_frame.textures.nv12.handle),
_shared_handle: Some(mf_frame.textures.nv12.handle)
.filter(|h| h.0 != std::ptr::null_mut()),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant