mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
[hal] Document buffer mapping and coherence.
This commit is contained in:
parent
d7a35ecda0
commit
3b5051071a
@ -40,12 +40,10 @@
|
|||||||
* taking objects by reference, returning them by value, and so on,
|
* taking objects by reference, returning them by value, and so on,
|
||||||
* unlike `wgpu-core`, which refers to objects by ID.
|
* unlike `wgpu-core`, which refers to objects by ID.
|
||||||
*
|
*
|
||||||
* - We map buffer contents *persistently*. This means that the buffer
|
* - We map buffer contents *persistently*. This means that the buffer can
|
||||||
* can remain mapped on the CPU while the GPU reads or writes to it.
|
* remain mapped on the CPU while the GPU reads or writes to it. You must
|
||||||
* You must explicitly indicate when data might need to be
|
* explicitly indicate when data might need to be transferred between CPU and
|
||||||
* transferred between CPU and GPU, if `wgpu-hal` indicates that the
|
* GPU, if [`Device::map_buffer`] indicates that this is necessary.
|
||||||
* mapping is not coherent (that is, automatically synchronized
|
|
||||||
* between the two devices).
|
|
||||||
*
|
*
|
||||||
* - You must record *explicit barriers* between different usages of a
|
* - You must record *explicit barriers* between different usages of a
|
||||||
* resource. For example, if a buffer is written to by a compute
|
* resource. For example, if a buffer is written to by a compute
|
||||||
@ -662,17 +660,93 @@ pub trait Device: WasmNotSendSync {
|
|||||||
&self,
|
&self,
|
||||||
desc: &BufferDescriptor,
|
desc: &BufferDescriptor,
|
||||||
) -> Result<<Self::A as Api>::Buffer, DeviceError>;
|
) -> Result<<Self::A as Api>::Buffer, DeviceError>;
|
||||||
|
|
||||||
|
/// Free `buffer` and any GPU resources it owns.
|
||||||
|
///
|
||||||
|
/// Note that backends are allowed to allocate GPU memory for buffers from
|
||||||
|
/// allocation pools, and this call is permitted to simply return `buffer`'s
|
||||||
|
/// storage to that pool, without making it available to other applications.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The given `buffer` must not currently be mapped.
|
||||||
unsafe fn destroy_buffer(&self, buffer: <Self::A as Api>::Buffer);
|
unsafe fn destroy_buffer(&self, buffer: <Self::A as Api>::Buffer);
|
||||||
|
|
||||||
|
/// Return a pointer to CPU memory mapping the contents of `buffer`.
|
||||||
|
///
|
||||||
|
/// Buffer mappings are persistent: the buffer may remain mapped on the CPU
|
||||||
|
/// while the GPU reads or writes to it. (Note that `wgpu_core` does not use
|
||||||
|
/// this feature: when a `wgpu_core::Buffer` is unmapped, the underlying
|
||||||
|
/// `wgpu_hal` buffer is also unmapped.)
|
||||||
|
///
|
||||||
|
/// If this function returns `Ok(mapping)`, then:
|
||||||
|
///
|
||||||
|
/// - `mapping.ptr` is the CPU address of the start of the mapped memory.
|
||||||
|
///
|
||||||
|
/// - If `mapping.is_coherent` is `true`, then CPU writes to the mapped
|
||||||
|
/// memory are immediately visible on the GPU, and vice versa.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The given `buffer` must have been created with the [`MAP_READ`] or
|
||||||
|
/// [`MAP_WRITE`] flags set in [`BufferDescriptor::usage`].
|
||||||
|
///
|
||||||
|
/// - The given `range` must fall within the size of `buffer`.
|
||||||
|
///
|
||||||
|
/// - The caller must avoid data races between the CPU and the GPU. A data
|
||||||
|
/// race is any pair of accesses to a particular byte, one of which is a
|
||||||
|
/// write, that are not ordered with respect to each other by some sort of
|
||||||
|
/// synchronization operation.
|
||||||
|
///
|
||||||
|
/// - If this function returns `Ok(mapping)` and `mapping.is_coherent` is
|
||||||
|
/// `false`, then:
|
||||||
|
///
|
||||||
|
/// - Every CPU write to a mapped byte followed by a GPU read of that byte
|
||||||
|
/// must have at least one call to [`Device::flush_mapped_ranges`]
|
||||||
|
/// covering that byte that occurs between those two accesses.
|
||||||
|
///
|
||||||
|
/// - Every GPU write to a mapped byte followed by a CPU read of that byte
|
||||||
|
/// must have at least one call to [`Device::invalidate_mapped_ranges`]
|
||||||
|
/// covering that byte that occurs between those two accesses.
|
||||||
|
///
|
||||||
|
/// Note that the data race rule above requires that all such access pairs
|
||||||
|
/// be ordered, so it is meaningful to talk about what must occur
|
||||||
|
/// "between" them.
|
||||||
|
///
|
||||||
|
/// [`MAP_READ`]: BufferUses::MAP_READ
|
||||||
|
/// [`MAP_WRITE`]: BufferUses::MAP_WRITE
|
||||||
//TODO: clarify if zero-sized mapping is allowed
|
//TODO: clarify if zero-sized mapping is allowed
|
||||||
unsafe fn map_buffer(
|
unsafe fn map_buffer(
|
||||||
&self,
|
&self,
|
||||||
buffer: &<Self::A as Api>::Buffer,
|
buffer: &<Self::A as Api>::Buffer,
|
||||||
range: MemoryRange,
|
range: MemoryRange,
|
||||||
) -> Result<BufferMapping, DeviceError>;
|
) -> Result<BufferMapping, DeviceError>;
|
||||||
|
|
||||||
|
/// Remove the mapping established by the last call to [`Device::map_buffer`].
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The given `buffer` must be currently mapped.
|
||||||
unsafe fn unmap_buffer(&self, buffer: &<Self::A as Api>::Buffer) -> Result<(), DeviceError>;
|
unsafe fn unmap_buffer(&self, buffer: &<Self::A as Api>::Buffer) -> Result<(), DeviceError>;
|
||||||
|
|
||||||
|
/// Indicate that CPU writes to mapped buffer memory should be made visible to the GPU.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The given `buffer` must be currently mapped.
|
||||||
|
///
|
||||||
|
/// - All ranges produced by `ranges` must fall within `buffer`'s size.
|
||||||
unsafe fn flush_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
|
unsafe fn flush_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
|
||||||
where
|
where
|
||||||
I: Iterator<Item = MemoryRange>;
|
I: Iterator<Item = MemoryRange>;
|
||||||
|
|
||||||
|
/// Indicate that GPU writes to mapped buffer memory should be made visible to the CPU.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The given `buffer` must be currently mapped.
|
||||||
|
///
|
||||||
|
/// - All ranges produced by `ranges` must fall within `buffer`'s size.
|
||||||
unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
|
unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
|
||||||
where
|
where
|
||||||
I: Iterator<Item = MemoryRange>;
|
I: Iterator<Item = MemoryRange>;
|
||||||
|
Loading…
Reference in New Issue
Block a user