// Copyright 2022 Simon Boyé #pragma once #include #include #include #include #include #include #include #include #include #include namespace vk { class Context; class ContextSettings { public: struct QueueInfo { uint32_t index; VkQueueFlagBits flags; bool use_swapchain_images; }; public: ContextSettings(); ~ContextSettings(); bool debug() const; ContextSettings& with_debug(bool enabled=true); const std::optional& physical_device() const; ContextSettings& with_physical_device(Uuid uuid); const std::vector& queues() const; ContextSettings& with_queue(uint32_t index, VkQueueFlagBits flags, bool use_swapchain_images=false); SDL_Window* window() const; ContextSettings& with_window(SDL_Window* window); private: bool m_debug = false; std::optional m_physical_device; std::vector m_queues; SDL_Window* m_window = nullptr; }; constexpr uint32_t INVALID_QUEUE_FAMILY = UINT32_MAX; class Context { public: using ContextDestructionCallback = std::function; public: Context(); Context(const Context&) = delete; ~Context(); Context& operator=(const Context&) = delete; explicit inline operator bool() const { return !is_null(); } inline bool is_null() const { return m_instance == nullptr; } VkInstance instance(); VkPhysicalDevice physical_device(); VkDevice device(); size_t queue_family_count() const; uint32_t queue_family(size_t queue_index) const; uint32_t presentation_queue_family() const; VkQueue queue(size_t queue_index); VkQueue presentation_queue(); inline VkPhysicalDeviceMemoryProperties memory_properties() const noexcept { return m_memory_properties; } SDL_Window* window(); VkSurfaceKHR surface(); VkSurfaceFormatKHR surface_format() const; VkPresentModeKHR present_mode() const; inline Allocator& allocator() noexcept { return *m_allocator; } void initialize(const ContextSettings& settings); void shutdown(); void register_context_destruction_callback(ContextDestructionCallback callback); static std::vector available_extensions(); static std::vector available_layers(); std::vector sdl_vulkan_extensions() const; std::vector physical_devices() const; std::vector queue_families(VkPhysicalDevice physical_device) const; std::vector device_extensions(VkPhysicalDevice physical_device) const; std::vector surface_formats(VkPhysicalDevice physical_device) const; std::vector present_modes(VkPhysicalDevice physical_device) const; void set_object_name(VkObjectType type, uint64_t object, const char* name); void set_object_name(VkObjectType type, uint64_t object, const std::string& name); VkShaderModule create_shader_module(const std::vector bytecode); VkShaderModule create_shader_module_from_file(const char* path); void copy_buffer(VkBuffer dst, VkBuffer src, uint32_t dst_queue_family, VkDeviceSize size); void destroy_instance(VkInstance& instance); void destroy_debug_messenger(VkDebugUtilsMessengerEXT& debug_messenger); void destroy_surface(VkSurfaceKHR& surface); void destroy_device(VkDevice& device); void destroy_swapchain(VkSwapchainKHR& swapchain); void destroy_image(VkImage& image); void destroy_image_view(VkImageView& image_view); void destroy_framebuffer(VkFramebuffer& framebuffer); void destroy_buffer(VkBuffer& buffer); void destroy_command_pool(VkCommandPool& command_pool); void destroy_descriptor_pool(VkDescriptorPool& descriptor_pool); void destroy_render_pass(VkRenderPass& render_pass); void destroy_descriptor_set_layout(VkDescriptorSetLayout& descriptor_set_layout); void destroy_pipeline_layout(VkPipelineLayout& pipeline_layout); void destroy_pipeline(VkPipeline& pipeline); void destroy_semaphore(VkSemaphore& semaphore); void destroy_fence(VkFence& fence); void free_memory(VkDeviceMemory& memory); PFN_vkCreateDebugUtilsMessengerEXT createDebugUtilsMessenger = nullptr; PFN_vkDestroyDebugUtilsMessengerEXT destroyDebugUtilsMessenger = nullptr; PFN_vkSetDebugUtilsObjectNameEXT setDebugUtilsObjectName = nullptr; private: void create_instance(const ContextSettings& settings); void create_surface(const ContextSettings& settings); void choose_physical_device(const ContextSettings& settings); std::optional select_physical_device( VkPhysicalDevice physical_device, const ContextSettings& settings ); void create_device(const ContextSettings& settings); void create_internal_objects(); void initialize_extension_functions(); static VKAPI_ATTR VkBool32 VKAPI_CALL log_debug_message( VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT* data, void* user_data ); private: SDL_Window* m_window = nullptr; VkInstance m_instance = nullptr; 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; uint32_t m_presentation_queue_family = UINT32_MAX; std::vector m_queues; VkQueue m_presentation_queue = nullptr; VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSurfaceFormatKHR m_surface_format; VkPresentModeKHR m_present_mode; uint32_t m_transfer_queue_index = UINT32_MAX; VkCommandPool m_transfer_command_pool = VK_NULL_HANDLE; Fence m_transfer_fence; std::vector m_context_destruction_callbacks; std::unique_ptr m_allocator; }; }