Developer Tools & Techniques

Streamlining Resource Binding with End-to-End Support for Vulkan Descriptor Heaps

Shaders are GPU programs that process visual data—such as rays, pixels, geometry, and textures—to produce specific rendering effects. Shaders find necessary data through a process called resource binding. CPU code orchestrates the creation of GPU resources such as textures and memory buffers and then carefully arranges for shader code to access them through a binding protocol. 

The new descriptor heap feature in Vulkan refactors this process from the ground up, addressing long-standing user feedback to streamline resource binding and bring greater parity to how it works in Direct3D 12 (D3D12). Descriptor heaps give direct control over descriptor memory management, are a better match for modern hardware, and simplify performance optimization of resource management. They’re especially useful for renderers using dynamic texture indexing, for complex ray tracing shaders, or when there is a shared backend supporting D3D12. This post highlights what descriptor heaps add, how they compare to descriptor sets, and how to get started.

The descriptor heap API is defined by VK_EXT_descriptor_heap, for which Khronos has published both a reference manual and usage guide. The EXT prefix signifies that the extension has received cross-vendor support. Khronos is actively seeking feedback about the current interface with the goal of refining it and promoting it to a KHR-level extension.

NVIDIA drivers 610 and later provide VK_EXT_descriptor_heap with support extending to both tooling and code samples. NVIDIA Nsight Graphics 2026.2 introduces descriptor heap support through the same familiar frame capture and inspection workflow, to quickly narrow down descriptor-related issues. The open source descriptor_heap sample application is a helpful starting point to learn how the extension can be used in practice.

To try it, download the latest version of Nsight Graphics and look under Help > Samples for the descriptor heap sample. Note that this menu is only available only on Windows. On Linux, you will need to download and build the sample.

What are the benefits of moving from descriptor sets to heaps?

Descriptors are vendor-specific bytes that describe resources such as buffers and textures. For example, a descriptor might consist of a low-level pointer plus some metadata, but to the shader it is simply an opaque chunk of memory. The resource binding process largely consists of managing descriptors and methods of accessing them in both CPU and shader code.

Vulkan originally only provided descriptor sets, which are arrays of descriptors that can be composed and reused by different shaders. These require cumbersome descriptor set layouts, additional grouping, and allocation through pools. The VK_EXT_descriptor_buffer extension introduced application-managed memory for descriptors, but retained the set-based binding model, layouts, and other required layers of infrastructure. 

In contrast, VK_EXT_descriptor_heap greatly simplifies the concepts to just user-written descriptors in a user-allocated “heap” of memory (not to be confused with binary heap data structures). Only one heap of resource descriptors can be bound at a time, and the Vulkan documentation recommends that the same heap be used throughout the lifetime of the application because binding a new heap can have significant cost and affect performance. A separate heap is used specifically for samplers, following the same guidelines. Accessing descriptors in the shader can be accomplished using a variety of methods, described in the following sections.

In return for this flexibility, the application accepts the responsibility of memory allocation and layout. The following gives a brief introduction to the API, including a comparison against descriptor sets. For more complete details, see the Descriptor Heap Guide.

How to use descriptor heaps 

Ready to start coding? To use descriptor heaps and supported tooling, you’ll want these versions of software:

  • NVIDIA Driver 610 or later for everything described in this post. Early access to new driver-level descriptor heap updates may sometimes be available in the Vulkan developer beta driver.
  • Vulkan Headers 1.4.340 or later (included with the Vulkan SDK)
  • Nsight Graphics 2026.2

As with any Vulkan extension, the VK_EXT_descriptor_heap extension must be requested before use. Add VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME and VkPhysicalDeviceDescriptorHeapFeaturesEXT to the VkDeviceCreateInfo extensions and pNext chain.

To use existing shader code without any modifications, descriptors can be mapped to set and binding indices with VkShaderDescriptorSetAndBindingMappingInfoEXT when creating the shader. For details, see mapping the heap to existing shaders. The following two examples are also demonstrated in the descriptor_heap sample:

  • Push Index: With the mapping source set to VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_PUSH_INDEX_EXT, the descriptor location gets offset by a value read from the push constant data. This allows the application to select different ranges of descriptors per-draw, for the same shader.
  • Constant Offset: Simpler yet, VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT just adds a constant offset for the set/binding descriptor location. The shader may always access the same descriptor for that binding, or if the binding is an array or has a bindingCount, the shader can then choose its own index from the offset dynamically.
