mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 08:14:20 +00:00
More documentation for buffers (#763)
This commit is contained in:
parent
f13454dc6e
commit
34027ac6e7
@ -46,9 +46,10 @@ use OomError;
|
||||
// But that's hard to do because we must prevent `increase_gpu_lock` from working while a
|
||||
// a buffer is locked.
|
||||
|
||||
/// Buffer from which "sub-buffers" can be individually allocated.
|
||||
/// Ring buffer from which "sub-buffers" can be individually allocated.
|
||||
///
|
||||
/// This buffer is especially suitable when you want to upload or download some data at each frame.
|
||||
/// This buffer is especially suitable when you want to upload or download some data regularly
|
||||
/// (for example, at each frame for a video game).
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
@ -57,13 +58,46 @@ use OomError;
|
||||
/// in size.
|
||||
///
|
||||
/// Contrary to a `Vec`, elements automatically free themselves when they are dropped (ie. usually
|
||||
/// when they are no longer in use by the GPU).
|
||||
/// when you call `cleanup_finished()` on a future, or when you drop that future).
|
||||
///
|
||||
/// # Arc-like
|
||||
///
|
||||
/// The `CpuBufferPool` struct internally contains an `Arc`. You can clone the `CpuBufferPool` for
|
||||
/// a cheap cost, and all the clones will share the same underlying buffer.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::buffer::CpuBufferPool;
|
||||
/// use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||
/// use vulkano::command_buffer::CommandBuffer;
|
||||
/// use vulkano::sync::GpuFuture;
|
||||
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||
/// # let queue: std::sync::Arc<vulkano::device::Queue> = return;
|
||||
///
|
||||
/// // Create the ring buffer.
|
||||
/// let buffer = CpuBufferPool::upload(device.clone());
|
||||
///
|
||||
/// for n in 0 .. 25u32 {
|
||||
/// // Each loop grabs a new entry from that ring buffer and stores ` data` in it.
|
||||
/// let data: [f32; 4] = [1.0, 0.5, n as f32 / 24.0, 0.0];
|
||||
/// let sub_buffer = buffer.next(data);
|
||||
///
|
||||
/// // You can then use `sub_buffer` as if it was an entirely separate buffer.
|
||||
/// AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
|
||||
/// .unwrap()
|
||||
/// // For the sake of the example we just call `update_buffer` on the buffer, even though
|
||||
/// // it is pointless to do that.
|
||||
/// .update_buffer(sub_buffer.clone(), [0.2, 0.3, 0.4, 0.5])
|
||||
/// .unwrap()
|
||||
/// .build().unwrap()
|
||||
/// .execute(queue.clone())
|
||||
/// .unwrap()
|
||||
/// .then_signal_fence_and_flush()
|
||||
/// .unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
pub struct CpuBufferPool<T, A = Arc<StdMemoryPool>>
|
||||
where A: MemoryPool
|
||||
{
|
||||
|
@ -14,33 +14,48 @@
|
||||
//! between a Vulkan buffer and a regular buffer is that the content of a Vulkan buffer is
|
||||
//! accessible from the GPU.
|
||||
//!
|
||||
//! # High-level wrappers
|
||||
//! # Various kinds of buffers
|
||||
//!
|
||||
//! The low level implementation of a buffer is `UnsafeBuffer`. However, the vulkano library
|
||||
//! provides high-level wrappers around that type that are specialized depending on the way you
|
||||
//! are going to use it:
|
||||
//! The low level implementation of a buffer is [`UnsafeBuffer`](sys/struct.UnsafeBuffer.html).
|
||||
//! This type makes it possible to use all the features that Vulkan is capable of, but as its name
|
||||
//! tells it is unsafe to use.
|
||||
//!
|
||||
//! - `CpuAccessibleBuffer` designates a buffer located in RAM and whose content can be directly
|
||||
//! written by your application.
|
||||
//! - `DeviceLocalBuffer` designates a buffer located in video memory and whose content can't be
|
||||
//! written by your application. Accessing this buffer from the GPU is usually faster than the
|
||||
//! `CpuAccessibleBuffer`.
|
||||
//! - `ImmutableBuffer` designates a buffer in video memory and whose content can only be
|
||||
//! written once. Compared to `DeviceLocalBuffer`, this buffer requires less processing on the
|
||||
//! CPU because we don't need to keep track of the reads and writes.
|
||||
//! Instead you are encouraged to use one of the high-level wrappers that vulkano provides. Which
|
||||
//! wrapper to use depends on the way you are going to use the buffer:
|
||||
//!
|
||||
//! If you have data that is modified at every single frame, you are encouraged to use a
|
||||
//! `CpuAccessibleBuffer`. If you have data that is very rarely modified, you are encouraged to
|
||||
//! use an `ImmutableBuffer` or a `DeviceLocalBuffer` instead.
|
||||
//! - A [`DeviceLocalBuffer`](device_local/struct.DeviceLocalBuffer.html) designates a buffer
|
||||
//! usually located in video memory and whose content can't be directly accessed by your
|
||||
//! application. Accessing this buffer from the GPU is generally faster compared to accessing a
|
||||
//! CPU-accessible buffer.
|
||||
//! - An [`ImmutableBuffer`](immutable/struct.ImmutableBuffer.html) designates a buffer in video
|
||||
//! memory and whose content can only be written at creation. Compared to `DeviceLocalBuffer`,
|
||||
//! this buffer requires less CPU processing because we don't need to keep track of the reads
|
||||
//! and writes.
|
||||
//! - A [`CpuBufferPool`](cpu_pool/struct.CpuBufferPool.html) is a ring buffer that can be used to
|
||||
//! transfer data between the CPU and the GPU at a high rate.
|
||||
//! - A [`CpuAccessibleBuffer`](cpu_access/struct.CpuAccessibleBuffer.html) is a simple buffer that
|
||||
//! can be used to prototype. It may be removed from vulkano in the far future.
|
||||
//!
|
||||
//! If you just want to get started, you can use the `CpuAccessibleBuffer` everywhere, as it is
|
||||
//! the most flexible type of buffer.
|
||||
//! Here is a quick way to choose which buffer to use. Do you need to often need to read or write
|
||||
//! the content of the buffer? If so, use a `CpuBufferPool`. Otherwise, do you need to be able to
|
||||
//! modify the content of the buffer after its initialization? If so, use a `DeviceLocalBuffer`.
|
||||
//! If no to both questions, use an `ImmutableBuffer`.
|
||||
//!
|
||||
//! When deciding how your buffer is going to be used, don't forget that sometimes the best
|
||||
//! solution is to manipulate multiple buffers instead. For example if you need to update a buffer's
|
||||
//! content only from time to time, it may be a good idea to simply recreate a new `ImmutableBuffer`
|
||||
//! every time.
|
||||
//! Another example: if a buffer is under constant access by the GPU but you need to
|
||||
//! read its content on the CPU from time to time, it may be a good idea to use a
|
||||
//! `DeviceLocalBuffer` as the main buffer and a `CpuBufferPool` for when you need to read it.
|
||||
//! Then whenever you need to read the main buffer, ask the GPU to copy from the device-local
|
||||
//! buffer to the CPU buffer pool, and read the CPU buffer pool instead.
|
||||
//!
|
||||
//! # Buffers usage
|
||||
//!
|
||||
//! When you create a buffer object, you have to specify its *usage*. In other words, you have to
|
||||
//! specify the way it is going to be used. Trying to use a buffer in a way that wasn't specified
|
||||
//! when you created it will result in an error.
|
||||
//! when you created it will result in a runtime error.
|
||||
//!
|
||||
//! You can use buffers for the following purposes:
|
||||
//!
|
||||
|
Loading…
Reference in New Issue
Block a user