Bump raw window handle to 0.6.0 (#4202)

Co-authored-by: junglie85 <junglie85@gmail.com>
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
TornaxO7 2023-10-27 07:24:46 +02:00 committed by GitHub
parent 2a9fdf9aa1
commit 4c5a817071
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1185 additions and 660 deletions

View File

@ -441,7 +441,9 @@ jobs:
**/*-difference.png
- name: generate coverage report
id: coverage
shell: bash
continue-on-error: true
run: |
set -e
@ -449,6 +451,7 @@ jobs:
- name: upload coverage report to codecov
uses: codecov/codecov-action@v3
if: steps.coverage.outcome == 'success'
with:
files: lcov.info

654
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -109,7 +109,7 @@ pico-args = { version = "0.5.0", features = [
png = "0.17.10"
pollster = "0.3"
profiling = { version = "1", default-features = false }
raw-window-handle = "0.5"
raw-window-handle = "0.6"
renderdoc-sys = "1.0.0"
ron = "0.8"
serde = "1"
@ -123,7 +123,7 @@ wgpu-example = { version = "0.18.0", path = "./examples/common" }
wgpu-macros = { version = "0.18.0", path = "./wgpu-macros" }
wgpu-test = { version = "0.18.0", path = "./tests" }
wgpu-types = { version = "0.18.0", path = "./wgpu-types" }
winit = { version = "0.28.7", features = ["android-native-activity"] }
winit = { version = "0.29.2", features = [ "android-native-activity" ] }
# Metal dependencies
block = "0.1"

View File

@ -2,6 +2,10 @@ use bytemuck::{Pod, Zeroable};
use nanorand::{Rng, WyRand};
use std::{borrow::Cow, mem};
use wgpu::util::DeviceExt;
use winit::{
event::{ElementState, KeyEvent},
keyboard::{Key, NamedKey},
};
const MAX_BUNNIES: usize = 1 << 20;
const BUNNY_SIZE: f32 = 0.15 * 256.0;
@ -18,24 +22,115 @@ struct Globals {
#[repr(C, align(256))]
#[derive(Clone, Copy, Zeroable)]
struct Locals {
struct Bunny {
position: [f32; 2],
velocity: [f32; 2],
color: u32,
_pad: u32,
}
impl Bunny {
fn update_data(&mut self, delta: f32, extent: &[u32; 2]) {
self.position[0] += self.velocity[0] * delta;
self.position[1] += self.velocity[1] * delta;
self.velocity[1] += GRAVITY * delta;
if (self.velocity[0] > 0.0 && self.position[0] + 0.5 * BUNNY_SIZE > extent[0] as f32)
|| (self.velocity[0] < 0.0 && self.position[0] - 0.5 * BUNNY_SIZE < 0.0)
{
self.velocity[0] *= -1.0;
}
if self.velocity[1] < 0.0 && self.position[1] < 0.5 * BUNNY_SIZE {
self.velocity[1] *= -1.0;
}
}
}
/// Example struct holds references to wgpu resources and frame persistent data
struct Example {
global_group: wgpu::BindGroup,
local_group: wgpu::BindGroup,
pipeline: wgpu::RenderPipeline,
bunnies: Vec<Locals>,
bunnies: Vec<Bunny>,
local_buffer: wgpu::Buffer,
extent: [u32; 2],
rng: WyRand,
}
impl Example {
fn spawn_bunnies(&mut self) {
let spawn_count = 64 + self.bunnies.len() / 2;
let color = self.rng.generate::<u32>();
println!(
"Spawning {} bunnies, total at {}",
spawn_count,
self.bunnies.len() + spawn_count
);
for _ in 0..spawn_count {
let speed = self.rng.generate::<f32>() * MAX_VELOCITY - (MAX_VELOCITY * 0.5);
self.bunnies.push(Bunny {
position: [0.0, 0.5 * (self.extent[1] as f32)],
velocity: [speed, 0.0],
color,
_pad: 0,
});
}
}
fn render_inner(
&mut self,
view: &wgpu::TextureView,
device: &wgpu::Device,
queue: &wgpu::Queue,
) {
let delta = 0.01;
for bunny in self.bunnies.iter_mut() {
bunny.update_data(delta, &self.extent);
}
let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment;
queue.write_buffer(&self.local_buffer, 0, unsafe {
std::slice::from_raw_parts(
self.bunnies.as_ptr() as *const u8,
self.bunnies.len() * uniform_alignment as usize,
)
});
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
{
let clear_color = wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
};
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(clear_color),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
rpass.set_pipeline(&self.pipeline);
rpass.set_bind_group(0, &self.global_group, &[]);
for i in 0..self.bunnies.len() {
let offset =
(i as wgpu::DynamicOffset) * (uniform_alignment as wgpu::DynamicOffset);
rpass.set_bind_group(1, &self.local_group, &[offset]);
rpass.draw(0..4, 0..1);
}
}
queue.submit(Some(encoder.finish()));
}
}
impl wgpu_example::framework::Example for Example {
fn init(
config: &wgpu::SurfaceConfiguration,
@ -90,7 +185,7 @@ impl wgpu_example::framework::Example for Example {
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: true,
min_binding_size: wgpu::BufferSize::new(mem::size_of::<Locals>() as _),
min_binding_size: wgpu::BufferSize::new(mem::size_of::<Bunny>() as _),
},
count: None,
}],
@ -228,7 +323,7 @@ impl wgpu_example::framework::Example for Example {
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: &local_buffer,
offset: 0,
size: wgpu::BufferSize::new(mem::size_of::<Locals>() as _),
size: wgpu::BufferSize::new(mem::size_of::<Bunny>() as _),
}),
}],
label: None,
@ -249,31 +344,16 @@ impl wgpu_example::framework::Example for Example {
fn update(&mut self, event: winit::event::WindowEvent) {
if let winit::event::WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(winit::event::VirtualKeyCode::Space),
state: winit::event::ElementState::Pressed,
event:
KeyEvent {
logical_key: Key::Named(NamedKey::Space),
state: ElementState::Pressed,
..
},
..
} = event
{
let spawn_count = 64 + self.bunnies.len() / 2;
let color = self.rng.generate::<u32>();
println!(
"Spawning {} bunnies, total at {}",
spawn_count,
self.bunnies.len() + spawn_count
);
for _ in 0..spawn_count {
let speed = self.rng.generate::<f32>() * MAX_VELOCITY - (MAX_VELOCITY * 0.5);
self.bunnies.push(Locals {
position: [0.0, 0.5 * (self.extent[1] as f32)],
velocity: [speed, 0.0],
color,
_pad: 0,
});
}
self.spawn_bunnies();
}
}
@ -287,64 +367,12 @@ impl wgpu_example::framework::Example for Example {
}
fn render(&mut self, view: &wgpu::TextureView, device: &wgpu::Device, queue: &wgpu::Queue) {
let delta = 0.01;
for bunny in self.bunnies.iter_mut() {
bunny.position[0] += bunny.velocity[0] * delta;
bunny.position[1] += bunny.velocity[1] * delta;
bunny.velocity[1] += GRAVITY * delta;
if (bunny.velocity[0] > 0.0
&& bunny.position[0] + 0.5 * BUNNY_SIZE > self.extent[0] as f32)
|| (bunny.velocity[0] < 0.0 && bunny.position[0] - 0.5 * BUNNY_SIZE < 0.0)
{
bunny.velocity[0] *= -1.0;
}
if bunny.velocity[1] < 0.0 && bunny.position[1] < 0.5 * BUNNY_SIZE {
bunny.velocity[1] *= -1.0;
}
}
self.spawn_bunnies();
let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment;
queue.write_buffer(&self.local_buffer, 0, unsafe {
std::slice::from_raw_parts(
self.bunnies.as_ptr() as *const u8,
self.bunnies.len() * uniform_alignment as usize,
)
});
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
{
let clear_color = wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
};
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(clear_color),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
rpass.set_pipeline(&self.pipeline);
rpass.set_bind_group(0, &self.global_group, &[]);
for i in 0..self.bunnies.len() {
let offset =
(i as wgpu::DynamicOffset) * (uniform_alignment as wgpu::DynamicOffset);
rpass.set_bind_group(1, &self.local_group, &[offset]);
rpass.draw(0..4, 0..1);
for _frame_number in 0..3 {
self.render_inner(view, device, queue);
}
}
queue.submit(Some(encoder.finish()));
}
}
#[cfg(not(test))]

View File

@ -9,8 +9,9 @@ use web_sys::{ImageBitmapRenderingContext, OffscreenCanvas};
use wgpu::{WasmNotSend, WasmNotSync};
use wgpu_test::GpuTestConfiguration;
use winit::{
event::{self, WindowEvent},
event::{self, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::{Key, NamedKey},
};
#[allow(dead_code)]
@ -31,9 +32,11 @@ pub trait Example: 'static + Sized {
fn optional_features() -> wgpu::Features {
wgpu::Features::empty()
}
fn required_features() -> wgpu::Features {
wgpu::Features::empty()
}
fn required_downlevel_capabilities() -> wgpu::DownlevelCapabilities {
wgpu::DownlevelCapabilities {
flags: wgpu::DownlevelFlags::empty(),
@ -41,27 +44,31 @@ pub trait Example: 'static + Sized {
..wgpu::DownlevelCapabilities::default()
}
}
fn required_limits() -> wgpu::Limits {
wgpu::Limits::downlevel_webgl2_defaults() // These downlevel limits will allow the code to run on all possible hardware
}
fn init(
config: &wgpu::SurfaceConfiguration,
adapter: &wgpu::Adapter,
device: &wgpu::Device,
queue: &wgpu::Queue,
) -> Self;
fn resize(
&mut self,
config: &wgpu::SurfaceConfiguration,
device: &wgpu::Device,
queue: &wgpu::Queue,
);
fn update(&mut self, event: WindowEvent);
fn render(&mut self, view: &wgpu::TextureView, device: &wgpu::Device, queue: &wgpu::Queue);
}
struct Setup {
window: winit::window::Window,
event_loop: EventLoop<()>,
instance: wgpu::Instance,
size: winit::dpi::PhysicalSize<u32>,
@ -85,7 +92,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
env_logger::init();
};
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let mut builder = winit::window::WindowBuilder::new();
builder = builder.with_title(title);
#[cfg(windows_OFF)] // TODO
@ -109,7 +116,9 @@ async fn setup<E: Example>(title: &str) -> Setup {
.and_then(|win| win.document())
.and_then(|doc| doc.body())
.and_then(|body| {
body.append_child(&web_sys::Element::from(window.canvas()))
body.append_child(&web_sys::Element::from(
window.canvas().expect("Couldn't get canvas"),
))
.ok()
})
.expect("couldn't append canvas to document body");
@ -133,6 +142,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
let bitmap_renderer = window
.canvas()
.expect("Couldn't get html canvas")
.get_context("bitmaprenderer")
.expect("couldn't create ImageBitmapRenderingContext (Result)")
.expect("couldn't create ImageBitmapRenderingContext (Option)")
@ -230,7 +240,6 @@ async fn setup<E: Example>(title: &str) -> Setup {
.expect("Unable to find a suitable GPU adapter!");
Setup {
window,
event_loop,
instance,
size,
@ -245,7 +254,6 @@ async fn setup<E: Example>(title: &str) -> Setup {
fn start<E: Example>(
#[cfg(not(target_arch = "wasm32"))] Setup {
window,
event_loop,
instance,
size,
@ -255,7 +263,6 @@ fn start<E: Example>(
queue,
}: Setup,
#[cfg(target_arch = "wasm32")] Setup {
window,
event_loop,
instance,
size,
@ -282,27 +289,20 @@ fn start<E: Example>(
let (mut frame_count, mut accum_time) = (0, 0.0);
log::info!("Entering render loop...");
event_loop.run(move |event, _, control_flow| {
event_loop
.run(move |event, target| {
let _ = (&instance, &adapter); // force ownership by the closure
*control_flow = if cfg!(feature = "metal-auto-capture") {
ControlFlow::Exit
} else {
ControlFlow::Poll
target.set_control_flow(ControlFlow::Poll);
if cfg!(feature = "metal-auto-capture") {
target.exit();
};
match event {
event::Event::RedrawEventsCleared => {
window.request_redraw();
}
event::Event::WindowEvent {
event:
WindowEvent::Resized(size)
| WindowEvent::ScaleFactorChanged {
new_inner_size: &mut size,
..
},
event: WindowEvent::Resized(size),
..
} => {
log::info!("Resizing to {:?}", size);
config.width = size.width.max(1);
config.height = size.height.max(1);
example.resize(&config, &device, &queue);
@ -310,34 +310,28 @@ fn start<E: Example>(
}
event::Event::WindowEvent { event, .. } => match event {
WindowEvent::KeyboardInput {
input:
event::KeyboardInput {
virtual_keycode: Some(event::VirtualKeyCode::Escape),
state: event::ElementState::Pressed,
event:
KeyEvent {
logical_key: Key::Named(NamedKey::Escape),
..
},
..
}
| WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit;
target.exit();
}
#[cfg(not(target_arch = "wasm32"))]
WindowEvent::KeyboardInput {
input:
event::KeyboardInput {
virtual_keycode: Some(event::VirtualKeyCode::R),
state: event::ElementState::Pressed,
event:
KeyEvent {
logical_key: Key::Character(s),
..
},
..
} => {
} if s == "r" => {
println!("{:#?}", instance.generate_report());
}
_ => {
example.update(event);
}
},
event::Event::RedrawRequested(_) => {
event::WindowEvent::RedrawRequested => {
#[cfg(not(target_arch = "wasm32"))]
{
accum_time += last_frame_inst.elapsed().as_secs_f32();
@ -386,9 +380,12 @@ fn start<E: Example>(
}
}
}
_ => example.update(event),
},
_ => {}
}
});
})
.unwrap();
}
#[cfg(not(target_arch = "wasm32"))]
@ -511,31 +508,8 @@ impl<E: Example + WasmNotSend + WasmNotSync> From<ExampleTestParams<E>> for GpuT
&ctx.queue,
);
{
example.render(&dst_view, &ctx.device, &ctx.queue);
// Handle specific case for bunnymark
#[allow(deprecated)]
if params.image_path == "/examples/bunnymark/screenshot.png" {
// Press spacebar to spawn bunnies
example.update(winit::event::WindowEvent::KeyboardInput {
input: winit::event::KeyboardInput {
scancode: 0,
state: winit::event::ElementState::Pressed,
virtual_keycode: Some(winit::event::VirtualKeyCode::Space),
modifiers: winit::event::ModifiersState::empty(),
},
device_id: unsafe { winit::event::DeviceId::dummy() },
is_synthetic: false,
});
// Step 3 extra frames
for _ in 0..3 {
example.render(&dst_view, &ctx.device, &ctx.queue);
}
}
}
let mut cmd_buf = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());

View File

@ -1,7 +1,7 @@
use std::borrow::Cow;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
event_loop::EventLoop,
window::Window,
};
@ -82,26 +82,28 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
surface.configure(&device, &config);
event_loop.run(move |event, _, control_flow| {
event_loop
.run(move |event, target| {
// Have the closure take ownership of the resources.
// `event_loop.run` never returns, therefore we must do this to ensure
// the resources are properly cleaned up.
let _ = (&instance, &adapter, &shader, &pipeline_layout);
*control_flow = ControlFlow::Wait;
if let Event::WindowEvent {
window_id: _,
event,
} = event
{
match event {
Event::WindowEvent {
event: WindowEvent::Resized(size),
..
} => {
WindowEvent::Resized(new_size) => {
// Reconfigure the surface with the new size
config.width = size.width;
config.height = size.height;
config.width = new_size.width;
config.height = new_size.height;
surface.configure(&device, &config);
// On macos the window needs to be redrawn manually after resizing
window.request_redraw();
}
Event::RedrawRequested(_) => {
WindowEvent::RedrawRequested => {
let frame = surface
.get_current_texture()
.expect("Failed to acquire next swap chain texture");
@ -109,9 +111,12 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder =
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: None,
});
{
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
let mut rpass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
@ -132,17 +137,16 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
queue.submit(Some(encoder.finish()));
frame.present();
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
WindowEvent::CloseRequested => target.exit(),
_ => {}
};
}
});
})
.unwrap();
}
fn main() {
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let window = winit::window::Window::new(&event_loop).unwrap();
#[cfg(not(target_arch = "wasm32"))]
{
@ -159,7 +163,7 @@ fn main() {
.and_then(|win| win.document())
.and_then(|doc| doc.body())
.and_then(|body| {
body.append_child(&web_sys::Element::from(window.canvas()))
body.append_child(&web_sys::Element::from(window.canvas().unwrap()))
.ok()
})
.expect("couldn't append canvas to document body");

View File

@ -3,7 +3,7 @@
use std::collections::HashMap;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
event_loop::EventLoop,
window::{Window, WindowId},
};
@ -95,45 +95,49 @@ async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
.map(|desc| (desc.window.id(), desc.build(&adapter, &device)))
.collect();
event_loop.run(move |event, _, control_flow| {
event_loop
.run(move |event, target| {
// Have the closure take ownership of the resources.
// `event_loop.run` never returns, therefore we must do this to ensure
// the resources are properly cleaned up.
let _ = (&instance, &adapter);
*control_flow = ControlFlow::Wait;
if let Event::WindowEvent { window_id, event } = event {
match event {
Event::WindowEvent {
window_id,
event: WindowEvent::Resized(size),
..
} => {
WindowEvent::Resized(new_size) => {
// Recreate the swap chain with the new size
if let Some(viewport) = viewports.get_mut(&window_id) {
viewport.resize(&device, size);
viewport.resize(&device, new_size);
// On macos the window needs to be redrawn manually after resizing
viewport.desc.window.request_redraw();
}
}
Event::RedrawRequested(window_id) => {
WindowEvent::RedrawRequested => {
if let Some(viewport) = viewports.get_mut(&window_id) {
let frame = viewport.get_current_texture();
let view = frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
{
let _rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
let mut encoder =
device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
});
{
let _rpass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(
wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(viewport.desc.background),
load: wgpu::LoadOp::Clear(
viewport.desc.background,
),
store: wgpu::StoreOp::Store,
},
})],
},
)],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
@ -144,19 +148,17 @@ async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
frame.present();
}
}
Event::WindowEvent {
window_id,
event: WindowEvent::CloseRequested,
..
} => {
WindowEvent::CloseRequested => {
viewports.remove(&window_id);
if viewports.is_empty() {
*control_flow = ControlFlow::Exit
target.exit();
}
}
_ => {}
}
});
}
})
.unwrap();
}
fn main() {
@ -169,7 +171,7 @@ fn main() {
const ROWS: u32 = 4;
const COLUMNS: u32 = 4;
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let mut viewports = Vec::with_capacity((ROWS * COLUMNS) as usize);
for row in 0..ROWS {
for column in 0..COLUMNS {

View File

@ -14,6 +14,10 @@ use wgpu::util::DeviceExt;
#[cfg(test)]
use wgpu_test::FailureCase;
use winit::{
event::{ElementState, KeyEvent, WindowEvent},
keyboard::{Key, NamedKey},
};
#[repr(C)]
#[derive(Clone, Copy, Pod, Zeroable)]
@ -215,27 +219,31 @@ impl wgpu_example::framework::Example for Example {
#[allow(clippy::single_match)]
fn update(&mut self, event: winit::event::WindowEvent) {
match event {
winit::event::WindowEvent::KeyboardInput { input, .. } => {
if let winit::event::ElementState::Pressed = input.state {
match input.virtual_keycode {
WindowEvent::KeyboardInput {
event:
KeyEvent {
logical_key,
state: ElementState::Pressed,
..
},
..
} => match logical_key {
// TODO: Switch back to full scans of possible options when we expose
// supported sample counts to the user.
Some(winit::event::VirtualKeyCode::Left) => {
Key::Named(NamedKey::ArrowLeft) => {
if self.sample_count == self.max_sample_count {
self.sample_count = 1;
self.rebuild_bundle = true;
}
}
Some(winit::event::VirtualKeyCode::Right) => {
Key::Named(NamedKey::ArrowRight) => {
if self.sample_count == 1 {
self.sample_count = self.max_sample_count;
self.rebuild_bundle = true;
}
}
_ => {}
}
}
}
},
_ => {}
}
}

View File

@ -20,8 +20,9 @@
// with actual GPU-allocated WGPU storage buffers.
use encase::ShaderType;
use winit::{
event::{Event, VirtualKeyCode, WindowEvent},
event::{Event, KeyEvent, WindowEvent},
event_loop::EventLoop,
keyboard::{Key, NamedKey},
window::Window,
};
@ -227,39 +228,55 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
// (6)
let mut state = Some(AppState::default());
let main_window_id = wgpu_context.as_ref().unwrap().window.id();
event_loop.run(move |event, _, control_flow| {
control_flow.set_wait();
event_loop
.run(move |event, target| {
match event {
Event::LoopDestroyed => {
Event::LoopExiting => {
wgpu_context = None;
state = None;
}
Event::WindowEvent { window_id, event } if window_id == main_window_id => match event {
Event::WindowEvent { window_id, event } if window_id == main_window_id => {
match event {
WindowEvent::CloseRequested => {
control_flow.set_exit();
target.exit();
}
WindowEvent::KeyboardInput { input, .. } => {
WindowEvent::KeyboardInput {
event:
KeyEvent {
logical_key, text, ..
},
..
} => {
let state_mut = state.as_mut().unwrap();
let wgpu_context_ref = wgpu_context.as_ref().unwrap();
if let Some(virtual_keycode) = input.virtual_keycode {
// (7a)
match virtual_keycode {
VirtualKeyCode::Escape => control_flow.set_exit(),
VirtualKeyCode::Up => state_mut.translate_view(1, 1),
VirtualKeyCode::Down => state_mut.translate_view(-1, 1),
VirtualKeyCode::Left => state_mut.translate_view(-1, 0),
VirtualKeyCode::Right => state_mut.translate_view(1, 0),
VirtualKeyCode::U => state_mut.max_iterations += 3,
VirtualKeyCode::D => state_mut.max_iterations -= 3,
if let Key::Named(key) = logical_key {
match key {
NamedKey::Escape => target.exit(),
NamedKey::ArrowUp => state_mut.translate_view(1, 1),
NamedKey::ArrowDown => state_mut.translate_view(-1, 1),
NamedKey::ArrowLeft => state_mut.translate_view(-1, 0),
NamedKey::ArrowRight => state_mut.translate_view(1, 0),
_ => {}
}
wgpu_context_ref.window.request_redraw();
}
if let Some(text) = text {
if text == "u" {
state_mut.max_iterations += 3;
} else if text == "d" {
state_mut.max_iterations -= 3;
}
};
wgpu_context_ref.window.request_redraw();
}
WindowEvent::MouseWheel { delta, .. } => {
let change = match delta {
winit::event::MouseScrollDelta::LineDelta(_, vertical) => vertical,
winit::event::MouseScrollDelta::PixelDelta(pos) => pos.y as f32 / 20.0,
winit::event::MouseScrollDelta::PixelDelta(pos) => {
pos.y as f32 / 20.0
}
};
let state_mut = state.as_mut().unwrap();
let wgpu_context_ref = wgpu_context.as_ref().unwrap();
@ -272,9 +289,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
wgpu_context_mut.resize(new_size);
wgpu_context_mut.window.request_redraw();
}
_ => {}
},
Event::RedrawRequested(id) if id == main_window_id => {
WindowEvent::RedrawRequested => {
let wgpu_context_ref = wgpu_context.as_ref().unwrap();
let state_ref = state.as_ref().unwrap();
let frame = wgpu_context_ref.surface.get_current_texture().unwrap();
@ -291,20 +306,23 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
struct to WGSL bytes.",
),
);
let mut encoder = wgpu_context_ref
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
let mut encoder = wgpu_context_ref.device.create_command_encoder(
&wgpu::CommandEncoderDescriptor { label: None },
);
{
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
color_attachments: &[Some(
wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::GREEN),
store: wgpu::StoreOp::Store,
},
})],
},
)],
depth_stencil_attachment: None,
occlusion_query_set: None,
timestamp_writes: None,
@ -319,11 +337,15 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
}
_ => {}
}
});
}
_ => {}
}
})
.unwrap();
}
fn main() {
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let window = winit::window::WindowBuilder::new()
.with_title("Remember: Use U/D to change sample count!")
.with_inner_size(winit::dpi::LogicalSize::new(900, 900))
@ -344,7 +366,9 @@ fn main() {
.and_then(|win| win.document())
.expect("Failed to get document.");
let body = document.body().unwrap();
body.append_child(&web_sys::Element::from(window.canvas()))
body.append_child(&web_sys::Element::from(
window.canvas().expect("Couldn't get canvas"),
))
.unwrap();
let controls_text = document
.create_element("p")

View File

@ -12,9 +12,14 @@ fn main() {
};
#[cfg(feature = "winit")]
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
#[cfg(feature = "winit")]
use winit::{event_loop::EventLoop, window::WindowBuilder};
use winit::{
event::KeyEvent,
event_loop::EventLoop,
keyboard::{Key, NamedKey},
window::WindowBuilder,
};
env_logger::init();
@ -35,7 +40,7 @@ fn main() {
#[cfg(feature = "winit")]
let event_loop = {
log::info!("Creating a window");
EventLoop::new()
EventLoop::new().unwrap()
};
#[cfg(feature = "winit")]
let window = WindowBuilder::new()
@ -53,8 +58,8 @@ fn main() {
#[cfg(feature = "winit")]
let surface = global.instance_create_surface(
window.raw_display_handle(),
window.raw_window_handle(),
window.display_handle().unwrap().into(),
window.window_handle().unwrap().into(),
wgc::id::TypedId::zip(0, 1, wgt::Backend::Empty),
);
@ -110,32 +115,32 @@ fn main() {
#[cfg(feature = "winit")]
{
use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event::{ElementState, Event, WindowEvent},
event_loop::ControlFlow,
};
let mut resize_config = None;
let mut frame_count = 0;
let mut done = false;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
event_loop.run(move |event, target| {
target.set_control_flow(ControlFlow::Poll);
match event {
Event::MainEventsCleared => {
window.request_redraw();
}
Event::RedrawRequested(_) if resize_config.is_none() => loop {
Event::WindowEvent { event, .. } => match event {
WindowEvent::RedrawRequested if resize_config.is_none() => {
match actions.pop() {
Some(trace::Action::ConfigureSurface(_device_id, config)) => {
log::info!("Configuring the surface");
let current_size: (u32, u32) = window.inner_size().into();
let size = (config.width, config.height);
if current_size != size {
window.set_inner_size(winit::dpi::PhysicalSize::new(
let _ = window.request_inner_size(winit::dpi::PhysicalSize::new(
config.width,
config.height,
));
resize_config = Some(config);
break;
target.exit();
} else {
let error = gfx_select!(device => global.surface_configure(surface, device, &config));
if let Some(e) = error {
@ -147,12 +152,12 @@ fn main() {
frame_count += 1;
log::debug!("Presenting frame {}", frame_count);
gfx_select!(device => global.surface_present(id)).unwrap();
break;
target.exit();
}
Some(trace::Action::DiscardSurfaceTexture(id)) => {
log::debug!("Discarding frame {}", frame_count);
gfx_select!(device => global.surface_texture_discard(id)).unwrap();
break;
target.exit();
}
Some(action) => {
gfx_select!(device => global.process(device, action, &dir, &mut command_buffer_id_manager));
@ -162,11 +167,10 @@ fn main() {
println!("Finished the end at frame {}", frame_count);
done = true;
}
break;
target.exit();
}
}
},
Event::WindowEvent { event, .. } => match event {
WindowEvent::Resized(_) => {
if let Some(config) = resize_config.take() {
let error = gfx_select!(device => global.surface_configure(surface, device, &config));
@ -176,26 +180,23 @@ fn main() {
}
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Escape),
event: KeyEvent {
logical_key: Key::Named(NamedKey::Escape),
state: ElementState::Pressed,
..
},
..
}
| WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit;
}
| WindowEvent::CloseRequested => target.exit(),
_ => {}
},
Event::LoopDestroyed => {
Event::LoopExiting => {
log::info!("Closing");
gfx_select!(device => global.device_poll(device, wgt::Maintain::Wait)).unwrap();
}
_ => {}
}
});
}).unwrap();
}
}

View File

@ -72,7 +72,7 @@ log = "0.4"
# parking_lot 0.12 switches from `winapi` to `windows`; permit either
parking_lot = ">=0.11,<0.13"
profiling = { version = "1", default-features = false }
raw-window-handle = { version = "0.5", optional = true }
raw-window-handle = { version = "0.6", optional = true }
ron = { version = "0.8", optional = true }
serde = { version = "1", features = ["serde_derive"], optional = true }
smallvec = "1"

View File

@ -86,7 +86,7 @@ required-features = ["gles"]
bitflags = "2"
parking_lot = ">=0.11,<0.13"
profiling = { version = "1", default-features = false }
raw-window-handle = "0.5"
raw-window-handle = "0.6"
thiserror = "1"
once_cell = "1.18.0"
@ -180,9 +180,7 @@ features = ["wgsl-in"]
[dev-dependencies]
cfg-if = "1"
env_logger = "0.10"
winit = { version = "0.28.7", features = [
"android-native-activity",
] } # for "halmark" example
winit = { version = "0.29.2", features = [ "android-native-activity" ] } # for "halmark" example
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
glutin = "0.29.1" # for "gles" example

View File

@ -5,7 +5,12 @@ extern crate wgpu_hal as hal;
use hal::{
Adapter as _, CommandEncoder as _, Device as _, Instance as _, Queue as _, Surface as _,
};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::ControlFlow,
keyboard::{Key, NamedKey},
};
use std::{
borrow::{Borrow, Cow},
@ -95,10 +100,15 @@ impl<A: hal::Api> Example<A> {
gles_minor_version: wgt::Gles3MinorVersion::default(),
};
let instance = unsafe { A::Instance::init(&instance_desc)? };
let mut surface = unsafe {
let mut surface = {
let raw_window_handle = window.window_handle()?.as_raw();
let raw_display_handle = window.display_handle()?.as_raw();
unsafe {
instance
.create_surface(window.raw_display_handle(), window.raw_window_handle())
.create_surface(raw_display_handle, raw_window_handle)
.unwrap()
}
};
let (adapter, capabilities) = unsafe {
@ -261,7 +271,7 @@ impl<A: hal::Api> Example<A> {
};
let pipeline = unsafe { device.create_render_pipeline(&pipeline_desc).unwrap() };
let texture_data = vec![0xFFu8; 4];
let texture_data = [0xFFu8; 4];
let staging_buffer_desc = hal::BufferDescriptor {
label: Some("stage"),
@ -563,10 +573,10 @@ impl<A: hal::Api> Example<A> {
fn update(&mut self, event: winit::event::WindowEvent) {
if let winit::event::WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(winit::event::VirtualKeyCode::Space),
state: winit::event::ElementState::Pressed,
event:
KeyEvent {
logical_key: Key::Named(NamedKey::Space),
state: ElementState::Pressed,
..
},
..
@ -777,7 +787,7 @@ cfg_if::cfg_if! {
fn main() {
env_logger::init();
let event_loop = winit::event_loop::EventLoop::new();
let event_loop = winit::event_loop::EventLoop::new().unwrap();
let window = winit::window::WindowBuilder::new()
.with_title("hal-bunnymark")
.build(&event_loop)
@ -789,31 +799,27 @@ fn main() {
let mut last_frame_inst = Instant::now();
let (mut frame_count, mut accum_time) = (0, 0.0);
event_loop.run(move |event, _, control_flow| {
event_loop
.run(move |event, target| {
let _ = &window; // force ownership by the closure
*control_flow = winit::event_loop::ControlFlow::Poll;
target.set_control_flow(ControlFlow::Poll);
match event {
winit::event::Event::RedrawEventsCleared => {
window.request_redraw();
Event::LoopExiting => {
example.take().unwrap().exit();
}
winit::event::Event::WindowEvent { event, .. } => match event {
winit::event::WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(winit::event::VirtualKeyCode::Escape),
state: winit::event::ElementState::Pressed,
Event::WindowEvent { event, .. } => match event {
WindowEvent::KeyboardInput {
event:
KeyEvent {
logical_key: Key::Named(NamedKey::Escape),
state: ElementState::Pressed,
..
},
..
}
| winit::event::WindowEvent::CloseRequested => {
*control_flow = winit::event_loop::ControlFlow::Exit;
}
_ => {
example.as_mut().unwrap().update(event);
}
},
winit::event::Event::RedrawRequested(_) => {
| WindowEvent::CloseRequested => target.exit(),
WindowEvent::RedrawRequested => {
let ex = example.as_mut().unwrap();
{
accum_time += last_frame_inst.elapsed().as_secs_f32();
@ -830,10 +836,12 @@ fn main() {
}
ex.render();
}
winit::event::Event::LoopDestroyed => {
example.take().unwrap().exit();
_ => {
example.as_mut().unwrap().update(event);
}
},
_ => {}
}
});
})
.unwrap();
}

View File

@ -114,7 +114,7 @@ impl crate::Instance<super::Api> for super::Instance {
raw_window_handle::RawWindowHandle::Win32(handle) => Ok(super::Surface {
factory: self.factory.clone(),
factory_media: self.factory_media.clone(),
target: SurfaceTarget::WndHandle(handle.hwnd as *mut _),
target: SurfaceTarget::WndHandle(handle.hwnd.get() as *mut _),
supports_allow_tearing: self.supports_allow_tearing,
swap_chain: None,
}),

View File

@ -865,7 +865,7 @@ impl crate::Instance<super::Api> for Instance {
.unwrap();
let ret = unsafe {
ANativeWindow_setBuffersGeometry(handle.a_native_window, 0, 0, format)
ANativeWindow_setBuffersGeometry(handle.a_native_window.as_ptr(), 0, 0, format)
};
if ret != 0 {
@ -878,7 +878,7 @@ impl crate::Instance<super::Api> for Instance {
(Rwh::Wayland(_), raw_window_handle::RawDisplayHandle::Wayland(display_handle)) => {
if inner
.wl_display
.map(|ptr| ptr != display_handle.display)
.map(|ptr| ptr != display_handle.display.as_ptr())
.unwrap_or(true)
{
/* Wayland displays are not sharable between surfaces so if the
@ -900,7 +900,7 @@ impl crate::Instance<super::Api> for Instance {
.unwrap()
.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
display_handle.display,
display_handle.display.as_ptr(),
&display_attributes,
)
}
@ -914,7 +914,7 @@ impl crate::Instance<super::Api> for Instance {
)?;
let old_inner = std::mem::replace(inner.deref_mut(), new_inner);
inner.wl_display = Some(display_handle.display);
inner.wl_display = Some(display_handle.display.as_ptr());
drop(old_inner);
}
@ -1155,29 +1155,35 @@ impl crate::Surface<super::Api> for Surface {
&mut temp_xcb_handle as *mut _ as *mut std::ffi::c_void
}
(WindowKind::AngleX11, Rwh::Xcb(handle)) => {
handle.window as *mut std::ffi::c_void
handle.window.get() as *mut std::ffi::c_void
}
(WindowKind::Unknown, Rwh::AndroidNdk(handle)) => {
handle.a_native_window.as_ptr()
}
(WindowKind::Unknown, Rwh::AndroidNdk(handle)) => handle.a_native_window,
(WindowKind::Wayland, Rwh::Wayland(handle)) => {
let library = &self.wsi.display_owner.as_ref().unwrap().library;
let wl_egl_window_create: libloading::Symbol<WlEglWindowCreateFun> =
unsafe { library.get(b"wl_egl_window_create") }.unwrap();
let window = unsafe { wl_egl_window_create(handle.surface, 640, 480) };
let window =
unsafe { wl_egl_window_create(handle.surface.as_ptr(), 640, 480) }
as *mut _;
wl_window = Some(window);
window
}
#[cfg(target_os = "emscripten")]
(WindowKind::Unknown, Rwh::Web(handle)) => handle.id as *mut std::ffi::c_void,
(WindowKind::Unknown, Rwh::Win32(handle)) => handle.hwnd,
(WindowKind::Unknown, Rwh::Win32(handle)) => {
handle.hwnd.get() as *mut std::ffi::c_void
}
(WindowKind::Unknown, Rwh::AppKit(handle)) => {
#[cfg(not(target_os = "macos"))]
let window_ptr = handle.ns_view;
let window_ptr = handle.ns_view.as_ptr();
#[cfg(target_os = "macos")]
let window_ptr = {
use objc::{msg_send, runtime::Object, sel, sel_impl};
// ns_view always have a layer and don't need to verify that it exists.
let layer: *mut Object =
msg_send![handle.ns_view as *mut Object, layer];
msg_send![handle.ns_view.as_ptr() as *mut Object, layer];
layer as *mut ffi::c_void
};
window_ptr

View File

@ -441,7 +441,7 @@ impl crate::Instance<super::Api> for Instance {
)));
};
Ok(Surface {
window: window.hwnd as *mut _,
window: window.hwnd.get() as *mut _,
presentable: true,
swapchain: None,
srgb_capable: self.srgb_capable,

View File

@ -96,11 +96,14 @@ impl crate::Instance<Api> for Instance {
#[cfg(target_os = "ios")]
raw_window_handle::RawWindowHandle::UiKit(handle) => {
let _ = &self.managed_metal_layer_delegate;
Ok(unsafe { Surface::from_view(handle.ui_view, None) })
Ok(unsafe { Surface::from_view(handle.ui_view.as_ptr(), None) })
}
#[cfg(target_os = "macos")]
raw_window_handle::RawWindowHandle::AppKit(handle) => Ok(unsafe {
Surface::from_view(handle.ns_view, Some(&self.managed_metal_layer_delegate))
Surface::from_view(
handle.ns_view.as_ptr(),
Some(&self.managed_metal_layer_delegate),
)
}),
_ => Err(crate::InstanceError::new(format!(
"window handle {window_handle:?} is not a Metal-compatible handle"

View File

@ -740,33 +740,37 @@ impl crate::Instance<super::Api> for super::Instance {
match (window_handle, display_handle) {
(Rwh::Wayland(handle), Rdh::Wayland(display)) => {
self.create_surface_from_wayland(display.display, handle.surface)
self.create_surface_from_wayland(display.display.as_ptr(), handle.surface.as_ptr())
}
(Rwh::Xlib(handle), Rdh::Xlib(display)) => {
self.create_surface_from_xlib(display.display as *mut _, handle.window)
let display = display.display.expect("Display pointer is not set.");
self.create_surface_from_xlib(display.as_ptr() as *mut *const c_void, handle.window)
}
(Rwh::Xcb(handle), Rdh::Xcb(display)) => {
self.create_surface_from_xcb(display.connection, handle.window)
let connection = display.connection.expect("Pointer to X-Server is not set.");
self.create_surface_from_xcb(connection.as_ptr(), handle.window.get())
}
(Rwh::AndroidNdk(handle), _) => {
self.create_surface_android(handle.a_native_window.as_ptr())
}
(Rwh::AndroidNdk(handle), _) => self.create_surface_android(handle.a_native_window),
#[cfg(windows)]
(Rwh::Win32(handle), _) => {
use winapi::um::libloaderapi::GetModuleHandleW;
let hinstance = unsafe { GetModuleHandleW(std::ptr::null()) };
self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd)
self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd.get() as *mut _)
}
#[cfg(target_os = "macos")]
(Rwh::AppKit(handle), _)
if self.shared.extensions.contains(&ext::MetalSurface::name()) =>
{
self.create_surface_from_view(handle.ns_view)
self.create_surface_from_view(handle.ns_view.as_ptr())
}
#[cfg(target_os = "ios")]
(Rwh::UiKit(handle), _)
if self.shared.extensions.contains(&ext::MetalSurface::name()) =>
{
self.create_surface_from_view(handle.ui_view)
self.create_surface_from_view(handle.ui_view.as_ptr())
}
(_, _) => Err(crate::InstanceError::new(format!(
"window handle {window_handle:?} is not a Vulkan-compatible handle"

View File

@ -107,7 +107,7 @@ flume.workspace = true
log.workspace = true
parking_lot.workspace = true
profiling.workspace = true
raw-window-handle.workspace = true
raw-window-handle = { workspace = true, features = ["std"] }
serde = { workspace = true, features = ["derive"], optional = true }
smallvec.workspace = true
static_assertions.workspace = true

View File

@ -1937,15 +1937,27 @@ impl Instance {
/// - On web: will panic if the `raw_window_handle` does not properly refer to a
/// canvas element.
pub unsafe fn create_surface<
W: raw_window_handle::HasRawWindowHandle + raw_window_handle::HasRawDisplayHandle,
W: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle,
>(
&self,
window: &W,
) -> Result<Surface, CreateSurfaceError> {
let raw_display_handle = window
.display_handle()
.map_err(|e| CreateSurfaceError {
inner: CreateSurfaceErrorKind::RawHandle(e),
})?
.as_raw();
let raw_window_handle = window
.window_handle()
.map_err(|e| CreateSurfaceError {
inner: CreateSurfaceErrorKind::RawHandle(e),
})?
.as_raw();
let (id, data) = DynContext::instance_create_surface(
&*self.context,
raw_window_handle::HasRawDisplayHandle::raw_display_handle(window),
raw_window_handle::HasRawWindowHandle::raw_window_handle(window),
raw_display_handle,
raw_window_handle,
)?;
Ok(Surface {
context: Arc::clone(&self.context),
@ -2925,6 +2937,10 @@ enum CreateSurfaceErrorKind {
/// Error from WebGPU surface creation.
#[allow(dead_code)] // may be unused depending on target and features
Web(String),
/// Error when trying to get a [`DisplayHandle`] or a [`WindowHandle`] from
/// `raw_window_handle`.
RawHandle(raw_window_handle::HandleError),
}
static_assertions::assert_impl_all!(CreateSurfaceError: Send, Sync);
@ -2938,6 +2954,7 @@ impl fmt::Display for CreateSurfaceError {
))]
CreateSurfaceErrorKind::Hal(e) => e.fmt(f),
CreateSurfaceErrorKind::Web(e) => e.fmt(f),
CreateSurfaceErrorKind::RawHandle(e) => e.fmt(f),
}
}
}
@ -2952,6 +2969,7 @@ impl error::Error for CreateSurfaceError {
))]
CreateSurfaceErrorKind::Hal(e) => e.source(),
CreateSurfaceErrorKind::Web(_) => None,
CreateSurfaceErrorKind::RawHandle(e) => e.source(),
}
}
}