diff options
author | 2023-03-25 10:45:39 -0700 | |
---|---|---|
committer | 2023-06-06 15:37:30 +0200 | |
commit | 233196eb14b40f8bd5201ea0262571f82136ad53 (patch) | |
tree | 410cf71cda98bdcb55ecc384f7fbc2f4ef669edd /wgpu/src/offscreen.rs | |
parent | c15f1b5f6575792cc89bb5fba2e613428397e46a (diff) | |
download | iced-233196eb14b40f8bd5201ea0262571f82136ad53.tar.gz iced-233196eb14b40f8bd5201ea0262571f82136ad53.tar.bz2 iced-233196eb14b40f8bd5201ea0262571f82136ad53.zip |
Added offscreen rendering support for wgpu & tiny-skia exposed with the window::screenshot command.
Diffstat (limited to 'wgpu/src/offscreen.rs')
-rw-r--r-- | wgpu/src/offscreen.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/wgpu/src/offscreen.rs b/wgpu/src/offscreen.rs new file mode 100644 index 00000000..29913d02 --- /dev/null +++ b/wgpu/src/offscreen.rs @@ -0,0 +1,102 @@ +use std::borrow::Cow; + +/// A simple compute pipeline to convert any texture to Rgba8UnormSrgb. +#[derive(Debug)] +pub struct Pipeline { + pipeline: wgpu::ComputePipeline, + layout: wgpu::BindGroupLayout, +} + +impl Pipeline { + pub fn new(device: &wgpu::Device) -> Self { + let shader = + device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("iced_wgpu.offscreen.blit.shader"), + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!( + "shader/offscreen_blit.wgsl" + ))), + }); + + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("iced_wgpu.offscreen.blit.bind_group_layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { + filterable: false, + }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::StorageTexture { + access: wgpu::StorageTextureAccess::WriteOnly, + format: wgpu::TextureFormat::Rgba8Unorm, + view_dimension: wgpu::TextureViewDimension::D2, + }, + count: None, + }, + ], + }); + + let pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("iced_wgpu.offscreen.blit.pipeline_layout"), + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[], + }); + + let pipeline = + device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { + label: Some("iced_wgpu.offscreen.blit.pipeline"), + layout: Some(&pipeline_layout), + module: &shader, + entry_point: "main", + }); + + Self { + pipeline, + layout: bind_group_layout, + } + } + + pub fn convert( + &self, + device: &wgpu::Device, + extent: wgpu::Extent3d, + frame: &wgpu::TextureView, + view: &wgpu::TextureView, + encoder: &mut wgpu::CommandEncoder, + ) { + let bind = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("iced_wgpu.offscreen.blit.bind_group"), + layout: &self.layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(frame), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(view), + }, + ], + }); + + let mut compute_pass = + encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("iced_wgpu.offscreen.blit.compute_pass"), + }); + + compute_pass.set_pipeline(&self.pipeline); + compute_pass.set_bind_group(0, &bind, &[]); + compute_pass.dispatch_workgroups(extent.width, extent.height, 1); + } +} |