Add create swapchain

This commit is contained in:
Jiga228
2025-09-24 21:48:34 +07:00
parent 84e3a2a378
commit 9a9fa710ff
2 changed files with 162 additions and 12 deletions
+142 -8
View File
@@ -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);
+17 -1
View File
@@ -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();