graphix_package_gui/
render.rs1use anyhow::{Context, Result};
12use iced_wgpu::graphics::{Shell, Viewport};
13use iced_wgpu::wgpu;
14use std::sync::Arc;
15use winit::window::Window;
16
17pub struct GpuState {
18 pub instance: wgpu::Instance,
19 pub adapter: wgpu::Adapter,
20 pub device: wgpu::Device,
21 pub queue: wgpu::Queue,
22 pub format: wgpu::TextureFormat,
23}
24
25impl GpuState {
26 pub async fn new(window: Arc<Window>) -> Result<Self> {
27 let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
28 backends: wgpu::Backends::all(),
29 ..Default::default()
30 });
31 let surface =
32 instance.create_surface(window).context("failed to create init surface")?;
33 let adapter = instance
34 .request_adapter(&wgpu::RequestAdapterOptions {
35 power_preference: wgpu::PowerPreference::default(),
36 compatible_surface: Some(&surface),
37 force_fallback_adapter: false,
38 })
39 .await
40 .context("no suitable GPU adapter found")?;
41 let (device, queue) = adapter
42 .request_device(&wgpu::DeviceDescriptor::default())
43 .await
44 .context("failed to create GPU device")?;
45 let format = surface
46 .get_capabilities(&adapter)
47 .formats
48 .into_iter()
49 .next()
50 .context("surface has no supported formats")?;
51 drop(surface);
52 Ok(Self { instance, adapter, device, queue, format })
53 }
54
55 pub fn create_renderer(&self) -> iced_wgpu::Renderer {
57 let engine = iced_wgpu::Engine::new(
58 &self.adapter,
59 self.device.clone(),
60 self.queue.clone(),
61 self.format,
62 None,
63 Shell::headless(),
64 );
65 iced_wgpu::Renderer::new(
66 engine,
67 iced_core::Font::DEFAULT,
68 iced_core::Pixels(16.0),
69 )
70 }
71}
72
73pub struct WindowSurface {
74 pub surface: wgpu::Surface<'static>,
75 pub config: wgpu::SurfaceConfiguration,
76 pub renderer: iced_wgpu::Renderer,
77 pub viewport: Viewport,
78}
79
80impl WindowSurface {
81 pub fn new(gpu: &GpuState, window: Arc<Window>) -> Result<Self> {
82 let size = window.inner_size();
83 let surface = gpu
84 .instance
85 .create_surface(window.clone())
86 .context("failed to create wgpu surface")?;
87 let config = wgpu::SurfaceConfiguration {
88 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
89 format: gpu.format,
90 width: size.width.max(1),
91 height: size.height.max(1),
92 present_mode: wgpu::PresentMode::AutoVsync,
93 alpha_mode: wgpu::CompositeAlphaMode::Auto,
94 view_formats: vec![],
95 desired_maximum_frame_latency: 2,
96 };
97 surface.configure(&gpu.device, &config);
98 let renderer = gpu.create_renderer();
99 let scale = window.scale_factor() as f32;
100 let viewport = Viewport::with_physical_size(
101 iced_core::Size::new(size.width, size.height),
102 scale,
103 );
104 Ok(Self { surface, config, renderer, viewport })
105 }
106
107 pub fn resize(&mut self, gpu: &GpuState, width: u32, height: u32, scale: f64) {
108 self.config.width = width.max(1);
109 self.config.height = height.max(1);
110 self.surface.configure(&gpu.device, &self.config);
111 self.viewport = Viewport::with_physical_size(
112 iced_core::Size::new(width, height),
113 scale as f32,
114 );
115 }
116
117 pub fn logical_size(&self) -> iced_core::Size {
118 self.viewport.logical_size()
119 }
120}