Add create swapchain
This commit is contained in:
+142
-8
@@ -1,5 +1,6 @@
|
|||||||
#include "RenderEngine.h"
|
#include "RenderEngine.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -10,6 +11,10 @@
|
|||||||
|
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
const std::vector<const char*> RenderEngine::deviceExtensions = {
|
||||||
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
|
||||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
@@ -31,6 +36,25 @@ VkResult RenderEngine::enable_layer_validation(VkDebugUtilsMessengerCreateInfoEX
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RenderEngine::SwapchainSupportDetails RenderEngine::query_swapchain_details()
|
||||||
|
{
|
||||||
|
SwapchainSupportDetails details;
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device_, surface_, &details.capabilities);
|
||||||
|
|
||||||
|
uint32_t surface_format_cnt = 0;
|
||||||
|
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, nullptr));
|
||||||
|
details.formats.resize(surface_format_cnt);
|
||||||
|
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, details.formats.data()));
|
||||||
|
|
||||||
|
uint32_t present_modes_cnt = 0;
|
||||||
|
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, nullptr));
|
||||||
|
details.present_modes.resize(surface_format_cnt);
|
||||||
|
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, details.present_modes.data()));
|
||||||
|
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<const char*> RenderEngine::get_required_extensions()
|
std::vector<const char*> RenderEngine::get_required_extensions()
|
||||||
{
|
{
|
||||||
uint32_t extensions_count = 0;
|
uint32_t extensions_count = 0;
|
||||||
@@ -58,9 +82,31 @@ bool RenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surf
|
|||||||
|
|
||||||
QueueFamilyIndices indices = find_queue_family_indices(device, surface);
|
QueueFamilyIndices indices = find_queue_family_indices(device, surface);
|
||||||
|
|
||||||
return device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
return indices.is_complete() && check_device_extensions_support(device);
|
||||||
&& device_features.geometryShader
|
}
|
||||||
&& indices.is_complete();
|
|
||||||
|
bool RenderEngine::check_device_extensions_support(VkPhysicalDevice device)
|
||||||
|
{
|
||||||
|
uint32_t extension_count;
|
||||||
|
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr));
|
||||||
|
std::vector<VkExtensionProperties> available_extensions(extension_count);
|
||||||
|
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data()));
|
||||||
|
|
||||||
|
for (const auto& extension : deviceExtensions)
|
||||||
|
{
|
||||||
|
bool isFind = false;
|
||||||
|
for (const auto& i : available_extensions)
|
||||||
|
{
|
||||||
|
if (std::strcmp(i.extensionName, extension) == 0)
|
||||||
|
{
|
||||||
|
isFind = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isFind)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface)
|
RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface)
|
||||||
@@ -88,6 +134,43 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi
|
|||||||
return queue_family_indices;
|
return queue_family_indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR RenderEngine::choose_surface_format(const std::vector<VkSurfaceFormatKHR>& surface_formats)
|
||||||
|
{
|
||||||
|
for (const auto& i : surface_formats)
|
||||||
|
{
|
||||||
|
if (i.format == VK_FORMAT_B8G8R8A8_SRGB && i.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return surface_formats[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR RenderEngine::choose_present_mode(const std::vector<VkPresentModeKHR>& present_modes, VkPresentModeKHR desired_present_mode)
|
||||||
|
{
|
||||||
|
for (const auto& i : present_modes)
|
||||||
|
{
|
||||||
|
if (i == desired_present_mode)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkExtent2D RenderEngine::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
||||||
|
return capabilities.currentExtent;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
|
VkExtent2D actualExtent = {
|
||||||
|
static_cast<uint32_t>(width),
|
||||||
|
static_cast<uint32_t>(height)
|
||||||
|
};
|
||||||
|
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
|
||||||
|
return actualExtent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderEngine::create_instance()
|
void RenderEngine::create_instance()
|
||||||
{
|
{
|
||||||
std::vector<const char*> extensions = get_required_extensions();
|
std::vector<const char*> extensions = get_required_extensions();
|
||||||
@@ -107,7 +190,7 @@ void RenderEngine::create_instance()
|
|||||||
instance_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
instance_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||||
instance_create_info.ppEnabledExtensionNames = extensions.data();
|
instance_create_info.ppEnabledExtensionNames = extensions.data();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
std::vector<const char*> layers_validation = {
|
const std::vector<const char*> layers_validation = {
|
||||||
"VK_LAYER_KHRONOS_validation"
|
"VK_LAYER_KHRONOS_validation"
|
||||||
};
|
};
|
||||||
instance_create_info.enabledLayerCount = static_cast<uint32_t>(layers_validation.size());
|
instance_create_info.enabledLayerCount = static_cast<uint32_t>(layers_validation.size());
|
||||||
@@ -174,11 +257,11 @@ void RenderEngine::create_logical_device()
|
|||||||
device_create_info.queueCreateInfoCount = static_cast<uint32_t>(unique_queue_families.size());
|
device_create_info.queueCreateInfoCount = static_cast<uint32_t>(unique_queue_families.size());
|
||||||
device_create_info.pQueueCreateInfos = queue_create_infos.data();
|
device_create_info.pQueueCreateInfos = queue_create_infos.data();
|
||||||
device_create_info.pEnabledFeatures = &device_features;
|
device_create_info.pEnabledFeatures = &device_features;
|
||||||
device_create_info.enabledExtensionCount = 0;
|
device_create_info.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||||
device_create_info.ppEnabledExtensionNames = nullptr;
|
device_create_info.ppEnabledExtensionNames = deviceExtensions.data();
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
std::vector<const char*> layers_validation = {
|
const std::vector<const char*> layers_validation = {
|
||||||
"VK_LAYER_KHRONOS_validation"
|
"VK_LAYER_KHRONOS_validation"
|
||||||
};
|
};
|
||||||
device_create_info.enabledLayerCount = static_cast<uint32_t>(layers_validation.size());
|
device_create_info.enabledLayerCount = static_cast<uint32_t>(layers_validation.size());
|
||||||
@@ -193,12 +276,59 @@ void RenderEngine::create_logical_device()
|
|||||||
vkGetDeviceQueue(device_, indices.present_family.value(), 0, &present_queue_);
|
vkGetDeviceQueue(device_, indices.present_family.value(), 0, &present_queue_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderEngine::create_swapchain(VkPresentModeKHR desired_present_mode)
|
||||||
|
{
|
||||||
|
SwapchainSupportDetails swapchain_support = query_swapchain_details();
|
||||||
|
VkSurfaceFormatKHR surface_format = choose_surface_format(swapchain_support.formats);
|
||||||
|
VkPresentModeKHR present_mode = choose_present_mode(swapchain_support.present_modes, desired_present_mode);
|
||||||
|
VkExtent2D extent = choose_extent(swapchain_support.capabilities, window_);
|
||||||
|
|
||||||
|
uint32_t image_count = swapchain_support.capabilities.minImageCount + 1;
|
||||||
|
if (swapchain_support.capabilities.maxImageCount > 0 && image_count > swapchain_support.capabilities.maxImageCount)
|
||||||
|
image_count = swapchain_support.capabilities.maxImageCount;
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR swapchain_create_info{};
|
||||||
|
swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
|
swapchain_create_info.surface = surface_;
|
||||||
|
swapchain_create_info.minImageCount = image_count;
|
||||||
|
swapchain_create_info.imageFormat = surface_format.format;
|
||||||
|
swapchain_create_info.imageColorSpace = surface_format.colorSpace;
|
||||||
|
swapchain_create_info.imageExtent = extent;
|
||||||
|
swapchain_create_info.imageArrayLayers = 1;
|
||||||
|
swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
swapchain_create_info.preTransform = swapchain_support.capabilities.currentTransform;
|
||||||
|
swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
swapchain_create_info.presentMode = present_mode;
|
||||||
|
swapchain_create_info.clipped = VK_TRUE;
|
||||||
|
swapchain_create_info.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
QueueFamilyIndices family_indices = find_queue_family_indices(physical_device_, surface_);
|
||||||
|
uint32_t queue_family_indices[] = {family_indices.graphycs_family.value(), family_indices.present_family.value()};
|
||||||
|
if (family_indices.graphycs_family != family_indices.present_family)
|
||||||
|
{
|
||||||
|
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
|
swapchain_create_info.queueFamilyIndexCount = 2;
|
||||||
|
swapchain_create_info.pQueueFamilyIndices = queue_family_indices;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
swapchain_create_info.queueFamilyIndexCount = 0;
|
||||||
|
swapchain_create_info.pQueueFamilyIndices = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VK_CHECK(vkCreateSwapchainKHR(device_, &swapchain_create_info, nullptr, &swapchain_));
|
||||||
|
|
||||||
|
swapchain_images_.resize(image_count);
|
||||||
|
vkGetSwapchainImagesKHR(device_, swapchain_, &image_count, swapchain_images_.data());
|
||||||
|
}
|
||||||
|
|
||||||
void RenderEngine::create_surface()
|
void RenderEngine::create_surface()
|
||||||
{
|
{
|
||||||
VK_CHECK(glfwCreateWindowSurface(instance_, window_, nullptr, &surface_));
|
VK_CHECK(glfwCreateWindowSurface(instance_, window_, nullptr, &surface_));
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderEngine::RenderEngine(CoreInstance& core, GLFWwindow* window):
|
RenderEngine::RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode):
|
||||||
core_(core),
|
core_(core),
|
||||||
window_(window)
|
window_(window)
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@@ -209,10 +339,14 @@ window_(window)
|
|||||||
create_surface();
|
create_surface();
|
||||||
pick_physical_device();
|
pick_physical_device();
|
||||||
create_logical_device();
|
create_logical_device();
|
||||||
|
create_swapchain(desired_present_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderEngine::~RenderEngine()
|
RenderEngine::~RenderEngine()
|
||||||
{
|
{
|
||||||
|
if (swapchain_ != VK_NULL_HANDLE)
|
||||||
|
vkDestroySwapchainKHR(device_, swapchain_, nullptr);
|
||||||
|
|
||||||
if (device_ != VK_NULL_HANDLE)
|
if (device_ != VK_NULL_HANDLE)
|
||||||
vkDestroyDevice(device_, nullptr);
|
vkDestroyDevice(device_, nullptr);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ class RenderEngine
|
|||||||
std::optional<uint32_t> present_family;
|
std::optional<uint32_t> present_family;
|
||||||
bool is_complete();
|
bool is_complete();
|
||||||
};
|
};
|
||||||
|
struct SwapchainSupportDetails
|
||||||
|
{
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
std::vector<VkSurfaceFormatKHR> formats;
|
||||||
|
std::vector<VkPresentModeKHR> present_modes;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::vector<const char*> deviceExtensions;
|
||||||
|
|
||||||
CoreInstance& core_;
|
CoreInstance& core_;
|
||||||
GLFWwindow* window_;
|
GLFWwindow* window_;
|
||||||
@@ -34,23 +42,31 @@ class RenderEngine
|
|||||||
VkDevice device_ = VK_NULL_HANDLE;
|
VkDevice device_ = VK_NULL_HANDLE;
|
||||||
VkQueue graphics_queue_ = VK_NULL_HANDLE;
|
VkQueue graphics_queue_ = VK_NULL_HANDLE;
|
||||||
VkQueue present_queue_ = VK_NULL_HANDLE;
|
VkQueue present_queue_ = VK_NULL_HANDLE;
|
||||||
|
VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
|
||||||
|
std::vector<VkImage> swapchain_images_;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
VkResult enable_layer_validation(VkDebugUtilsMessengerCreateInfoEXT* create_info);
|
VkResult enable_layer_validation(VkDebugUtilsMessengerCreateInfoEXT* create_info);
|
||||||
VkDebugUtilsMessengerEXT debug_messenger_;
|
VkDebugUtilsMessengerEXT debug_messenger_;
|
||||||
#endif
|
#endif
|
||||||
|
SwapchainSupportDetails query_swapchain_details();
|
||||||
|
|
||||||
static std::vector<const char*> get_required_extensions();
|
static std::vector<const char*> get_required_extensions();
|
||||||
static bool is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface);
|
static bool is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface);
|
||||||
|
static bool check_device_extensions_support(VkPhysicalDevice device);
|
||||||
static QueueFamilyIndices find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface);
|
static QueueFamilyIndices find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface);
|
||||||
|
static VkSurfaceFormatKHR choose_surface_format(const std::vector<VkSurfaceFormatKHR>& surface_formats);
|
||||||
|
static VkPresentModeKHR choose_present_mode(const std::vector<VkPresentModeKHR>& present_modes, VkPresentModeKHR desired_present_mode);
|
||||||
|
static VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
|
||||||
|
|
||||||
void create_instance();
|
void create_instance();
|
||||||
void create_surface();
|
void create_surface();
|
||||||
void pick_physical_device();
|
void pick_physical_device();
|
||||||
void create_logical_device();
|
void create_logical_device();
|
||||||
|
void create_swapchain(VkPresentModeKHR desired_present_mode);
|
||||||
public:
|
public:
|
||||||
// Can throw the exception
|
// Can throw the exception
|
||||||
RenderEngine(CoreInstance& core, GLFWwindow* window);
|
RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode = VK_PRESENT_MODE_MAILBOX_KHR);
|
||||||
~RenderEngine();
|
~RenderEngine();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|||||||
Reference in New Issue
Block a user