Add create swapchain
This commit is contained in:
+143
-9
@@ -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());
|
||||
@@ -168,17 +251,17 @@ void RenderEngine::create_logical_device()
|
||||
device_queue_create_info.queueCount = 1;
|
||||
queue_create_infos.push_back(device_queue_create_info);
|
||||
}
|
||||
|
||||
|
||||
VkDeviceCreateInfo device_create_info{};
|
||||
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user