diff --git a/src/Vulkan/Context.cpp b/src/Vulkan/Context.cpp index 02f2664..c67d3b3 100644 --- a/src/Vulkan/Context.cpp +++ b/src/Vulkan/Context.cpp @@ -270,22 +270,70 @@ VkShaderModule Context::create_shader_module_from_file(const char* path) { return VK_NULL_HANDLE; } -int32_t Context::find_memory(uint32_t type_filter, VkMemoryPropertyFlags properties) { - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties( - m_physical_device, - &memory_properties - ); - - for(uint32_t type_index = 0; type_index < memory_properties.memoryTypeCount; type_index += 1) { +int32_t Context::find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties) { + for(uint32_t type_index = 0; type_index < m_memory_properties.memoryTypeCount; type_index += 1) { if(((1 << type_index) & type_filter) && - (memory_properties.memoryTypes[type_index].propertyFlags & properties) == properties) + (m_memory_properties.memoryTypes[type_index].propertyFlags & properties) == properties) return type_index; } return -1; } +VkDeviceMemory Context::allocate_memory(VkDeviceSize size, uint32_t type_filter, VkMemoryPropertyFlags properties) { + uint32_t memory_type = find_memory_type(type_filter, properties); + + VkMemoryAllocateInfo malloc_info { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = size, + .memoryTypeIndex = memory_type, + }; + + VkDeviceMemory memory = VK_NULL_HANDLE; + if(vkAllocateMemory(m_device, &malloc_info, nullptr, &memory) != VK_SUCCESS) + throw std::runtime_error("failed to allocate device memory"); + + return memory; +} + +std::tuple Context::create_buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_properties) { + VkDeviceMemory memory = VK_NULL_HANDLE; + VkBuffer buffer = VK_NULL_HANDLE; + + VkBufferCreateInfo buffer_info { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = size, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + + if(vkCreateBuffer( + m_device, + &buffer_info, + nullptr, + &buffer + ) != VK_SUCCESS) + throw std::runtime_error("failed to create buffer"); + + VkMemoryRequirements memory_requirements; + vkGetBufferMemoryRequirements( + m_device, + buffer, + &memory_requirements + ); + + memory = allocate_memory( + memory_requirements.size, + memory_requirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + ); + + vkBindBufferMemory(m_device, buffer, memory, 0); + + return { buffer, memory }; +} + void Context::destroy_instance(VkInstance& instance) { if(instance == nullptr) @@ -531,6 +579,7 @@ void Context::choose_physical_device(const ContextSettings& settings) { if(maybe_properties) { m_physical_device = physical_device; m_physical_device_properties = *maybe_properties; + vkGetPhysicalDeviceMemoryProperties(m_physical_device, &m_memory_properties); break; } } diff --git a/src/Vulkan/Context.h b/src/Vulkan/Context.h index 45171c9..5db2695 100644 --- a/src/Vulkan/Context.h +++ b/src/Vulkan/Context.h @@ -100,7 +100,10 @@ public: VkShaderModule create_shader_module(const std::vector bytecode); VkShaderModule create_shader_module_from_file(const char* path); - int32_t find_memory(uint32_t type_filter, VkMemoryPropertyFlags properties); + int32_t find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties); + VkDeviceMemory allocate_memory(VkDeviceSize size, uint32_t type_filter, VkMemoryPropertyFlags properties); + + std::tuple create_buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_properties); void destroy_instance(VkInstance& instance); @@ -157,6 +160,7 @@ private: VkDebugUtilsMessengerEXT m_debug_messenger = VK_NULL_HANDLE; VkPhysicalDevice m_physical_device = nullptr; VkPhysicalDeviceProperties m_physical_device_properties; + VkPhysicalDeviceMemoryProperties m_memory_properties; VkDevice m_device = nullptr; std::vector m_queue_families; diff --git a/src/Vulkan/Swapchain.cpp b/src/Vulkan/Swapchain.cpp index d256b73..aabe197 100644 --- a/src/Vulkan/Swapchain.cpp +++ b/src/Vulkan/Swapchain.cpp @@ -385,6 +385,8 @@ void Swapchain::destroy() { } void Swapchain::recreate() { + vkDeviceWaitIdle(m_context->device()); + destroy(); create(); } diff --git a/src/VulkanTutorial.cpp b/src/VulkanTutorial.cpp index c09dcb2..6230c2e 100644 --- a/src/VulkanTutorial.cpp +++ b/src/VulkanTutorial.cpp @@ -436,68 +436,26 @@ void VulkanTutorial::create_vertex_buffer() { if(m_vertex_buffer != VK_NULL_HANDLE) return; - VkBufferCreateInfo buffer_info { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = sizeof(vertices[0]) * vertices.size(), - .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - - if(vkCreateBuffer( - m_context.device(), - &buffer_info, - nullptr, - &m_vertex_buffer - ) != VK_SUCCESS) - throw std::runtime_error("failed to create vertex buffer"); + VkDeviceSize buffer_size = sizeof(vertices[0]) * vertices.size(); - VkMemoryRequirements memory_requirements; - vkGetBufferMemoryRequirements( - m_context.device(), - m_vertex_buffer, - &memory_requirements - ); - - const auto memory_type = m_context.find_memory( - memory_requirements.memoryTypeBits, + std::tie(m_vertex_buffer, m_vertex_buffer_memory) = m_context.create_buffer( + buffer_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ); - if(memory_type < 0) - throw std::runtime_error("failed to find suitable memory type for vertex buffer"); - - VkMemoryAllocateInfo alloc_info { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = memory_requirements.size, - .memoryTypeIndex = uint32_t(memory_type), - }; - - if(vkAllocateMemory( - m_context.device(), - &alloc_info, - nullptr, - &m_vertex_buffer_memory - ) != VK_SUCCESS) - throw std::runtime_error("failed to allocate vertex buffer memory"); - - vkBindBufferMemory( - m_context.device(), - m_vertex_buffer, - m_vertex_buffer_memory, - 0 - ); void* buffer = nullptr; vkMapMemory( m_context.device(), m_vertex_buffer_memory, 0, - buffer_info.size, + buffer_size, 0, &buffer ); - memcpy(buffer, vertices.data(), size_t(buffer_info.size)); + memcpy(buffer, vertices.data(), size_t(buffer_size)); vkUnmapMemory( m_context.device(),