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}