Refacto: Move basic setup to VulkanContext class.
This commit is contained in:
@@ -83,5 +83,6 @@ void VkExpe::run() {
|
||||
}
|
||||
|
||||
m_vulkan.draw_frame();
|
||||
// m_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
1019
src/VulkanContext.cpp
Normal file
1019
src/VulkanContext.cpp
Normal file
File diff suppressed because it is too large
Load Diff
215
src/VulkanContext.h
Normal file
215
src/VulkanContext.h
Normal file
@@ -0,0 +1,215 @@
|
||||
#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>
|
||||
|
||||
|
||||
class VulkanContext;
|
||||
|
||||
class VulkanContextSettings {
|
||||
public:
|
||||
struct QueueInfo {
|
||||
uint32_t index;
|
||||
VkQueueFlagBits flags;
|
||||
bool use_swapchain_images;
|
||||
};
|
||||
|
||||
public:
|
||||
VulkanContextSettings();
|
||||
~VulkanContextSettings();
|
||||
|
||||
bool debug() const;
|
||||
VulkanContextSettings& with_debug(bool enabled=true);
|
||||
|
||||
const std::optional<Uuid>& physical_device() const;
|
||||
VulkanContextSettings& with_physical_device(Uuid uuid);
|
||||
|
||||
const std::vector<QueueInfo>& queues() const;
|
||||
VulkanContextSettings& with_queue(uint32_t index, VkQueueFlagBits flags, bool use_swapchain_images=false);
|
||||
|
||||
SDL_Window* window() const;
|
||||
VulkanContextSettings& 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 VulkanContext {
|
||||
public:
|
||||
static constexpr uint32_t CURRENT_IMAGE_INDEX = UINT32_MAX;
|
||||
static constexpr uint32_t MAX_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
using SwapchainCreationCallback = std::function<void(uint32_t)>;
|
||||
using SwapchainDestructionCallback = std::function<void()>;
|
||||
using ContextDestructionCallback = std::function<void()>;
|
||||
|
||||
public:
|
||||
VulkanContext();
|
||||
VulkanContext(const VulkanContext&) = delete;
|
||||
~VulkanContext();
|
||||
|
||||
VulkanContext& operator=(const VulkanContext&) = delete;
|
||||
|
||||
VkInstance instance();
|
||||
VkPhysicalDevice physical_device();
|
||||
VkDevice device();
|
||||
uint32_t queue_family(size_t queue_index) const;
|
||||
VkQueue queue(size_t queue_index);
|
||||
|
||||
VkSurfaceKHR surface();
|
||||
VkSwapchainKHR swapchain();
|
||||
|
||||
VkSurfaceFormatKHR surface_format() const;
|
||||
VkPresentModeKHR present_mode() const;
|
||||
VkExtent2D swapchain_extent() const;
|
||||
size_t swapchain_image_count() const;
|
||||
uint32_t current_image_index() const;
|
||||
VkImage swapchain_image();
|
||||
VkImage swapchain_image(size_t image_index);
|
||||
VkImageView swapchain_image_view();
|
||||
VkImageView swapchain_image_view(size_t image_index);
|
||||
// VkFramebuffer framebuffer();
|
||||
VkSemaphore ready_to_render();
|
||||
VkFence render_done();
|
||||
|
||||
|
||||
void initialize(const VulkanContextSettings& settings);
|
||||
void shutdown();
|
||||
|
||||
void begin_frame();
|
||||
void swap_buffers(uint32_t semaphore_count, VkSemaphore* wait_semaphores);
|
||||
|
||||
void invalidate_swapchain();
|
||||
|
||||
void register_swapchain_creation_callback(SwapchainCreationCallback callback);
|
||||
void register_swapchain_destruction_callback(SwapchainDestructionCallback callback);
|
||||
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);
|
||||
|
||||
|
||||
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_render_pass(VkRenderPass& render_pass);
|
||||
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);
|
||||
|
||||
private:
|
||||
struct ImageResources {
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkFence render_done = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
struct FrameResources {
|
||||
VkSemaphore ready_to_render = VK_NULL_HANDLE;
|
||||
VkFence render_done = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
private:
|
||||
void create_instance(const VulkanContextSettings& settings);
|
||||
void create_surface(const VulkanContextSettings& settings);
|
||||
void choose_physical_device(const VulkanContextSettings& settings);
|
||||
bool select_physical_device(
|
||||
VkPhysicalDevice physical_device,
|
||||
const VulkanContextSettings& settings
|
||||
);
|
||||
void create_device(const VulkanContextSettings& settings);
|
||||
void create_swapchain(const VulkanContextSettings& settings);
|
||||
void create_swapchain();
|
||||
|
||||
void destroy_swapchain();
|
||||
void recreate_swapchain();
|
||||
|
||||
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;
|
||||
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;
|
||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||
|
||||
VkSurfaceFormatKHR m_surface_format;
|
||||
VkPresentModeKHR m_present_mode;
|
||||
VkExtent2D m_swapchain_extent;
|
||||
std::vector<uint32_t> m_swapchain_queue_families;
|
||||
std::vector<ImageResources> m_image_resources;
|
||||
std::vector<FrameResources> m_frame_resources;
|
||||
bool m_invalid_swapchain = false;
|
||||
|
||||
std::vector<SwapchainCreationCallback> m_swapchain_creation_callbacks;
|
||||
std::vector<SwapchainDestructionCallback> m_swapchain_destruction_callbacks;
|
||||
std::vector<ContextDestructionCallback> m_context_destruction_callbacks;
|
||||
|
||||
uint32_t m_current_image_index = CURRENT_IMAGE_INDEX;
|
||||
size_t m_frame_index = 0;
|
||||
size_t m_frame_resources_index = 0;
|
||||
|
||||
friend class VulkanContextSettings;
|
||||
};
|
||||
|
||||
extern PFN_vkCreateDebugUtilsMessengerEXT vkeCreateDebugUtilsMessengerEXT;
|
||||
extern PFN_vkDestroyDebugUtilsMessengerEXT vkeDestroyDebugUtilsMessengerEXT;
|
||||
extern PFN_vkSetDebugUtilsObjectNameEXT vkeSetDebugUtilsObjectNameEXT;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "VulkanContext.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <Eigen/Dense>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if defined(VKEXPE_ENABLE_VALIDATION) || !defined(NDEBUG)
|
||||
#define VKEXPE_VALIDATION true
|
||||
#else
|
||||
#define VKEXPE_VALIDATION false
|
||||
#endif
|
||||
|
||||
extern PFN_vkCreateDebugUtilsMessengerEXT vkeCreateDebugUtilsMessengerEXT;
|
||||
extern PFN_vkDestroyDebugUtilsMessengerEXT vkeDestroyDebugUtilsMessengerEXT;
|
||||
|
||||
|
||||
struct Vertex {
|
||||
Eigen::Vector2f position;
|
||||
Eigen::Vector3f color;
|
||||
@@ -26,6 +18,11 @@ struct Vertex {
|
||||
|
||||
|
||||
class VulkanTutorial {
|
||||
public:
|
||||
enum QueueIndex {
|
||||
GRAPHIC_QUEUE,
|
||||
};
|
||||
|
||||
public:
|
||||
VulkanTutorial();
|
||||
VulkanTutorial(const VulkanTutorial&) = delete;
|
||||
@@ -39,59 +36,27 @@ public:
|
||||
void draw_frame();
|
||||
void invalidate_swapchain();
|
||||
|
||||
static std::vector<VkExtensionProperties> available_extensions();
|
||||
static std::vector<VkLayerProperties> available_layers();
|
||||
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL print_debug_message(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT type,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* data,
|
||||
void* user_data
|
||||
);
|
||||
|
||||
private:
|
||||
void create_instance();
|
||||
void create_surface();
|
||||
void find_physical_device();
|
||||
void create_device();
|
||||
void create_swapchain();
|
||||
void create_swapchain_objects(uint32_t image_count);
|
||||
void destroy_swapchain_objects();
|
||||
|
||||
void create_render_pass();
|
||||
void create_graphic_pipeline();
|
||||
void create_framebuffers();
|
||||
void create_command_pool();
|
||||
void create_vertex_buffer();
|
||||
void create_command_buffers();
|
||||
void create_sync_objects();
|
||||
|
||||
void cleanup_swap_chain();
|
||||
void recreate_swap_chain();
|
||||
|
||||
VkShaderModule create_shader_module(const std::vector<char> bytecode);
|
||||
VkShaderModule create_shader_module_from_file(const char* path);
|
||||
|
||||
int32_t find_memory(uint32_t type_filter, VkMemoryPropertyFlags properties);
|
||||
|
||||
std::vector<VkPhysicalDevice> get_physical_devices() const;
|
||||
std::vector<VkQueueFamilyProperties> get_queue_families(VkPhysicalDevice physical_device) const;
|
||||
std::vector<VkExtensionProperties> get_device_extensions(VkPhysicalDevice physical_device) const;
|
||||
std::vector<VkSurfaceFormatKHR> get_surface_formats(VkPhysicalDevice physical_device) const;
|
||||
std::vector<VkPresentModeKHR> get_present_modes(VkPhysicalDevice physical_device) const;
|
||||
|
||||
void initialize_extension_functions();
|
||||
|
||||
private:
|
||||
SDL_Window* m_window = nullptr;
|
||||
|
||||
VkInstance m_instance = nullptr;
|
||||
VkDebugUtilsMessengerEXT m_debug_messenger = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR m_surface;
|
||||
VkPhysicalDevice m_physical_device = nullptr;
|
||||
VkDevice m_device = nullptr;
|
||||
VulkanContext m_context;
|
||||
VkQueue m_graphic_queue = nullptr;
|
||||
VkQueue m_presentation_queue = nullptr;
|
||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||
std::vector<VkImage> m_swapchain_images;
|
||||
std::vector<VkImageView> m_swapchain_image_views;
|
||||
|
||||
VkRenderPass m_render_pass = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE;
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
@@ -100,22 +65,5 @@ private:
|
||||
VkBuffer m_vertex_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory m_vertex_buffer_memory = VK_NULL_HANDLE;
|
||||
std::vector<VkCommandBuffer> m_command_buffers;
|
||||
std::vector<VkSemaphore> m_image_available_semaphores;
|
||||
std::vector<VkSemaphore> m_render_finished_semaphores;
|
||||
std::vector<VkFence> m_in_flight_fence;
|
||||
std::vector<VkFence> m_images_in_flight;
|
||||
|
||||
uint32_t m_graphic_queue_family = -1;
|
||||
uint32_t m_presentation_queue_family = -1;
|
||||
VkSurfaceFormatKHR m_swapchain_format;
|
||||
VkPresentModeKHR m_present_mode;
|
||||
VkExtent2D m_swapchain_extent;
|
||||
|
||||
size_t m_frame_index = 0;
|
||||
bool m_invalid_swapchain = true;
|
||||
|
||||
VkDebugUtilsMessengerCreateInfoEXT m_debug_info;
|
||||
bool m_enableValidation = VKEXPE_VALIDATION;
|
||||
|
||||
static constexpr size_t MAX_FRAMES_IN_FLIGHT = 2;
|
||||
std::vector<VkSemaphore> m_render_done;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
Uuid make_uuid(uint8_t const* bytes) {
|
||||
Uuid uuid;
|
||||
std::memcpy(uuid.data(), bytes, UUID_SIZE);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
std::vector<char> read_binary_file(const char* path) {
|
||||
std::ifstream istream(path, std::ios_base::ate | std::ios_base::binary);
|
||||
if(!istream.is_open())
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <array>
|
||||
|
||||
|
||||
constexpr size_t UUID_SIZE = 16;
|
||||
using Uuid = std::array<uint8_t, UUID_SIZE>;
|
||||
Uuid make_uuid(uint8_t const* bytes);
|
||||
|
||||
|
||||
template<typename T>
|
||||
|
||||
Reference in New Issue
Block a user