diff --git a/Cargo.lock b/Cargo.lock index 606ec4a2d5..d53366e135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1918,7 +1918,6 @@ dependencies = [ "metal", "naga", "raw-window-handle", - "smallvec", "thiserror", "wgpu-types", "winit", diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 54773646ef..6812e2a403 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -28,8 +28,6 @@ pub mod queue; #[cfg(any(feature = "trace", feature = "replay"))] pub mod trace; -use smallvec::SmallVec; - pub const SHADER_STAGE_COUNT: usize = 3; const CLEANUP_WAIT_MS: u32 = 5000; @@ -1138,6 +1136,9 @@ impl Device { let mut used_buffer_ranges = Vec::new(); let mut hal_entries = Vec::with_capacity(desc.entries.len()); + let mut hal_buffers = Vec::new(); + let mut hal_samplers = Vec::new(); + let mut hal_textures = Vec::new(); for entry in desc.entries.iter() { let binding = entry.binding; // Find the corresponding declaration in the layout @@ -1145,7 +1146,7 @@ impl Device { .entries .get(&binding) .ok_or(Error::MissingBindingDeclaration(binding))?; - let hal_resource = match entry.resource { + let res_index = match entry.resource { Br::Buffer(ref bb) => { let bb = Self::create_buffer_binding( &bb, @@ -1157,7 +1158,10 @@ impl Device { &*buffer_guard, &self.limits, )?; - hal::BindingResource::Buffers([bb].into()) + + let res_index = hal_buffers.len(); + hal_buffers.push(bb); + res_index } Br::BufferArray(ref bindings_array) => { if let Some(count) = decl.count { @@ -1173,7 +1177,7 @@ impl Device { return Err(Error::SingleBindingExpected); } - let mut hal_bindings = SmallVec::with_capacity(bindings_array.len()); + let res_index = hal_buffers.len(); for bb in bindings_array.iter() { let bb = Self::create_buffer_binding( bb, @@ -1185,9 +1189,9 @@ impl Device { &*buffer_guard, &self.limits, )?; - hal_bindings.push(bb); + hal_buffers.push(bb); } - hal::BindingResource::Buffers(hal_bindings) + res_index } Br::Sampler(id) => { match decl.ty { @@ -1217,7 +1221,9 @@ impl Device { }); } - hal::BindingResource::Sampler(&sampler.raw) + let res_index = hal_samplers.len(); + hal_samplers.push(&sampler.raw); + res_index } _ => { return Err(Error::WrongBindingType { @@ -1351,7 +1357,12 @@ impl Device { } } - hal::BindingResource::TextureViews([&view.raw].into(), internal_use) + let res_index = hal_textures.len(); + hal_textures.push(hal::TextureBinding { + view: &view.raw, + usage: internal_use, + }); + res_index } Br::TextureViewArray(ref bindings_array) => { if let Some(count) = decl.count { @@ -1367,8 +1378,7 @@ impl Device { return Err(Error::SingleBindingExpected); } - let mut hal_bindings = SmallVec::with_capacity(bindings_array.len()); - let mut common_internal_use = None; + let res_index = hal_textures.len(); for &id in bindings_array.iter() { let view = used .views @@ -1386,9 +1396,6 @@ impl Device { }) } }; - //TODO: ensure these match across the whole array - common_internal_use = Some(internal_use); - hal_bindings.push(&view.raw); match view.source { resource::TextureViewSource::Native(ref source_id) => { @@ -1409,15 +1416,20 @@ impl Device { return Err(Error::SwapChainImage); } } + + hal_textures.push(hal::TextureBinding { + view: &view.raw, + usage: internal_use, + }); } - hal::BindingResource::TextureViews(hal_bindings, common_internal_use.unwrap()) + res_index } }; hal_entries.push(hal::BindGroupEntry { binding, - resource: hal_resource, + resource_index: res_index as u32, }); } @@ -1432,6 +1444,9 @@ impl Device { label: desc.label.borrow_option(), layout: &layout.raw, entries: &hal_entries, + buffers: &hal_buffers, + samplers: &hal_samplers, + textures: &hal_textures, }; let raw = unsafe { self.raw diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 6a99e63d6c..a05529153f 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -748,10 +748,13 @@ impl Global { } unsafe { - device.queue.submit( - command_buffers.into_iter(), - Some((&mut device.fence, submit_index)), - ); + device + .queue + .submit( + command_buffers.into_iter(), + Some((&mut device.fence, submit_index)), + ) + .map_err(DeviceError::from)?; } } diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index f7bc6f0902..c3fb9129ec 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -17,7 +17,6 @@ metal = ["mtl"] [dependencies] bitflags = "1.0" raw-window-handle = "0.3" -smallvec = "1" thiserror = "1" wgt = { package = "wgpu-types", path = "../wgpu-types" } diff --git a/wgpu-hal/examples/bunnymark/main.rs b/wgpu-hal/examples/bunnymark/main.rs index 161ff343a2..54d5071aac 100644 --- a/wgpu-hal/examples/bunnymark/main.rs +++ b/wgpu-hal/examples/bunnymark/main.rs @@ -27,6 +27,7 @@ struct Locals { } struct Example { + #[allow(dead_code)] instance: A::Instance, surface: A::Surface, surface_format: wgt::TextureFormat, @@ -48,7 +49,7 @@ impl Example { let mut surface = unsafe { instance.create_surface(window).unwrap() }; let hal::OpenDevice { device, mut queue } = unsafe { let adapters = instance.enumerate_adapters(); - let exposed = &adapters[0]; + let exposed = adapters.get(0).ok_or(hal::InstanceError)?; println!( "Surface caps: {:?}", exposed.adapter.surface_capabilities(&surface) @@ -329,26 +330,28 @@ impl Example { offset: 0, size: None, }; + let texture_binding = hal::TextureBinding { + view: &view, + usage: hal::TextureUse::SAMPLED, + }; let global_group_desc = hal::BindGroupDescriptor { label: Some("global"), layout: &global_bind_group_layout, + buffers: &[global_buffer_binding], + samplers: &[&sampler], + textures: &[texture_binding], entries: &[ hal::BindGroupEntry { binding: 0, - resource: hal::BindingResource::Buffers( - iter::once(global_buffer_binding).collect(), - ), + resource_index: 0, }, hal::BindGroupEntry { binding: 1, - resource: hal::BindingResource::TextureViews( - iter::once(&view).collect(), - hal::TextureUse::SAMPLED, - ), + resource_index: 0, }, hal::BindGroupEntry { binding: 2, - resource: hal::BindingResource::Sampler(&sampler), + resource_index: 0, }, ], }; @@ -364,11 +367,12 @@ impl Example { let local_group_desc = hal::BindGroupDescriptor { label: Some("local"), layout: &local_bind_group_layout, + buffers: &[local_buffer_binding], + samplers: &[], + textures: &[], entries: &[hal::BindGroupEntry { binding: 0, - resource: hal::BindingResource::Buffers( - iter::once(local_buffer_binding).collect(), - ), + resource_index: 0, }], }; unsafe { device.create_bind_group(&local_group_desc).unwrap() } @@ -532,5 +536,52 @@ fn main() { .unwrap(); #[cfg(feature = "metal")] - let mut example = Example::init::(&window); + let example_result = Example::::init(&window); + #[cfg(not(any(feature = "metal")))] + let example_result = Example::::init(&window); + let mut example = example_result.expect("Selected backend is not supported"); + + let mut last_frame_inst = Instant::now(); + let (mut frame_count, mut accum_time) = (0, 0.0); + + event_loop.run(move |event, _, control_flow| { + let _ = &window; // force ownership by the closure + *control_flow = winit::event_loop::ControlFlow::Poll; + match event { + 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, + .. + }, + .. + } + | winit::event::WindowEvent::CloseRequested => { + *control_flow = winit::event_loop::ControlFlow::Exit; + } + _ => { + example.update(event); + } + }, + winit::event::Event::RedrawRequested(_) => { + { + accum_time += last_frame_inst.elapsed().as_secs_f32(); + last_frame_inst = Instant::now(); + frame_count += 1; + if frame_count == 100 { + println!( + "Avg frame time {}ms", + accum_time * 1000.0 / frame_count as f32 + ); + accum_time = 0.0; + frame_count = 0; + } + } + example.render(); + } + _ => {} + } + }); } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index a171777e47..7807f9771b 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -55,7 +55,6 @@ use std::{ }; use bitflags::bitflags; -use smallvec::SmallVec; use thiserror::Error; pub const MAX_ANISOTROPY: u8 = 16; @@ -717,34 +716,35 @@ impl Clone for BufferBinding<'_, A> { } #[derive(Debug)] -pub enum BindingResource<'a, A: Api> { - Buffers(SmallVec<[BufferBinding<'a, A>; 1]>), - Sampler(&'a A::Sampler), - TextureViews(SmallVec<[&'a A::TextureView; 1]>, TextureUse), +pub struct TextureBinding<'a, A: Api> { + pub view: &'a A::TextureView, + pub usage: TextureUse, } // Rust gets confused about the impl requirements for `A` -impl Clone for BindingResource<'_, A> { +impl Clone for TextureBinding<'_, A> { fn clone(&self) -> Self { - match *self { - Self::Buffers(ref slice) => Self::Buffers(slice.clone()), - Self::Sampler(sampler) => Self::Sampler(sampler), - Self::TextureViews(ref slice, usage) => Self::TextureViews(slice.clone(), usage), + Self { + view: self.view, + usage: self.usage, } } } #[derive(Clone, Debug)] -pub struct BindGroupEntry<'a, A: Api> { +pub struct BindGroupEntry { pub binding: u32, - pub resource: BindingResource<'a, A>, + pub resource_index: u32, } #[derive(Clone, Debug)] pub struct BindGroupDescriptor<'a, A: Api> { pub label: Label<'a>, pub layout: &'a A::BindGroupLayout, - pub entries: &'a [BindGroupEntry<'a, A>], + pub buffers: &'a [BufferBinding<'a, A>], + pub samplers: &'a [&'a A::Sampler], + pub textures: &'a [TextureBinding<'a, A>], + pub entries: &'a [BindGroupEntry], } #[derive(Clone, Debug)]