Skip to content
This repository has been archived by the owner on Jun 18, 2021. It is now read-only.

Commit

Permalink
Merge #204
Browse files Browse the repository at this point in the history
204: Return futures from request adapter/request device r=kvark a=grovesNL

Relevant to #175

Backporting some parts of #193 for async request adapter and async request device.

Co-authored-by: Joshua Groves <josh@joshgroves.com>
  • Loading branch information
bors[bot] and grovesNL authored Mar 16, 2020
2 parents 6238e85 + b3e4253 commit 82c8f34
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 67 deletions.
4 changes: 3 additions & 1 deletion examples/capture/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ async fn run() {
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();

let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions {
anisotropic_filtering: false,
},
limits: wgpu::Limits::default(),
});
})
.await;

// Rendered image is 256×256 with 32-bit RGBA color
let size = 256u32;
Expand Down
4 changes: 4 additions & 0 deletions examples/describe/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
/// This example shows how to describe the adapter in use.
fn main() {
env_logger::init();
futures::executor::block_on(run());
}

async fn run() {
let adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();

println!("{:?}", adapter.get_info())
Expand Down
10 changes: 8 additions & 2 deletions examples/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub trait Example: 'static + Sized {
) -> wgpu::CommandBuffer;
}

pub fn run<E: Example>(title: &str) {
async fn run_async<E: Example>(title: &str) {
use winit::{
event,
event_loop::{ControlFlow, EventLoop},
Expand Down Expand Up @@ -105,14 +105,16 @@ pub fn run<E: Example>(title: &str) {
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();

let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions {
anisotropic_filtering: false,
},
limits: wgpu::Limits::default(),
});
})
.await;

let mut sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
Expand Down Expand Up @@ -180,6 +182,10 @@ pub fn run<E: Example>(title: &str) {
});
}

pub fn run<E: Example>(title: &str) {
futures::executor::block_on(run_async::<E>(title));
}

// This allows treating the framework as a standalone example,
// thus avoiding listing the example names in `Cargo.toml`.
#[allow(dead_code)]
Expand Down
27 changes: 15 additions & 12 deletions examples/hello-compute/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ use std::{convert::TryInto as _, str::FromStr};
use zerocopy::AsBytes as _;

async fn run() {
env_logger::init();

// For now this just panics if you didn't pass numbers. Could add proper error handling.
if std::env::args().len() == 1 {
panic!("You must pass a list of positive integers!")
}
let numbers: Vec<u32> = std::env::args()
.skip(1)
.map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!"))
.collect();
let numbers = if std::env::args().len() == 1 {
let default = vec![1, 2, 3, 4];
log::info!("No numbers were provided, defaulting to {:?}", default);
default
} else {
std::env::args()
.skip(1)
.map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!"))
.collect()
};

println!("Times: {:?}", execute_gpu(numbers).await);
log::info!("Times: {:?}", execute_gpu(numbers).await);
}

async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
Expand All @@ -26,14 +26,16 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();

let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions {
anisotropic_filtering: false,
},
limits: wgpu::Limits::default(),
});
})
.await;

let cs = include_bytes!("shader.comp.spv");
let cs_module =
Expand Down Expand Up @@ -108,6 +110,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
}

fn main() {
env_logger::init();
futures::executor::block_on(run());
}

Expand Down
63 changes: 22 additions & 41 deletions examples/hello-triangle/main.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,29 @@
fn main() {
use winit::{
event,
event_loop::{ControlFlow, EventLoop},
};

env_logger::init();
let event_loop = EventLoop::new();

#[cfg(not(feature = "gl"))]
let (window, size, surface) = {
let window = winit::window::Window::new(&event_loop).unwrap();
let size = window.inner_size();
let surface = wgpu::Surface::create(&window);
(window, size, surface)
};

#[cfg(feature = "gl")]
let (window, instance, size, surface) = {
let wb = winit::WindowBuilder::new();
let cb = wgpu::glutin::ContextBuilder::new().with_vsync(true);
let context = cb.build_windowed(wb, &event_loop).unwrap();

let size = context
.window()
.get_inner_size()
.unwrap()
.to_physical(context.window().get_hidpi_factor());
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::Window
};

let (context, window) = unsafe { context.make_current().unwrap().split() };

let instance = wgpu::Instance::new(context);
let surface = instance.get_surface();

(window, instance, size, surface)
};
async fn run(event_loop: EventLoop<()>, window: Window) {
let size = window.inner_size();
let surface = wgpu::Surface::create(&window);

let adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();

let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions {
anisotropic_filtering: false,
},
limits: wgpu::Limits::default(),
});
})
.await;

