Skip to content

Commit 4e78829

Browse files
authored
[wgpu-core] when mapping buffers for reading, mark buffers as initialized only when they have MAP_WRITE usage (#6178)
1 parent ee35b0e commit 4e78829

File tree

2 files changed

+75
-12
lines changed

2 files changed

+75
-12
lines changed

wgpu-core/src/device/mod.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -336,19 +336,41 @@ fn map_buffer(
336336

337337
let mapped = unsafe { std::slice::from_raw_parts_mut(mapping.ptr.as_ptr(), size as usize) };
338338

339-
for uninitialized in buffer
340-
.initialization_status
341-
.write()
342-
.drain(offset..(size + offset))
339+
// We can't call flush_mapped_ranges in this case, so we can't drain the uninitialized ranges either
340+
if !mapping.is_coherent
341+
&& kind == HostMap::Read
342+
&& !buffer.usage.contains(wgt::BufferUsages::MAP_WRITE)
343343
{
344-
// The mapping's pointer is already offset, however we track the
345-
// uninitialized range relative to the buffer's start.
346-
let fill_range =
347-
(uninitialized.start - offset) as usize..(uninitialized.end - offset) as usize;
348-
mapped[fill_range].fill(0);
349-
350-
if !mapping.is_coherent && kind == HostMap::Read {
351-
unsafe { raw.flush_mapped_ranges(raw_buffer, &[uninitialized]) };
344+
for uninitialized in buffer
345+
.initialization_status
346+
.write()
347+
.uninitialized(offset..(size + offset))
348+
{
349+
// The mapping's pointer is already offset, however we track the
350+
// uninitialized range relative to the buffer's start.
351+
let fill_range =
352+
(uninitialized.start - offset) as usize..(uninitialized.end - offset) as usize;
353+
mapped[fill_range].fill(0);
354+
}
355+
} else {
356+
for uninitialized in buffer
357+
.initialization_status
358+
.write()
359+
.drain(offset..(size + offset))
360+
{
361+
// The mapping's pointer is already offset, however we track the
362+
// uninitialized range relative to the buffer's start.
363+
let fill_range =
364+
(uninitialized.start - offset) as usize..(uninitialized.end - offset) as usize;
365+
mapped[fill_range].fill(0);
366+
367+
// NOTE: This is only possible when MAPPABLE_PRIMARY_BUFFERS is enabled.
368+
if !mapping.is_coherent
369+
&& kind == HostMap::Read
370+
&& buffer.usage.contains(wgt::BufferUsages::MAP_WRITE)
371+
{
372+
unsafe { raw.flush_mapped_ranges(raw_buffer, &[uninitialized]) };
373+
}
352374
}
353375
}
354376

wgpu-core/src/init_tracker/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@ pub(crate) struct InitTracker<Idx: Ord + Copy + Default> {
6565
uninitialized_ranges: UninitializedRangeVec<Idx>,
6666
}
6767

68+
pub(crate) struct UninitializedIter<'a, Idx: fmt::Debug + Ord + Copy> {
69+
uninitialized_ranges: &'a UninitializedRangeVec<Idx>,
70+
drain_range: Range<Idx>,
71+
next_index: usize,
72+
}
73+
74+
impl<'a, Idx> Iterator for UninitializedIter<'a, Idx>
75+
where
76+
Idx: fmt::Debug + Ord + Copy,
77+
{
78+
type Item = Range<Idx>;
79+
80+
fn next(&mut self) -> Option<Self::Item> {
81+
self.uninitialized_ranges
82+
.get(self.next_index)
83+
.and_then(|range| {
84+
if range.start < self.drain_range.end {
85+
self.next_index += 1;
86+
Some(
87+
range.start.max(self.drain_range.start)
88+
..range.end.min(self.drain_range.end),
89+
)
90+
} else {
91+
None
92+
}
93+
})
94+
}
95+
}
96+
6897
pub(crate) struct InitTrackerDrain<'a, Idx: fmt::Debug + Ord + Copy> {
6998
uninitialized_ranges: &'a mut UninitializedRangeVec<Idx>,
7099
drain_range: Range<Idx>,
@@ -190,6 +219,18 @@ where
190219
})
191220
}
192221

222+
// Returns an iterator over the uninitialized ranges in a query range.
223+
pub(crate) fn uninitialized(&mut self, drain_range: Range<Idx>) -> UninitializedIter<Idx> {
224+
let index = self
225+
.uninitialized_ranges
226+
.partition_point(|r| r.end <= drain_range.start);
227+
UninitializedIter {
228+
drain_range,
229+
uninitialized_ranges: &self.uninitialized_ranges,
230+
next_index: index,
231+
}
232+
}
233+
193234
// Drains uninitialized ranges in a query range.
194235
pub(crate) fn drain(&mut self, drain_range: Range<Idx>) -> InitTrackerDrain<Idx> {
195236
let index = self

0 commit comments

Comments
 (0)