Skip to content

Commit 4f65cbe

Browse files
committed
Support descriptor arrays shorter than binding length
1 parent 180e3e3 commit 4f65cbe

File tree

13 files changed

+424
-116
lines changed

13 files changed

+424
-116
lines changed

wgpu-core/src/binding_model.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,16 @@ pub enum CreateBindGroupError {
6565
InvalidTextureView(TextureViewId),
6666
#[error("sampler {0:?} is invalid")]
6767
InvalidSampler(SamplerId),
68-
#[error("binding count declared with {expected} items, but {actual} items were provided")]
68+
#[error(
69+
"binding count declared with at most {expected} items, but {actual} items were provided"
70+
)]
71+
BindingArrayPartialLengthMismatch { actual: usize, expected: usize },
72+
#[error(
73+
"binding count declared with exactly {expected} items, but {actual} items were provided"
74+
)]
6975
BindingArrayLengthMismatch { actual: usize, expected: usize },
76+
#[error("array binding provided zero elements")]
77+
BindingArrayZeroLength,
7078
#[error("bound buffer range {range:?} does not fit in buffer of size {size}")]
7179
BindingRangeTooLarge {
7280
buffer: BufferId,

wgpu-core/src/device/mod.rs

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use smallvec::SmallVec;
1919
use thiserror::Error;
2020
use wgt::{BufferAddress, TextureFormat, TextureViewDimension};
2121

22-
use std::{borrow::Cow, iter, marker::PhantomData, mem, ops::Range, ptr};
22+
use std::{borrow::Cow, iter, marker::PhantomData, mem, num::NonZeroU32, ops::Range, ptr};
2323

2424
mod life;
2525
pub mod queue;
@@ -1387,7 +1387,7 @@ impl<A: HalApi> Device<A> {
13871387
.entries
13881388
.get(&binding)
13891389
.ok_or(Error::MissingBindingDeclaration(binding))?;
1390-
let res_index = match entry.resource {
1390+
let (res_index, count) = match entry.resource {
13911391
Br::Buffer(ref bb) => {
13921392
let bb = Self::create_buffer_binding(
13931393
bb,
@@ -1402,21 +1402,11 @@ impl<A: HalApi> Device<A> {
14021402

14031403
let res_index = hal_buffers.len();
14041404
hal_buffers.push(bb);
1405-
res_index
1405+
(res_index, 1)
14061406
}
14071407
Br::BufferArray(ref bindings_array) => {
1408-
if let Some(count) = decl.count {
1409-
let count = count.get() as usize;
1410-
let num_bindings = bindings_array.len();
1411-
if count != num_bindings {
1412-
return Err(Error::BindingArrayLengthMismatch {
1413-
actual: num_bindings,
1414-
expected: count,
1415-
});
1416-
}
1417-
} else {
1418-
return Err(Error::SingleBindingExpected);
1419-
}
1408+
let num_bindings = bindings_array.len();
1409+
Self::check_array_binding(self.features, decl.count, num_bindings)?;
14201410

14211411
let res_index = hal_buffers.len();
14221412
for bb in bindings_array.iter() {
@@ -1432,7 +1422,7 @@ impl<A: HalApi> Device<A> {
14321422
)?;
14331423
hal_buffers.push(bb);
14341424
}
1435-
res_index
1425+
(res_index, num_bindings)
14361426
}
14371427
Br::Sampler(id) => {
14381428
match decl.ty {
@@ -1464,7 +1454,7 @@ impl<A: HalApi> Device<A> {
14641454

14651455
let res_index = hal_samplers.len();
14661456
hal_samplers.push(&sampler.raw);
1467-
res_index
1457+
(res_index, 1)
14681458
}
14691459
_ => {
14701460
return Err(Error::WrongBindingType {
@@ -1505,21 +1495,11 @@ impl<A: HalApi> Device<A> {
15051495
view: &view.raw,
15061496
usage: internal_use,
15071497
});
1508-
res_index
1498+
(res_index, 1)
15091499
}
15101500
Br::TextureViewArray(ref bindings_array) => {
1511-
if let Some(count) = decl.count {
1512-
let count = count.get() as usize;
1513-
let num_bindings = bindings_array.len();
1514-
if count != num_bindings {
1515-
return Err(Error::BindingArrayLengthMismatch {
1516-
actual: num_bindings,
1517-
expected: count,
1518-
});
1519-
}
1520-
} else {
1521-
return Err(Error::SingleBindingExpected);
1522-
}
1501+
let num_bindings = bindings_array.len();
1502+
Self::check_array_binding(self.features, decl.count, num_bindings)?;
15231503

15241504
let res_index = hal_textures.len();
15251505
for &id in bindings_array.iter() {
@@ -1551,13 +1531,14 @@ impl<A: HalApi> Device<A> {
15511531
});
15521532
}
15531533

1554-
res_index
1534+
(res_index, num_bindings)
15551535
}
15561536
};
15571537

15581538
hal_entries.push(hal::BindGroupEntry {
15591539
binding,
15601540
resource_index: res_index as u32,
1541+
count: count as u32,
15611542
});
15621543
}
15631544

@@ -1596,6 +1577,39 @@ impl<A: HalApi> Device<A> {
15961577
})
15971578
}
15981579

1580+
fn check_array_binding(
1581+
features: wgt::Features,
1582+
count: Option<NonZeroU32>,
1583+
num_bindings: usize,
1584+
) -> Result<(), super::binding_model::CreateBindGroupError> {
1585+
use super::binding_model::CreateBindGroupError as Error;
1586+
1587+
if let Some(count) = count {
1588+
let count = count.get() as usize;
1589+
if count < num_bindings {
1590+
return Err(Error::BindingArrayPartialLengthMismatch {
1591+
actual: num_bindings,
1592+
expected: count,
1593+
});
1594+
}
1595+
if count != num_bindings
1596+
&& !features.contains(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY)
1597+
{
1598+
return Err(Error::BindingArrayLengthMismatch {
1599+
actual: num_bindings,
1600+
expected: count,
1601+
});
1602+
}
1603+
if num_bindings == 0 {
1604+
return Err(Error::BindingArrayZeroLength);
1605+
}
1606+
} else {
1607+
return Err(Error::SingleBindingExpected);
1608+
};
1609+
1610+
Ok(())
1611+
}
1612+
15991613
fn texture_use_parameters(
16001614
binding: u32,
16011615
decl: &wgt::BindGroupLayoutEntry,

wgpu-core/src/instance.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,12 @@ impl<A: HalApi> Adapter<A> {
334334
desc: &DeviceDescriptor,
335335
trace_path: Option<&std::path::Path>,
336336
) -> Result<Device<A>, RequestDeviceError> {
337-
let open = unsafe { self.raw.adapter.open(desc.features) }.map_err(|err| match err {
338-
hal::DeviceError::Lost => RequestDeviceError::DeviceLost,
339-
hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory,
340-
})?;
337+
let open = unsafe { self.raw.adapter.open(desc.features, &desc.limits) }.map_err(
338+
|err| match err {
339+
hal::DeviceError::Lost => RequestDeviceError::DeviceLost,
340+
hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory,
341+
},
342+
)?;
341343

342344
self.create_device_from_hal(self_id, open, desc, trace_path)
343345
}

wgpu-hal/examples/halmark/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,14 +417,17 @@ impl<A: hal::Api> Example<A> {
417417
hal::BindGroupEntry {
418418
binding: 0,
419419
resource_index: 0,
420+
count: 1,
420421
},
421422
hal::BindGroupEntry {
422423
binding: 1,
423424
resource_index: 0,
425+
count: 1,
424426
},
425427
hal::BindGroupEntry {
426428
binding: 2,
427429
resource_index: 0,
430+
count: 1,
428431
},
429432
],
430433
};
@@ -446,6 +449,7 @@ impl<A: hal::Api> Example<A> {
446449
entries: &[hal::BindGroupEntry {
447450
binding: 0,
448451
resource_index: 0,
452+
count: 1,
449453
}],
450454
};
451455
unsafe { device.create_bind_group(&local_group_desc).unwrap() }

wgpu-hal/src/dx12/adapter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
262262
unsafe fn open(
263263
&self,
264264
features: wgt::Features,
265+
_limits: &wgt::Limits,
265266
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
266267
let queue = self
267268
.device

wgpu-hal/src/empty.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ impl crate::Surface<Api> for Context {
7474
}
7575

7676
impl crate::Adapter<Api> for Context {
77-
unsafe fn open(&self, features: wgt::Features) -> DeviceResult<crate::OpenDevice<Api>> {
77+
unsafe fn open(
78+
&self,
79+
features: wgt::Features,
80+
_limits: &wgt::Limits,
81+
) -> DeviceResult<crate::OpenDevice<Api>> {
7882
Err(crate::DeviceError::Lost)
7983
}
8084
unsafe fn texture_format_capabilities(

wgpu-hal/src/gles/adapter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
419419
unsafe fn open(
420420
&self,
421421
features: wgt::Features,
422+
_limits: &wgt::Limits,
422423
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
423424
let gl = &self.shared.context.lock();
424425
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);

wgpu-hal/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,11 @@ pub trait Surface<A: Api>: Send + Sync {
188188
}
189189

190190
pub trait Adapter<A: Api>: Send + Sync {
191-
unsafe fn open(&self, features: wgt::Features) -> Result<OpenDevice<A>, DeviceError>;
191+
unsafe fn open(
192+
&self,
193+
features: wgt::Features,
194+
limits: &wgt::Limits,
195+
) -> Result<OpenDevice<A>, DeviceError>;
192196

193197
/// Return the set of supported capabilities for a texture format.
194198
unsafe fn texture_format_capabilities(
@@ -847,6 +851,7 @@ impl<A: Api> Clone for TextureBinding<'_, A> {
847851
pub struct BindGroupEntry {
848852
pub binding: u32,
849853
pub resource_index: u32,
854+
pub count: u32,
850855
}
851856

852857
/// BindGroup descriptor.

wgpu-hal/src/metal/adapter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
1919
unsafe fn open(
2020
&self,
2121
features: wgt::Features,
22+
_limits: &wgt::Limits,
2223
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
2324
let queue = self
2425
.shared

0 commit comments

Comments
 (0)