mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Merge #204
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>
This commit is contained in:
@@ -13,6 +13,7 @@ async fn run() {
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
@@ -20,7 +21,8 @@ async fn run() {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits::default(),
|
||||
});
|
||||
})
|
||||
.await;
|
||||
|
||||
// Rendered image is 256×256 with 32-bit RGBA color
|
||||
let size = 256u32;
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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},
|
||||
@@ -105,6 +105,7 @@ pub fn run<E: Example>(title: &str) {
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
@@ -112,7 +113,8 @@ pub fn run<E: Example>(title: &str) {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits::default(),
|
||||
});
|
||||
})
|
||||
.await;
|
||||
|
||||
let mut sc_desc = wgpu::SwapChainDescriptor {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
@@ -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)]
|
||||
|
||||
@@ -2,18 +2,18 @@ use std::{convert::TryInto as _, str::FromStr};
|
||||
use zerocopy::AsBytes as _;
|
||||
|
||||
async fn run() {
|
||||
env_logger::init();
|
||||
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()
|
||||
};
|
||||
|
||||
// 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();
|
||||
|
||||
println!("Times: {:?}", execute_gpu(numbers).await);
|
||||
log::info!("Times: {:?}", execute_gpu(numbers).await);
|
||||
}
|
||||
|
||||
async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
@@ -26,6 +26,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
@@ -33,7 +34,8 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits::default(),
|
||||
});
|
||||
})
|
||||
.await;
|
||||
|
||||
let cs = include_bytes!("shader.comp.spv");
|
||||
let cs_module =
|
||||
@@ -108,6 +110,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
futures::executor::block_on(run());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,12 @@
|
||||
fn main() {
|
||||
use winit::{
|
||||
event,
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
};
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::Window
|
||||
};
|
||||
|
||||
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());
|
||||
|
||||
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 {
|
||||
@@ -41,6 +14,7 @@ fn main() {
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
@@ -48,7 +22,8 @@ fn main() {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits::default(),
|
||||
});
|
||||
})
|
||||
.await;
|
||||
|
||||
let vs = include_bytes!("shader.vert.spv");
|
||||
let vs_module =
|
||||
@@ -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");
|
||||
@@ -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
src/backend/mod.rs
Normal file
1
src/backend/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub(crate) mod native_gpu_future;
|
||||
22
src/lib.rs
22
src/lib.rs
@@ -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;
|
||||
@@ -12,6 +11,7 @@ use smallvec::SmallVec;
|
||||
|
||||
use std::{
|
||||
ffi::CString,
|
||||
future::Future,
|
||||
ops::Range,
|
||||
ptr,
|
||||
slice,
|
||||
@@ -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,
|
||||
@@ -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(),
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user