#pragma once #include #include #include #include #include namespace lt::renderer::vk { class Device: public IDevice { public: Device(IGpu *gpu, ISurface *surface); ~Device() override; Device(Device &&) = default; Device(const Device &) = delete; auto operator=(Device &&) -> Device & = default; auto operator=(const Device &) const -> Device & = delete; [[nodiscard]] auto vk() const -> VkDevice { return m_device; } [[nodiscard]] auto get_family_indices() const -> std::array { return { m_graphics_queue_family_index, m_present_queue_family_index }; } [[nodiscard]] auto get_graphics_queue() const -> VkQueue { return m_graphics_queue; } [[nodiscard]] auto get_present_queue() const -> VkQueue { return m_present_queue; } /** utilities */ template void name(const T &object, std::format_string fmt, Args &&...args) { const auto name = std::format(fmt, std::forward(args)...); auto info = VkDebugUtilsObjectNameInfoEXT { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .objectType = get_object_type(object), .objectHandle = (uint64_t)(object), .pObjectName = name.c_str(), }; vk_set_debug_object_name(m_device, &info); } template void name(const T &object, const char *name) { auto info = VkDebugUtilsObjectNameInfoEXT { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .objectType = get_object_type(object), .objectHandle = (uint64_t)(object), .pObjectName = name, }; vk_set_debug_object_name(m_device, &info); } /** work functions */ void submit(VkSubmitInfo info, VkFence fence) const; void present(VkPresentInfoKHR info) const; void wait_idle() const; void wait_for_fence(VkFence fence) const; void wait_for_fences(std::span fences) const; void reset_fence(VkFence fence) const; void reset_fences(std::span fences) const; /** getter functions */ [[nodiscard]] auto acquire_image( VkSwapchainKHR swapchain, VkSemaphore semaphore, uint64_t timeout = 100'000'000 ) -> std::optional; [[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector; /** create functions */ [[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR; [[nodiscard]] auto create_framebuffer(VkFramebufferCreateInfo info) const -> VkFramebuffer; [[nodiscard]] auto create_image_view(VkImageViewCreateInfo info) const -> VkImageView; [[nodiscard]] auto create_graphics_pipeline(VkGraphicsPipelineCreateInfo info) const -> VkPipeline; [[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass; [[nodiscard]] auto create_pipeline_layout(VkPipelineLayoutCreateInfo info) const -> VkPipelineLayout; [[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule; [[nodiscard]] auto create_command_pool(VkCommandPoolCreateInfo info) const -> VkCommandPool; [[nodiscard]] auto create_semaphores(uint32_t count) const -> std::vector; [[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const -> std::vector; /** allocation functions */ [[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const -> std::vector; /** destroy functions */ void destroy_swapchain(VkSwapchainKHR swapchain) const; void destroy_framebuffer(VkFramebuffer framebuffer) const; void destroy_framebuffers(std::span framebuffers) const; void destroy_image_view(VkImageView image_view) const; void destroy_image_views(std::span image_views) const; void destroy_pipeline(VkPipeline pipeline) const; void destroy_pass(VkRenderPass pass) const; void destroy_pipeline_layout(VkPipelineLayout pipeline_layout) const; void destroy_shader_module(VkShaderModule shader_module) const; void destroy_command_pool(VkCommandPool command_pool) const; void destroy_semaphore(VkSemaphore semaphore) const; void destroy_semaphores(std::span semaphores) const; void destroy_fence(VkFence fence) const; void destroy_fences(std::span fences) const; private: template static auto get_object_type(const T &object) -> VkObjectType { std::ignore = object; if constexpr (std::is_same_v) { return VK_OBJECT_TYPE_QUEUE; } if constexpr (std::is_same_v) { return VK_OBJECT_TYPE_FENCE; } if constexpr (std::is_same_v) { return VK_OBJECT_TYPE_SEMAPHORE; } if constexpr (std::is_same_v) { return VK_OBJECT_TYPE_SWAPCHAIN_KHR; } if constexpr (std::is_same_v) { return VK_OBJECT_TYPE_IMAGE; } if constexpr (std::is_same_v) { return VK_OBJECT_TYPE_IMAGE_VIEW; } static_assert("invalid type"); } void initialize_physical_device(); void initialize_logical_device(); void initialize_queue_indices(); [[nodiscard]] auto find_suitable_queue_family() const -> uint32_t; memory::NullOnMove m_gpu {}; class Surface *m_surface {}; VkAllocationCallbacks *m_allocator = nullptr; VkDevice m_device = VK_NULL_HANDLE; VkQueue m_graphics_queue = VK_NULL_HANDLE; VkQueue m_present_queue = VK_NULL_HANDLE; uint32_t m_graphics_queue_family_index = VK_QUEUE_FAMILY_IGNORED; uint32_t m_present_queue_family_index = VK_QUEUE_FAMILY_IGNORED; }; } // namespace lt::renderer::vk