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 7bb4a7e..b5332ad 100644 --- a/main.c +++ b/main.c @@ -120,17 +120,19 @@ xstrdup(const char *s) return dup; } -static int find_image_memory(struct vkcube *vc, unsigned allowed) +int32_t +choose_memory_type_index(struct vkcube *vc, uint32_t allowed_memory_types, + VkMemoryPropertyFlags required_props) { - VkMemoryPropertyFlags flags = - 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 @@ -433,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);