Added swapchain

This commit is contained in:
Pasha Bibko
2025-11-15 21:54:02 +00:00
parent 9754629059
commit b2f33a76fb
2 changed files with 162 additions and 6 deletions

View File

@@ -13,6 +13,12 @@ namespace PB::Renderer
VkQueue VulkanManager::s_GraphicsQueue = VK_NULL_HANDLE; VkQueue VulkanManager::s_GraphicsQueue = VK_NULL_HANDLE;
VkQueue VulkanManager::s_PresentQueue = VK_NULL_HANDLE; VkQueue VulkanManager::s_PresentQueue = VK_NULL_HANDLE;
VkSwapchainKHR VulkanManager::s_SwapChain = VK_NULL_HANDLE;
std::vector<VkImage> VulkanManager::s_SwapChainImages = {};
std::vector<VkImageView> VulkanManager::s_SwapChainImageViews = {};
VkFormat VulkanManager::s_SwapChainImageFormat = {};
VkExtent2D VulkanManager::s_SwapChainExtent = {};
bool VulkanManager::InitAll(GLFWwindow* window) bool VulkanManager::InitAll(GLFWwindow* window)
{ {
if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance) if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
@@ -70,6 +76,18 @@ namespace PB::Renderer
return instance; return instance;
} }
bool VulkanManager::Cleanup()
{
if (s_Surface != std::nullopt)
vkDestroySurfaceKHR(s_Instance.value(), s_Surface.value(), nullptr);
if (s_Instance != std::nullopt)
vkDestroyInstance(s_Instance.value(), nullptr);
s_Instance = std::nullopt;
return true;
}
std::optional<VkSurfaceKHR> VulkanManager::CreateSurface(GLFWwindow* window) std::optional<VkSurfaceKHR> VulkanManager::CreateSurface(GLFWwindow* window)
{ {
if (s_Instance == std::nullopt) if (s_Instance == std::nullopt)
@@ -256,15 +274,134 @@ namespace PB::Renderer
return true; return true;
} }
bool VulkanManager::Cleanup() bool VulkanManager::CreateSwapChain(GLFWwindow* window)
{ {
if (s_Surface != std::nullopt) auto [capabilities, formats, presentModes] = QuerySwapChainSupport();
vkDestroySurfaceKHR(s_Instance.value(), s_Surface.value(), nullptr); auto [format, colorSpace] = ChooseSurfaceFormat(formats);
if (s_Instance != std::nullopt) const VkPresentModeKHR presentMode = ChoosePresentMode(presentModes);
vkDestroyInstance(s_Instance.value(), nullptr); s_SwapChainExtent = ChooseSwapExtent(capabilities, window);
uint32_t imageCount = capabilities.minImageCount + 1;
if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount)
imageCount = capabilities.maxImageCount;
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = s_Surface.value();
createInfo.minImageCount = imageCount;
createInfo.imageFormat = format;
createInfo.imageColorSpace = colorSpace;
createInfo.imageExtent = s_SwapChainExtent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
const uint32_t queueFamilyIndices[] =
{
s_QueueIndices.graphicsFamily.value(),
s_QueueIndices.presentFamily.value()
};
if (queueFamilyIndices[0] != queueFamilyIndices[1])
{
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else
{
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
}
createInfo.preTransform = capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (!vkCreateSwapchainKHR(s_Device, &createInfo, nullptr, &s_SwapChain))
{
std::cout << "PB::Renderer::VulkanManager::CreateSwapChain(): Failed to create swap chain" << std::endl;
return false;
}
vkGetSwapchainImagesKHR(s_Device, s_SwapChain, &imageCount, nullptr);
s_SwapChainImages.resize(imageCount);
vkGetSwapchainImagesKHR(s_Device, s_SwapChain, &imageCount, s_SwapChainImages.data());
s_SwapChainImageFormat = format;
s_Instance = std::nullopt;
return true; return true;
} }
SwapChainSupportDetails VulkanManager::QuerySwapChainSupport()
{
SwapChainSupportDetails details;
const VkSurfaceKHR surface = s_Surface.value();
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(s_PhysicalDevice, surface, &details.capabilities);
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(s_PhysicalDevice, surface, &formatCount, nullptr);
details.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(s_PhysicalDevice, surface, &formatCount, details.formats.data());
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(s_PhysicalDevice, surface, &presentModeCount, nullptr);
details.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(s_PhysicalDevice, surface, &presentModeCount, details.presentModes.data());
return details;
}
VkSurfaceFormatKHR VulkanManager::ChooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
{
for (const auto& format : availableFormats)
{
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
{
return format;
}
}
return availableFormats[0];
}
VkPresentModeKHR VulkanManager::ChoosePresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes)
{
for (const auto& mode : availablePresentModes)
{
if (mode == VK_PRESENT_MODE_MAILBOX_KHR)
{
return mode;
}
}
return VK_PRESENT_MODE_FIFO_KHR;
}
VkExtent2D VulkanManager::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
{
if (capabilities.currentExtent.width != UINT32_MAX)
{
return capabilities.currentExtent;
}
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));
actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));
return actualExtent;
}
} }

View File

@@ -15,6 +15,13 @@ namespace PB::Renderer
} }
}; };
struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
class VulkanManager class VulkanManager
{ {
public: public:
@@ -25,12 +32,18 @@ namespace PB::Renderer
static std::optional<VkSurfaceKHR> CreateSurface(GLFWwindow* window); static std::optional<VkSurfaceKHR> CreateSurface(GLFWwindow* window);
static bool PickPhysicalDevice(); static bool PickPhysicalDevice();
static bool CreateLogicalDevice(); static bool CreateLogicalDevice();
static bool CreateSwapChain(GLFWwindow* window);
private: private:
static bool IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface); static bool IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface);
static QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface); static QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface);
static bool CheckDeviceExtensionSupport(VkPhysicalDevice device); static bool CheckDeviceExtensionSupport(VkPhysicalDevice device);
static SwapChainSupportDetails QuerySwapChainSupport();
static VkSurfaceFormatKHR ChooseSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
static VkPresentModeKHR ChoosePresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
static VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
static std::optional<VkInstance> s_Instance; static std::optional<VkInstance> s_Instance;
static std::optional<VkSurfaceKHR> s_Surface; static std::optional<VkSurfaceKHR> s_Surface;
@@ -41,5 +54,11 @@ namespace PB::Renderer
static VkQueue s_GraphicsQueue; static VkQueue s_GraphicsQueue;
static VkQueue s_PresentQueue; static VkQueue s_PresentQueue;
static VkSwapchainKHR s_SwapChain;
static std::vector<VkImage> s_SwapChainImages;
static std::vector<VkImageView> s_SwapChainImageViews;
static VkFormat s_SwapChainImageFormat;
static VkExtent2D s_SwapChainExtent;
}; };
} }