More documentation for buffers (#763)

This commit is contained in:
tomaka 2017-08-25 11:49:29 +02:00 committed by GitHub
parent f13454dc6e
commit 34027ac6e7
2 changed files with 70 additions and 21 deletions

View File

@ -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
{

View File

@ -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:
//!