let vs = include_bytes!("shader.vert.spv");
let vs_module =
Expand Down Expand Up @@ -113,13 +88,13 @@ fn main() {
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll;
match event {
event::Event::MainEventsCleared => window.request_redraw(),
event::Event::WindowEvent { event: event::WindowEvent::Resized(size), .. } => {
Event::MainEventsCleared => window.request_redraw(),
Event::WindowEvent { event: WindowEvent::Resized(size), .. } => {
sc_desc.width = size.width;
sc_desc.height = size.height;
swap_chain = device.create_swap_chain(&surface, &sc_desc);
}
event::Event::RedrawRequested(_) => {
Event::RedrawRequested(_) => {
let frame = swap_chain
.get_next_texture()
.expect("Timeout when acquiring next swap chain texture");
Expand All @@ -143,11 +118,17 @@ fn main() {

queue.submit(&[encoder.finish()]);
}
event::Event::WindowEvent {
event: event::WindowEvent::CloseRequested,
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
_ => {}
}
});
}
fn main() {
let event_loop = EventLoop::new();
let window = winit::window::Window::new(&event_loop).unwrap();
env_logger::init();
futures::executor::block_on(run(event_loop, window));
}
1 change: 1 addition & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod native_gpu_future;
File renamed without changes.
22 changes: 11 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! A cross-platform graphics and compute library based on WebGPU.
mod future;
use future::GpuFutureCompletion;
pub use future::GpuFuture;
mod backend;
use crate::backend::native_gpu_future;

#[macro_use]
mod macros;
Expand All @@ -12,6 +11,7 @@ use smallvec::SmallVec;

use std::{
ffi::CString,
future::Future,
ops::Range,
ptr,
slice,
Expand Down Expand Up @@ -501,7 +501,7 @@ impl Adapter {
/// Some options are "soft", so treated as non-mandatory. Others are "hard".
///
/// If no adapters are found that suffice all the "hard" options, `None` is returned.
pub fn request(options: &RequestAdapterOptions, backends: BackendBit) -> Option<Self> {
pub async fn request(options: &RequestAdapterOptions, backends: BackendBit) -> Option<Self> {
unsafe extern "C" fn adapter_callback(
id: wgc::id::AdapterId,
user_data: *mut std::ffi::c_void,
Expand All @@ -527,7 +527,7 @@ impl Adapter {
/// # Panics
///
/// Panics if the extensions specified by `desc` are not supported by this adapter.
pub fn request_device(&self, desc: &DeviceDescriptor) -> (Device, Queue) {
pub async fn request_device(&self, desc: &DeviceDescriptor) -> (Device, Queue) {
let device = Device {
id: wgn::wgpu_adapter_request_device(self.id, Some(desc)),
temp: Temp::default(),
Expand Down Expand Up @@ -910,22 +910,22 @@ impl<T> Drop for BufferAsyncMapping<T> {
struct BufferMapReadFutureUserData
{
size: BufferAddress,
completion: GpuFutureCompletion<BufferMapReadResult>,
completion: native_gpu_future::GpuFutureCompletion<BufferMapReadResult>,
buffer_id: wgc::id::BufferId,
}

struct BufferMapWriteFutureUserData
{
size: BufferAddress,
completion: GpuFutureCompletion<BufferMapWriteResult>,
completion: native_gpu_future::GpuFutureCompletion<BufferMapWriteResult>,
buffer_id: wgc::id::BufferId,
}

impl Buffer {
/// Map the buffer for reading. The result is returned in a future.
pub fn map_read(&self, start: BufferAddress, size: BufferAddress) -> GpuFuture<BufferMapReadResult>
pub fn map_read(&self, start: BufferAddress, size: BufferAddress) -> impl Future<Output = crate::BufferMapReadResult>
{
let (future, completion) = future::new_gpu_future(self.device_id);
let (future, completion) = native_gpu_future::new_gpu_future(self.device_id);

extern "C" fn buffer_map_read_future_wrapper(
status: wgc::resource::BufferMapAsyncStatus,
Expand Down Expand Up @@ -963,9 +963,9 @@ impl Buffer {
}

/// Map the buffer for writing. The result is returned in a future.
pub fn map_write(&self, start: BufferAddress, size: BufferAddress) -> GpuFuture<BufferMapWriteResult>
pub fn map_write(&self, start: BufferAddress, size: BufferAddress) -> impl Future<Output = crate::BufferMapWriteResult>
{
let (future, completion) = future::new_gpu_future(self.device_id);
let (future, completion) = native_gpu_future::new_gpu_future(self.device_id);

extern "C" fn buffer_map_write_future_wrapper(
status: wgc::resource::BufferMapAsyncStatus,
Expand Down

0 comments on commit 82c8f34

Please sign in to comment.