mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
[rs] Merge #82
82: Return Queue separately r=grovesNL a=kvark What problem is this PR trying to solve? We want `Device` to be freely accessible from multiple threads/objects and internally synchronized. `Arc<Device>` seems like a natural choice of such a sharable object, especially since all except one methods are `&self`. That one method is `get_queue()`, and it returns a temporary object `Queue<'a>`. If we turn it into `&self`, we'd end up with multiple instances of `Queue` created at any time, which contradicts the initial design (of this Rust wrapper). If it stays `&mut` and the user wraps the device into `Arc`, they'll never be able to submit any work... So this PR solves this by moving the `Queue` completely outside of the device. Co-authored-by: Dzmitry Malyshau <dmalyshau@mozilla.com>
This commit is contained in:
commit
b01a4bb169
@ -12,7 +12,7 @@ fn main() {
|
||||
backends: wgpu::BackendBit::PRIMARY,
|
||||
}).unwrap();
|
||||
|
||||
let mut device = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
@ -80,7 +80,7 @@ fn main() {
|
||||
encoder.finish()
|
||||
};
|
||||
|
||||
device.get_queue().submit(&[command_buffer]);
|
||||
queue.submit(&[command_buffer]);
|
||||
|
||||
// Write the buffer as a PNG
|
||||
output_buffer.map_read_async(
|
||||
|
@ -106,7 +106,7 @@ impl Example {
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
use std::mem;
|
||||
|
||||
let mut init_encoder =
|
||||
@ -294,23 +294,22 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Done
|
||||
let init_command_buf = init_encoder.finish();
|
||||
device.get_queue().submit(&[init_command_buf]);
|
||||
Example {
|
||||
let this = Example {
|
||||
vertex_buf,
|
||||
index_buf,
|
||||
index_count: index_data.len(),
|
||||
bind_group,
|
||||
uniform_buf,
|
||||
pipeline,
|
||||
}
|
||||
};
|
||||
(this, Some(init_encoder.finish()))
|
||||
}
|
||||
|
||||
fn update(&mut self, _event: winit::event::WindowEvent) {
|
||||
//empty
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) {
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
|
||||
@ -321,10 +320,10 @@ impl framework::Example for Example {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.uniform_buf, 0, 64);
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
Some(encoder.finish())
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
{
|
||||
@ -350,7 +349,7 @@ impl framework::Example for Example {
|
||||
rpass.draw_indexed(0 .. self.index_count as u32, 0, 0 .. 1);
|
||||
}
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
encoder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,11 +35,11 @@ pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec<u32> {
|
||||
wgpu::read_spirv(glsl_to_spirv::compile(&code, ty).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
pub trait Example: 'static {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self;
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device);
|
||||
pub trait Example: 'static + Sized {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>);
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer>;
|
||||
fn update(&mut self, event: WindowEvent);
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device);
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer;
|
||||
}
|
||||
|
||||
pub fn run<E: Example>(title: &str) {
|
||||
@ -89,7 +89,7 @@ pub fn run<E: Example>(title: &str) {
|
||||
backends: wgpu::BackendBit::PRIMARY,
|
||||
}).unwrap();
|
||||
|
||||
let mut device = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
@ -106,7 +106,10 @@ pub fn run<E: Example>(title: &str) {
|
||||
let mut swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
|
||||
info!("Initializing the example...");
|
||||
let mut example = E::init(&sc_desc, &mut device);
|
||||
let (mut example, init_command_buf) = E::init(&sc_desc, &device);
|
||||
if let Some(command_buf) = init_command_buf {
|
||||
queue.submit(&[command_buf]);
|
||||
}
|
||||
|
||||
info!("Entering render loop...");
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
@ -125,7 +128,10 @@ pub fn run<E: Example>(title: &str) {
|
||||
sc_desc.width = physical.width.round() as u32;
|
||||
sc_desc.height = physical.height.round() as u32;
|
||||
swap_chain = device.create_swap_chain(&surface, &sc_desc);
|
||||
example.resize(&sc_desc, &mut device);
|
||||
let command_buf = example.resize(&sc_desc, &device);
|
||||
if let Some(command_buf) = command_buf {
|
||||
queue.submit(&[command_buf]);
|
||||
}
|
||||
}
|
||||
event::Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::KeyboardInput {
|
||||
@ -146,7 +152,8 @@ pub fn run<E: Example>(title: &str) {
|
||||
},
|
||||
event::Event::EventsCleared => {
|
||||
let frame = swap_chain.get_next_texture();
|
||||
example.render(&frame, &mut device);
|
||||
let command_buf = example.render(&frame, &device);
|
||||
queue.submit(&[command_buf]);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
||||
backends: wgpu::BackendBit::PRIMARY,
|
||||
}).unwrap();
|
||||
|
||||
let mut device = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
@ -88,7 +88,7 @@ fn main() {
|
||||
}
|
||||
encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
queue.submit(&[encoder.finish()]);
|
||||
|
||||
staging_buffer.map_read_async(0, size, |result: wgpu::BufferMapAsyncResult<&[u32]>| {
|
||||
if let Ok(mapping) = result {
|
||||
|
@ -43,7 +43,7 @@ fn main() {
|
||||
backends: wgpu::BackendBit::PRIMARY,
|
||||
}).unwrap();
|
||||
|
||||
let mut device = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
@ -152,7 +152,7 @@ fn main() {
|
||||
rpass.draw(0 .. 3, 0 .. 1);
|
||||
}
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
queue.submit(&[encoder.finish()]);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
@ -69,8 +69,11 @@ impl Example {
|
||||
}
|
||||
|
||||
fn generate_mipmaps(
|
||||
device: &wgpu::Device, texture: &wgpu::Texture, mip_count: u32
|
||||
) -> wgpu::CommandBuffer {
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
device: &wgpu::Device,
|
||||
texture: &wgpu::Texture,
|
||||
mip_count: u32,
|
||||
) {
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
@ -159,10 +162,6 @@ impl Example {
|
||||
}))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut encoder = device.create_command_encoder(
|
||||
&wgpu::CommandEncoderDescriptor { todo: 0 }
|
||||
);
|
||||
|
||||
for target_mip in 1 .. mip_count as usize {
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
@ -192,13 +191,11 @@ impl Example {
|
||||
rpass.set_bind_group(0, &bind_group, &[]);
|
||||
rpass.draw(0 .. 4, 0 .. 1);
|
||||
}
|
||||
|
||||
encoder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
use std::mem;
|
||||
|
||||
let mut init_encoder =
|
||||
@ -380,22 +377,22 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Done
|
||||
let init_command_buf = init_encoder.finish();
|
||||
let mipmap_command_buf = Self::generate_mipmaps(&device, &texture, mip_level_count);
|
||||
device.get_queue().submit(&[init_command_buf, mipmap_command_buf]);
|
||||
Example {
|
||||
Self::generate_mipmaps(&mut init_encoder, &device, &texture, mip_level_count);
|
||||
|
||||
let this = Example {
|
||||
vertex_buf,
|
||||
bind_group,
|
||||
uniform_buf,
|
||||
draw_pipeline,
|
||||
}
|
||||
};
|
||||
(this, Some(init_encoder.finish()))
|
||||
}
|
||||
|
||||
fn update(&mut self, _event: winit::event::WindowEvent) {
|
||||
//empty
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) {
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
|
||||
@ -406,10 +403,10 @@ impl framework::Example for Example {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.uniform_buf, 0, 64);
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
Some(encoder.finish())
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
{
|
||||
@ -434,7 +431,7 @@ impl framework::Example for Example {
|
||||
rpass.draw(0 .. 4, 0 .. 1);
|
||||
}
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
encoder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ impl Example {
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
println!("Press left/right arrow keys to change sample_count.");
|
||||
let sample_count = 4;
|
||||
|
||||
@ -138,7 +138,7 @@ impl framework::Example for Example {
|
||||
.fill_from_slice(&vertex_data);
|
||||
let vertex_count = vertex_data.len() as u32;
|
||||
|
||||
Example {
|
||||
let this = Example {
|
||||
vs_module,
|
||||
fs_module,
|
||||
pipeline_layout,
|
||||
@ -149,7 +149,8 @@ impl framework::Example for Example {
|
||||
rebuild_pipeline: false,
|
||||
sample_count,
|
||||
sc_desc: sc_desc.clone(),
|
||||
}
|
||||
};
|
||||
(this, None)
|
||||
}
|
||||
|
||||
fn update(&mut self, event: winit::event::WindowEvent) {
|
||||
@ -177,12 +178,13 @@ impl framework::Example for Example {
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) {
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
self.sc_desc = sc_desc.clone();
|
||||
self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count);
|
||||
None
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
if self.rebuild_pipeline {
|
||||
self.pipeline = Example::create_pipeline(device, &self.sc_desc, &self.vs_module, &self.fs_module, &self.pipeline_layout, self.sample_count);
|
||||
self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count);
|
||||
@ -218,7 +220,7 @@ impl framework::Example for Example {
|
||||
rpass.draw(0..self.vertex_count, 0..1);
|
||||
}
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
encoder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ impl Example {
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
// Create the vertex and index buffers
|
||||
let vertex_size = mem::size_of::<Vertex>();
|
||||
let (cube_vertex_data, cube_index_data) = create_cube();
|
||||
@ -636,7 +636,7 @@ impl framework::Example for Example {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
Example {
|
||||
let this = Example {
|
||||
entities,
|
||||
lights,
|
||||
lights_are_dirty: true,
|
||||
@ -644,15 +644,16 @@ impl framework::Example for Example {
|
||||
forward_pass,
|
||||
forward_depth: depth_texture.create_default_view(),
|
||||
light_uniform_buf,
|
||||
}
|
||||
};
|
||||
(this, None)
|
||||
}
|
||||
|
||||
fn update(&mut self, _event: winit::event::WindowEvent) {
|
||||
//empty
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) {
|
||||
{
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
let command_buf = {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
let temp_buf = device
|
||||
@ -662,8 +663,8 @@ impl framework::Example for Example {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.forward_pass.uniform_buf, 0, 64);
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
}
|
||||
encoder.finish()
|
||||
};
|
||||
|
||||
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size: wgpu::Extent3d {
|
||||
@ -679,9 +680,11 @@ impl framework::Example for Example {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
self.forward_depth = depth_texture.create_default_view();
|
||||
|
||||
Some(command_buf)
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
|
||||
@ -807,7 +810,7 @@ impl framework::Example for Example {
|
||||
}
|
||||
}
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
encoder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,6 @@ pub use wgn::glutin;
|
||||
struct Temp {
|
||||
//bind_group_descriptors: Vec<wgn::BindGroupDescriptor>,
|
||||
//vertex_buffers: Vec<wgn::VertexBufferDescriptor>,
|
||||
command_buffers: Vec<wgn::CommandBufferId>,
|
||||
}
|
||||
|
||||
/// A handle to a physical graphics and/or compute device.
|
||||
@ -245,11 +244,11 @@ pub struct ComputePass<'a> {
|
||||
|
||||
/// A handle to a command queue on a device.
|
||||
///
|
||||
/// A `Queue` executes finished [`CommandBuffer`] objects.
|
||||
/// A `Queue` executes recorded [`CommandBuffer`] objects.
|
||||
#[derive(Debug)]
|
||||
pub struct Queue<'a> {
|
||||
pub struct Queue {
|
||||
id: wgn::QueueId,
|
||||
temp: &'a mut Temp,
|
||||
temp_command_buffers: Vec<wgn::CommandBufferId>,
|
||||
}
|
||||
|
||||
/// A resource that can be bound to a pipeline.
|
||||
@ -546,15 +545,21 @@ impl Adapter {
|
||||
}
|
||||
|
||||
/// Requests a connection to a physical device, creating a logical device.
|
||||
/// Returns the device together with a queue that executes command buffers.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the extensions specified by `desc` are not supported by this adapter.
|
||||
pub fn request_device(&self, desc: &DeviceDescriptor) -> Device {
|
||||
Device {
|
||||
pub fn request_device(&self, desc: &DeviceDescriptor) -> (Device, Queue) {
|
||||
let device = Device {
|
||||
id: wgn::wgpu_adapter_request_device(self.id, Some(desc)),
|
||||
temp: Temp::default(),
|
||||
}
|
||||
};
|
||||
let queue = Queue {
|
||||
id: wgn::wgpu_device_get_queue(device.id),
|
||||
temp_command_buffers: Vec::new(),
|
||||
};
|
||||
(device, queue)
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,14 +582,6 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtains a queue which can accept [`CommandBuffer`] submissions.
|
||||
pub fn get_queue(&mut self) -> Queue {
|
||||
Queue {
|
||||
id: wgn::wgpu_device_get_queue(self.id),
|
||||
temp: &mut self.temp,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an empty [`CommandEncoder`].
|
||||
pub fn create_command_encoder(&self, desc: &CommandEncoderDescriptor) -> CommandEncoder {
|
||||
CommandEncoder {
|
||||
@ -1299,17 +1296,16 @@ impl<'a> Drop for ComputePass<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Queue<'a> {
|
||||
impl Queue {
|
||||
/// Submits a series of finished command buffers for execution.
|
||||
pub fn submit(&mut self, command_buffers: &[CommandBuffer]) {
|
||||
self.temp.command_buffers.clear();
|
||||
self.temp
|
||||
.command_buffers
|
||||
self.temp_command_buffers.clear();
|
||||
self.temp_command_buffers
|
||||
.extend(command_buffers.iter().map(|cb| cb.id));
|
||||
|
||||
wgn::wgpu_queue_submit(
|
||||
self.id,
|
||||
self.temp.command_buffers.as_ptr(),
|
||||
self.temp_command_buffers.as_ptr(),
|
||||
command_buffers.len(),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user