Skip to content

Add VK_KHR_buffer_device_address Support #63

@SpinnerX

Description

@SpinnerX

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);
*/

Metadata

Metadata

Assignees

Labels

💠coreCritical tasks are reserved for maintainers during fundamental architectural changes.📐designTasks that involve the core systems. Highly involve in API design.
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions