#pragma once #include "freelist.hpp" #include "vk-bindless.hpp" #include "vk-command-buffer.hpp" using VmaAllocator = struct VmaAllocator_T*; struct command_buffer; class window; class vkdevice { struct queue { VkQueue vk_queue = VK_NULL_HANDLE; uint32_t index = UINT32_MAX; VkQueueFlags usages; VkCommandPool command_pool = VK_NULL_HANDLE; }; public: void init(); void deinit(); static inline vkdevice& get() { return render_device; } handle create_texture(const texture_desc& desc); handle create_sampler(const sampler_desc& desc); handle create_buffer(const buffer_desc& desc); handle create_graphics_pipeline(const graphics_pipeline_desc& desc); handle create_compute_pipeline(const compute_pipeline_desc& desc); handle create_surface(const surface_desc& desc); handle create_semaphore(const semaphore_desc& desc, const char* name); void destroy_texture(handle handle); void destroy_sampler(handle handle); void destroy_buffer(handle handle); void destroy_pipeline(handle handle); void destroy_semaphore(handle handle); void destroy_surface(handle handle); template void allocate_command_buffers(buffer_type* buffers, size_t count, QueueType queue_type, const char* name) { allocate_command_buffers(static_cast(buffers), count, queue_type, name); } [[nodiscard]] inline device_texture& get_texture(handle handle) { return textures[handle]; } [[nodiscard]] inline device_sampler& get_sampler(handle handle) { return samplers[handle]; } [[nodiscard]] inline device_buffer& get_buffer(handle handle) { return buffers[handle]; } [[nodiscard]] inline const device_pipeline& get_pipeline(handle handle) const { return pipelines[handle]; } [[nodiscard]] inline device_surface& get_surface(handle handle) { return surfaces[handle]; } [[nodiscard]] inline device_semaphore& get_semaphore(handle handle) { return semaphores[handle]; } [[nodiscard]] inline const bindless_model& get_bindingmodel() const { return bindless; } const freelist& get_textures() const { return textures; } inline VkDevice get_device() const { return device; } inline VmaAllocator get_allocator() { return gpu_allocator; } inline const VkPhysicalDeviceLimits& get_device_limits() const { return physical_device_props.properties.limits; } // uint64_t submit(std::span buffers, handle wait_handle, handle signal_handle, handle fence_handle); uint32_t acquire_image_index(handle surface_handle); uint64_t submit_before_present(handle surface_handle, command_buffer* buffers, uint32_t count); uint64_t submit(command_buffer* buffers, uint32_t count); void present(handle surface_handle); void wait(); private: vkdevice() = default; ~vkdevice() = default; void allocate_command_buffers(command_buffer* buffers, size_t count, QueueType type, const char* name); void create_swapchain(const surface_desc& desc, device_surface& surface); // TODO: Wrap in a struct called adapter ? void create_instance(); void create_device(); void create_memory_allocator(); void create_command_pools(); void pick_physical_device(); bool device_support_features(VkPhysicalDevice physical_dev); void create_debug_layer_callback(); queue queues[static_cast(QueueType::MAX)]; VkInstance instance; VkPhysicalDevice physical_device; VkPhysicalDeviceProperties2 physical_device_props; VkDevice device; VmaAllocator gpu_allocator; bindless_model bindless; static constexpr size_t max_allocable_command_buffers = 16; static constexpr size_t max_submitable_command_buffers = 16; freelist textures; freelist samplers; freelist buffers; freelist pipelines; freelist surfaces; freelist semaphores; device_semaphore timeline_semaphore; static vkdevice render_device; #ifdef _DEBUG VkDebugUtilsMessengerEXT debug_messenger; #endif // _DEBUG };