[wgpu-core] fix .zip() usages

This commit is contained in:
teoxoy 2024-07-10 12:12:12 +02:00 committed by Teodor Tanasoaia
parent 4349e20b8d
commit ef0ce05d3a
4 changed files with 81 additions and 5 deletions

View File

@ -144,7 +144,10 @@ mod compat {
let mut expected_bgl_entries = expected_bgl.entries.iter();
let mut assigned_bgl_entries = assigned_bgl.entries.iter();
let zipped = (&mut expected_bgl_entries).zip(&mut assigned_bgl_entries);
let zipped = crate::utils::ZipWithProperAdvance::new(
&mut expected_bgl_entries,
&mut assigned_bgl_entries,
);
for ((&binding, expected_entry), (_, assigned_entry)) in zipped {
if assigned_entry.visibility != expected_entry.visibility {

View File

@ -1532,8 +1532,17 @@ impl Global {
let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
pipeline_layout_guard.insert(ids.root_id, pipeline.layout.clone());
let group_ids = &mut ids.group_ids.iter();
for (bgl_id, bgl) in group_ids.zip(pipeline.layout.bind_group_layouts.iter()) {
let mut group_ids = ids.group_ids.iter();
// NOTE: If the first iterator is longer than the second, the `.zip()` impl will still advance the
// the first iterator before realizing that the second iterator has finished.
// The `pipeline.layout.bind_group_layouts` iterator will always be shorter than `ids.group_ids`,
// so using it as the first iterator for `.zip()` will work properly.
for (bgl, bgl_id) in pipeline
.layout
.bind_group_layouts
.iter()
.zip(&mut group_ids)
{
bgl_guard.insert(*bgl_id, bgl.clone());
}
for bgl_id in group_ids {
@ -1721,8 +1730,17 @@ impl Global {
let mut pipeline_layout_guard = hub.pipeline_layouts.write();
let mut bgl_guard = hub.bind_group_layouts.write();
pipeline_layout_guard.insert(ids.root_id, pipeline.layout.clone());
let group_ids = &mut ids.group_ids.iter();
for (bgl_id, bgl) in group_ids.zip(pipeline.layout.bind_group_layouts.iter()) {
let mut group_ids = ids.group_ids.iter();
// NOTE: If the first iterator is longer than the second, the `.zip()` impl will still advance the
// the first iterator before realizing that the second iterator has finished.
// The `pipeline.layout.bind_group_layouts` iterator will always be shorter than `ids.group_ids`,
// so using it as the first iterator for `.zip()` will work properly.
for (bgl, bgl_id) in pipeline
.layout
.bind_group_layouts
.iter()
.zip(&mut group_ids)
{
bgl_guard.insert(*bgl_id, bgl.clone());
}
for bgl_id in group_ids {

View File

@ -71,6 +71,7 @@ pub mod resource;
mod snatch;
pub mod storage;
mod track;
mod utils;
// This is public for users who pre-compile shaders while still wanting to
// preserve all run-time checks that `wgpu-core` does.
// See <https://github.com/gfx-rs/wgpu/issues/3103>, after which this can be

54
wgpu-core/src/utils.rs Normal file
View File

@ -0,0 +1,54 @@
/// If the first iterator is longer than the second, the zip implementation
/// in the standard library will still advance the the first iterator before
/// realizing that the second iterator has finished.
///
/// This implementation will advance the shorter iterator first avoiding
/// the issue above.
///
/// If you can guarantee that the first iterator is always shorter than the
/// second, you should use the zip impl in stdlib.
pub(crate) struct ZipWithProperAdvance<
A: ExactSizeIterator<Item = IA>,
B: ExactSizeIterator<Item = IB>,
IA,
IB,
> {
a: A,
b: B,
iter_a_first: bool,
}
impl<A: ExactSizeIterator<Item = IA>, B: ExactSizeIterator<Item = IB>, IA, IB>
ZipWithProperAdvance<A, B, IA, IB>
{
pub(crate) fn new(a: A, b: B) -> Self {
let iter_a_first = a.len() <= b.len();
Self { a, b, iter_a_first }
}
}
impl<A: ExactSizeIterator<Item = IA>, B: ExactSizeIterator<Item = IB>, IA, IB> Iterator
for ZipWithProperAdvance<A, B, IA, IB>
{
type Item = (IA, IB);
fn next(&mut self) -> Option<Self::Item> {
if self.iter_a_first {
let a = self.a.next()?;
let b = self.b.next()?;
Some((a, b))
} else {
let b = self.b.next()?;
let a = self.a.next()?;
Some((a, b))
}
}
}
impl<A: ExactSizeIterator<Item = IA>, B: ExactSizeIterator<Item = IB>, IA, IB> ExactSizeIterator
for ZipWithProperAdvance<A, B, IA, IB>
{
fn len(&self) -> usize {
self.a.len().min(self.b.len())
}
}