mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-27 15:14:58 +00:00
193 lines
7.7 KiB
C++
193 lines
7.7 KiB
C++
#include "app/sdl3_app.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
|
|
namespace sdl3cpp::app {
|
|
|
|
void Sdl3App::CreateSwapChain() {
|
|
SwapChainSupportDetails support = QuerySwapChainSupport(physicalDevice_);
|
|
|
|
VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(support.formats);
|
|
VkPresentModeKHR presentMode = ChooseSwapPresentMode(support.presentModes);
|
|
VkExtent2D extent = ChooseSwapExtent(support.capabilities);
|
|
|
|
uint32_t imageCount = support.capabilities.minImageCount + 1;
|
|
if (support.capabilities.maxImageCount > 0 && imageCount > support.capabilities.maxImageCount) {
|
|
imageCount = support.capabilities.maxImageCount;
|
|
}
|
|
|
|
VkSwapchainCreateInfoKHR createInfo{};
|
|
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
createInfo.surface = surface_;
|
|
createInfo.minImageCount = imageCount;
|
|
createInfo.imageFormat = surfaceFormat.format;
|
|
createInfo.imageColorSpace = surfaceFormat.colorSpace;
|
|
createInfo.imageExtent = extent;
|
|
createInfo.imageArrayLayers = 1;
|
|
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
QueueFamilyIndices indices = FindQueueFamilies(physicalDevice_);
|
|
uint32_t queueFamilyIndices[] = {*indices.graphicsFamily, *indices.presentFamily};
|
|
if (indices.graphicsFamily != indices.presentFamily) {
|
|
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
createInfo.queueFamilyIndexCount = 2;
|
|
createInfo.pQueueFamilyIndices = queueFamilyIndices;
|
|
} else {
|
|
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
}
|
|
|
|
createInfo.preTransform = support.capabilities.currentTransform;
|
|
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
createInfo.presentMode = presentMode;
|
|
createInfo.clipped = VK_TRUE;
|
|
|
|
if (vkCreateSwapchainKHR(device_, &createInfo, nullptr, &swapChain_) != VK_SUCCESS) {
|
|
throw std::runtime_error("Failed to create swap chain");
|
|
}
|
|
|
|
vkGetSwapchainImagesKHR(device_, swapChain_, &imageCount, nullptr);
|
|
swapChainImages_.resize(imageCount);
|
|
vkGetSwapchainImagesKHR(device_, swapChain_, &imageCount, swapChainImages_.data());
|
|
|
|
swapChainImageFormat_ = surfaceFormat.format;
|
|
swapChainExtent_ = extent;
|
|
}
|
|
|
|
void Sdl3App::CreateImageViews() {
|
|
swapChainImageViews_.resize(swapChainImages_.size());
|
|
for (size_t i = 0; i < swapChainImages_.size(); ++i) {
|
|
VkImageViewCreateInfo viewInfo{};
|
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
viewInfo.image = swapChainImages_[i];
|
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
viewInfo.format = swapChainImageFormat_;
|
|
viewInfo.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
|
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
viewInfo.subresourceRange.levelCount = 1;
|
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
viewInfo.subresourceRange.layerCount = 1;
|
|
|
|
if (vkCreateImageView(device_, &viewInfo, nullptr, &swapChainImageViews_[i]) != VK_SUCCESS) {
|
|
throw std::runtime_error("Failed to create image views");
|
|
}
|
|
}
|
|
}
|
|
|
|
void Sdl3App::CreateRenderPass() {
|
|
VkAttachmentDescription colorAttachment{};
|
|
colorAttachment.format = swapChainImageFormat_;
|
|
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
|
|
VkAttachmentReference colorAttachmentRef{};
|
|
colorAttachmentRef.attachment = 0;
|
|
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
VkSubpassDescription subpass{};
|
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
subpass.colorAttachmentCount = 1;
|
|
subpass.pColorAttachments = &colorAttachmentRef;
|
|
|
|
VkSubpassDependency dependency{};
|
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
|
dependency.dstSubpass = 0;
|
|
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
dependency.srcAccessMask = 0;
|
|
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
|
|
VkRenderPassCreateInfo renderPassInfo{};
|
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
renderPassInfo.attachmentCount = 1;
|
|
renderPassInfo.pAttachments = &colorAttachment;
|
|
renderPassInfo.subpassCount = 1;
|
|
renderPassInfo.pSubpasses = &subpass;
|
|
renderPassInfo.dependencyCount = 1;
|
|
renderPassInfo.pDependencies = &dependency;
|
|
|
|
if (vkCreateRenderPass(device_, &renderPassInfo, nullptr, &renderPass_) != VK_SUCCESS) {
|
|
throw std::runtime_error("Failed to create render pass");
|
|
}
|
|
}
|
|
|
|
void Sdl3App::CleanupSwapChain() {
|
|
for (auto framebuffer : swapChainFramebuffers_) {
|
|
vkDestroyFramebuffer(device_, framebuffer, nullptr);
|
|
}
|
|
vkFreeCommandBuffers(device_, commandPool_,
|
|
static_cast<uint32_t>(commandBuffers_.size()), commandBuffers_.data());
|
|
for (auto& entry : graphicsPipelines_) {
|
|
vkDestroyPipeline(device_, entry.second, nullptr);
|
|
}
|
|
graphicsPipelines_.clear();
|
|
if (pipelineLayout_ != VK_NULL_HANDLE) {
|
|
vkDestroyPipelineLayout(device_, pipelineLayout_, nullptr);
|
|
pipelineLayout_ = VK_NULL_HANDLE;
|
|
}
|
|
vkDestroyRenderPass(device_, renderPass_, nullptr);
|
|
for (auto imageView : swapChainImageViews_) {
|
|
vkDestroyImageView(device_, imageView, nullptr);
|
|
}
|
|
vkDestroySwapchainKHR(device_, swapChain_, nullptr);
|
|
}
|
|
|
|
void Sdl3App::RecreateSwapChain() {
|
|
int width = 0;
|
|
int height = 0;
|
|
while (width == 0 || height == 0) {
|
|
SDL_GetWindowSize(window_, &width, &height);
|
|
SDL_Event event;
|
|
SDL_WaitEvent(&event);
|
|
}
|
|
vkDeviceWaitIdle(device_);
|
|
CleanupSwapChain();
|
|
CreateSwapChain();
|
|
CreateImageViews();
|
|
CreateRenderPass();
|
|
CreateGraphicsPipeline();
|
|
CreateFramebuffers();
|
|
CreateCommandBuffers();
|
|
framebufferResized_ = false;
|
|
}
|
|
|
|
VkSurfaceFormatKHR Sdl3App::ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
|
|
for (const auto& availableFormat : availableFormats) {
|
|
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
|
availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
|
return availableFormat;
|
|
}
|
|
}
|
|
return availableFormats[0];
|
|
}
|
|
|
|
VkPresentModeKHR Sdl3App::ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
|
|
for (const auto& availablePresentMode : availablePresentModes) {
|
|
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
|
return availablePresentMode;
|
|
}
|
|
}
|
|
return VK_PRESENT_MODE_FIFO_KHR;
|
|
}
|
|
|
|
VkExtent2D Sdl3App::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {
|
|
int width, height;
|
|
SDL_GetWindowSize(window_, &width, &height);
|
|
VkExtent2D actualExtent = {
|
|
static_cast<uint32_t>(std::clamp(width, static_cast<int>(capabilities.minImageExtent.width),
|
|
static_cast<int>(capabilities.maxImageExtent.width))),
|
|
static_cast<uint32_t>(std::clamp(height, static_cast<int>(capabilities.minImageExtent.height),
|
|
static_cast<int>(capabilities.maxImageExtent.height)))
|
|
};
|
|
return actualExtent;
|
|
}
|
|
|
|
} // namespace sdl3cpp::app
|