wgpu_quick_start/
lib.rs

1//!
2//!
3//!
4//!
5//! A starter crate to get started with wgpu
6//!
7//! # Features
8#![cfg_attr(doc, doc = document_features::document_features!())]
9//!
10//!
11//! # Examples
12//!
13//! An example to launch a `winit` window and use this library to get started.
14//!
15//! ```rust
16//! use wgpu_quick_start::{MyDevice};
17//!
18//! use wgpu_quick_start::create_new_device;
19//! use winit::{event::WindowEvent, window::WindowAttributes};
20//! use winit_app::{AppWindowEvent, Application};
21//!
22//!
23//! fn launch() -> Result<(), Box<dyn std::error::Error>> {
24//!    let winit_app = Application::new();
25//!    let mut opt_device: Option<Box<dyn MyDevice>> = None;
26//!    winit_app.run(
27//!        WindowAttributes::default().with_title("wgpu starter app"),
28//!        move |app_window_event| match app_window_event {
29//!            AppWindowEvent::NewWindow(window) => match create_new_device(window) {
30//!                Ok(value) => {
31//!                    opt_device = Some(value);
32//!                }
33//!                Err(err) => {
34//!                    // warning - Error creating new surface from the window
35//!                }
36//!            },
37//!            AppWindowEvent::OnWindowEvent(event, event_loop) => {
38//!                if let Some(local_device) = opt_device.as_mut() {
39//!                    match event {
40//!                        WindowEvent::CloseRequested => {
41//!                            event_loop.exit();
42//!                        }
43//!                        WindowEvent::SurfaceResized(size) => {
44//!                            // Resized
45//!                            local_device.resize((size.width, size.height));
46//!                        }
47//!                        WindowEvent::RedrawRequested => {
48//!                            match local_device.get_current_texture() {
49//!                                Ok(output) => {
50//!                                    let texture_view_descriptor=  wgpu::TextureViewDescriptor::default();
51//!                                    let view = output.texture.create_view(&texture_view_descriptor);
52//!                                    let device = local_device.get_device();
53//!                                    let mut encoder = device.create_command_encoder(
54//!                                         &wgpu::CommandEncoderDescriptor {
55//!                                             label: Some("Render Encoder"),
56//!                                         },
57//!                                    );
58//!                                    {
59//!                                     let _render_pass =
60//!                                        wgpu_quick_start::create_default_render_pass(
61//!                                            &mut encoder,
62//!                                            "root-render-pass".to_owned(),
63//!                                            wgpu::Color {
64//!                                                r: 0.9,
65//!                                                g: 0.9,
66//!                                                b: 0.9,
67//!                                                a: 1.0,
68//!                                            },
69//!                                            &view,
70//!                                        );
71//!                                        // TODO: Render objects using render pass
72//!                                    }
73//!                                    let queue = local_device.get_queue();
74//!                                    queue.submit(std::iter::once(encoder.finish()));
75//!                                    output.present();
76//!                                }
77//!                                Err(err) => {
78//!                                    // warning - error creating the texture
79//!                                }
80//!                            }
81//!                        }
82//!                        _ => {}
83//!                    }
84//!                }
85//!            }
86//!        },
87//!    )?;
88//!    Ok(())
89//! }
90//! ```
91//!
92
93mod my_render_pipeline;
94pub use my_render_pipeline::{
95    MyRenderPipelineDescriptor, create_default_pipeline_layout, create_default_render_pipeline,
96};
97
98mod my_shader;
99pub use my_shader::create_shader;
100
101mod render_pass_factory;
102pub use render_pass_factory::create_default_render_pass;
103
104mod my_device;
105pub use my_device::MyDeviceImpl;
106
107mod buffers;
108pub use buffers::{create_index_buffer, create_vertex_buffer};
109
110#[cfg(feature = "enable-sync-winit")]
111mod sync_create;
112
113#[cfg(feature = "enable-sync-winit")]
114pub use sync_create::create_new_device;
115
116#[cfg(feature = "enable-sync")]
117mod sync_nowindow;
118
119#[cfg(feature = "enable-sync")]
120pub use sync_nowindow::create_new_windowless_device;
121
122use thiserror::Error;
123
124/// GPUStarterError indicates the kind of error thrown by the `wgpu-quick-start-rs` project
125#[derive(Error, Debug)]
126pub enum GPUStarterError {
127    #[error(transparent)]
128    SurfaceError(#[from] wgpu::SurfaceError),
129    #[error(transparent)]
130    CreateSurfaceError(#[from] wgpu::CreateSurfaceError),
131    #[error(transparent)]
132    RequestAdapterError(#[from] wgpu::RequestAdapterError),
133    #[error(transparent)]
134    RequestDeviceError(#[from] wgpu::RequestDeviceError),
135    #[error("Unsupported error")]
136    UnsupportedError,
137}
138
139/// Result type that goes with error type [`GPUStarterError`]
140pub type GPUStarterResult<T> = Result<T, GPUStarterError>;
141
142/// GPUInstance is a abstraction of [`wgpu::Instance`].
143pub struct GPUInstance {
144    pub instance: wgpu::Instance,
145}
146
147impl Default for GPUInstance {
148    fn default() -> Self {
149        Self::new()
150    }
151}
152
153impl GPUInstance {
154    /// Create a new instance based on the platform
155    pub fn new() -> Self {
156        // The instance is a handle to our GPU
157        // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
158        let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
159            #[cfg(not(target_arch = "wasm32"))]
160            backends: wgpu::Backends::PRIMARY,
161            #[cfg(target_arch = "wasm32")]
162            backends: wgpu::Backends::GL,
163            ..Default::default()
164        });
165        Self { instance }
166    }
167
168    pub fn create_surface<'a>(
169        &self,
170        window: impl Into<wgpu::SurfaceTarget<'a>>,
171    ) -> GPUStarterResult<wgpu::Surface<'a>> {
172        Ok(self.instance.create_surface(window)?)
173    }
174}
175
176/// Trait as an abstraction of the underlying device
177pub trait MyDevice: Send + Sync {
178    /// Retrieve the adapter
179    fn get_adapter(&self) -> &wgpu::Adapter;
180
181    /// Retrieve the device associated with this surface
182    fn get_device(&self) -> &wgpu::Device;
183
184    /// Retrieve the underlying queue present
185    fn get_queue(&self) -> &wgpu::Queue;
186
187    /// Retrieve the current texture
188    fn get_current_texture(&self) -> GPUStarterResult<wgpu::SurfaceTexture>;
189
190    /// Retrieve the texture format
191    fn get_texture_format(&self) -> GPUStarterResult<wgpu::TextureFormat>;
192
193    /// Resize the window
194    fn resize(&mut self, sizes: (u32, u32));
195}