feat: enable proper detection of hdr texture
This commit is contained in:
@@ -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 {
|
pub struct State {
|
||||||
window: Arc<Window>,
|
window: Arc<Window>,
|
||||||
gst: Video,
|
gst: Video,
|
||||||
@@ -62,7 +79,14 @@ impl State {
|
|||||||
.await
|
.await
|
||||||
.context("Failed to request wgpu device")?;
|
.context("Failed to request wgpu device")?;
|
||||||
let surface_caps = surface.get_capabilities(&adapter);
|
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 size = window.inner_size();
|
||||||
let config = wgpu::SurfaceConfiguration {
|
let config = wgpu::SurfaceConfiguration {
|
||||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
@@ -72,7 +96,7 @@ impl State {
|
|||||||
present_mode: surface_caps.present_modes[0],
|
present_mode: surface_caps.present_modes[0],
|
||||||
alpha_mode: surface_caps.alpha_modes[0],
|
alpha_mode: surface_caps.alpha_modes[0],
|
||||||
view_formats: vec![],
|
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);
|
surface.configure(&device, &config);
|
||||||
|
|
||||||
@@ -148,13 +172,13 @@ impl State {
|
|||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: wgpu::TextureDimension::D2,
|
dimension: wgpu::TextureDimension::D2,
|
||||||
format: wgpu::TextureFormat::Rgb10a2Unorm,
|
format: surface_format,
|
||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
label: Some("Jello Video Texture"),
|
label: Some("Jello Video Texture"),
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Todo: Use a better sampler
|
// TODO: Use a better sampler
|
||||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
label: Some("texture_sampler"),
|
label: Some("texture_sampler"),
|
||||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||||
@@ -183,6 +207,7 @@ impl State {
|
|||||||
label: Some("Jello Texture Bind Group"),
|
label: Some("Jello Texture Bind Group"),
|
||||||
});
|
});
|
||||||
let gst = Video::new().context("Failed to create Video")?;
|
let gst = Video::new().context("Failed to create Video")?;
|
||||||
|
// surface.configure(&device, &config);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
window,
|
window,
|
||||||
@@ -214,7 +239,7 @@ impl State {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.copy_next_frame_to_texture(&self.surface_texture)
|
self.copy_next_frame_to_texture()
|
||||||
.inspect_err(|e| {
|
.inspect_err(|e| {
|
||||||
tracing::error!("Failed to copy video frame to texture: {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_pipeline(&self.pipeline);
|
||||||
render_pass.set_bind_group(0, &self.bind_group, &[]);
|
render_pass.set_bind_group(0, &self.bind_group, &[]);
|
||||||
render_pass.draw(0..3, 0..1);
|
render_pass.draw(0..3, 0..1);
|
||||||
|
|
||||||
drop(render_pass);
|
drop(render_pass);
|
||||||
|
|
||||||
self.queue.submit(std::iter::once(encoder.finish()));
|
self.queue.submit(std::iter::once(encoder.finish()));
|
||||||
output.present();
|
output.present();
|
||||||
self.window.request_redraw();
|
self.window.request_redraw();
|
||||||
Ok(())
|
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
|
let frame = self
|
||||||
.gst
|
.gst
|
||||||
.appsink
|
.appsink
|
||||||
@@ -280,6 +305,18 @@ impl State {
|
|||||||
.get::<i32>("height")
|
.get::<i32>("height")
|
||||||
.context("Failed to get height from caps")?;
|
.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 buffer = frame.buffer().context("Failed to get buffer from sample")?;
|
||||||
let map = buffer
|
let map = buffer
|
||||||
.map_readable()
|
.map_readable()
|
||||||
@@ -299,6 +336,7 @@ impl State {
|
|||||||
},
|
},
|
||||||
texture.size(),
|
texture.size(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,7 +376,10 @@ impl ApplicationHandler<State> for App {
|
|||||||
|
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::CloseRequested => event_loop.exit(),
|
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 => {
|
WindowEvent::RedrawRequested => {
|
||||||
// dbg!("RedrawRequested");
|
// dbg!("RedrawRequested");
|
||||||
// if state.gst.poll() {
|
// if state.gst.poll() {
|
||||||
@@ -418,6 +459,8 @@ impl Video {
|
|||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
anyhow::anyhow!("Failed to downcast video-sink appsink to gst_app::AppSink")
|
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(
|
appsink.set_callbacks(
|
||||||
gst_app::AppSinkCallbacks::builder()
|
gst_app::AppSinkCallbacks::builder()
|
||||||
.new_sample(|_appsink| Ok(gst::FlowSuccess::Ok))
|
.new_sample(|_appsink| Ok(gst::FlowSuccess::Ok))
|
||||||
|
|||||||
Reference in New Issue
Block a user