/// Returns index of type of parent memory object. #[inline(always)] pubfn memory_type(&self) -> u32 { self.memory_type
}
/// Returns pointer to mapped memory range of this block. /// This blocks becomes mapped. /// /// The user of returned pointer must guarantee that any previously submitted command that writes to this range has completed /// before the host reads from or writes to that range, /// and that any previously submitted command that reads from that range has completed /// before the host writes to that region. /// If the device memory was allocated without the `HOST_COHERENT` property flag set, /// these guarantees must be made for an extended range: /// the user must round down the start of the range to the nearest multiple of `non_coherent_atom_size`, /// and round the end of the range up to the nearest multiple of `non_coherent_atom_size`. /// /// # Panics /// /// This function panics if block is currently mapped. /// /// # Safety /// /// `block` must have been allocated from specified `device`. #[inline(always)] pubunsafefn map(
&mutself,
device: &impl MemoryDevice<M>,
offset: u64,
size: usize,
) -> Result<NonNull<u8>, MapError> { let size_u64 = u64::try_from(size).expect("`size` doesn't fit device address space");
assert!(offset < self.size, "`offset` is out of memory block bounds");
assert!(
size_u64 <= self.size - offset, "`offset + size` is out of memory block bounds"
);
let ptr = match &mutself.flavor {
MemoryBlockFlavor::Dedicated { memory } => { let end = align_up(offset + size_u64, self.atom_mask)
.expect("mapping end doesn't fit device address space"); let aligned_offset = align_down(offset, self.atom_mask);
if !acquire_mapping(&mutself.mapped) { return Err(MapError::AlreadyMapped);
} let result =
device.map_memory(memory, self.offset + aligned_offset, end - aligned_offset);
match result { // the overflow is checked in `Self::new()`
Ok(ptr) => { let ptr_offset = (offset - aligned_offset) as isize;
ptr.as_ptr().offset(ptr_offset)
}
Err(err) => {
release_mapping(&mutself.mapped); return Err(err.into());
}
}
}
MemoryBlockFlavor::FreeList { ptr: Some(ptr), .. }
| MemoryBlockFlavor::Buddy { ptr: Some(ptr), .. } => { if !acquire_mapping(&mutself.mapped) { return Err(MapError::AlreadyMapped);
} let offset_isize = isize::try_from(offset)
.expect("Buddy and linear block should fit host address space");
ptr.as_ptr().offset(offset_isize)
}
_ => return Err(MapError::NonHostVisible),
};
Ok(NonNull::new_unchecked(ptr))
}
/// Unmaps memory range of this block that was previously mapped with `Block::map`. /// This block becomes unmapped. /// /// # Panics /// /// This function panics if this block is not currently mapped. /// /// # Safety /// /// `block` must have been allocated from specified `device`. #[inline(always)] pubunsafefn unmap(&mutself, device: &impl MemoryDevice<M>) -> bool { if !release_mapping(&mutself.mapped) { returnfalse;
} match &mutself.flavor {
MemoryBlockFlavor::Dedicated { memory } => {
device.unmap_memory(memory);
}
MemoryBlockFlavor::Buddy { .. } => {}
MemoryBlockFlavor::FreeList { .. } => {}
} true
}
/// Transiently maps block memory range and copies specified data /// to the mapped memory range. /// /// # Panics /// /// This function panics if block is currently mapped. /// /// # Safety /// /// `block` must have been allocated from specified `device`. /// The caller must guarantee that any previously submitted command that reads or writes to this range has completed. #[inline(always)] pubunsafefn write_bytes(
&mutself,
device: &impl MemoryDevice<M>,
offset: u64,
data: &[u8],
) -> Result<(), MapError> { let size = data.len(); let ptr = self.map(device, offset, size)?;
copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), size); let result = if !self.coherent() { let aligned_offset = align_down(offset, self.atom_mask); let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap();
/// Transiently maps block memory range and copies specified data /// from the mapped memory range. /// /// # Panics /// /// This function panics if block is currently mapped. /// /// # Safety /// /// `block` must have been allocated from specified `device`. /// The caller must guarantee that any previously submitted command that reads to this range has completed. #[inline(always)] pubunsafefn read_bytes(
&mutself,
device: &impl MemoryDevice<M>,
offset: u64,
data: &mut [u8],
) -> Result<(), MapError> { #[cfg(feature = "tracing")]
{ if !self.cached() {
tracing::warn!("Reading from non-cached memory may be slow. Consider allocating HOST_CACHED memory block for host reads.")
}
}
let size = data.len(); let ptr = self.map(device, offset, size)?; let result = if !self.coherent() { let aligned_offset = align_down(offset, self.atom_mask); let end = align_up(offset + data.len() as u64, self.atom_mask).unwrap();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.