Experimentation using Vulkan.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

195 lines
6.3 KiB

#pragma once
#include <utils.h>
#include <Logger.h>
#include <SDL2/SDL.h>
#include <vulkan/vulkan.h>
#include <optional>
#include <initializer_list>
#include <vector>
#include <functional>
namespace Vulkan {
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<Uuid>& physical_device() const;
ContextSettings& with_physical_device(Uuid uuid);
const std::vector<QueueInfo>& 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<Uuid> m_physical_device;
std::vector<QueueInfo> m_queues;
SDL_Window* m_window = nullptr;
};
constexpr uint32_t INVALID_QUEUE_FAMILY = UINT32_MAX;
class Context {
public:
using ContextDestructionCallback = std::function<void()>;
public:
Context();
Context(const Context&) = delete;
~Context();
Context& operator=(const Context&) = delete;
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();
SDL_Window* window();
VkSurfaceKHR surface();
VkSurfaceFormatKHR surface_format() const;
VkPresentModeKHR present_mode() const;
void initialize(const ContextSettings& settings);
void shutdown();
void register_context_destruction_callback(ContextDestructionCallback callback);
static std::vector<VkExtensionProperties> available_extensions();
static std::vector<VkLayerProperties> available_layers();
std::vector<const char*> sdl_vulkan_extensions() const;
std::vector<VkPhysicalDevice> physical_devices() const;
std::vector<VkQueueFamilyProperties> queue_families(VkPhysicalDevice physical_device) const;
std::vector<VkExtensionProperties> device_extensions(VkPhysicalDevice physical_device) const;
std::vector<VkSurfaceFormatKHR> surface_formats(VkPhysicalDevice physical_device) const;
std::vector<VkPresentModeKHR> 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<char> bytecode);
VkShaderModule create_shader_module_from_file(const char* path);
int32_t find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties);
VkDeviceMemory allocate_memory(VkDeviceSize size, uint32_t type_filter, VkMemoryPropertyFlags properties);
std::tuple<VkBuffer, VkDeviceMemory> create_buffer(
VkDeviceSize size,
VkBufferUsageFlags usage,
VkMemoryPropertyFlags memory_properties);
std::tuple<VkBuffer, VkDeviceMemory> create_buffer(
VkDeviceSize size, char* buffer,
VkBufferUsageFlags usage,
VkMemoryPropertyFlags memory_properties,
uint32_t dst_queue_family);
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<VkPhysicalDeviceProperties> 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<uint32_t> m_queue_families;
uint32_t m_presentation_queue_family = UINT32_MAX;
std::vector<VkQueue> 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;
VkFence m_transfer_fence = VK_NULL_HANDLE;
std::vector<ContextDestructionCallback> m_context_destruction_callbacks;
};
}