Skip to content

Commit 3384688

Browse files
committed
bla
1 parent c16ec2f commit 3384688

File tree

5 files changed

+329
-6
lines changed

5 files changed

+329
-6
lines changed

generated/graphics/wgpu/cargo-gpu/mygraphics/src/wgpu_renderer/mod.rs

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,110 @@
1-
pub fn main() -> anyhow::Result<()> {
2-
println!("wgpu renderer");
1+
use crate::wgpu_renderer::render_pipeline::MyRenderPipeline;
2+
use crate::wgpu_renderer::swapchain::MySwapchainManager;
3+
use anyhow::Context;
4+
use mygraphics_shaders::ShaderConstants;
5+
use wgpu::RenderPassDescriptor;
6+
use wgpu::wgt::CommandEncoderDescriptor;
7+
use winit::event::{Event, WindowEvent};
8+
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
9+
10+
mod render_pipeline;
11+
mod renderer;
12+
mod swapchain;
13+
14+
pub async fn main() -> anyhow::Result<()> {
15+
// env_logger::init();
16+
let event_loop = EventLoop::new()?;
17+
// FIXME(eddyb) incomplete `winit` upgrade, follow the guides in:
18+
// https://github.com/rust-windowing/winit/releases/tag/v0.30.0
19+
#[allow(deprecated)]
20+
let window = event_loop.create_window(
21+
winit::window::Window::default_attributes()
22+
.with_title("Rust GPU - wgpu")
23+
.with_inner_size(winit::dpi::LogicalSize::new(
24+
f64::from(1280),
25+
f64::from(720),
26+
)),
27+
)?;
28+
29+
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::from_env_or_default());
30+
let surface = instance.create_surface(&window)?;
31+
let adapter =
32+
wgpu::util::initialize_adapter_from_env_or_default(&instance, Some(&surface)).await?;
33+
34+
let required_features = wgpu::Features::PUSH_CONSTANTS;
35+
let required_limits = wgpu::Limits {
36+
max_push_constant_size: 128,
37+
..Default::default()
38+
};
39+
let (device, queue) = adapter
40+
.request_device(&wgpu::DeviceDescriptor {
41+
label: None,
42+
required_features,
43+
required_limits,
44+
experimental_features: wgpu::ExperimentalFeatures::disabled(),
45+
memory_hints: wgpu::MemoryHints::Performance,
46+
trace: Default::default(),
47+
})
48+
.await
49+
.context("Failed to create device")?;
50+
51+
let mut swapchain = MySwapchainManager::new(adapter.clone(), device.clone(), window, surface);
52+
let render_pipeline = MyRenderPipeline::new(&device, swapchain.format())?;
53+
54+
let start = std::time::Instant::now();
55+
let mut event_handler =
56+
move |event: Event<_>, event_loop_window_target: &ActiveEventLoop| match event {
57+
Event::AboutToWait => swapchain.render(|f| {
58+
let mut cmd = device.create_command_encoder(&CommandEncoderDescriptor {
59+
label: Some("main draw"),
60+
});
61+
let mut rpass = cmd.begin_render_pass(&RenderPassDescriptor {
62+
label: Some("main renderpass"),
63+
color_attachments: &[],
64+
depth_stencil_attachment: None,
65+
timestamp_writes: None,
66+
occlusion_query_set: None,
67+
});
68+
render_pipeline.draw(
69+
&mut rpass,
70+
&ShaderConstants {
71+
time: start.elapsed().as_secs_f32(),
72+
width: f.texture().width(),
73+
height: f.texture().height(),
74+
},
75+
);
76+
queue.submit(std::iter::once(cmd));
77+
}),
78+
Event::WindowEvent { event, .. } => {
79+
match event {
80+
WindowEvent::KeyboardInput {
81+
event:
82+
winit::event::KeyEvent {
83+
logical_key:
84+
winit::keyboard::Key::Named(winit::keyboard::NamedKey::Escape),
85+
state: winit::event::ElementState::Pressed,
86+
..
87+
},
88+
..
89+
}
90+
| WindowEvent::CloseRequested => event_loop_window_target.exit(),
91+
WindowEvent::Resized(_) => swapchain.should_recreate(),
92+
_ => {}
93+
}
94+
95+
Ok(())
96+
}
97+
_ => {
98+
event_loop_window_target.set_control_flow(ControlFlow::Poll);
99+
Ok(())
100+
}
101+
};
102+
103+
// FIXME(eddyb) incomplete `winit` upgrade, follow the guides in:
104+
// https://github.com/rust-windowing/winit/releases/tag/v0.30.0
105+
#[allow(deprecated)]
106+
event_loop.run(move |event, event_loop_window_target| {
107+
event_handler(event, event_loop_window_target).unwrap();
108+
})?;
3109
Ok(())
4110
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use mygraphics_shaders::ShaderConstants;
2+
use wgpu::{
3+
ColorTargetState, ColorWrites, Device, FragmentState, FrontFace, MultisampleState, PolygonMode,
4+
PrimitiveState, PrimitiveTopology, RenderPass, RenderPipeline, RenderPipelineDescriptor,
5+
ShaderStages, TextureFormat, VertexState, include_spirv,
6+
};
7+
8+
pub struct MyRenderPipeline {
9+
pipeline: RenderPipeline,
10+
}
11+
12+
impl MyRenderPipeline {
13+
pub fn new(device: &Device, out_format: TextureFormat) -> anyhow::Result<Self> {
14+
let module = device.create_shader_module(include_spirv!(env!("SHADER_SPV_PATH")));
15+
Ok(Self {
16+
pipeline: device.create_render_pipeline(&RenderPipelineDescriptor {
17+
label: Some("MyRenderPipeline"),
18+
layout: None,
19+
vertex: VertexState {
20+
module: &module,
21+
entry_point: None,
22+
compilation_options: Default::default(),
23+
buffers: &[],
24+
},
25+
primitive: PrimitiveState {
26+
topology: PrimitiveTopology::TriangleList,
27+
strip_index_format: None,
28+
front_face: FrontFace::Ccw,
29+
cull_mode: None,
30+
unclipped_depth: false,
31+
polygon_mode: PolygonMode::Fill,
32+
conservative: false,
33+
},
34+
depth_stencil: None,
35+
multisample: MultisampleState::default(),
36+
fragment: Some(FragmentState {
37+
module: &module,
38+
entry_point: None,
39+
compilation_options: Default::default(),
40+
targets: &[Some(ColorTargetState {
41+
format: out_format,
42+
blend: None,
43+
write_mask: ColorWrites::ALL,
44+
})],
45+
}),
46+
multiview: None,
47+
cache: None,
48+
}),
49+
})
50+
}
51+
52+
pub fn draw(&self, rpass: &mut RenderPass<'_>, shader_constants: &ShaderConstants) {
53+
rpass.set_pipeline(&self.pipeline);
54+
rpass.set_push_constants(
55+
ShaderStages::VERTEX_FRAGMENT,
56+
0,
57+
bytemuck::bytes_of(shader_constants),
58+
);
59+
rpass.draw(0..3, 0..1);
60+
}
61+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::wgpu_renderer::render_pipeline::MyRenderPipeline;
2+
use mygraphics_shaders::ShaderConstants;
3+
use wgpu::wgt::CommandEncoderDescriptor;
4+
use wgpu::{
5+
Color, Device, LoadOp, Operations, Queue, RenderPassColorAttachment, RenderPassDescriptor,
6+
StoreOp, TextureFormat, TextureView,
7+
};
8+
9+
pub struct MyRenderer {
10+
pub device: Device,
11+
pub queue: Queue,
12+
pipeline: MyRenderPipeline,
13+
}
14+
15+
impl MyRenderer {
16+
pub fn new(device: Device, queue: Queue, out_format: TextureFormat) -> anyhow::Result<Self> {
17+
Ok(Self {
18+
pipeline: MyRenderPipeline::new(&device, out_format)?,
19+
device,
20+
queue,
21+
})
22+
}
23+
24+
pub fn render(&self, shader_constants: &ShaderConstants, output: TextureView) {
25+
let mut cmd = self
26+
.device
27+
.create_command_encoder(&CommandEncoderDescriptor {
28+
label: Some("main draw"),
29+
});
30+
31+
let mut rpass = cmd.begin_render_pass(&RenderPassDescriptor {
32+
label: Some("main renderpass"),
33+
color_attachments: &[Some(RenderPassColorAttachment {
34+
view: &output,
35+
depth_slice: None,
36+
resolve_target: None,
37+
ops: Operations {
38+
load: LoadOp::Clear(Color::BLACK),
39+
store: StoreOp::Store,
40+
},
41+
})],
42+
depth_stencil_attachment: None,
43+
timestamp_writes: None,
44+
occlusion_query_set: None,
45+
});
46+
self.pipeline.draw(&mut rpass, shader_constants);
47+
48+
self.queue.submit(std::iter::once(cmd.finish()));
49+
}
50+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use anyhow::Context;
2+
use wgpu::{Adapter, Device, Surface, SurfaceError, TextureFormat, TextureView};
3+
use winit::dpi::PhysicalSize;
4+
use winit::window::Window;
5+
6+
pub struct MySwapchainManager {
7+
adapter: Adapter,
8+
device: Device,
9+
window: Window,
10+
surface: Surface<'static>,
11+
format: TextureFormat,
12+
13+
// state below
14+
active: Option<ActiveConfiguration>,
15+
should_recreate: bool,
16+
}
17+
18+
pub struct ActiveConfiguration {
19+
size: PhysicalSize<u32>,
20+
}
21+
22+
impl MySwapchainManager {
23+
pub fn new(
24+
adapter: Adapter,
25+
device: Device,
26+
window: Window,
27+
surface: Surface<'static>,
28+
) -> Self {
29+
let caps = surface.get_capabilities(&adapter);
30+
Self {
31+
adapter,
32+
device,
33+
window,
34+
surface,
35+
format: caps.formats[0],
36+
active: None,
37+
should_recreate: true,
38+
}
39+
}
40+
41+
#[inline]
42+
pub fn should_recreate(&mut self) {
43+
self.should_recreate = true;
44+
}
45+
46+
pub fn format(&self) -> TextureFormat {
47+
self.format
48+
}
49+
50+
pub fn render<R>(&mut self, f: impl FnOnce(TextureView) -> R) -> R {
51+
let size = self.window.inner_size();
52+
if let Some(active) = self.active {
53+
if active.size != size {
54+
self.should_recreate();
55+
}
56+
} else {
57+
self.should_recreate();
58+
}
59+
60+
const RECREATE_ATTEMPTS: u32 = 10;
61+
for _ in 0..RECREATE_ATTEMPTS {
62+
if self.should_recreate {
63+
self.should_recreate = false;
64+
self.configure_surface(size)?;
65+
}
66+
67+
match self.surface.get_current_texture() {
68+
Ok(surface_texture) => {
69+
if surface_texture.suboptimal {
70+
self.should_recreate = true;
71+
}
72+
let output_view =
73+
surface_texture
74+
.texture
75+
.create_view(&wgpu::TextureViewDescriptor {
76+
format: Some(self.format),
77+
..wgpu::TextureViewDescriptor::default()
78+
});
79+
let r = f(output_view);
80+
surface_texture.present();
81+
return Ok(r);
82+
}
83+
Err(SurfaceError::Outdated | SurfaceError::Lost) => {
84+
self.should_recreate = true;
85+
}
86+
};
87+
}
88+
}
89+
90+
fn configure_surface(&mut self, size: PhysicalSize<u32>) -> anyhow::Result<()> {
91+
let mut surface_config = self
92+
.surface
93+
.get_default_config(&self.adapter, size.width, size.height)
94+
.with_context(|| {
95+
format!(
96+
"Incompatible adapter for surface, returned capabilities: {:?}",
97+
self.surface.get_capabilities(&self.adapter)
98+
)
99+
})?;
100+
101+
// force srgb surface format
102+
surface_config.view_formats.push(self.format);
103+
// limit framerate to vsync
104+
surface_config.present_mode = wgpu::PresentMode::AutoVsync;
105+
self.surface.configure(&self.device, &surface_config);
106+
107+
self.active = Some(ActiveConfiguration { size });
108+
Ok(())
109+
}
110+
}

0 commit comments

Comments
 (0)