|
|
@ -1,7 +1,7 @@ |
|
|
#include "VulkanContext.h" |
|
|
#include <Vulkan/Context.h> |
|
|
|
|
|
|
|
|
#include "utils.h" |
|
|
#include <utils.h> |
|
|
#include "Logger.h" |
|
|
#include <Logger.h> |
|
|
|
|
|
|
|
|
#include <SDL2/SDL_vulkan.h> |
|
|
#include <SDL2/SDL_vulkan.h> |
|
|
|
|
|
|
|
|
@ -11,137 +11,140 @@ |
|
|
#include <tuple> |
|
|
#include <tuple> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VulkanContextSettings::VulkanContextSettings() { |
|
|
namespace Vulkan { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ContextSettings::ContextSettings() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VulkanContextSettings::~VulkanContextSettings() { |
|
|
ContextSettings::~ContextSettings() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool VulkanContextSettings::debug() const { |
|
|
bool ContextSettings::debug() const { |
|
|
return m_debug; |
|
|
return m_debug; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VulkanContextSettings& VulkanContextSettings::with_debug(bool enabled) { |
|
|
ContextSettings& ContextSettings::with_debug(bool enabled) { |
|
|
m_debug = enabled; |
|
|
m_debug = enabled; |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const std::optional<Uuid>& VulkanContextSettings::physical_device() const { |
|
|
const std::optional<Uuid>& ContextSettings::physical_device() const { |
|
|
return m_physical_device; |
|
|
return m_physical_device; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VulkanContextSettings& VulkanContextSettings::with_physical_device(Uuid uuid) { |
|
|
ContextSettings& ContextSettings::with_physical_device(Uuid uuid) { |
|
|
m_physical_device = uuid; |
|
|
m_physical_device = uuid; |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const std::vector<VulkanContextSettings::QueueInfo>& VulkanContextSettings::queues() const { |
|
|
const std::vector<ContextSettings::QueueInfo>& ContextSettings::queues() const { |
|
|
return m_queues; |
|
|
return m_queues; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VulkanContextSettings& VulkanContextSettings::with_queue( |
|
|
ContextSettings& ContextSettings::with_queue( |
|
|
uint32_t index, VkQueueFlagBits flags, bool use_swapchain_images |
|
|
uint32_t index, VkQueueFlagBits flags, bool use_swapchain_images |
|
|
) { |
|
|
) { |
|
|
m_queues.emplace_back(QueueInfo { index, flags, use_swapchain_images }); |
|
|
m_queues.emplace_back(QueueInfo { index, flags, use_swapchain_images }); |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
SDL_Window* VulkanContextSettings::window() const { |
|
|
SDL_Window* ContextSettings::window() const { |
|
|
return m_window; |
|
|
return m_window; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VulkanContextSettings& VulkanContextSettings::with_window(SDL_Window* window) { |
|
|
ContextSettings& ContextSettings::with_window(SDL_Window* window) { |
|
|
m_window = window; |
|
|
m_window = window; |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
// VulkanContext
|
|
|
// Context
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VulkanContext::VulkanContext() { |
|
|
Context::Context() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VulkanContext::~VulkanContext() { |
|
|
Context::~Context() { |
|
|
shutdown(); |
|
|
shutdown(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkInstance VulkanContext::instance() { |
|
|
VkInstance Context::instance() { |
|
|
return m_instance; |
|
|
return m_instance; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkPhysicalDevice VulkanContext::physical_device() { |
|
|
VkPhysicalDevice Context::physical_device() { |
|
|
return m_physical_device; |
|
|
return m_physical_device; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkDevice VulkanContext::device() { |
|
|
VkDevice Context::device() { |
|
|
return m_device; |
|
|
return m_device; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint32_t VulkanContext::queue_family(size_t queue_index) const { |
|
|
uint32_t Context::queue_family(size_t queue_index) const { |
|
|
return m_queue_families[queue_index]; |
|
|
return m_queue_families[queue_index]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkQueue VulkanContext::queue(size_t queue_index) { |
|
|
VkQueue Context::queue(size_t queue_index) { |
|
|
return m_queues[queue_index]; |
|
|
return m_queues[queue_index]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkSurfaceKHR VulkanContext::surface() { |
|
|
VkSurfaceKHR Context::surface() { |
|
|
return m_surface; |
|
|
return m_surface; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkSwapchainKHR VulkanContext::swapchain() { |
|
|
VkSwapchainKHR Context::swapchain() { |
|
|
return m_swapchain; |
|
|
return m_swapchain; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkSurfaceFormatKHR VulkanContext::surface_format() const { |
|
|
VkSurfaceFormatKHR Context::surface_format() const { |
|
|
return m_surface_format; |
|
|
return m_surface_format; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkPresentModeKHR VulkanContext::present_mode() const { |
|
|
VkPresentModeKHR Context::present_mode() const { |
|
|
return m_present_mode; |
|
|
return m_present_mode; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkExtent2D VulkanContext::swapchain_extent() const { |
|
|
VkExtent2D Context::swapchain_extent() const { |
|
|
return m_swapchain_extent; |
|
|
return m_swapchain_extent; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
size_t VulkanContext::swapchain_image_count() const { |
|
|
size_t Context::swapchain_image_count() const { |
|
|
return m_image_resources.size(); |
|
|
return m_image_resources.size(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint32_t VulkanContext::current_image_index() const { |
|
|
uint32_t Context::current_image_index() const { |
|
|
return m_current_image_index; |
|
|
return m_current_image_index; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkImage VulkanContext::swapchain_image() { |
|
|
VkImage Context::swapchain_image() { |
|
|
assert(m_current_image_index != CURRENT_IMAGE_INDEX); |
|
|
assert(m_current_image_index != CURRENT_IMAGE_INDEX); |
|
|
return m_image_resources[m_current_image_index].image; |
|
|
return m_image_resources[m_current_image_index].image; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkImage VulkanContext::swapchain_image(size_t image_index) { |
|
|
VkImage Context::swapchain_image(size_t image_index) { |
|
|
return m_image_resources[image_index].image; |
|
|
return m_image_resources[image_index].image; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkImageView VulkanContext::swapchain_image_view() { |
|
|
VkImageView Context::swapchain_image_view() { |
|
|
assert(m_current_image_index != CURRENT_IMAGE_INDEX); |
|
|
assert(m_current_image_index != CURRENT_IMAGE_INDEX); |
|
|
return m_image_resources[m_current_image_index].view; |
|
|
return m_image_resources[m_current_image_index].view; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkImageView VulkanContext::swapchain_image_view(size_t image_index) { |
|
|
VkImageView Context::swapchain_image_view(size_t image_index) { |
|
|
return m_image_resources[image_index].view; |
|
|
return m_image_resources[image_index].view; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkSemaphore VulkanContext::ready_to_render() { |
|
|
VkSemaphore Context::ready_to_render() { |
|
|
return m_frame_resources[m_frame_resources_index].ready_to_render; |
|
|
return m_frame_resources[m_frame_resources_index].ready_to_render; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VkFence VulkanContext::render_done() { |
|
|
VkFence Context::render_done() { |
|
|
return m_frame_resources[m_frame_resources_index].render_done; |
|
|
return m_frame_resources[m_frame_resources_index].render_done; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::initialize(const VulkanContextSettings& settings) { |
|
|
void Context::initialize(const ContextSettings& settings) { |
|
|
m_window = settings.window(); |
|
|
m_window = settings.window(); |
|
|
|
|
|
|
|
|
create_instance(settings); |
|
|
create_instance(settings); |
|
|
@ -151,7 +154,7 @@ void VulkanContext::initialize(const VulkanContextSettings& settings) { |
|
|
create_swapchain(settings); |
|
|
create_swapchain(settings); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::shutdown() { |
|
|
void Context::shutdown() { |
|
|
if(!m_instance) |
|
|
if(!m_instance) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -168,7 +171,7 @@ void VulkanContext::shutdown() { |
|
|
destroy_instance(m_instance); |
|
|
destroy_instance(m_instance); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::begin_frame() { |
|
|
void Context::begin_frame() { |
|
|
assert(m_current_image_index == CURRENT_IMAGE_INDEX); |
|
|
assert(m_current_image_index == CURRENT_IMAGE_INDEX); |
|
|
|
|
|
|
|
|
auto& frame_resources = m_frame_resources[m_frame_resources_index]; |
|
|
auto& frame_resources = m_frame_resources[m_frame_resources_index]; |
|
|
@ -229,7 +232,7 @@ void VulkanContext::begin_frame() { |
|
|
vkResetFences(m_device, 1, &frame_resources.render_done); |
|
|
vkResetFences(m_device, 1, &frame_resources.render_done); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::swap_buffers(uint32_t semaphore_count, VkSemaphore* wait_semaphores) { |
|
|
void Context::swap_buffers(uint32_t semaphore_count, VkSemaphore* wait_semaphores) { |
|
|
assert(m_current_image_index != CURRENT_IMAGE_INDEX); |
|
|
assert(m_current_image_index != CURRENT_IMAGE_INDEX); |
|
|
|
|
|
|
|
|
VkPresentInfoKHR present_info { |
|
|
VkPresentInfoKHR present_info { |
|
|
@ -262,23 +265,23 @@ void VulkanContext::swap_buffers(uint32_t semaphore_count, VkSemaphore* wait_sem |
|
|
m_current_image_index = CURRENT_IMAGE_INDEX; |
|
|
m_current_image_index = CURRENT_IMAGE_INDEX; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::invalidate_swapchain() { |
|
|
void Context::invalidate_swapchain() { |
|
|
m_invalid_swapchain = true; |
|
|
m_invalid_swapchain = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::register_swapchain_creation_callback(SwapchainCreationCallback callback) { |
|
|
void Context::register_swapchain_creation_callback(SwapchainCreationCallback callback) { |
|
|
m_swapchain_creation_callbacks.emplace_back(std::move(callback)); |
|
|
m_swapchain_creation_callbacks.emplace_back(std::move(callback)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::register_swapchain_destruction_callback(SwapchainDestructionCallback callback) { |
|
|
void Context::register_swapchain_destruction_callback(SwapchainDestructionCallback callback) { |
|
|
m_swapchain_destruction_callbacks.emplace_back(std::move(callback)); |
|
|
m_swapchain_destruction_callbacks.emplace_back(std::move(callback)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::register_context_destruction_callback(ContextDestructionCallback callback) { |
|
|
void Context::register_context_destruction_callback(ContextDestructionCallback callback) { |
|
|
m_context_destruction_callbacks.emplace_back(std::move(callback)); |
|
|
m_context_destruction_callbacks.emplace_back(std::move(callback)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkExtensionProperties> VulkanContext::available_extensions() { |
|
|
std::vector<VkExtensionProperties> Context::available_extensions() { |
|
|
uint32_t count; |
|
|
uint32_t count; |
|
|
vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); |
|
|
vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); |
|
|
|
|
|
|
|
|
@ -288,7 +291,7 @@ std::vector<VkExtensionProperties> VulkanContext::available_extensions() { |
|
|
return extensions; |
|
|
return extensions; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkLayerProperties> VulkanContext::available_layers() { |
|
|
std::vector<VkLayerProperties> Context::available_layers() { |
|
|
uint32_t count; |
|
|
uint32_t count; |
|
|
vkEnumerateInstanceLayerProperties(&count, nullptr); |
|
|
vkEnumerateInstanceLayerProperties(&count, nullptr); |
|
|
|
|
|
|
|
|
@ -298,7 +301,7 @@ std::vector<VkLayerProperties> VulkanContext::available_layers() { |
|
|
return layers; |
|
|
return layers; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<const char*> VulkanContext::sdl_vulkan_extensions() const { |
|
|
std::vector<const char*> Context::sdl_vulkan_extensions() const { |
|
|
unsigned count; |
|
|
unsigned count; |
|
|
if(!SDL_Vulkan_GetInstanceExtensions(m_window, &count, nullptr)) |
|
|
if(!SDL_Vulkan_GetInstanceExtensions(m_window, &count, nullptr)) |
|
|
throw std::runtime_error("failed to get window's vulkan extensions"); |
|
|
throw std::runtime_error("failed to get window's vulkan extensions"); |
|
|
@ -310,7 +313,7 @@ std::vector<const char*> VulkanContext::sdl_vulkan_extensions() const { |
|
|
return extensions; |
|
|
return extensions; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkPhysicalDevice> VulkanContext::physical_devices() const { |
|
|
std::vector<VkPhysicalDevice> Context::physical_devices() const { |
|
|
uint32_t devices_count = 0; |
|
|
uint32_t devices_count = 0; |
|
|
vkEnumeratePhysicalDevices(m_instance, &devices_count, nullptr); |
|
|
vkEnumeratePhysicalDevices(m_instance, &devices_count, nullptr); |
|
|
|
|
|
|
|
|
@ -320,7 +323,7 @@ std::vector<VkPhysicalDevice> VulkanContext::physical_devices() const { |
|
|
return physical_devices; |
|
|
return physical_devices; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkQueueFamilyProperties> VulkanContext::queue_families(VkPhysicalDevice physical_device) const { |
|
|
std::vector<VkQueueFamilyProperties> Context::queue_families(VkPhysicalDevice physical_device) const { |
|
|
uint32_t queue_families_count = 0; |
|
|
uint32_t queue_families_count = 0; |
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr); |
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr); |
|
|
|
|
|
|
|
|
@ -330,7 +333,7 @@ std::vector<VkQueueFamilyProperties> VulkanContext::queue_families(VkPhysicalDev |
|
|
return queue_families; |
|
|
return queue_families; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkExtensionProperties> VulkanContext::device_extensions(VkPhysicalDevice physical_device) const { |
|
|
std::vector<VkExtensionProperties> Context::device_extensions(VkPhysicalDevice physical_device) const { |
|
|
uint32_t extensions_count = 0; |
|
|
uint32_t extensions_count = 0; |
|
|
vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extensions_count, nullptr); |
|
|
vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extensions_count, nullptr); |
|
|
|
|
|
|
|
|
@ -340,7 +343,7 @@ std::vector<VkExtensionProperties> VulkanContext::device_extensions(VkPhysicalDe |
|
|
return extensions; |
|
|
return extensions; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkSurfaceFormatKHR> VulkanContext::surface_formats(VkPhysicalDevice physical_device) const { |
|
|
std::vector<VkSurfaceFormatKHR> Context::surface_formats(VkPhysicalDevice physical_device) const { |
|
|
uint32_t surface_formats_count = 0; |
|
|
uint32_t surface_formats_count = 0; |
|
|
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, m_surface, &surface_formats_count, nullptr); |
|
|
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, m_surface, &surface_formats_count, nullptr); |
|
|
|
|
|
|
|
|
@ -350,7 +353,7 @@ std::vector<VkSurfaceFormatKHR> VulkanContext::surface_formats(VkPhysicalDevice |
|
|
return surface_formats; |
|
|
return surface_formats; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::vector<VkPresentModeKHR> VulkanContext::present_modes(VkPhysicalDevice physical_device) const { |
|
|
std::vector<VkPresentModeKHR> Context::present_modes(VkPhysicalDevice physical_device) const { |
|
|
uint32_t present_modes_count = 0; |
|
|
uint32_t present_modes_count = 0; |
|
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, m_surface, &present_modes_count, nullptr); |
|
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, m_surface, &present_modes_count, nullptr); |
|
|
|
|
|
|
|
|
@ -361,23 +364,23 @@ std::vector<VkPresentModeKHR> VulkanContext::present_modes(VkPhysicalDevice phys |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void VulkanContext::set_object_name(VkObjectType type, uint64_t object, const char* name) { |
|
|
void Context::set_object_name(VkObjectType type, uint64_t object, const char* name) { |
|
|
VkDebugUtilsObjectNameInfoEXT name_info { |
|
|
VkDebugUtilsObjectNameInfoEXT name_info { |
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, |
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, |
|
|
.objectType = type, |
|
|
.objectType = type, |
|
|
.objectHandle = object, |
|
|
.objectHandle = object, |
|
|
.pObjectName = name |
|
|
.pObjectName = name |
|
|
}; |
|
|
}; |
|
|
if(vkeSetDebugUtilsObjectNameEXT(m_device, &name_info) != VK_SUCCESS) |
|
|
if(setDebugUtilsObjectName(m_device, &name_info) != VK_SUCCESS) |
|
|
throw std::runtime_error("failed to set debug name"); |
|
|
throw std::runtime_error("failed to set debug name"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::set_object_name(VkObjectType type, uint64_t object, const std::string& name) { |
|
|
void Context::set_object_name(VkObjectType type, uint64_t object, const std::string& name) { |
|
|
set_object_name(type, object, name.c_str()); |
|
|
set_object_name(type, object, name.c_str()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void VulkanContext::destroy_instance(VkInstance& instance) { |
|
|
void Context::destroy_instance(VkInstance& instance) { |
|
|
if(instance == nullptr) |
|
|
if(instance == nullptr) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -385,15 +388,15 @@ void VulkanContext::destroy_instance(VkInstance& instance) { |
|
|
instance = nullptr; |
|
|
instance = nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_debug_messenger(VkDebugUtilsMessengerEXT& debug_messenger) { |
|
|
void Context::destroy_debug_messenger(VkDebugUtilsMessengerEXT& debug_messenger) { |
|
|
if(debug_messenger == VK_NULL_HANDLE) |
|
|
if(debug_messenger == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
vkeDestroyDebugUtilsMessengerEXT(m_instance, debug_messenger, nullptr); |
|
|
destroyDebugUtilsMessenger(m_instance, debug_messenger, nullptr); |
|
|
debug_messenger = VK_NULL_HANDLE; |
|
|
debug_messenger = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_surface(VkSurfaceKHR& surface) { |
|
|
void Context::destroy_surface(VkSurfaceKHR& surface) { |
|
|
if(surface == VK_NULL_HANDLE) |
|
|
if(surface == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -401,7 +404,7 @@ void VulkanContext::destroy_surface(VkSurfaceKHR& surface) { |
|
|
surface = VK_NULL_HANDLE; |
|
|
surface = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_device(VkDevice& device) { |
|
|
void Context::destroy_device(VkDevice& device) { |
|
|
if(device == nullptr) |
|
|
if(device == nullptr) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -409,7 +412,7 @@ void VulkanContext::destroy_device(VkDevice& device) { |
|
|
device = nullptr; |
|
|
device = nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_swapchain(VkSwapchainKHR& swapchain) { |
|
|
void Context::destroy_swapchain(VkSwapchainKHR& swapchain) { |
|
|
if(swapchain == VK_NULL_HANDLE) |
|
|
if(swapchain == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -417,7 +420,7 @@ void VulkanContext::destroy_swapchain(VkSwapchainKHR& swapchain) { |
|
|
swapchain = VK_NULL_HANDLE; |
|
|
swapchain = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_image(VkImage& image) { |
|
|
void Context::destroy_image(VkImage& image) { |
|
|
if(image == VK_NULL_HANDLE) |
|
|
if(image == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -425,7 +428,7 @@ void VulkanContext::destroy_image(VkImage& image) { |
|
|
image = VK_NULL_HANDLE; |
|
|
image = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_image_view(VkImageView& image_view) { |
|
|
void Context::destroy_image_view(VkImageView& image_view) { |
|
|
if(image_view == VK_NULL_HANDLE) |
|
|
if(image_view == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -433,7 +436,7 @@ void VulkanContext::destroy_image_view(VkImageView& image_view) { |
|
|
image_view = VK_NULL_HANDLE; |
|
|
image_view = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_framebuffer(VkFramebuffer& framebuffer) { |
|
|
void Context::destroy_framebuffer(VkFramebuffer& framebuffer) { |
|
|
if(framebuffer == VK_NULL_HANDLE) |
|
|
if(framebuffer == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -441,7 +444,7 @@ void VulkanContext::destroy_framebuffer(VkFramebuffer& framebuffer) { |
|
|
framebuffer = VK_NULL_HANDLE; |
|
|
framebuffer = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_buffer(VkBuffer& buffer) { |
|
|
void Context::destroy_buffer(VkBuffer& buffer) { |
|
|
if(buffer == VK_NULL_HANDLE) |
|
|
if(buffer == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -449,7 +452,7 @@ void VulkanContext::destroy_buffer(VkBuffer& buffer) { |
|
|
buffer = VK_NULL_HANDLE; |
|
|
buffer = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_command_pool(VkCommandPool& command_pool) { |
|
|
void Context::destroy_command_pool(VkCommandPool& command_pool) { |
|
|
if(command_pool == VK_NULL_HANDLE) |
|
|
if(command_pool == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -457,7 +460,7 @@ void VulkanContext::destroy_command_pool(VkCommandPool& command_pool) { |
|
|
command_pool = VK_NULL_HANDLE; |
|
|
command_pool = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_render_pass(VkRenderPass& render_pass) { |
|
|
void Context::destroy_render_pass(VkRenderPass& render_pass) { |
|
|
if(render_pass == VK_NULL_HANDLE) |
|
|
if(render_pass == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -465,7 +468,7 @@ void VulkanContext::destroy_render_pass(VkRenderPass& render_pass) { |
|
|
render_pass = VK_NULL_HANDLE; |
|
|
render_pass = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_pipeline_layout(VkPipelineLayout& pipeline_layout) { |
|
|
void Context::destroy_pipeline_layout(VkPipelineLayout& pipeline_layout) { |
|
|
if(pipeline_layout == VK_NULL_HANDLE) |
|
|
if(pipeline_layout == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -473,7 +476,7 @@ void VulkanContext::destroy_pipeline_layout(VkPipelineLayout& pipeline_layout) { |
|
|
pipeline_layout = VK_NULL_HANDLE; |
|
|
pipeline_layout = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_pipeline(VkPipeline& pipeline) { |
|
|
void Context::destroy_pipeline(VkPipeline& pipeline) { |
|
|
if(pipeline == VK_NULL_HANDLE) |
|
|
if(pipeline == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -481,7 +484,7 @@ void VulkanContext::destroy_pipeline(VkPipeline& pipeline) { |
|
|
pipeline = VK_NULL_HANDLE; |
|
|
pipeline = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_semaphore(VkSemaphore& semaphore) { |
|
|
void Context::destroy_semaphore(VkSemaphore& semaphore) { |
|
|
if(semaphore == VK_NULL_HANDLE) |
|
|
if(semaphore == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -489,7 +492,7 @@ void VulkanContext::destroy_semaphore(VkSemaphore& semaphore) { |
|
|
semaphore = VK_NULL_HANDLE; |
|
|
semaphore = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_fence(VkFence& fence) { |
|
|
void Context::destroy_fence(VkFence& fence) { |
|
|
if(fence == VK_NULL_HANDLE) |
|
|
if(fence == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -497,7 +500,7 @@ void VulkanContext::destroy_fence(VkFence& fence) { |
|
|
fence = VK_NULL_HANDLE; |
|
|
fence = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::free_memory(VkDeviceMemory& memory) { |
|
|
void Context::free_memory(VkDeviceMemory& memory) { |
|
|
if(memory == VK_NULL_HANDLE) |
|
|
if(memory == VK_NULL_HANDLE) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -505,7 +508,7 @@ void VulkanContext::free_memory(VkDeviceMemory& memory) { |
|
|
memory = VK_NULL_HANDLE; |
|
|
memory = VK_NULL_HANDLE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::create_instance(const VulkanContextSettings& settings) { |
|
|
void Context::create_instance(const ContextSettings& settings) { |
|
|
if(m_instance) |
|
|
if(m_instance) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
@ -527,7 +530,7 @@ void VulkanContext::create_instance(const VulkanContextSettings& settings) { |
|
|
if(settings.debug()) { |
|
|
if(settings.debug()) { |
|
|
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); |
|
|
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); |
|
|
|
|
|
|
|
|
auto const available_layers = VulkanContext::available_layers(); |
|
|
auto const available_layers = Context::available_layers(); |
|
|
|
|
|
|
|
|
auto add_layer_if_available = [&](const char* requested_layer) { |
|
|
auto add_layer_if_available = [&](const char* requested_layer) { |
|
|
if(std::find_if( |
|
|
if(std::find_if( |
|
|
@ -587,17 +590,17 @@ void VulkanContext::create_instance(const VulkanContextSettings& settings) { |
|
|
initialize_extension_functions(); |
|
|
initialize_extension_functions(); |
|
|
|
|
|
|
|
|
if(settings.debug()) { |
|
|
if(settings.debug()) { |
|
|
vkeCreateDebugUtilsMessengerEXT( |
|
|
createDebugUtilsMessenger( |
|
|
m_instance, &debug_info, nullptr, &m_debug_messenger); |
|
|
m_instance, &debug_info, nullptr, &m_debug_messenger); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::create_surface(const VulkanContextSettings& settings) { |
|
|
void Context::create_surface(const ContextSettings& settings) { |
|
|
if(!SDL_Vulkan_CreateSurface(m_window, m_instance, &m_surface)) |
|
|
if(!SDL_Vulkan_CreateSurface(m_window, m_instance, &m_surface)) |
|
|
throw std::runtime_error("failed to create surface"); |
|
|
throw std::runtime_error("failed to create surface"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::choose_physical_device(const VulkanContextSettings& settings) { |
|
|
void Context::choose_physical_device(const ContextSettings& settings) { |
|
|
auto physical_devices = this->physical_devices(); |
|
|
auto physical_devices = this->physical_devices(); |
|
|
if(settings.physical_device()) { |
|
|
if(settings.physical_device()) { |
|
|
auto const device_it = std::find_if( |
|
|
auto const device_it = std::find_if( |
|
|
@ -617,8 +620,10 @@ void VulkanContext::choose_physical_device(const VulkanContextSettings& settings |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for(auto const physical_device: physical_devices) { |
|
|
for(auto const physical_device: physical_devices) { |
|
|
if(select_physical_device(physical_device, settings)) { |
|
|
auto maybe_properties = select_physical_device(physical_device, settings); |
|
|
|
|
|
if(maybe_properties) { |
|
|
m_physical_device = physical_device; |
|
|
m_physical_device = physical_device; |
|
|
|
|
|
m_physical_device_properties = *maybe_properties; |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -626,17 +631,14 @@ void VulkanContext::choose_physical_device(const VulkanContextSettings& settings |
|
|
if(!m_physical_device) |
|
|
if(!m_physical_device) |
|
|
throw std::runtime_error("failed to find suitable physical device"); |
|
|
throw std::runtime_error("failed to find suitable physical device"); |
|
|
|
|
|
|
|
|
VkPhysicalDeviceProperties device_properties; |
|
|
logger.info() << "use suitable device: " << m_physical_device_properties.deviceName; |
|
|
vkGetPhysicalDeviceProperties(m_physical_device, &device_properties); |
|
|
|
|
|
|
|
|
|
|
|
logger.info() << "use suitable device: " << device_properties.deviceName; |
|
|
|
|
|
logger.debug() << "swapchain format: " << m_surface_format.format; |
|
|
logger.debug() << "swapchain format: " << m_surface_format.format; |
|
|
logger.debug() << "present mode: " << m_present_mode; |
|
|
logger.debug() << "present mode: " << m_present_mode; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool VulkanContext::select_physical_device( |
|
|
std::optional<VkPhysicalDeviceProperties> Context::select_physical_device( |
|
|
VkPhysicalDevice physical_device, |
|
|
VkPhysicalDevice physical_device, |
|
|
const VulkanContextSettings& settings |
|
|
const ContextSettings& settings |
|
|
) { |
|
|
) { |
|
|
VkPhysicalDeviceProperties device_properties; |
|
|
VkPhysicalDeviceProperties device_properties; |
|
|
vkGetPhysicalDeviceProperties(physical_device, &device_properties); |
|
|
vkGetPhysicalDeviceProperties(physical_device, &device_properties); |
|
|
@ -675,7 +677,7 @@ bool VulkanContext::select_physical_device( |
|
|
|
|
|
|
|
|
for(auto const queue_family: m_queue_families) { |
|
|
for(auto const queue_family: m_queue_families) { |
|
|
if(queue_family == INVALID_QUEUE_FAMILY) |
|
|
if(queue_family == INVALID_QUEUE_FAMILY) |
|
|
return false; |
|
|
return std::nullopt; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
auto const available_extensions = this->device_extensions(physical_device); |
|
|
auto const available_extensions = this->device_extensions(physical_device); |
|
|
@ -691,15 +693,15 @@ bool VulkanContext::select_physical_device( |
|
|
|
|
|
|
|
|
if(m_window) { |
|
|
if(m_window) { |
|
|
if(!has_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) |
|
|
if(!has_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) |
|
|
return false; |
|
|
return std::nullopt; |
|
|
|
|
|
|
|
|
auto const surface_formats = this->surface_formats(physical_device); |
|
|
auto const surface_formats = this->surface_formats(physical_device); |
|
|
if(surface_formats.empty()) |
|
|
if(surface_formats.empty()) |
|
|
return false; |
|
|
return std::nullopt; |
|
|
|
|
|
|
|
|
auto const present_modes = this->present_modes(physical_device); |
|
|
auto const present_modes = this->present_modes(physical_device); |
|
|
if(present_modes.empty()) |
|
|
if(present_modes.empty()) |
|
|
return false; |
|
|
return std::nullopt; |
|
|
|
|
|
|
|
|
auto const surface_format_it = std::find_if( |
|
|
auto const surface_format_it = std::find_if( |
|
|
surface_formats.begin(), |
|
|
surface_formats.begin(), |
|
|
@ -716,10 +718,10 @@ bool VulkanContext::select_physical_device( |
|
|
m_present_mode = VK_PRESENT_MODE_FIFO_KHR; |
|
|
m_present_mode = VK_PRESENT_MODE_FIFO_KHR; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true; |
|
|
return device_properties; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::create_device(const VulkanContextSettings& settings) { |
|
|
void Context::create_device(const ContextSettings& settings) { |
|
|
std::vector<uint32_t> queue_families = m_queue_families; |
|
|
std::vector<uint32_t> queue_families = m_queue_families; |
|
|
std::sort(queue_families.begin(), queue_families.end()); |
|
|
std::sort(queue_families.begin(), queue_families.end()); |
|
|
queue_families.erase( |
|
|
queue_families.erase( |
|
|
@ -776,7 +778,7 @@ void VulkanContext::create_device(const VulkanContextSettings& settings) { |
|
|
vkGetDeviceQueue(m_device, m_presentation_queue_family, 0, &m_presentation_queue); |
|
|
vkGetDeviceQueue(m_device, m_presentation_queue_family, 0, &m_presentation_queue); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::create_swapchain(const VulkanContextSettings& settings) { |
|
|
void Context::create_swapchain(const ContextSettings& settings) { |
|
|
m_swapchain_queue_families = { |
|
|
m_swapchain_queue_families = { |
|
|
m_presentation_queue_family, |
|
|
m_presentation_queue_family, |
|
|
}; |
|
|
}; |
|
|
@ -793,7 +795,7 @@ void VulkanContext::create_swapchain(const VulkanContextSettings& settings) { |
|
|
create_swapchain(); |
|
|
create_swapchain(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::create_swapchain() { |
|
|
void Context::create_swapchain() { |
|
|
VkSurfaceCapabilitiesKHR capabilities; |
|
|
VkSurfaceCapabilitiesKHR capabilities; |
|
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physical_device, m_surface, &capabilities); |
|
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physical_device, m_surface, &capabilities); |
|
|
|
|
|
|
|
|
@ -931,7 +933,7 @@ void VulkanContext::create_swapchain() { |
|
|
callback(image_count); |
|
|
callback(image_count); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::destroy_swapchain() { |
|
|
void Context::destroy_swapchain() { |
|
|
for(auto& callback: m_swapchain_destruction_callbacks) |
|
|
for(auto& callback: m_swapchain_destruction_callbacks) |
|
|
callback(); |
|
|
callback(); |
|
|
|
|
|
|
|
|
@ -949,32 +951,32 @@ void VulkanContext::destroy_swapchain() { |
|
|
destroy_swapchain(m_swapchain); |
|
|
destroy_swapchain(m_swapchain); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::recreate_swapchain() { |
|
|
void Context::recreate_swapchain() { |
|
|
destroy_swapchain(); |
|
|
destroy_swapchain(); |
|
|
create_swapchain(); |
|
|
create_swapchain(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void VulkanContext::initialize_extension_functions() { |
|
|
void Context::initialize_extension_functions() { |
|
|
uint32_t errors_count = 0; |
|
|
uint32_t errors_count = 0; |
|
|
|
|
|
|
|
|
#define GET_PROC_ADDR(func_name) \ |
|
|
#define GET_PROC_ADDR(ptr_name, func_name) \ |
|
|
vke ## func_name = (PFN_vk ## func_name)vkGetInstanceProcAddr( \ |
|
|
ptr_name = (PFN_vk ## func_name)vkGetInstanceProcAddr( \ |
|
|
m_instance, "vk" #func_name); \ |
|
|
m_instance, "vk" #func_name); \ |
|
|
if(vke ## func_name == nullptr) \ |
|
|
if(ptr_name == nullptr) \ |
|
|
{ \ |
|
|
{ \ |
|
|
logger.error() << "failed to load extension function 'vk" #func_name "'"; \ |
|
|
logger.error() << "failed to load extension function 'vk" #func_name "'"; \ |
|
|
errors_count += 1; \ |
|
|
errors_count += 1; \ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
GET_PROC_ADDR(CreateDebugUtilsMessengerEXT) |
|
|
GET_PROC_ADDR(createDebugUtilsMessenger, CreateDebugUtilsMessengerEXT) |
|
|
GET_PROC_ADDR(DestroyDebugUtilsMessengerEXT) |
|
|
GET_PROC_ADDR(destroyDebugUtilsMessenger, DestroyDebugUtilsMessengerEXT) |
|
|
GET_PROC_ADDR(SetDebugUtilsObjectNameEXT) |
|
|
GET_PROC_ADDR(setDebugUtilsObjectName, SetDebugUtilsObjectNameEXT) |
|
|
|
|
|
|
|
|
if(errors_count != 0) |
|
|
if(errors_count != 0) |
|
|
throw std::runtime_error("failed to load extensions"); |
|
|
throw std::runtime_error("failed to load extensions"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::log_debug_message( |
|
|
VKAPI_ATTR VkBool32 VKAPI_CALL Context::log_debug_message( |
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT severity, |
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT severity, |
|
|
VkDebugUtilsMessageTypeFlagsEXT type, |
|
|
VkDebugUtilsMessageTypeFlagsEXT type, |
|
|
const VkDebugUtilsMessengerCallbackDataEXT* data, |
|
|
const VkDebugUtilsMessengerCallbackDataEXT* data, |
|
|
@ -1014,6 +1016,5 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::log_debug_message( |
|
|
return VK_FALSE; |
|
|
return VK_FALSE; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
PFN_vkCreateDebugUtilsMessengerEXT vkeCreateDebugUtilsMessengerEXT = nullptr; |
|
|
|
|
|
PFN_vkDestroyDebugUtilsMessengerEXT vkeDestroyDebugUtilsMessengerEXT = nullptr; |
|
|
} |
|
|
PFN_vkSetDebugUtilsObjectNameEXT vkeSetDebugUtilsObjectNameEXT = nullptr; |
|
|
|