mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hal: redesign the bind group descriptor
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1918,7 +1918,6 @@ dependencies = [
|
||||
"metal",
|
||||
"naga",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"wgpu-types",
|
||||
"winit",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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" }
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
Reference in New Issue
Block a user