Skip to content

Commit da022d7

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

File tree

8 files changed

+332
-92
lines changed

8 files changed

+332
-92
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: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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,35 @@ 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+
let num_bindings = bindings_array.len();
14081409
if let Some(count) = decl.count {
14091410
let count = count.get() as usize;
1410-
let num_bindings = bindings_array.len();
1411-
if count != num_bindings {
1412-
return Err(Error::BindingArrayLengthMismatch {
1411+
if count < num_bindings {
1412+
return Err(Error::BindingArrayPartialLengthMismatch {
14131413
actual: num_bindings,
14141414
expected: count,
14151415
});
14161416
}
1417+
if count != num_bindings {
1418+
if !self
1419+
.features
1420+
.contains(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY)
1421+
{
1422+
return Err(Error::BindingArrayLengthMismatch {
1423+
actual: num_bindings,
1424+
expected: count,
1425+
});
1426+
}
1427+
}
1428+
if num_bindings == 0 {
1429+
return Err(Error::BindingArrayZeroLength);
1430+
}
14171431
} else {
14181432
return Err(Error::SingleBindingExpected);
1419-
}
1433+
};
14201434

14211435
let res_index = hal_buffers.len();
14221436
for bb in bindings_array.iter() {
@@ -1432,7 +1446,7 @@ impl<A: HalApi> Device<A> {
14321446
)?;
14331447
hal_buffers.push(bb);
14341448
}
1435-
res_index
1449+
(res_index, num_bindings)
14361450
}
14371451
Br::Sampler(id) => {
14381452
match decl.ty {
@@ -1464,7 +1478,7 @@ impl<A: HalApi> Device<A> {
14641478

14651479
let res_index = hal_samplers.len();
14661480
hal_samplers.push(&sampler.raw);
1467-
res_index
1481+
(res_index, 1)
14681482
}
14691483
_ => {
14701484
return Err(Error::WrongBindingType {
@@ -1505,21 +1519,35 @@ impl<A: HalApi> Device<A> {
15051519
view: &view.raw,
15061520
usage: internal_use,
15071521
});
1508-
res_index
1522+
(res_index, 1)
15091523
}
15101524
Br::TextureViewArray(ref bindings_array) => {
1525+
let num_bindings = bindings_array.len();
15111526
if let Some(count) = decl.count {
15121527
let count = count.get() as usize;
1513-
let num_bindings = bindings_array.len();
1514-
if count != num_bindings {
1515-
return Err(Error::BindingArrayLengthMismatch {
1528+
if count < num_bindings {
1529+
return Err(Error::BindingArrayPartialLengthMismatch {
15161530
actual: num_bindings,
15171531
expected: count,
15181532
});
15191533
}
1534+
if count != num_bindings {
1535+
if !self
1536+
.features
1537+
.contains(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY)
1538+
{
1539+
return Err(Error::BindingArrayLengthMismatch {
1540+
actual: num_bindings,
1541+
expected: count,
1542+
});
1543+
}
1544+
}
1545+
if num_bindings == 0 {
1546+
return Err(Error::BindingArrayZeroLength);
1547+
}
15201548
} else {
15211549
return Err(Error::SingleBindingExpected);
1522-
}
1550+
};
15231551

15241552
let res_index = hal_textures.len();
15251553
for &id in bindings_array.iter() {
@@ -1551,13 +1579,14 @@ impl<A: HalApi> Device<A> {
15511579
});
15521580
}
15531581

1554-
res_index
1582+
(res_index, num_bindings)
15551583
}
15561584
};
15571585

15581586
hal_entries.push(hal::BindGroupEntry {
15591587
binding,
15601588
resource_index: res_index as u32,
1589+
count: count as u32,
15611590
});
15621591
}
15631592

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/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ impl<A: Api> Clone for TextureBinding<'_, A> {
847847
pub struct BindGroupEntry {
848848
pub binding: u32,
849849
pub resource_index: u32,
850+
pub count: u32,
850851
}
851852

852853
/// BindGroup descriptor.

0 commit comments

Comments
 (0)