Look here to learn more about Vulkan Buffer Device Address.
For more technical deep dive into how Vulkan buffer device addresses work, here is another resource to check out.
API Proposal
Raw Vulkan Code for Reference
Creating the specific VkBuffer handle just like any other buffer handle. Only difference is being configured with the VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT flag set.
VkBufferCreateInfo bufferInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = 1024,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
};
vkCreateBuffer(device, &bufferInfo, nullptr, &myBuffer);
// Getting memory requirements for allocation params
VkMemoryRequirements memReqs;
vkGetBufferMemoryRequirements(device, myBuffer, &memReqs);
// Buffer Device Address (BDA) requirees the VkMemoryAllocateFlagsInfo to be set here.
VkMemoryAllocateFlagsInfo flagsInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT // REQUIRED
};
VkMemoryAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &flagsInfo, // Chain the flags
.allocationSize = memReqs.size,
.memoryTypeIndex = /* select memory index (specifically to
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) */
};
vkAllocateMemory(device, &allocInfo, nullptr, &myMemory);
vkBindBufferMemory(device, myBuffer, myMemory, 0);
To getting the Buffer Device Address
// Usage:
VkBufferDeviceAddressInfo addressInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = myBuffer
};
// This is to get the buffer device address "GPU Pointer"
VkDeviceAddress gpuAddress = vkGetBufferDeviceAddress(device, &addressInfo);
// You can now send this uint64_t to your shader via Push Constants
vkCmdPushConstants(commandBuffer,
pipelineLayout,
VK_SHADER_STAGE_ALL,
0,
sizeof(uint64_t),
&gpuAddress);
Proposal API
vk::dyn::buffer_device_address_params buffer_device_params = {
.flags =
vk::buffer_usage::storage | vk::buffer_usage::shader_device_address_bit,
.allocate_flags = vk::memory_allocate::device_address_bit,
.memory_mask = /* memory mask index */,
};
const uint64_t size = 1024;
vk::dyn::gpu_buffer buffer_device_address(logical_device,
size,
buffer_device_params);
// Automates:
// VkDeviceAddress gpuAddress = vkGetBufferDeviceAddress(device, &addressInfo);
const uint64_t gpu_address = buffer_device_address.get();
// Assume we want to get it working with `vk::pipeline`.
vk::pipeline graphics_pipeline = /* ... */;
graphics_pipeline.push_constants<uint64_t>(
std::span<const uint64_t>(&gpu_address, 1), vk::shader_stage::all);
/*
// Automates:
vkCmdPushConstants(commandBuffer,
pipelineLayout,
VK_SHADER_STAGE_ALL,
0,
sizeof(uint64_t),
&gpuAddress);
*/
Look here to learn more about Vulkan Buffer Device Address.
For more technical deep dive into how Vulkan buffer device addresses work, here is another resource to check out.
API Proposal
Raw Vulkan Code for Reference
Creating the specific
VkBufferhandle just like any other buffer handle. Only difference is being configured with theVK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BITflag set.VkBufferCreateInfo bufferInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = 1024, .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, }; vkCreateBuffer(device, &bufferInfo, nullptr, &myBuffer); // Getting memory requirements for allocation params VkMemoryRequirements memReqs; vkGetBufferMemoryRequirements(device, myBuffer, &memReqs); // Buffer Device Address (BDA) requirees the VkMemoryAllocateFlagsInfo to be set here. VkMemoryAllocateFlagsInfo flagsInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT // REQUIRED }; VkMemoryAllocateInfo allocInfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .pNext = &flagsInfo, // Chain the flags .allocationSize = memReqs.size, .memoryTypeIndex = /* select memory index (specifically to VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) */ }; vkAllocateMemory(device, &allocInfo, nullptr, &myMemory); vkBindBufferMemory(device, myBuffer, myMemory, 0);To getting the Buffer Device Address
Proposal API
vk::dyn::buffer_device_address_params buffer_device_params = { .flags = vk::buffer_usage::storage | vk::buffer_usage::shader_device_address_bit, .allocate_flags = vk::memory_allocate::device_address_bit, .memory_mask = /* memory mask index */, }; const uint64_t size = 1024; vk::dyn::gpu_buffer buffer_device_address(logical_device, size, buffer_device_params); // Automates: // VkDeviceAddress gpuAddress = vkGetBufferDeviceAddress(device, &addressInfo); const uint64_t gpu_address = buffer_device_address.get(); // Assume we want to get it working with `vk::pipeline`. vk::pipeline graphics_pipeline = /* ... */; graphics_pipeline.push_constants<uint64_t>( std::span<const uint64_t>(&gpu_address, 1), vk::shader_stage::all); /* // Automates: vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_ALL, 0, sizeof(uint64_t), &gpuAddress); */