Vulkan: Require and document descriptor-heap device extensions.

This commit is contained in:
Jan Aleksander Górski 2026-08-06 02:57:36 +09:00 committed by ocornut
parent c33ea3ccb6
commit 5c666e59d0
2 changed files with 35 additions and 12 deletions

View File

@ -130,6 +130,12 @@ struct ImGui_ImplVulkan_DescriptorHeapInfo
// - ImTextureID is the GPU descriptor device address returned by RegisterImage.
// Requires a 64-bit ImTextureID.
// - ImGui_ImplVulkan_AddTexture()/RemoveTexture() are pool-path only.
// - Device extensions / features the application must enable:
// - VK_EXT_descriptor_heap (feature: descriptorHeap).
// - VK_KHR_maintenance5 (formal dependency of descriptor_heap; used for VkPipelineCreateFlags2 / DESCRIPTOR_HEAP pipeline flag).
// - VK_KHR_buffer_device_address, or Vulkan 1.2+ where BDA is core (formal dependency; enable the bufferDeviceAddress feature either way).
// - VK_KHR_shader_untyped_pointers (feature: shaderUntypedPointers): required by the default heap shaders (layout(descriptor_heap)).
// Not a formal dependency of VK_EXT_descriptor_heap; mapping-based custom shaders could omit it.
struct ImGui_ImplVulkan_InitInfo
{
uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE)
@ -169,6 +175,7 @@ struct ImGui_ImplVulkan_InitInfo
#ifdef IMGUI_IMPL_VULKAN_HAS_DESCRIPTOR_HEAP
// (Optional) If set, use VK_EXT_descriptor_heap (app-owned Register*/UnRegister* callbacks; see comment above).
// ImTextureID = RegisterImage(...) device address. ImGui_ImplVulkan_AddTexture() is unavailable in this mode.
// App must enable the device extensions/features listed under "About descriptor heap".
const ImGui_ImplVulkan_DescriptorHeapInfo *DescriptorHeapInfo;
#endif
};

View File

@ -244,6 +244,18 @@ static bool PhysicalDeviceHasExtension(VkPhysicalDevice physical_device, const c
return IsExtensionAvailable(properties, extension);
}
// Extensions required by this example's VK_EXT_descriptor_heap path (Vulkan 1.1 instance → BDA is an extension).
// Formal deps of VK_EXT_descriptor_heap: maintenance5 + (buffer_device_address | Vulkan 1.2).
// shader_untyped_pointers is required by ImGui's default layout(descriptor_heap) shaders, not by the Vulkan extension itself.
// See "About descriptor heap" in imgui_impl_vulkan.h.
static bool PhysicalDeviceSupportsImGuiDescriptorHeap(VkPhysicalDevice physical_device)
{
return PhysicalDeviceHasExtension(physical_device, VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME)
&& PhysicalDeviceHasExtension(physical_device, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)
&& PhysicalDeviceHasExtension(physical_device, VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME)
&& PhysicalDeviceHasExtension(physical_device, VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
}
static void SetupVulkan(ImVector<const char*> instance_extensions, bool require_descriptor_heap)
{
VkResult err;
@ -321,17 +333,21 @@ static void SetupVulkan(ImVector<const char*> instance_extensions, bool require_
VkPhysicalDevice device_with_heap = VK_NULL_HANDLE;
for (uint32_t i = 0; i < device_count; i++)
{
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(physical_devices[i], &props);
const bool has_heap = PhysicalDeviceHasExtension(physical_devices[i], VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
if (has_heap && device_with_heap == VK_NULL_HANDLE)
if (PhysicalDeviceSupportsImGuiDescriptorHeap(physical_devices[i]))
{
device_with_heap = physical_devices[i];
break;
}
}
if (device_with_heap == VK_NULL_HANDLE)
{
fprintf(stderr, "Error: --require-descriptor-heap requested but no device with VK_EXT_descriptor_heap was found.\n");
fprintf(stderr, "Error: --require-descriptor-heap requested but no device with VK_EXT_descriptor_heap and its required dependencies was found.\n");
fprintf(stderr, " Required: %s, %s, %s, %s\n",
VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME,
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME,
VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
exit(1);
}
g_PhysicalDevice = device_with_heap;
@ -364,19 +380,19 @@ static void SetupVulkan(ImVector<const char*> instance_extensions, bool require_
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
#endif
if (IsExtensionAvailable(properties, VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME))
if (PhysicalDeviceSupportsImGuiDescriptorHeap(g_PhysicalDevice))
{
device_extensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_MAINTENANCE_2_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
device_extensions.push_back(VK_KHR_SHADER_UNTYPED_POINTERS_EXTENSION_NAME);
device_extensions.push_back(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME);
g_UsingDescriptorHeap = true;
}
else if (require_descriptor_heap)
{
fprintf(stderr, "Error: --require-descriptor-heap but selected device is missing a required dependency.\n");
exit(1);
}
const float queue_priority[] = { 1.0f };
VkDeviceQueueCreateInfo queue_info[1] = {};