Add create swapchain
This commit is contained in:
+142
-8
@@ -1,5 +1,6 @@
|
||||
#include "RenderEngine.h"
|
||||
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
@@ -10,6 +11,10 @@
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
const std::vector<const char*> RenderEngine::deviceExtensions = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
@@ -31,6 +36,25 @@ VkResult RenderEngine::enable_layer_validation(VkDebugUtilsMessengerCreateInfoEX
|
||||
}
|
||||
#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()
|
||||
{
|
||||
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);
|
||||
|
||||
return device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||
&& device_features.geometryShader
|
||||
&& indices.is_complete();
|
||||
return indices.is_complete() && check_device_extensions_support(device);
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -88,6 +134,43 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi
|
||||
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()
|
||||
{
|
||||
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.ppEnabledExtensionNames = extensions.data();
|
||||
#ifdef _DEBUG
|
||||
std::vector<const char*> layers_validation = {
|
||||
const std::vector<const char*> layers_validation = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
};
|
||||
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.pQueueCreateInfos = queue_create_infos.data();
|
||||
device_create_info.pEnabledFeatures = &device_features;
|
||||
device_create_info.enabledExtensionCount = 0;
|
||||
device_create_info.ppEnabledExtensionNames = nullptr;
|
||||
device_create_info.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||
device_create_info.ppEnabledExtensionNames = deviceExtensions.data();
|
||||
|
||||
#ifdef _DEBUG
|
||||
std::vector<const char*> layers_validation = {
|
||||
const std::vector<const char*> layers_validation = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
};
|
||||
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_);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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),
|
||||
window_(window)
|
||||
#ifdef _DEBUG
|
||||
@@ -209,10 +339,14 @@ window_(window)
|
||||
create_surface();
|
||||
pick_physical_device();
|
||||
create_logical_device();
|
||||
create_swapchain(desired_present_mode);
|
||||
}
|
||||
|
||||
RenderEngine::~RenderEngine()
|
||||
{
|
||||
if (swapchain_ != VK_NULL_HANDLE)
|
||||
vkDestroySwapchainKHR(device_, swapchain_, nullptr);
|
||||
|
||||
if (device_ != VK_NULL_HANDLE)
|
||||
vkDestroyDevice(device_, nullptr);
|
||||
|
||||
|
||||
@@ -25,6 +25,14 @@ class RenderEngine
|
||||
std::optional<uint32_t> present_family;
|
||||
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_;
|
||||
GLFWwindow* window_;
|
||||
@@ -34,23 +42,31 @@ class RenderEngine
|
||||
VkDevice device_ = VK_NULL_HANDLE;
|
||||
VkQueue graphics_queue_ = VK_NULL_HANDLE;
|
||||
VkQueue present_queue_ = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
|
||||
std::vector<VkImage> swapchain_images_;
|
||||
|
||||
#ifdef _DEBUG
|
||||
VkResult enable_layer_validation(VkDebugUtilsMessengerCreateInfoEXT* create_info);
|
||||
VkDebugUtilsMessengerEXT debug_messenger_;
|
||||
#endif
|
||||
SwapchainSupportDetails query_swapchain_details();
|
||||
|
||||
static std::vector<const char*> get_required_extensions();
|
||||
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 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_surface();
|
||||
void pick_physical_device();
|
||||
void create_logical_device();
|
||||
void create_swapchain(VkPresentModeKHR desired_present_mode);
|
||||
public:
|
||||
// Can throw the exception
|
||||
RenderEngine(CoreInstance& core, GLFWwindow* window);
|
||||
RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode = VK_PRESENT_MODE_MAILBOX_KHR);
|
||||
~RenderEngine();
|
||||
|
||||
void start();
|
||||
|
||||
Reference in New Issue
Block a user