Skip to content

Commit 0808dd3

Browse files
committed
Filled init wgpu page, more clarification pending
1 parent 72a858d commit 0808dd3

File tree

6 files changed

+300
-67
lines changed

6 files changed

+300
-67
lines changed

code/guide/getting-started/hello-triangle/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ impl Renderer {
7878
.expect("Failed to request device")
7979
});
8080

81+
// #region renderer-new-surface-config
8182
let surface_capabilities = surface.get_capabilities(&adapter);
8283

8384
let surface_format = surface_capabilities
@@ -98,6 +99,7 @@ impl Renderer {
9899
alpha_mode: CompositeAlphaMode::Auto,
99100
view_formats: vec![],
100101
};
102+
// #endregion renderer-new-surface-config
101103

102104
let mut renderer = Self {
103105
device,

code/guide/getting-started/init-wgpu/src/main.rs

Lines changed: 72 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ use std::sync::Arc;
55
use tokio::runtime;
66
use tokio::runtime::Runtime;
77
use wgpu::{
8-
Backends, Color, CommandEncoderDescriptor, CompositeAlphaMode, Device, DeviceDescriptor,
9-
ExperimentalFeatures, Features, Instance, InstanceDescriptor, Limits, LoadOp, MemoryHints,
10-
Operations, PowerPreference, PresentMode, Queue, RenderPassColorAttachment,
11-
RenderPassDescriptor, RequestAdapterOptions, StoreOp, Surface, SurfaceConfiguration,
12-
SurfaceError, TextureFormat, TextureUsages, TextureViewDescriptor,
8+
Backends, Color, CommandEncoderDescriptor, Device, DeviceDescriptor, ExperimentalFeatures,
9+
Features, Instance, InstanceDescriptor, Limits, LoadOp, MemoryHints, Operations,
10+
PowerPreference, Queue, RenderPassColorAttachment, RenderPassDescriptor, RequestAdapterOptions,
11+
StoreOp, Surface, SurfaceConfiguration, SurfaceError, TextureViewDescriptor,
1312
};
1413
use winit::application::ApplicationHandler;
1514
use winit::dpi::PhysicalSize;
@@ -23,8 +22,8 @@ enum App {
2322
Loading,
2423
Ready {
2524
window: Arc<Window>,
26-
renderer: Box<Renderer>,
27-
need_to_resize_surface: bool,
25+
renderer: Box<Renderer>, // [!code ++]
26+
need_to_resize_surface: bool, // [!code ++]
2827
},
2928
}
3029
// #endregion appstate
@@ -39,20 +38,27 @@ struct Renderer {
3938
// #endregion renderer
4039

4140
impl Renderer {
42-
// #region renderer-new
41+
// #region renderer-new-size
4342
fn new(window: Arc<Window>, runtime: Arc<Runtime>) -> Self {
4443
let mut physical_size = window.inner_size();
4544
physical_size.width = physical_size.width.max(1);
4645
physical_size.height = physical_size.height.max(1);
46+
// #endregion renderer-new-size
4747

48+
// #region renderer-new-instance
4849
let instance = Instance::new(&InstanceDescriptor {
4950
backends: Backends::PRIMARY,
5051
..Default::default()
5152
});
53+
// #endregion renderer-new-instance
5254

55+
// #region renderer-new-surface
5356
let surface = instance
5457
.create_surface(window)
5558
.expect("Failed to create surface");
59+
// #endregion renderer-new-surface
60+
61+
// #region renderer-new-adapter
5662
let adapter = runtime.block_on(async {
5763
instance
5864
.request_adapter(&RequestAdapterOptions {
@@ -63,11 +69,13 @@ impl Renderer {
6369
.await
6470
.expect("Failed to request adapter")
6571
});
72+
// #endregion renderer-new-adapter
6673

74+
// #region renderer-new-device
6775
let (device, queue) = runtime.block_on(async {
6876
adapter
6977
.request_device(&DeviceDescriptor {
70-
label: None,
78+
label: Some("Main device"),
7179
required_features: adapter.features() & Features::default(),
7280
required_limits: Limits::default().using_resolution(adapter.limits()),
7381
memory_hints: MemoryHints::Performance,
@@ -77,40 +85,25 @@ impl Renderer {
7785
.await
7886
.expect("Failed to request device")
7987
});
88+
// #endregion renderer-new-device
8089

81-
let surface_capabilities = surface.get_capabilities(&adapter);
82-
83-
let surface_format = surface_capabilities
84-
.formats
85-
.iter()
86-
.copied()
87-
.find(TextureFormat::is_srgb)
88-
.or_else(|| surface_capabilities.formats.first().copied())
89-
.expect("Failed to get surface format");
90-
91-
let surface_config = SurfaceConfiguration {
92-
usage: TextureUsages::RENDER_ATTACHMENT,
93-
format: surface_format,
94-
width: physical_size.width,
95-
height: physical_size.height,
96-
present_mode: PresentMode::AutoNoVsync,
97-
desired_maximum_frame_latency: 2,
98-
alpha_mode: CompositeAlphaMode::Auto,
99-
view_formats: vec![],
100-
};
90+
// #region renderer-new-surface-config
91+
let surface_config = surface
92+
.get_default_config(&adapter, physical_size.width, physical_size.height)
93+
.expect("Failed to get default surface config");
94+
// #endregion renderer-new-surface-config
10195

102-
let renderer = Self {
96+
// #region renderer-new-return
97+
surface.configure(&device, &surface_config);
98+
99+
Self {
103100
device,
104101
queue,
105102
surface,
106103
surface_config,
107-
};
108-
109-
renderer.resize_surface(physical_size);
110-
111-
renderer
104+
}
112105
}
113-
// #endregion renderer-new
106+
// #endregion renderer-new-return
114107

115108
// #region renderer-resize
116109
fn resize_surface(&self, size: PhysicalSize<u32>) {
@@ -128,18 +121,26 @@ impl Renderer {
128121
}
129122
// #endregion renderer-resize
130123

131-
// #region renderer-render
124+
// #region renderer-render-texture
132125
fn render(&mut self, window: Arc<Window>) {
133126
match self.surface.get_current_texture() {
134127
Ok(frame) => {
128+
// #endregion renderer-render-texture
129+
// #region renderer-render-encoder
135130
let mut encoder = self
136131
.device
137-
.create_command_encoder(&CommandEncoderDescriptor { label: None });
132+
.create_command_encoder(&CommandEncoderDescriptor {
133+
label: Some("Main command encoder"),
134+
});
135+
// #endregion renderer-render-encoder
138136

137+
// #region renderer-render-view
139138
let view = frame.texture.create_view(&TextureViewDescriptor::default());
139+
// #endregion renderer-render-view
140140

141+
// #region renderer-render-pass
141142
encoder.begin_render_pass(&RenderPassDescriptor {
142-
label: None,
143+
label: Some("Clear render pass"),
143144
color_attachments: &[Some(RenderPassColorAttachment {
144145
view: &view,
145146
resolve_target: None,
@@ -153,10 +154,14 @@ impl Renderer {
153154
timestamp_writes: None,
154155
occlusion_query_set: None,
155156
});
157+
// #endregion renderer-render-pass
156158

159+
// #region renderer-render-finish
157160
self.queue.submit([encoder.finish()]);
158161
window.pre_present_notify();
159162
frame.present();
163+
// #endregion renderer-render-finish
164+
// #region renderer-render-error
160165
}
161166
Err(error) => match error {
162167
SurfaceError::OutOfMemory => {
@@ -168,22 +173,24 @@ impl Renderer {
168173
},
169174
};
170175
}
176+
// #endregion renderer-render-error
171177
// #endregion renderer-render
172178
}
173179

174180
impl ApplicationHandler for App {
175181
// #region appsetup
176182
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
177183
if let Self::Loading = self {
184+
// [!code ++]
178185
let runtime = Arc::new(
179-
runtime::Builder::new_current_thread()
180-
.build()
181-
.expect("Failed to create tokio runtime"),
182-
);
186+
runtime::Builder::new_current_thread() // [!code ++]
187+
.build() // [!code ++]
188+
.expect("Failed to create tokio runtime"), // [!code ++]
189+
); // [!code ++]
183190

184191
let window_attributes = WindowAttributes::default()
185192
.with_title("WGPU Tutorial")
186-
.with_visible(false);
193+
.with_visible(false); // [!code ++]
187194

188195
let window = Arc::new(
189196
event_loop
@@ -193,27 +200,27 @@ impl ApplicationHandler for App {
193200

194201
center_window(window.clone());
195202

196-
event_loop.set_control_flow(ControlFlow::Wait);
203+
event_loop.set_control_flow(ControlFlow::Wait); // [!code ++]
197204

198-
let renderer = Renderer::new(window.clone(), runtime.clone());
205+
let renderer = Renderer::new(window.clone(), runtime.clone()); // [!code ++]
199206

200207
*self = Self::Ready {
201208
window,
202-
renderer: Box::new(renderer),
203-
need_to_resize_surface: false,
209+
renderer: Box::new(renderer), // [!code ++]
210+
need_to_resize_surface: false, // [!code ++]
204211
}
205212
}
206213

207-
let Self::Ready {
208-
window, renderer, ..
209-
} = self
210-
else {
211-
return;
212-
};
214+
let Self::Ready { // [!code ++]
215+
window, renderer, .. // [!code ++]
216+
} = self // [!code ++]
217+
else { // [!code ++]
218+
return; // [!code ++]
219+
}; // [!code ++]
213220

214-
renderer.render(window.clone());
221+
renderer.render(window.clone()); // [!code ++]
215222

216-
window.set_visible(true);
223+
window.set_visible(true); // [!code ++]
217224
}
218225
// #endregion appsetup
219226

@@ -226,8 +233,8 @@ impl ApplicationHandler for App {
226233
) {
227234
let Self::Ready {
228235
window,
229-
renderer,
230-
need_to_resize_surface,
236+
renderer, // [!code ++]
237+
need_to_resize_surface, // [!code ++]
231238
..
232239
} = self
233240
else {
@@ -236,20 +243,21 @@ impl ApplicationHandler for App {
236243

237244
match event {
238245
WindowEvent::RedrawRequested => {
246+
// [!code ++]
239247
if *need_to_resize_surface {
240-
let size = window.inner_size();
248+
let size = window.inner_size(); // [!code ++]
241249

242-
renderer.resize_surface(size);
250+
renderer.resize_surface(size); // [!code ++]
243251

244-
*need_to_resize_surface = false;
245-
}
252+
*need_to_resize_surface = false; // [!code ++]
253+
} // [!code ++]
246254

247-
renderer.render(window.clone());
255+
renderer.render(window.clone()); // [!code ++]
248256

249257
window.request_redraw();
250258
}
251259
WindowEvent::Resized(_) => {
252-
*need_to_resize_surface = true;
260+
*need_to_resize_surface = true; // [!code ++]
253261
window.request_redraw();
254262
}
255263
WindowEvent::CloseRequested => {

docs/guide/getting-started/creating-window/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ wgpu требует resolver 2 в Cargo.toml для корректной раб
8282

8383
Трейт `ApplicationHandler` имеет следующие обязательные для реализации методы, наравне с множеством опциональных:
8484

85-
```rust
85+
```rs
8686
trait ApplicationHandler {
8787
fn resumed(&mut self, event_loop: &ActiveEventLoop);
8888
fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent);
@@ -102,7 +102,7 @@ trait ApplicationHandler {
102102

103103
Реализация выглядит стандартно:
104104

105-
```rust
105+
```rs
106106
impl ApplicationHandler for App {
107107
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
108108
// ...
@@ -210,7 +210,7 @@ winit сначала вызовет наш обработчик события `
210210

211211
## Результаты работы
212212

213-
В результате выполнения данного кода мы должны увидеть в центре экрана пустое окно. Содержимое и внешний вид будет
213+
В результате выполнения данного кода мы должны увидеть в центре экрана пустое окно. Содержимое и внешний вид будут
214214
различаться в зависимости от операционной системы, ниже приведен скриншот с Windows 11:
215215

216216
![Window](./window.png)

docs/guide/getting-started/hello-triangle/index.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,23 @@ next:
88
---
99

1010
# Первый треугольник
11+
12+
13+
<<< @/../code/guide/getting-started/hello-triangle/src/main.rs#renderer-new-surface-config
14+
15+
Получаем доступные возможности нашей поверхности, которые исходят из возможностей переданного адаптера
16+
17+
Далее нам нужно определиться с форматом кадров, которые мы будем выводить на поверхность, то есть в окно. На данный момент мы просто можем взять поддерживаемый список форматов поверхности, попытаться выбрать формат с поддержкой `SRGB`, и взять первый попавшийся, если такого не нашлось.
18+
19+
В реальном приложении вы, скорее всего, захотите организовать здесь более сложную логику выбора формата.
20+
21+
Теперь, получив подходящий формат поверхности, мы можем создать объект ее конфигурации `SurfaceConfiguration`:
22+
23+
- `usage` - как мы будем использовать эту поверхность. На самом деле это параметр текстуры, поскольку отрисовку мы производим именно в нее. Но эта текстура находится в поверхности, поэтому данный параметр задается здесь. Выбираем `RENDER_ATTACHMENT`, то есть указываем, что данная текстура в поверхности будет использоваться как цель рендера, в нее будет выводиться полученная картинка.э
24+
- `format` - полученный нами формат поверхности
25+
- `width` - ширина поверхности. Передаем вычисленное ранее значение
26+
- `height` - высота поверхности. Передаем вычисленное ранее значение
27+
- `present_mode` - режим отображения кадров на поверхности. Режимов достаточно много, и разные устройства поддерживают разные режимы. Но wgpu сильно облегчает нам здесь жизнь, предоставляя опции `AutoVsync` и `AutoNoVsync`. Эти опции будут перебирать разные режимы отображения, пока не наткнутся на первый поддерживаемый нашим устройством. Различие между ними, соответственно, в наличии или отсутствии вертикальной синхронизации, то есть ограничения частоты вывода кадров частотой монитора.
28+
- `desired_maximum_frame_latency` - число кадров, которое может одновременно ожидать вывода на экран. Обычно указывается от 1 до 3, но может быть и больше. Не может быть меньше 1. Слишком низкое значение может привести к простою GPU, которой просто некуда будет отдавать готовый кадр, если поверхность не успевает их отрисовывать. По-умолчанию принято ставить 2, как оптимальное значение для большинства случаев.
29+
- `alpha_mode` - режим альфа-канала, отвечающего за прозрачность цветов. В данном случае выбираем автоматическое определение на основании поддерживаемого
30+
- `view_formats` - форматы представлений текстур, которые будут поддерживаться данной поверхностью для рендера. Собственный формат поверхности поддерживается всегда, поэтому нет нужды что-либо туда передавать.

0 commit comments

Comments
 (0)