summaryrefslogtreecommitdiffstats
path: root/wgpu/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--wgpu/src/backend.rs44
-rw-r--r--wgpu/src/color.rs165
-rw-r--r--wgpu/src/lib.rs2
-rw-r--r--wgpu/src/offscreen.rs188
-rw-r--r--wgpu/src/window/compositor.rs17
5 files changed, 180 insertions, 236 deletions
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index 7c962308..b524c615 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -1,3 +1,4 @@
+use crate::core;
use crate::core::{Color, Font, Point, Size};
use crate::graphics::backend;
use crate::graphics::color;
@@ -5,7 +6,6 @@ use crate::graphics::{Primitive, Transformation, Viewport};
use crate::quad;
use crate::text;
use crate::triangle;
-use crate::{core, offscreen};
use crate::{Layer, Settings};
#[cfg(feature = "tracing")]
@@ -123,48 +123,6 @@ impl Backend {
self.image_pipeline.end_frame();
}
- /// Performs an offscreen render pass. If the `format` selected by WGPU is not
- /// `wgpu::TextureFormat::Rgba8UnormSrgb`, it will be run through a blit.
- ///
- /// Returns `None` if the `frame` is `Rgba8UnormSrgb`, else returns the newly
- /// converted texture view in `Rgba8UnormSrgb`.
- pub fn offscreen<T: AsRef<str>>(
- &mut self,
- device: &wgpu::Device,
- queue: &wgpu::Queue,
- encoder: &mut wgpu::CommandEncoder,
- clear_color: Option<Color>,
- frame: &wgpu::TextureView,
- format: wgpu::TextureFormat,
- primitives: &[Primitive],
- viewport: &Viewport,
- overlay_text: &[T],
- size: wgpu::Extent3d,
- ) -> Option<wgpu::Texture> {
- #[cfg(feature = "tracing")]
- let _ = info_span!("iced_wgpu::offscreen", "DRAW").entered();
-
- self.present(
- device,
- queue,
- encoder,
- clear_color,
- frame,
- primitives,
- viewport,
- overlay_text,
- );
-
- if format != wgpu::TextureFormat::Rgba8UnormSrgb {
- log::info!("Texture format is {format:?}; performing conversion to rgba8..");
- let pipeline = offscreen::Pipeline::new(device);
-
- return Some(pipeline.convert(device, frame, size, encoder));
- }
-
- None
- }
-
fn prepare_text(
&mut self,
device: &wgpu::Device,
diff --git a/wgpu/src/color.rs b/wgpu/src/color.rs
new file mode 100644
index 00000000..a1025601
--- /dev/null
+++ b/wgpu/src/color.rs
@@ -0,0 +1,165 @@
+use std::borrow::Cow;
+
+pub fn convert(
+ device: &wgpu::Device,
+ encoder: &mut wgpu::CommandEncoder,
+ source: wgpu::Texture,
+ format: wgpu::TextureFormat,
+) -> wgpu::Texture {
+ if source.format() == format {
+ return source;
+ }
+
+ let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
+ label: Some("iced_wgpu.offscreen.sampler"),
+ ..Default::default()
+ });
+
+ //sampler in 0
+ let sampler_layout =
+ device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.sampler_layout"),
+ entries: &[wgpu::BindGroupLayoutEntry {
+ binding: 0,
+ visibility: wgpu::ShaderStages::FRAGMENT,
+ ty: wgpu::BindingType::Sampler(
+ wgpu::SamplerBindingType::NonFiltering,
+ ),
+ count: None,
+ }],
+ });
+
+ let sampler_bind_group =
+ device.create_bind_group(&wgpu::BindGroupDescriptor {
+ label: Some("iced_wgpu.offscreen.sampler.bind_group"),
+ layout: &sampler_layout,
+ entries: &[wgpu::BindGroupEntry {
+ binding: 0,
+ resource: wgpu::BindingResource::Sampler(&sampler),
+ }],
+ });
+
+ let texture_layout =
+ device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.texture_layout"),
+ entries: &[wgpu::BindGroupLayoutEntry {
+ binding: 0,
+ visibility: wgpu::ShaderStages::FRAGMENT,
+ ty: wgpu::BindingType::Texture {
+ sample_type: wgpu::TextureSampleType::Float {
+ filterable: false,
+ },
+ view_dimension: wgpu::TextureViewDimension::D2,
+ multisampled: false,
+ },
+ count: None,
+ }],
+ });
+
+ let pipeline_layout =
+ device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.pipeline_layout"),
+ bind_group_layouts: &[&sampler_layout, &texture_layout],
+ push_constant_ranges: &[],
+ });
+
+ let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.shader"),
+ source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!(
+ "shader/blit.wgsl"
+ ))),
+ });
+
+ let pipeline =
+ device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.pipeline"),
+ layout: Some(&pipeline_layout),
+ vertex: wgpu::VertexState {
+ module: &shader,
+ entry_point: "vs_main",
+ buffers: &[],
+ },
+ fragment: Some(wgpu::FragmentState {
+ module: &shader,
+ entry_point: "fs_main",
+ targets: &[Some(wgpu::ColorTargetState {
+ format,
+ blend: Some(wgpu::BlendState {
+ color: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::SrcAlpha,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ alpha: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::One,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ }),
+ write_mask: wgpu::ColorWrites::ALL,
+ })],
+ }),
+ primitive: wgpu::PrimitiveState {
+ topology: wgpu::PrimitiveTopology::TriangleList,
+ front_face: wgpu::FrontFace::Cw,
+ ..Default::default()
+ },
+ depth_stencil: None,
+ multisample: Default::default(),
+ multiview: None,
+ });
+
+ let texture = device.create_texture(&wgpu::TextureDescriptor {
+ label: Some("iced_wgpu.offscreen.conversion.source_texture"),
+ size: source.size(),
+ mip_level_count: 1,
+ sample_count: 1,
+ dimension: wgpu::TextureDimension::D2,
+ format,
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT
+ | wgpu::TextureUsages::COPY_SRC,
+ view_formats: &[],
+ });
+
+ let view = &texture.create_view(&wgpu::TextureViewDescriptor::default());
+
+ let texture_bind_group =
+ device.create_bind_group(&wgpu::BindGroupDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.texture_bind_group"),
+ layout: &texture_layout,
+ entries: &[wgpu::BindGroupEntry {
+ binding: 0,
+ resource: wgpu::BindingResource::TextureView(
+ &source
+ .create_view(&wgpu::TextureViewDescriptor::default()),
+ ),
+ }],
+ });
+
+ let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: Some("iced_wgpu.offscreen.blit.render_pass"),
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
+ view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: true,
+ },
+ })],
+ depth_stencil_attachment: None,
+ });
+
+ pass.set_pipeline(&pipeline);
+ pass.set_bind_group(0, &sampler_bind_group, &[]);
+ pass.set_bind_group(1, &texture_bind_group, &[]);
+ pass.draw(0..6, 0..1);
+
+ texture
+}
+
+#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
+#[repr(C)]
+struct Vertex {
+ ndc: [f32; 2],
+ uv: [f32; 2],
+}
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index 827acb89..86a962a5 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -46,7 +46,7 @@ pub mod geometry;
mod backend;
mod buffer;
-mod offscreen;
+mod color;
mod quad;
mod text;
mod triangle;
diff --git a/wgpu/src/offscreen.rs b/wgpu/src/offscreen.rs
deleted file mode 100644
index b25602e4..00000000
--- a/wgpu/src/offscreen.rs
+++ /dev/null
@@ -1,188 +0,0 @@
-use crate::graphics::color;
-use std::borrow::Cow;
-
-/// A simple compute pipeline to convert any texture to Rgba8UnormSrgb.
-#[derive(Debug)]
-pub struct Pipeline {
- pipeline: wgpu::RenderPipeline,
- sampler_bind_group: wgpu::BindGroup,
- texture_layout: wgpu::BindGroupLayout,
-}
-
-#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
-#[repr(C)]
-struct Vertex {
- ndc: [f32; 2],
- uv: [f32; 2],
-}
-
-impl Pipeline {
- pub fn new(device: &wgpu::Device) -> Self {
- let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
- label: Some("iced_wgpu.offscreen.sampler"),
- ..Default::default()
- });
-
- //sampler in 0
- let sampler_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: Some("iced_wgpu.offscreen.blit.sampler_layout"),
- entries: &[wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStages::FRAGMENT,
- ty: wgpu::BindingType::Sampler(
- wgpu::SamplerBindingType::NonFiltering,
- ),
- count: None,
- }],
- });
-
- let sampler_bind_group =
- device.create_bind_group(&wgpu::BindGroupDescriptor {
- label: Some("iced_wgpu.offscreen.sampler.bind_group"),
- layout: &sampler_layout,
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: wgpu::BindingResource::Sampler(&sampler),
- }],
- });
-
- let texture_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- label: Some("iced_wgpu.offscreen.blit.texture_layout"),
- entries: &[wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStages::FRAGMENT,
- ty: wgpu::BindingType::Texture {
- sample_type: wgpu::TextureSampleType::Float {
- filterable: false,
- },
- view_dimension: wgpu::TextureViewDimension::D2,
- multisampled: false,
- },
- count: None,
- }],
- });
-
- let pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: Some("iced_wgpu.offscreen.blit.pipeline_layout"),
- bind_group_layouts: &[&sampler_layout, &texture_layout],
- push_constant_ranges: &[],
- });
-
- let shader =
- device.create_shader_module(wgpu::ShaderModuleDescriptor {
- label: Some("iced_wgpu.offscreen.blit.shader"),
- source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!(
- "shader/blit.wgsl"
- ))),
- });
-
- let pipeline =
- device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: Some("iced_wgpu.offscreen.blit.pipeline"),
- layout: Some(&pipeline_layout),
- vertex: wgpu::VertexState {
- module: &shader,
- entry_point: "vs_main",
- buffers: &[],
- },
- fragment: Some(wgpu::FragmentState {
- module: &shader,
- entry_point: "fs_main",
- targets: &[Some(wgpu::ColorTargetState {
- format: if color::GAMMA_CORRECTION {
- wgpu::TextureFormat::Rgba8UnormSrgb
- } else {
- wgpu::TextureFormat::Rgba8Unorm
- },
- blend: Some(wgpu::BlendState {
- color: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- }),
- write_mask: wgpu::ColorWrites::ALL,
- })],
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleList,
- front_face: wgpu::FrontFace::Cw,
- ..Default::default()
- },
- depth_stencil: None,
- multisample: Default::default(),
- multiview: None,
- });
-
- Self {
- pipeline,
- sampler_bind_group,
- texture_layout,
- }
- }
-
- pub fn convert(
- &self,
- device: &wgpu::Device,
- frame: &wgpu::TextureView,
- size: wgpu::Extent3d,
- encoder: &mut wgpu::CommandEncoder,
- ) -> wgpu::Texture {
- let texture = device.create_texture(&wgpu::TextureDescriptor {
- label: Some("iced_wgpu.offscreen.conversion.source_texture"),
- size,
- mip_level_count: 1,
- sample_count: 1,
- dimension: wgpu::TextureDimension::D2,
- format: if color::GAMMA_CORRECTION {
- wgpu::TextureFormat::Rgba8UnormSrgb
- } else {
- wgpu::TextureFormat::Rgba8Unorm
- },
- usage: wgpu::TextureUsages::RENDER_ATTACHMENT
- | wgpu::TextureUsages::COPY_SRC,
- view_formats: &[],
- });
-
- let view =
- &texture.create_view(&wgpu::TextureViewDescriptor::default());
-
- let texture_bind_group =
- device.create_bind_group(&wgpu::BindGroupDescriptor {
- label: Some("iced_wgpu.offscreen.blit.texture_bind_group"),
- layout: &self.texture_layout,
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: wgpu::BindingResource::TextureView(frame),
- }],
- });
-
- let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: Some("iced_wgpu.offscreen.blit.render_pass"),
- color_attachments: &[Some(wgpu::RenderPassColorAttachment {
- view,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: true,
- },
- })],
- depth_stencil_attachment: None,
- });
-
- pass.set_pipeline(&self.pipeline);
- pass.set_bind_group(0, &self.sampler_bind_group, &[]);
- pass.set_bind_group(1, &texture_bind_group, &[]);
- pass.draw(0..6, 0..1);
-
- texture
- }
-}
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 43c3dce5..1cfd7b67 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -345,17 +345,26 @@ pub fn screenshot<Theme, T: AsRef<str>>(
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
- let rgba_texture = backend.offscreen(
+ backend.present(
&compositor.device,
&compositor.queue,
&mut encoder,
Some(background_color),
&view,
- compositor.format,
primitives,
viewport,
overlay,
- texture_extent,
+ );
+
+ let texture = crate::color::convert(
+ &compositor.device,
+ &mut encoder,
+ texture,
+ if color::GAMMA_CORRECTION {
+ wgpu::TextureFormat::Rgba8UnormSrgb
+ } else {
+ wgpu::TextureFormat::Rgba8Unorm
+ },
);
let output_buffer =
@@ -368,7 +377,7 @@ pub fn screenshot<Theme, T: AsRef<str>>(
});
encoder.copy_texture_to_buffer(
- rgba_texture.unwrap_or(texture).as_image_copy(),
+ texture.as_image_copy(),
wgpu::ImageCopyBuffer {
buffer: &output_buffer,
layout: wgpu::ImageDataLayout {