Basic window surface
This commit is contained in:
parent
d25d006cec
commit
4cd1a3e7cd
|
@ -1039,6 +1039,12 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pollster"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
|
||||
|
||||
[[package]]
|
||||
name = "presser"
|
||||
version = "0.3.1"
|
||||
|
@ -1232,6 +1238,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"env_logger",
|
||||
"log",
|
||||
"pollster",
|
||||
"wgpu",
|
||||
"winit",
|
||||
]
|
||||
|
|
|
@ -9,5 +9,6 @@ edition = "2021"
|
|||
anyhow = "1.0.80"
|
||||
env_logger = "0.11.3"
|
||||
log = "0.4.21"
|
||||
pollster = "0.3.0"
|
||||
wgpu = "0.19.3"
|
||||
winit = "0.29.14"
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
use anyhow::Result;
|
||||
use winit::{
|
||||
dpi::PhysicalSize, event::WindowEvent, event_loop::EventLoopWindowTarget, window::Window,
|
||||
};
|
||||
|
||||
pub struct Context<'w> {
|
||||
pub window: &'w Window,
|
||||
pub instance: wgpu::Instance,
|
||||
pub size: PhysicalSize<u32>,
|
||||
pub surface: wgpu::Surface<'w>,
|
||||
pub surface_config: wgpu::SurfaceConfiguration,
|
||||
pub adapter: wgpu::Adapter,
|
||||
pub device: wgpu::Device,
|
||||
pub queue: wgpu::Queue,
|
||||
}
|
||||
|
||||
impl<'w> Context<'w> {
|
||||
pub async fn new(window: &'w Window, limits: wgpu::Limits) -> Result<Self> {
|
||||
log::info!("Initialising WGPU context...");
|
||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||
backends: wgpu::Backends::VULKAN,
|
||||
dx12_shader_compiler: Default::default(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// To be able to start drawing we need a few things:
|
||||
// - A surface
|
||||
// - A GPU device to draw to the surface
|
||||
// - A draw command queue
|
||||
log::info!("Initialising window surface...");
|
||||
let surface = instance.create_surface(window)?;
|
||||
|
||||
log::info!("Requesting GPU adapter...");
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: Some(&surface),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
log::info!("Checking GPU adapter meets requirements");
|
||||
log::info!("Requesting GPU device...");
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
required_features: wgpu::Features::empty(),
|
||||
required_limits: limits,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
log::info!("Configuring window surface...");
|
||||
let size = window.inner_size();
|
||||
let surface_config = surface
|
||||
.get_default_config(&adapter, size.width, size.height)
|
||||
.unwrap();
|
||||
surface.configure(&device, &surface_config);
|
||||
|
||||
Ok(Self {
|
||||
window,
|
||||
instance,
|
||||
size,
|
||||
surface,
|
||||
surface_config,
|
||||
adapter,
|
||||
device,
|
||||
queue,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resize_surface(&mut self, new_size: PhysicalSize<u32>) {
|
||||
if new_size.width > 0 && new_size.height > 0 {
|
||||
self.size = new_size;
|
||||
self.surface_config.width = new_size.width;
|
||||
self.surface_config.height = new_size.height;
|
||||
self.surface.configure(&self.device, &self.surface_config);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_window_event(
|
||||
&mut self,
|
||||
event: &WindowEvent,
|
||||
elwt: &EventLoopWindowTarget<()>,
|
||||
) -> bool {
|
||||
let mut handled = true;
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
elwt.exit();
|
||||
}
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
self.resize_surface(*physical_size);
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { .. } => {
|
||||
self.resize_surface(self.window.inner_size());
|
||||
}
|
||||
|
||||
_ => handled = false,
|
||||
}
|
||||
|
||||
handled
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
mod context;
|
||||
|
||||
pub use self::context::Context;
|
59
src/main.rs
59
src/main.rs
|
@ -1,8 +1,12 @@
|
|||
mod gfx;
|
||||
|
||||
use anyhow::Result;
|
||||
use gfx::Context;
|
||||
use wgpu::Limits;
|
||||
use winit::{
|
||||
dpi::LogicalSize,
|
||||
event::*,
|
||||
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::{Window, WindowBuilder},
|
||||
};
|
||||
|
||||
|
@ -10,15 +14,23 @@ pub fn main() -> Result<()> {
|
|||
env_logger::init();
|
||||
|
||||
let (event_loop, window) = make_window()?;
|
||||
run(event_loop, window)?;
|
||||
let context = pollster::block_on(Context::new(&window, Limits::default()))?;
|
||||
run(event_loop, context)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(event_loop: EventLoop<()>, window: Window) -> Result<()> {
|
||||
pub fn run(event_loop: EventLoop<()>, mut context: Context) -> Result<()> {
|
||||
event_loop.run(|event, elwt| match event {
|
||||
Event::WindowEvent { window_id, event } if window_id == window.id() => {
|
||||
handle_window_event(event, elwt);
|
||||
Event::WindowEvent { window_id, event } if window_id == context.window.id() => {
|
||||
if context.handle_window_event(&event, elwt) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let WindowEvent::RedrawRequested = event {
|
||||
render(&context);
|
||||
context.window.request_redraw();
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
})?;
|
||||
|
@ -38,8 +50,39 @@ fn make_window() -> Result<(EventLoop<()>, Window)> {
|
|||
Ok((event_loop, window))
|
||||
}
|
||||
|
||||
fn handle_window_event(event: WindowEvent, elwt: &EventLoopWindowTarget<()>) {
|
||||
if let WindowEvent::CloseRequested = event {
|
||||
elwt.exit();
|
||||
fn render(context: &Context) {
|
||||
let output = context.surface.get_current_texture().unwrap();
|
||||
let view = output
|
||||
.texture
|
||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
let mut encoder = context
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("Render Encoder"),
|
||||
});
|
||||
{
|
||||
let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("Render Pass"),
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &view,
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||
r: 0.1,
|
||||
g: 0.2,
|
||||
b: 0.3,
|
||||
a: 1.0,
|
||||
}),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
occlusion_query_set: None,
|
||||
timestamp_writes: None,
|
||||
});
|
||||
}
|
||||
|
||||
// submit will accept anything that implements IntoIter
|
||||
context.queue.submit(std::iter::once(encoder.finish()));
|
||||
output.present();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue