feat: enable proper detection of hdr texture
Some checks failed
build / checks-matrix (push) Has been cancelled
build / checks-build (push) Has been cancelled
build / codecov (push) Has been cancelled
docs / docs (push) Has been cancelled

This commit is contained in:
uttarayan21
2025-12-16 19:14:20 +05:30
parent 232c0f4d53
commit ccae03d105

View File

@@ -22,6 +22,23 @@ impl App {
}
}
pub trait HdrTextureFormatExt {
fn is_hdr_format(&self) -> bool;
}
impl HdrTextureFormatExt for wgpu::TextureFormat {
fn is_hdr_format(&self) -> bool {
matches!(
self,
wgpu::TextureFormat::Rgba16Float
// | wgpu::TextureFormat::Rg11b10float
// | wgpu::TextureFormat::R11g11b10float
| wgpu::TextureFormat::Rgb10a2Unorm
| wgpu::TextureFormat::Rgba32Float
)
}
}
pub struct State {
window: Arc<Window>,
gst: Video,
@@ -62,7 +79,14 @@ impl State {
.await
.context("Failed to request wgpu device")?;
let surface_caps = surface.get_capabilities(&adapter);
let surface_format = surface_caps.formats.last().unwrap().clone();
dbg!(&surface_caps);
let surface_format = surface_caps
.formats
.iter()
.rev() // float one comes first
.find(|f| f.is_hdr_format())
.expect("HDR format not supported")
.clone();
let size = window.inner_size();
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
@@ -72,7 +96,7 @@ impl State {
present_mode: surface_caps.present_modes[0],
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 3, // calculate upto 5 frames ahead
desired_maximum_frame_latency: 2, // calculate upto 5 frames ahead
};
surface.configure(&device, &config);
@@ -148,13 +172,13 @@ impl State {
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgb10a2Unorm,
format: surface_format,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: Some("Jello Video Texture"),
view_formats: &[],
});
/// Todo: Use a better sampler
// TODO: Use a better sampler
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("texture_sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
@@ -183,6 +207,7 @@ impl State {
label: Some("Jello Texture Bind Group"),
});
let gst = Video::new().context("Failed to create Video")?;
// surface.configure(&device, &config);
Ok(Self {
window,
@@ -214,7 +239,7 @@ impl State {
return Ok(());
}
self.copy_next_frame_to_texture(&self.surface_texture)
self.copy_next_frame_to_texture()
.inspect_err(|e| {
tracing::error!("Failed to copy video frame to texture: {e:?}");
})
@@ -254,15 +279,15 @@ impl State {
render_pass.set_pipeline(&self.pipeline);
render_pass.set_bind_group(0, &self.bind_group, &[]);
render_pass.draw(0..3, 0..1);
drop(render_pass);
self.queue.submit(std::iter::once(encoder.finish()));
output.present();
self.window.request_redraw();
Ok(())
}
pub fn copy_next_frame_to_texture(&self, texture: &wgpu::Texture) -> Result<()> {
pub fn copy_next_frame_to_texture(&mut self) -> Result<()> {
let frame = self
.gst
.appsink
@@ -280,6 +305,18 @@ impl State {
.get::<i32>("height")
.context("Failed to get height from caps")?;
if self.config.width != width as u32 || self.config.height != height as u32 {
tracing::info!(
"Resizing surface from {}x{} to {}x{}",
self.config.width,
self.config.height,
width,
height
);
self.resize(width as u32, height as u32);
}
let texture = &self.surface_texture;
let buffer = frame.buffer().context("Failed to get buffer from sample")?;
let map = buffer
.map_readable()
@@ -299,6 +336,7 @@ impl State {
},
texture.size(),
);
Ok(())
}
}
@@ -338,7 +376,10 @@ impl ApplicationHandler<State> for App {
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::Resized(size) => state.resize(size.width, size.height),
WindowEvent::Resized(size) => {
tracing::info!("Window resized to {size:?}");
state.resize(size.width, size.height)
}
WindowEvent::RedrawRequested => {
// dbg!("RedrawRequested");
// if state.gst.poll() {
@@ -418,6 +459,8 @@ impl Video {
.map_err(|_| {
anyhow::anyhow!("Failed to downcast video-sink appsink to gst_app::AppSink")
})?;
// appsink.set_property("max-buffers", 10u32);
appsink.set_property("max-bytes", 10 * 4096 * 2160u64);
appsink.set_callbacks(
gst_app::AppSinkCallbacks::builder()
.new_sample(|_appsink| Ok(gst::FlowSuccess::Ok))