ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

Commit: 08c7d10e22f145d9e88933fb7ed79d72520e28c9
Parent: 69b27ac9b6b786fa6ea2cca3594208951b7d4311
Author: Randy Palamar
Date:   Tue,  6 Jan 2026 10:31:00 -0700

vulkan: check for and report missing extension requirements

Diffstat:
Mvulkan.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mvulkan.h | 1+
2 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/vulkan.c b/vulkan.c @@ -53,7 +53,6 @@ typedef alignas(64) struct { static_assert(sizeof(VulkanQueue) == 64 && alignof(VulkanQueue) == 64, "VulkanQueue must be placed on its own cacheline"); - typedef struct { VkInstance handle; VkDevice device; @@ -82,17 +81,34 @@ typedef struct { read_only global const char *vk_required_instance_extensions[] = { }; +#if OS_WINDOWS +#define VK_OS_REQUIRED_DEVICE_EXTENSIONS_LIST \ + X("VK_KHR_external_memory_win32") \ + X("VK_KHR_external_semaphore_win32") \ + +#else +#define VK_OS_REQUIRED_DEVICE_EXTENSIONS_LIST \ + X("VK_KHR_external_memory_fd") \ + X("VK_KHR_external_semaphore_fd") \ + +#endif + +#define VK_REQUIRED_DEVICE_EXTENSIONS_LIST \ + X("VK_KHR_external_memory") \ + X("VK_KHR_external_semaphore") \ + VK_OS_REQUIRED_DEVICE_EXTENSIONS_LIST + +#define X(str) str, read_only global const char *vk_required_device_extensions[] = { - "VK_KHR_external_memory", - "VK_KHR_external_semaphore", - #if OS_WINDOWS - "VK_KHR_external_memory_win32", - "VK_KHR_external_semaphore_win32", - #else - "VK_KHR_external_memory_fd", - "VK_KHR_external_semaphore_fd", - #endif +VK_REQUIRED_DEVICE_EXTENSIONS_LIST }; +#undef X + +#define X(str) sizeof(str) - 1, +read_only global u32 vk_required_device_extension_name_lengths[] = { +VK_REQUIRED_DEVICE_EXTENSIONS_LIST +}; +#undef X global VulkanContext vulkan_context[1]; @@ -199,6 +215,49 @@ vk_load_physical_device(Arena arena, Stream *err) stream_append_s8s(err, vulkan_info("selecting device: "), c_str_to_s8(dp->properties.deviceName), s8("\n")); + { + Arena scratch = arena; + u32 extension_count = 0; + vkEnumerateDeviceExtensionProperties(vk->physical_device, 0, &extension_count, 0); + VkExtensionProperties *extensions = push_array(&scratch, VkExtensionProperties, extension_count); + vkEnumerateDeviceExtensionProperties(vk->physical_device, 0, &extension_count, extensions); + + s8 *ext_str8s = push_array(&scratch, s8, extension_count); + for (u32 index = 0; index < extension_count; index++) + ext_str8s[index] = c_str_to_s8(extensions[index].extensionName); + + b8 *supported = push_array(&scratch, b8, countof(vk_required_device_extensions)); + for (u32 index = 0; index < extension_count; index++) { + for EachElement(vk_required_device_extensions, it) { + s8 test = { + .data = (u8 *)vk_required_device_extensions[it], + .len = vk_required_device_extension_name_lengths[it], + }; + supported[it] |= s8_equal(test, ext_str8s[index]); + } + } + + u32 supported_count = 0; + for EachElement(vk_required_device_extensions, it) + supported_count += supported[it]; + + u32 missing_count = countof(vk_required_device_extensions) - supported_count; + if (missing_count) { + stream_append_s8s(err, vulkan_info("fatal error: missing required device extension"), + missing_count > 1 ? s8("s") : s8(""), s8(":\n")); + for EachElement(vk_required_device_extensions, it) { + if (!supported[it]) { + s8 name = { + .data = (u8 *)vk_required_device_extensions[it], + .len = vk_required_device_extension_name_lengths[it], + }; + stream_append_s8s(err, vulkan_info(" "), name, s8("\n")); + } + } + fatal(stream_to_s8(err)); + } + } + VkPhysicalDeviceMemoryProperties2 *mp = push_struct(&arena, typeof(*mp)); mp->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; vkGetPhysicalDeviceMemoryProperties2(vk->physical_device, mp); @@ -452,8 +511,8 @@ vk_load(OSLibrary vulkan_library_handle, Arena *memory, Stream *err) fatal(stream_to_s8(err)); } - vulkan_context->entity_arena = sub_arena_end(memory, KB(32), KB(4)); - vulkan_context->arena = sub_arena_end(memory, KB(32), KB(4)); + vulkan_context->entity_arena = sub_arena_end(memory, KB(64), KB(4)); + vulkan_context->arena = sub_arena_end(memory, KB(96), KB(4)); vk_load_instance(); vk_load_physical_device(vulkan_context->arena, err); diff --git a/vulkan.h b/vulkan.h @@ -2116,6 +2116,7 @@ typedef struct { /* X(name, ret, params) */ #define VkInstanceProcedureList \ X(vkCreateDevice, VkResult, (VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)) \ + X(vkEnumerateDeviceExtensionProperties, VkResult, (VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)) \ X(vkEnumeratePhysicalDevices, VkResult, (VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices)) \ X(vkGetDeviceProcAddr, void *, (VkDevice device, const char *pName)) \ X(vkGetPhysicalDeviceMemoryProperties2, void, (VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)) \