Module vulkano::buffer

source ·
Expand description

Location in memory that contains data.

A Vulkan buffer is very similar to a buffer that you would use in programming languages in general, in the sense that it is a location in memory that contains data. The difference between a Vulkan buffer and a regular buffer is that the content of a Vulkan buffer is accessible from the GPU.

Vulkano does not perform any specific marshalling of buffer data. The representation of the buffer in memory is identical between the CPU and GPU. Because the Rust compiler is allowed to reorder struct fields at will by default when using #[repr(Rust)], it is advised to mark each struct requiring imput assembly as #[repr(C)]. This forces Rust to follow the standard C procedure. Each element is laid out in memory in the order of declaration and aligned to a multiple of their alignment.

Multiple levels of abstraction

  • The low-level implementation of a buffer is RawBuffer, which corresponds directly to a VkBuffer, and as such doesn’t hold onto any memory.
  • Buffer is a RawBuffer with memory bound to it, and with state tracking.
  • Subbuffer is what you will use most of the time, as it is what all the APIs expect. It is a reference to a portion of a Buffer. Subbuffer also has a type parameter, which is a hint for how the data in the portion of the buffer is going to be interpreted.

Subbuffer allocation

There are two ways to get a Subbuffer:

  • By using the functions on Buffer, which create a new buffer and memory allocation each time, and give you a Subbuffer that has an entire Buffer dedicated to it.
  • By using the SubbufferAllocator, which creates Subbuffers by suballocating existing Buffers such that the Buffers can keep being reused.

Which of these you should choose depends on the use case. For example, if you need to upload data to the device each frame, then you should use SubbufferAllocator. Same goes for if you need to download data very frequently, or if you need to allocate a lot of intermediary buffers that are only accessed by the device. On the other hand, if you need to upload some data just once, or you can keep reusing the same buffer (because its size is unchanging) it’s best to use a dedicated Buffer for that.

Buffer usage

When you create a buffer, 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 a runtime error.

You can use buffers for the following purposes:

  • Can contain arbitrary data that can be transferred from/to other buffers and images.
  • Can be read and modified from a shader.
  • Can be used as a source of vertices and indices.
  • Can be used as a source of list of models for draw indirect commands.

Accessing a buffer from a shader can be done in the following ways:

  • As a uniform buffer. Uniform buffers are read-only.
  • As a storage buffer. Storage buffers can be read and written.
  • As a uniform texel buffer. Contrary to a uniform buffer, the data is interpreted by the GPU and can be for example normalized.
  • As a storage texel buffer. Additionally, some data formats can be modified with atomic operations.

Using uniform/storage texel buffers requires creating a buffer view. See the view module for how to create a buffer view.

See also the shader module documentation for information about how buffer contents need to be laid out in accordance with the shader interface.

Re-exports

Modules

  • Efficiently suballocates buffers into smaller subbuffers.
  • A subpart of a buffer.
  • Low level implementation of buffers.
  • View of a buffer, in order to use it as a uniform texel buffer or storage texel buffer.

Structs

Enums

  • Error that can happen when allocating a new buffer.
  • The type of backing memory that a buffer can have.
  • A buffer holding index values, which index into buffers holding vertex data.
  • An enumeration of all valid index types.