generated from engine3d-dev/conan-starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Storage buffers in Vulkan can store more data compared to both push constants and uniform buffers.
Different Uses to Storage Buffers Comparisons
These are the different resource sizes that can be sent to the shader
Push Constants
- Only store 128 to 256 bytes
- Very small and faster data transfer
- Used if data is changed every draw call
Uniform Buffers
- Stores 64kb (65,536 bytes)
- Small to medium, read only data.
- Used for data changed less like camera data.
- Optimized for fast, cached reads by the shader
Storage Buffers
- Stores 4 GB (up to full VRAM capacity)
- Large read/write of resources
- Used for bulky storage such as vertex data, large array of light sources, or even compute shader I/O.
API Design
The API design is going to look quite similar to vk::uniform_buffer, really. I would suspect the difference would be called vk::storage_buffer.
Code Example of API Usage
Setting up the storage buffer
vk::storage_buffer storage(m_device, m_arbitrary_large_light_sources);
storage.write(some_light_data); // write to the GPUSetting up buffer_memory_barriers
Difference between .compute_write does the buffer memory barrier, whereas .write does not. Which sets up the buffer memory barrier with the set parameters with the buffer your doing the operation on.
vk::buffer_memory_barrier barrier_info = {
.src_mask = vk::access::write,
.dst_mask = vk::access::read,
.src_index = VK_QUEUE_FAMILY_IGNORED,
.dst_index = VK_QUEUE_FAMILY_IGNORED,
.src_stage = vk::shader_stage::compute, // set in vkCmdPipelineBarrier
.dst_stage = vk:shader_stage::vertex, // set in vkCmdPipelineBarrier
};
storage.compute_write(barrier_info);OR free-standing helpers for memory barriers
vk::buffer_memory_barrier barrier_info = {
.src_mask = vk::access::write,
.dst_mask = vk::access::read,
.src_index = VK_QUEUE_FAMILY_IGNORED,
.dst_index = VK_QUEUE_FAMILY_IGNORED,
.src_stage = vk::shader_stage::compute, // set in vkCmdPipelineBarrier
.dst_stage = vk:shader_stage::vertex, // set in vkCmdPipelineBarrier
};
vk::buffer_memory_barrier(storage, barrier_info);storage.write(some_light_data);
.write is equivalent to doing this below.
/*
Equivalent to doing
VkMappedMemoryRange memory_range = {
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.offset = 0,
.size = VK_WHOLE_SIZE // can be typed in directly using that
};
vkFlushMappedMemoryRange(m_device, 1, &memory_range);
*/.compute_write is equivalent to doing this raw Vulkan sample code
// Equivalent to doing:
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = NULL,
// The scope of the *previous* memory operations to wait on (Compute Shader Write)
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
// The scope of the *upcoming* memory operations to make visible (Vertex Shader Read)
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
// The queue families involved (often the same)
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// The VkBuffer being synchronized
.buffer = storageBuffer,
.offset = 0,
.size = VK_WHOLE_SIZE
};
// The first pipeline stage (Compute) must be completed before the second stage (Vertex) begins.
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, // Wait for the Compute Write stage to finish
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, // Block until the Vertex Read stage is ready
0, // Dependency flags
0, NULL, // Memory barriers (none here)
1, &barrier, // Buffer memory barriers
0, NULL // Image memory barriers (none here)
);Last Few Notes
These are just some examples in comparisons to their equivalency. These may change when I begin working on getting the implementations to work as I continue learning more about descriptor indexing.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request