Descriptor setsDescriptor heaps
vkCreateDescriptorPool vkAllocateDescriptorSetsVkBuffer with VkDeviceMemory bound and VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT
VkDescriptorSetLayoutBinding
vkCreateDescriptorSetLayout
VkShaderDescriptorSetAndBindingMappingInfoEXT
vkUpdateDescriptorSets
vkCmdPushDescriptorSet
vkWriteResourceDescriptorsEXT
vkCmdPushConstantsvkCmdPushDataEXT
vkCmdBindDescriptorSetsvkCmdBindSamplerHeapEXTvkCmdBindResourceHeapEXT
Table 1. Descriptor sets (left) with their descriptor heap counterparts (right)

In the following GLSL and Slang shader examples, the whole heap has been mapped to bindings with a zero constant offset. The shaders then effectively index descriptors in the heap globally. The application mapping code specifies not just the binding set and location but also type and stride detail about the descriptors, which must be matched by the types bound in the corresponding shader code.

GLSL:

layout(set = 0, binding = 0)
uniform texture2D heapImages[];

layout(set = 0, binding = 1)
uniform sampler heapSamplers[];

layout(push_constant)
uniform PushConstants {
  uint textureIndex;
} push;

layout(location = 0) in vec2 uv;
layout(location = 0) out vec4 outColor;

void main
{
  outColor = texture(
    sampler2D(
      heapTextures[nonuniformEXT(push.textureIndex)],
      heapSamplers[0]),
    uv);
}

Slang shading language:

[[vk::binding(0, 0)]]  // (binding, set)
Texture2D<float4> heapImages[];

[[vk::binding(1, 0)]]
SamplerState heapSamplers[];

[[vk::push_constant]]
ConstantBuffer<PushConstants> push;

[shader("fragment")]
float4 fragmentMain(float2 uv : TEXCOORD0) : SV_Target
{
  return heapImages[NonUniformResourceIndex(push.textureIndex)].Sample(
    heapSamplers[0], uv);
}

This organization may look familiar, especially for those who are used to D3D12 descriptor heaps:

  • Shaders can index descriptors dynamically
  • Indices are managed by the application
  • Heaps are globally bound state

However, Vulkan differs from D3D12 in several ways, including that the application chooses the exact memory location for the heap, and that descriptors of different types can be different sizes.

Direct descriptor heap access

Shaders can index descriptor arrays directly from bound resource and sampler descriptor heaps instead of mapping descriptors to set and binding indices. This approach implies pointer aliasing, requires careful indexing for valid access and the VK_KHR_shader_untyped_pointers extension must be enabled. To learn more, see the untyped shader model section of the Vulkan guide. 

The descriptor_heap application includes an example using untyped pointers and it also works with Nsight Graphics. This capability is now available to try, but the feature is new and still maturing across shader languages and toolchains. Stay tuned for updates.

Inspection and debugging

In Nsight Graphics 2026.2, descriptor heaps show up in the same shader resource views developers already use to see descriptor sets. If you’re using VkShaderDescriptorSetAndBindingMappingInfoEXT, only the mapped descriptors are shown. 

For example, see the six textures for one cube in Figure 2. To view the mapping values, click on the pipeline or shader object linked in the API Inspector, and look in the Object Browser under
createInfo > pNext > pMappings (Figure 3).

Capture and replay of descriptor heaps in debugging tools requires implementations to support the device feature VkPhysicalDeviceDescriptorHeapFeaturesEXT::descriptorHeapCaptureReplay. NVIDIA drivers have added support for this feature starting with driver version 610.

If this is your first time working with Nsight Graphics, the process is to first create a capture and then inspect it with the graphics debugger and live replay:

  1. Click Start Activity
  2. Click Launch Graphics Capture in the dialog window
  3. Press F11 or click the Capture button in the application window to create a capture file, which contains all the Vulkan API calls used to render a frame
  4. Terminate the app
  5. Back in Nsight Graphics, you should see the capture file document. In the document tab, click Start Graphics Debugger
  6. In the toolbar at the top of the window, click Start Live Replay
  7. Explore windows under Graphics Debugger. Isolate draw calls by typing “draw” into the Filter text box of the Events listing on the left. Then click FS to inspect the fragment shader API state

Get started with descriptor heaps

Descriptor heaps are ready to use with NVIDIA drivers and developer tools. The best way to understand descriptor heaps is to start building with them.

  • Run and inspect a sample: The easiest way is to run the sample that comes with Nsight Graphics under Help > Samples
  • Build and debug locally: Instructions for building the descriptor_heap sample are in its repository at https://github.com/nvpro-samples/vk_mini_samples/
  • Provide feedback: For Nsight Graphics issues, use Help > Send Feedback. For issues with the vk_mini_samples implementation, open a GitHub issue. Feedback on real-world use and adoption is appreciated and can be discussed on the NVIDIA Developer Forums and posted in the Khronos Vulkan-Docs repository.

Be on the lookout for future updates as usage patterns mature and shading language support continues to evolve.

Discuss (0)

Tags