mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
[wgpu-core] when mapping buffers for reading, mark buffers as initialized only when they have MAP_WRITE
usage (#6178)
This commit is contained in:
parent
ee35b0e586
commit
4e78829d82
@ -336,6 +336,23 @@ fn map_buffer(
|
||||
|
||||
let mapped = unsafe { std::slice::from_raw_parts_mut(mapping.ptr.as_ptr(), size as usize) };
|
||||
|
||||
// We can't call flush_mapped_ranges in this case, so we can't drain the uninitialized ranges either
|
||||
if !mapping.is_coherent
|
||||
&& kind == HostMap::Read
|
||||
&& !buffer.usage.contains(wgt::BufferUsages::MAP_WRITE)
|
||||
{
|
||||
for uninitialized in buffer
|
||||
.initialization_status
|
||||
.write()
|
||||
.uninitialized(offset..(size + offset))
|
||||
{
|
||||
// The mapping's pointer is already offset, however we track the
|
||||
// uninitialized range relative to the buffer's start.
|
||||
let fill_range =
|
||||
(uninitialized.start - offset) as usize..(uninitialized.end - offset) as usize;
|
||||
mapped[fill_range].fill(0);
|
||||
}
|
||||
} else {
|
||||
for uninitialized in buffer
|
||||
.initialization_status
|
||||
.write()
|
||||
@ -347,10 +364,15 @@ fn map_buffer(
|
||||
(uninitialized.start - offset) as usize..(uninitialized.end - offset) as usize;
|
||||
mapped[fill_range].fill(0);
|
||||
|
||||
if !mapping.is_coherent && kind == HostMap::Read {
|
||||
// NOTE: This is only possible when MAPPABLE_PRIMARY_BUFFERS is enabled.
|
||||
if !mapping.is_coherent
|
||||
&& kind == HostMap::Read
|
||||
&& buffer.usage.contains(wgt::BufferUsages::MAP_WRITE)
|
||||
{
|
||||
unsafe { raw.flush_mapped_ranges(raw_buffer, &[uninitialized]) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mapping)
|
||||
}
|
||||
|
@ -65,6 +65,35 @@ pub(crate) struct InitTracker<Idx: Ord + Copy + Default> {
|
||||
uninitialized_ranges: UninitializedRangeVec<Idx>,
|
||||
}
|
||||
|
||||
pub(crate) struct UninitializedIter<'a, Idx: fmt::Debug + Ord + Copy> {
|
||||
uninitialized_ranges: &'a UninitializedRangeVec<Idx>,
|
||||
drain_range: Range<Idx>,
|
||||
next_index: usize,
|
||||
}
|
||||
|
||||
impl<'a, Idx> Iterator for UninitializedIter<'a, Idx>
|
||||
where
|
||||
Idx: fmt::Debug + Ord + Copy,
|
||||
{
|
||||
type Item = Range<Idx>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.uninitialized_ranges
|
||||
.get(self.next_index)
|
||||
.and_then(|range| {
|
||||
if range.start < self.drain_range.end {
|
||||
self.next_index += 1;
|
||||
Some(
|
||||
range.start.max(self.drain_range.start)
|
||||
..range.end.min(self.drain_range.end),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct InitTrackerDrain<'a, Idx: fmt::Debug + Ord + Copy> {
|
||||
uninitialized_ranges: &'a mut UninitializedRangeVec<Idx>,
|
||||
drain_range: Range<Idx>,
|
||||
@ -190,6 +219,18 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
// Returns an iterator over the uninitialized ranges in a query range.
|
||||
pub(crate) fn uninitialized(&mut self, drain_range: Range<Idx>) -> UninitializedIter<Idx> {
|
||||
let index = self
|
||||
.uninitialized_ranges
|
||||
.partition_point(|r| r.end <= drain_range.start);
|
||||
UninitializedIter {
|
||||
drain_range,
|
||||
uninitialized_ranges: &self.uninitialized_ranges,
|
||||
next_index: index,
|
||||
}
|
||||
}
|
||||
|
||||
// Drains uninitialized ranges in a query range.
|
||||
pub(crate) fn drain(&mut self, drain_range: Range<Idx>) -> InitTrackerDrain<Idx> {
|
||||
let index = self
|
||||
|
Loading…
Reference in New Issue
Block a user