diff --git a/config/Sources.cmake b/config/Sources.cmake index 8fc0aa9a2605a629596e26d5eeb0772164e6ec7a..6fc477cc9552d0a9a8921151ca4435b894630755 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -50,10 +50,7 @@ set(vkcv_sources ${vkcv_include}/vkcv/QueueManager.hpp ${vkcv_source}/vkcv/QueueManager.cpp - - ${vkcv_source}/vkcv/Surface.hpp - ${vkcv_source}/vkcv/Surface.cpp - + ${vkcv_source}/vkcv/ImageLayoutTransitions.hpp ${vkcv_source}/vkcv/ImageLayoutTransitions.cpp diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 2894b7a191ce64b25f18cc4bad64b68e86978c8f..e102c266f141d238c1ccc6c41f1fbc5192585fc9 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -62,7 +62,6 @@ namespace vkcv Core() = delete; Result acquireSwapchainImage(); - void destroyTemporaryFramebuffers(); Context m_Context; @@ -80,11 +79,10 @@ namespace vkcv CommandResources m_CommandResources; SyncResources m_SyncResources; uint32_t m_currentSwapchainImageIndex; - std::vector<vk::Framebuffer> m_TemporaryFramebuffers; - + ImageHandle m_DepthImage; - std::function<void(int, int)> m_resizeHandle; + std::function<void(int, int)> e_resizeHandle; /** * recreates the swapchain @@ -234,14 +232,14 @@ namespace vkcv * @brief render a beautiful triangle */ void renderMesh( - const PassHandle renderpassHandle, - const PipelineHandle pipelineHandle, + const PassHandle &renderpassHandle, + const PipelineHandle &pipelineHandle, const uint32_t width, const uint32_t height, const size_t pushConstantSize, const void* pushConstantData, const std::vector<VertexBufferBinding> &vertexBufferBindings, - const BufferHandle indexBuffer, + const BufferHandle &indexBuffer, const size_t indexCount, const vkcv::ResourcesHandle resourceHandle, const size_t resourceDescriptorSetIndex); diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/SwapChain.hpp index 852a907e33f1a54dbbdc3e5c17b5fdc922503eed..c4ffae6350fc3631dd837d2900498acff47961a2 100644 --- a/include/vkcv/SwapChain.hpp +++ b/include/vkcv/SwapChain.hpp @@ -3,16 +3,25 @@ #include "Context.hpp" #include "vkcv/Window.hpp" -namespace vkcv { +namespace vkcv +{ class SwapChain final { private: - vk::SurfaceKHR m_surface; - vk::SwapchainKHR m_swapchain; - vk::SurfaceFormatKHR m_format; - vk::PresentModeKHR m_presentMode; + struct Surface + { + vk::SurfaceKHR handle; + std::vector<vk::SurfaceFormatKHR> formats; + vk::SurfaceCapabilitiesKHR capabilities; + std::vector<vk::PresentModeKHR> presentModes; + }; + Surface m_Surface; - uint32_t m_ImageCount; + vk::SwapchainKHR m_Swapchain; + vk::Format m_SwapchainFormat; + vk::ColorSpaceKHR m_SwapchainColorSpace; + vk::PresentModeKHR m_SwapchainPresentMode; + uint32_t m_SwapchainImageCount; /** * Constructor of a SwapChain object @@ -22,7 +31,13 @@ namespace vkcv { * @param swapchain to show images in the window * @param format */ - SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format, uint32_t imageCount, vk::PresentModeKHR presentMode); + // TODO: + SwapChain(const Surface &surface, + vk::SwapchainKHR swapchain, + vk::Format format, + vk::ColorSpaceKHR colorSpace, + vk::PresentModeKHR presentMode, + uint32_t imageCount) noexcept; public: SwapChain(const SwapChain &other) = default; @@ -40,13 +55,14 @@ namespace vkcv { * @return current surface */ [[nodiscard]] - vk::SurfaceKHR getSurface(); + vk::SurfaceKHR getSurface() const; + /** - * gets the current surface format - * @return gets the surface format + * gets the chosen swapchain format + * @return gets the chosen swapchain format */ [[nodiscard]] - vk::SurfaceFormatKHR getSurfaceFormat(); + vk::Format getSwapchainFormat() const; /** * creates a swap chain object out of the given window and the given context @@ -54,7 +70,7 @@ namespace vkcv { * @param context of the application * @return returns an object of swapChain */ - static SwapChain create(const Window &window, const Context &context, const vk::SurfaceKHR surface); + static SwapChain create(const Window &window, const Context &context); /** * Destructor of SwapChain @@ -71,7 +87,6 @@ namespace vkcv { * @param width * @param height */ - void recreateSwapchain( const Context &context, const Window &window, int width, int height); + void recreateSwapchain(const Context &context, const Window &window, int width, int height); }; - } diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index ec65f4dc23468b063bbbfa98afba4422b527f529..58c56dbad802331ffe7b3c42f172633f06c96837 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -8,16 +8,14 @@ int main(int argc, const char** argv) { const char* applicationName = "First Mesh"; - const int windowWidth = 800; - const int windowHeight = 600; vkcv::Window window = vkcv::Window::create( applicationName, - windowWidth, - windowHeight, + 800, + 600, true ); - vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); + vkcv::CameraManager cameraManager(window, window.getWidth(), window.getHeight()); window.initEvents(); @@ -112,9 +110,9 @@ int main(int argc, const char** argv) { //end of exemplary code const vkcv::PipelineConfig trianglePipelineDefinition( - triangleShaderProgram, - windowWidth, - windowHeight, + triangleShaderProgram, + UINT32_MAX, + UINT32_MAX, trianglePass, mesh.vertexGroups[0].vertexBuffer.attributes, { core.getDescriptorSetLayout(set, 0) }); @@ -149,6 +147,10 @@ int main(int argc, const char** argv) { auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { window.pollEvents(); + + if(window.getHeight() == 0 || window.getWidth() == 0) + continue; + core.beginFrame(); auto end = std::chrono::system_clock::now(); auto deltatime = end - start; @@ -159,8 +161,8 @@ int main(int argc, const char** argv) { core.renderMesh( trianglePass, trianglePipeline, - windowWidth, - windowHeight, + window.getWidth(), + window.getHeight(), sizeof(mvp), &mvp, vertexBufferBindings, diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index ad25e79a80ea4a66af76cd3a7102298dca7475a6..ad6a8756b57657800e873ace705e8b1a4a18eb97 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -13,7 +13,6 @@ #include "SamplerManager.hpp" #include "ImageManager.hpp" #include "DescriptorManager.hpp" -#include "Surface.hpp" #include "ImageLayoutTransitions.hpp" namespace vkcv @@ -32,14 +31,8 @@ namespace vkcv instanceExtensions, deviceExtensions ); - - const vk::SurfaceKHR surface = createSurface( - window.getWindow(), - context.getInstance(), - context.getPhysicalDevice() - ); - SwapChain swapChain = SwapChain::create(window, context, surface); + SwapChain swapChain = SwapChain::create(window, context); std::vector<vk::ImageView> imageViews; imageViews = createImageViews( context, swapChain); @@ -79,7 +72,7 @@ namespace vkcv m_ImageManager->m_core = this; - m_resizeHandle = window.e_resize.add( [&](int width, int height) { recreateSwapchain( width ,height ); }); + e_resizeHandle = window.e_resize.add( [&](int width, int height) { recreateSwapchain( width ,height ); }); } Core::~Core() noexcept { @@ -90,7 +83,6 @@ namespace vkcv destroyCommandResources(m_Context.getDevice(), m_CommandResources); destroySyncResources(m_Context.getDevice(), m_SyncResources); - destroyTemporaryFramebuffers(); m_Context.m_Device.destroySwapchainKHR(m_swapchain.getSwapchain()); m_Context.m_Instance.destroySurfaceKHR(m_swapchain.getSurface()); @@ -126,37 +118,22 @@ namespace vkcv return Result::SUCCESS; } - void Core::destroyTemporaryFramebuffers() { - for (const vk::Framebuffer f : m_TemporaryFramebuffers) { - m_Context.getDevice().destroyFramebuffer(f); - } - m_TemporaryFramebuffers.clear(); - } - void Core::beginFrame() { if (acquireSwapchainImage() != Result::SUCCESS) { return; } - m_Context.getDevice().waitIdle(); // FIMXE: this is a sin against graphics programming, but its getting late - Alex - destroyTemporaryFramebuffers(); - } - - vk::Framebuffer createFramebuffer(const vk::Device device, const vk::RenderPass& renderpass, - const int width, const int height, const std::vector<vk::ImageView>& attachments) { - const vk::FramebufferCreateFlags flags = {}; - const vk::FramebufferCreateInfo createInfo(flags, renderpass, attachments.size(), attachments.data(), width, height, 1); - return device.createFramebuffer(createInfo); + m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but its getting late - Alex } void Core::renderMesh( - const PassHandle renderpassHandle, - const PipelineHandle pipelineHandle, + const PassHandle &renderpassHandle, + const PipelineHandle &pipelineHandle, const uint32_t width, const uint32_t height, - const size_t pushConstantSize, + const size_t pushConstantSize, const void *pushConstantData, const std::vector<VertexBufferBinding>& vertexBufferBindings, - const BufferHandle indexBuffer, + const BufferHandle &indexBuffer, const size_t indexCount, const vkcv::ResourcesHandle resourceHandle, const size_t resourceDescriptorSetIndex @@ -197,15 +174,25 @@ namespace vkcv attachments.push_back(m_ImageManager->getVulkanImageView(m_DepthImage)); } - const vk::Framebuffer framebuffer = createFramebuffer( - m_Context.getDevice(), - renderpass, - width, - height, - attachments - ); - - m_TemporaryFramebuffers.push_back(framebuffer); + vk::Framebuffer framebuffer = nullptr; + const vk::FramebufferCreateInfo createInfo({}, + renderpass, + static_cast<uint32_t>(attachments.size()), + attachments.data(), + width, + height, + 1); + if(m_Context.m_Device.createFramebuffer(&createInfo, nullptr, &framebuffer) != vk::Result::eSuccess) + { + std::cout << "FAILED TO CREATE TEMPORARY FRAMEBUFFER!" << std::endl; + return; + } + + vk::Viewport dynamicViewport(0.0f, 0.0f, + static_cast<float>(width), static_cast<float>(height), + 0.0f, 1.0f); + + vk::Rect2D dynamicScissor({0, 0}, {width, height}); auto &bufferManager = m_BufferManager; @@ -213,48 +200,58 @@ namespace vkcv submitInfo.queueType = QueueType::Graphics; submitInfo.signalSemaphores = { m_SyncResources.renderFinished }; - submitCommands(submitInfo, [&](const vk::CommandBuffer& cmdBuffer) { - std::vector<vk::ClearValue> clearValues; - - for (const auto& attachment : passConfig.attachments) { - if (attachment.load_operation == AttachmentOperation::CLEAR) { - float clear = 0.0f; - - if (attachment.layout_final == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) { - clear = 1.0f; - } - - clearValues.emplace_back(std::array<float, 4>{ - clear, - clear, - clear, - 1.f - }); - } - } - - const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(), clearValues.data()); - const vk::SubpassContents subpassContents = {}; - cmdBuffer.beginRenderPass(beginInfo, subpassContents, {}); + auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { + std::vector<vk::ClearValue> clearValues; + + for (const auto& attachment : passConfig.attachments) { + if (attachment.load_operation == AttachmentOperation::CLEAR) { + float clear = 0.0f; + + if (attachment.layout_final == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) { + clear = 1.0f; + } + + clearValues.emplace_back(std::array<float, 4>{ + clear, + clear, + clear, + 1.f + }); + } + } + + const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(), clearValues.data()); + const vk::SubpassContents subpassContents = {}; + cmdBuffer.beginRenderPass(beginInfo, subpassContents, {}); + + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); + cmdBuffer.setViewport(0, 1, &dynamicViewport); + cmdBuffer.setScissor(0, 1, &dynamicScissor); + + for (uint32_t i = 0; i < vertexBufferBindings.size(); i++) { + const auto &vertexBinding = vertexBufferBindings[i]; + const auto vertexBuffer = bufferManager->getBuffer(vertexBinding.buffer); + cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset)); + } + + if (resourceHandle) { + const vk::DescriptorSet descriptorSet = m_DescriptorManager->getDescriptorSet(resourceHandle, resourceDescriptorSetIndex); + cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, descriptorSet, nullptr); + } + + cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size + cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData); + cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {}); + cmdBuffer.endRenderPass(); + }; + + auto finishFunction = [&]() + { + m_Context.m_Device.destroy(framebuffer); + }; - cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); + submitCommands(submitInfo, submitFunction, finishFunction); - for (uint32_t i = 0; i < vertexBufferBindings.size(); i++) { - const auto &vertexBinding = vertexBufferBindings[i]; - const auto vertexBuffer = bufferManager->getBuffer(vertexBinding.buffer); - cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset)); - } - - if (resourceHandle) { - const vk::DescriptorSet descriptorSet = m_DescriptorManager->getDescriptorSet(resourceHandle, resourceDescriptorSetIndex); - cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, descriptorSet, nullptr); - } - - cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size - cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData); - cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {}); - cmdBuffer.endRenderPass(); - }, nullptr); } void Core::endFrame() { @@ -263,8 +260,7 @@ namespace vkcv } const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain()); - const vk::Image presentImage = swapchainImages[m_currentSwapchainImageIndex]; - + const auto& queueManager = m_Context.getQueueManager(); std::array<vk::Semaphore, 2> waitSemaphores{ m_SyncResources.renderFinished, @@ -284,17 +280,17 @@ namespace vkcv } vk::Format Core::getSwapchainImageFormat() { - return m_swapchain.getSurfaceFormat().format; + return m_swapchain.getSwapchainFormat(); } void Core::recreateSwapchain( int width, int height) { m_Context.getDevice().waitIdle(); - destroyTemporaryFramebuffers(); + if(width == 0 || height == 0) + return; - for (auto image : m_swapchainImageViews) { + for (auto image : m_swapchainImageViews) m_Context.m_Device.destroyImageView(image); - } m_swapchain.recreateSwapchain(m_Context, m_window, width, height); m_swapchainImageViews = createImageViews(m_Context, m_swapchain); @@ -372,7 +368,7 @@ namespace vkcv vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, - swapChain.getSurfaceFormat().format, + swapChain.getSwapchainFormat(), componentMapping, subResourceRange ); diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp index 1b866c05d4a12c9bf28d08178438cb3a1ff70a3c..344e541c842b2c9fb2472fadee43a59b6f652ae4 100644 --- a/src/vkcv/PipelineManager.cpp +++ b/src/vkcv/PipelineManager.cpp @@ -94,8 +94,8 @@ namespace vkcv //FIXME: hoping that order is the same and compatible: add explicit mapping and validation const VertexAttribute attribute = config.m_vertexAttributes[i]; - vertexAttributeDescriptions.push_back({location, binding, vertexFormatToVulkanFormat(attachment.format), 0}); - vertexBindingDescriptions.push_back(vk::VertexInputBindingDescription( + vertexAttributeDescriptions.emplace_back(location, binding, vertexFormatToVulkanFormat(attachment.format), 0); + vertexBindingDescriptions.emplace_back(vk::VertexInputBindingDescription( binding, attribute.stride + getFormatSize(attachment.format), vk::VertexInputRate::eVertex)); @@ -211,8 +211,19 @@ namespace vkcv break; } } - - // graphics pipeline create + + std::vector<vk::DynamicState> dynamicStates = {}; + if(config.m_Width == UINT32_MAX && config.m_Height == UINT32_MAX) + { + dynamicStates.push_back(vk::DynamicState::eViewport); + dynamicStates.push_back(vk::DynamicState::eScissor); + } + + vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo({}, + static_cast<uint32_t>(dynamicStates.size()), + dynamicStates.data()); + + // graphics pipeline create std::vector<vk::PipelineShaderStageCreateInfo> shaderStages = { pipelineVertexShaderStageInfo, pipelineFragmentShaderStageInfo }; const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( {}, @@ -226,7 +237,7 @@ namespace vkcv &pipelineMultisampleStateCreateInfo, p_depthStencilCreateInfo, &pipelineColorBlendStateCreateInfo, - nullptr, + &dynamicStateCreateInfo, vkPipelineLayout, pass, 0, diff --git a/src/vkcv/Surface.cpp b/src/vkcv/Surface.cpp deleted file mode 100644 index 29b6c646dc212cba2cc31f32dca5c4fcc023cd03..0000000000000000000000000000000000000000 --- a/src/vkcv/Surface.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "Surface.hpp" - -#define GLFW_INCLUDE_VULKAN -#include <GLFW/glfw3.h> - -namespace vkcv { - /** - * creates surface and checks availability - * @param window current window for the surface - * @param instance Vulkan-Instance - * @param physicalDevice Vulkan-PhysicalDevice - * @return created surface - */ - vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice) { - //create surface - VkSurfaceKHR surface; - if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) { - throw std::runtime_error("failed to create a window surface!"); - } - vk::Bool32 surfaceSupport = false; - if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) { - throw std::runtime_error("surface is not supported by the device!"); - } - - return vk::SurfaceKHR(surface); - } -} diff --git a/src/vkcv/Surface.hpp b/src/vkcv/Surface.hpp deleted file mode 100644 index 74aafeba821334767ac5e13cd33e1d9674e12f5b..0000000000000000000000000000000000000000 --- a/src/vkcv/Surface.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include <vulkan/vulkan.hpp> - -struct GLFWwindow; - -namespace vkcv { - vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice); -} \ No newline at end of file diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/SwapChain.cpp index ce874c8646ac740ad38528fa361444a3082bbd24..2a40eba44a1ab85eb5aa835ae97bc4cae5c0a7a6 100644 --- a/src/vkcv/SwapChain.cpp +++ b/src/vkcv/SwapChain.cpp @@ -1,29 +1,56 @@ #include <vkcv/SwapChain.hpp> +#include <utility> -namespace vkcv { +#define GLFW_INCLUDE_VULKAN +#include <GLFW/glfw3.h> - SwapChain::SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format, uint32_t imageCount, vk::PresentModeKHR presentMode) - : m_surface(surface), m_swapchain(swapchain), m_format( format), m_ImageCount(imageCount), m_presentMode(presentMode) +namespace vkcv +{ + /** + * creates surface and checks availability + * @param window current window for the surface + * @param instance Vulkan-Instance + * @param physicalDevice Vulkan-PhysicalDevice + * @return created surface + */ + vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice) { + //create surface + VkSurfaceKHR surface; + if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) { + throw std::runtime_error("failed to create a window surface!"); + } + vk::Bool32 surfaceSupport = false; + if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) { + throw std::runtime_error("surface is not supported by the device!"); + } + + return vk::SurfaceKHR(surface); + } + + SwapChain::SwapChain(const Surface &surface, + vk::SwapchainKHR swapchain, + vk::Format format, + vk::ColorSpaceKHR colorSpace, + vk::PresentModeKHR presentMode, + uint32_t imageCount) noexcept : + m_Surface(surface), + m_Swapchain(swapchain), + m_SwapchainFormat(format), + m_SwapchainColorSpace(colorSpace), + m_SwapchainPresentMode(presentMode), + m_SwapchainImageCount(imageCount) {} const vk::SwapchainKHR& SwapChain::getSwapchain() const { - return m_swapchain; + return m_Swapchain; } - /** - * gets surface of the swapchain - * @return current surface - */ - vk::SurfaceKHR SwapChain::getSurface() { - return m_surface; + vk::SurfaceKHR SwapChain::getSurface() const { + return m_Surface.handle; } - /** - * gets the surface of the swapchain - * @return chosen format - */ - vk::SurfaceFormatKHR SwapChain::getSurfaceFormat(){ - return m_format; + vk::Format SwapChain::getSwapchainFormat() const{ + return m_SwapchainFormat; } /** @@ -33,7 +60,7 @@ namespace vkcv { * @param window of the current application * @return chosen Extent for the surface */ - vk::Extent2D chooseSwapExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window){ + vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window){ vk::SurfaceCapabilitiesKHR surfaceCapabilities; if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){ throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface."); @@ -46,12 +73,6 @@ namespace vkcv { extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); - if (extent2D.width > surfaceCapabilities.maxImageExtent.width || - extent2D.width < surfaceCapabilities.minImageExtent.width || - extent2D.height > surfaceCapabilities.maxImageExtent.height || - extent2D.height < surfaceCapabilities.minImageExtent.height) { - std::printf("Surface size not matching. Resizing to allowed value."); - } return extent2D; } @@ -61,7 +82,7 @@ namespace vkcv { * @param surface of the swapchain * @return available Format */ - vk::SurfaceFormatKHR chooseSwapSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { + vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { uint32_t formatCount; physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, nullptr); std::vector<vk::SurfaceFormatKHR> availableFormats(formatCount); @@ -126,23 +147,29 @@ namespace vkcv { * @param context that keeps instance, physicalDevice and a device. * @return swapchain */ - SwapChain SwapChain::create(const Window &window, const Context &context, const vk::SurfaceKHR surface) { + SwapChain SwapChain::create(const Window &window, const Context &context) { const vk::Instance& instance = context.getInstance(); const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); const vk::Device& device = context.getDevice(); - vk::Extent2D extent2D = chooseSwapExtent(physicalDevice, surface, window); - vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(physicalDevice, surface); - vk::PresentModeKHR presentMode = choosePresentMode(physicalDevice, surface); - uint32_t imageCount = chooseImageCount(physicalDevice, surface); + Surface surface; + surface.handle = createSurface(window.getWindow(), instance, physicalDevice); + surface.formats = physicalDevice.getSurfaceFormatsKHR(surface.handle); + surface.capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.handle); + surface.presentModes = physicalDevice.getSurfacePresentModesKHR(surface.handle); + + vk::Extent2D chosenExtent = chooseExtent(physicalDevice, surface.handle, window); + vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, surface.handle); + vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, surface.handle); + uint32_t chosenImageCount = chooseImageCount(physicalDevice, surface.handle); vk::SwapchainCreateInfoKHR swapchainCreateInfo( vk::SwapchainCreateFlagsKHR(), //flags - surface, // surface - imageCount, // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" -> 3 for Triple Buffering, else 2 for Double Buffering (should be the standard) - surfaceFormat.format, // imageFormat - surfaceFormat.colorSpace, // imageColorSpace - extent2D, // imageExtent + surface.handle, // surface + chosenImageCount, // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" -> 3 for Triple Buffering, else 2 for Double Buffering (should be the standard) + chosenSurfaceFormat.format, // imageFormat + chosenSurfaceFormat.colorSpace, // imageColorSpace + chosenExtent, // imageExtent 1, // imageArrayLayers TODO: should we only allow non-stereoscopic applications? yes -> 1, no -> ? "must be greater than 0, less or equal to maxImageArrayLayers" vk::ImageUsageFlagBits::eColorAttachment, // imageUsage TODO: what attachments? only color? depth? vk::SharingMode::eExclusive, // imageSharingMode TODO: which sharing mode? "VK_SHARING_MODE_EXCLUSIV access exclusive to a single queue family, better performance", "VK_SHARING_MODE_CONCURRENT access from multiple queues" @@ -150,26 +177,31 @@ namespace vkcv { nullptr, // pQueueFamilyIndices, the pointer to an array of queue family indices having access to the images(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT vk::SurfaceTransformFlagBitsKHR::eIdentity, // preTransform, transformations applied onto the image before display vk::CompositeAlphaFlagBitsKHR::eOpaque, // compositeAlpha, TODO: how to handle transparent pixels? do we need transparency? If no -> opaque - presentMode, // presentMode + chosenPresentMode, // presentMode true, // clipped nullptr // oldSwapchain ); vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo); - return SwapChain(surface, swapchain, surfaceFormat, imageCount, presentMode); + return SwapChain(surface, + swapchain, + chosenSurfaceFormat.format, + chosenSurfaceFormat.colorSpace, + chosenPresentMode, + chosenImageCount); } void SwapChain::recreateSwapchain( const Context &context, const Window &window, int width, int height){ - vk::SwapchainKHR oldSwapchain = m_swapchain; - vk::Extent2D extent2D = chooseSwapExtent(context.getPhysicalDevice(), m_surface, window); + vk::SwapchainKHR oldSwapchain = m_Swapchain; + vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window); vk::SwapchainCreateInfoKHR swapchainCreateInfo( vk::SwapchainCreateFlagsKHR(), - m_surface, - m_ImageCount, - m_format.format, - m_format.colorSpace, + m_Surface.handle, + m_SwapchainImageCount, + m_SwapchainFormat, + m_SwapchainColorSpace, extent2D, 1, vk::ImageUsageFlagBits::eColorAttachment, @@ -178,11 +210,11 @@ namespace vkcv { nullptr, vk::SurfaceTransformFlagBitsKHR::eIdentity, vk::CompositeAlphaFlagBitsKHR::eOpaque, - m_presentMode, + m_SwapchainPresentMode, true, oldSwapchain ); - m_swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo); + m_Swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo); } @@ -191,6 +223,6 @@ namespace vkcv { } uint32_t SwapChain::getImageCount() { - return m_ImageCount; + return m_SwapchainImageCount; } }