From 722854b85ea3354a17da1ce4b0052301987aa284 Mon Sep 17 00:00:00 2001 From: Lina Versace Date: Thu, 9 Jan 2025 12:48:36 -0800 Subject: [PATCH 1/3] Fix property matching in find_image_memory() If multiple VkMemoryPropertyFlags were required, the function checked if *any* flag was supported instead of checking for *all* flags. --- main.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index 7bb4a7e..8488cdb 100644 --- a/main.c +++ b/main.c @@ -120,17 +120,22 @@ xstrdup(const char *s) return dup; } -static int find_image_memory(struct vkcube *vc, unsigned allowed) +static int32_t +find_image_memory(struct vkcube *vc, uint32_t allowed_memory_types) { - VkMemoryPropertyFlags flags = + VkMemoryPropertyFlags required_props = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | (vc->protected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0); - for (unsigned i = 0; (1u << i) <= allowed && i <= vc->memory_properties.memoryTypeCount; ++i) { - if ((allowed & (1u << i)) && (vc->memory_properties.memoryTypes[i].propertyFlags & flags)) - return i; - } - return -1; + for (uint32_t i = 0; i < vc->memory_properties.memoryTypeCount; ++i) { + VkMemoryPropertyFlags props = vc->memory_properties.memoryTypes[i].propertyFlags; + + if (((1u << i) & allowed_memory_types) && + (required_props & props) == required_props) + return i; + } + + return -1; } static void From 5a67f9cd94cae4a38ef990f024e50dc5a9cf6f1e Mon Sep 17 00:00:00 2001 From: Lina Versace Date: Thu, 9 Jan 2025 12:53:34 -0800 Subject: [PATCH 2/3] Fix headless mode vkMapMemory failed because the memory lacked VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT. Require that bit. Drop the requirement for VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT because (a) it is unneeded and (b) it may intefere with finding a type that supports VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT. Fail if protected mode is requested on the cmdline because host-visible protected memory is useless and contradictory. With these fixes, find_image_memory() is now independent of images. So rename it choose_memory_type_index(). --- main.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index 8488cdb..10461e0 100644 --- a/main.c +++ b/main.c @@ -121,12 +121,9 @@ xstrdup(const char *s) } static int32_t -find_image_memory(struct vkcube *vc, uint32_t allowed_memory_types) +choose_memory_type_index(struct vkcube *vc, uint32_t allowed_memory_types, + VkMemoryPropertyFlags required_props) { - VkMemoryPropertyFlags required_props = - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - (vc->protected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0); - for (uint32_t i = 0; i < vc->memory_properties.memoryTypeCount; ++i) { VkMemoryPropertyFlags props = vc->memory_properties.memoryTypes[i].propertyFlags; @@ -438,11 +435,24 @@ init_headless(struct vkcube *vc) VkMemoryRequirements requirements; vkGetImageMemoryRequirements(vc->device, b->image, &requirements); + if (vc->protected) { + /* Host-visible protected memory is useless and contradictory. + * And the Vulkan 1.4.304 spec says it does not exist. + */ + fail("headless mode and protected mode are incompatible\n"); + } + + int32_t mem_type = choose_memory_type_index(vc, requirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + if (mem_type == -1) { + fail("failed to choose VkMemoryType\n"); + } + vkAllocateMemory(vc->device, &(VkMemoryAllocateInfo) { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .allocationSize = requirements.size, - .memoryTypeIndex = find_image_memory(vc, requirements.memoryTypeBits), + .memoryTypeIndex = mem_type, }, NULL, &b->mem); From e8c42e80eb4e1f73fb2861454780cec8702485d6 Mon Sep 17 00:00:00 2001 From: Lina Versace Date: Thu, 9 Jan 2025 13:08:15 -0800 Subject: [PATCH 3/3] Delete duplicate func find_host_coherent_memory() It's merely a special case of choose_memory_type_index(). --- common.h | 3 +++ cube.c | 17 ++++------------- main.c | 2 +- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/common.h b/common.h index d3edbeb..d8bcc7c 100644 --- a/common.h +++ b/common.h @@ -127,3 +127,6 @@ streq(const char *a, const char *b) { return strcmp(a, b) == 0; } + +int32_t choose_memory_type_index(struct vkcube *vc, uint32_t allowed_memory_types, + VkMemoryPropertyFlags required_props); diff --git a/cube.c b/cube.c index ccebfde..b5aa7ac 100644 --- a/cube.c +++ b/cube.c @@ -39,17 +39,6 @@ static uint32_t fs_spirv_source[] = { #include "vkcube.frag.spv.h" }; -static int find_host_coherent_memory(struct vkcube *vc, unsigned allowed) -{ - for (unsigned i = 0; (1u << i) <= allowed && i <= vc->memory_properties.memoryTypeCount; ++i) { - if ((allowed & (1u << i)) && - (vc->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && - (vc->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) - return i; - } - return -1; -} - static void init_cube(struct vkcube *vc) { @@ -342,8 +331,10 @@ init_cube(struct vkcube *vc) VkMemoryRequirements reqs; vkGetBufferMemoryRequirements(vc->device, vc->buffer, &reqs); - int memory_type = find_host_coherent_memory(vc, reqs.memoryTypeBits); - if (memory_type < 0) + int32_t memory_type = choose_memory_type_index(vc, reqs.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + if (memory_type == -1) fail("find_host_coherent_memory failed"); vkAllocateMemory(vc->device, diff --git a/main.c b/main.c index 10461e0..b5332ad 100644 --- a/main.c +++ b/main.c @@ -120,7 +120,7 @@ xstrdup(const char *s) return dup; } -static int32_t +int32_t choose_memory_type_index(struct vkcube *vc, uint32_t allowed_memory_types, VkMemoryPropertyFlags required_props) {