hal: redesign the bind group descriptor

This commit is contained in:
Dzmitry Malyshau
2021-06-08 17:12:28 -04:00
parent a0b51ce35c
commit 6d229847be
6 changed files with 115 additions and 48 deletions

1
Cargo.lock generated
View File

@@ -1918,7 +1918,6 @@ dependencies = [
"metal",
"naga",
"raw-window-handle",
"smallvec",
"thiserror",
"wgpu-types",
"winit",

View File

@@ -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<A: HalApi> Device<A> {
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<A: HalApi> Device<A> {
.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<A: HalApi> Device<A> {
&*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<A: HalApi> Device<A> {
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<A: HalApi> Device<A> {
&*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<A: HalApi> Device<A> {
});
}
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<A: HalApi> Device<A> {
}
}
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<A: HalApi> Device<A> {
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<A: HalApi> Device<A> {
})
}
};
//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<A: HalApi> Device<A> {
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<A: HalApi> Device<A> {
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

View File

@@ -748,10 +748,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
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)?;
}
}

View File

@@ -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" }

View File

@@ -27,6 +27,7 @@ struct Locals {
}
struct Example<A: hal::Api> {
#[allow(dead_code)]
instance: A::Instance,
surface: A::Surface,
surface_format: wgt::TextureFormat,
@@ -48,7 +49,7 @@ impl<A: hal::Api> Example<A> {
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<A: hal::Api> Example<A> {
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<A: hal::Api> Example<A> {
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::<hal::api::Metal>(&window);
let example_result = Example::<hal::api::Metal>::init(&window);
#[cfg(not(any(feature = "metal")))]
let example_result = Example::<hal::api::Empty>::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();
}
_ => {}
}
});
}

View File

@@ -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<A: Api> 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<A: Api> Clone for BindingResource<'_, A> {
impl<A: Api> 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)]