diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 08991c6083ce433a0eb27aa439f8645805c8fa0d..f27ca4cc13365731218254dc69ce975f6d45c096 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -95,7 +95,6 @@ namespace vkcv * * @param[in] applicationName Name of the application * @param[in] applicationVersion Version of the application - * @param[in] queueCount (optional) Amount of queues which is requested * @param[in] queueFlags (optional) Requested flags of queues * @param[in] instanceExtensions (optional) Requested instance extensions * @param[in] deviceExtensions (optional) Requested device extensions @@ -104,7 +103,6 @@ namespace vkcv static Core create(const Window &window, const char *applicationName, uint32_t applicationVersion, - uint32_t queueCount, std::vector<vk::QueueFlagBits> queueFlags = {}, std::vector<const char*> instanceExtensions = {}, std::vector<const char*> deviceExtensions = {}); diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/SwapChain.hpp index 5dad2d95cd9e853af0382ec8c1e5af8be484e5a6..15633badd4c6a3aef9766049317f3f5c8382bab8 100644 --- a/include/vkcv/SwapChain.hpp +++ b/include/vkcv/SwapChain.hpp @@ -4,24 +4,25 @@ #include "vkcv/Window.hpp" #include <iostream> - -// glfw is not initialized in this class because ist must be sure that there exists a context first -// glfw is already initialized by the context or the window class - namespace vkcv { class SwapChain final { private: vk::SurfaceKHR m_surface; - const vkcv::Context& m_context; - vk::SwapchainKHR m_swapchain; - vk::SurfaceFormatKHR m_format; - - SwapChain(vk::SurfaceKHR surface, const vkcv::Context &context, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format); + vk::SwapchainKHR m_swapchain; + vk::SurfaceFormatKHR m_format; + + /** + * Constructor of a SwapChain object + * glfw is not initialized in this class because ist must be sure that there exists a context first + * glfw is already initialized by the window class + * @param surface used by the swapchain + * @param swapchain to show images in the window + * @param format + */ + SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format); public: - // bin mir grade unsicher wegen der Mehrfachinstanziierung der Klasse - // es muessen ja oefter mal neue erstellt werden, aber diese existieren ja nicht gleichzeitig, oder? SwapChain(const SwapChain &other) = default; SwapChain(SwapChain &&other) = default; @@ -32,13 +33,30 @@ namespace vkcv { [[nodiscard]] vk::SwapchainKHR getSwapchain(); + /** + * gets the current surface object + * @return current surface + */ [[nodiscard]] vk::SurfaceKHR getSurface(); - + /** + * gets the current surface format + * @return gets the surface format + */ [[nodiscard]] vk::SurfaceFormatKHR getSurfaceFormat(); + /** + * creates a swap chain object out of the given window and the given context + * @param window a wrapper that represents a glfw window + * @param context of the application + * @return returns an object of swapChain + */ static SwapChain create(const Window &window, const Context &context); + + /** + * Destructor of SwapChain + */ virtual ~SwapChain(); }; diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 53bea036f235716f917bb77e80e772566569ad94..5cafedcaf0af5ca82cc10be357b5a8afb9d9d3ed 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -17,8 +17,7 @@ int main(int argc, const char** argv) { window, applicationName, VK_MAKE_VERSION(0, 0, 1), - 20, - {vk::QueueFlagBits::eTransfer}, + {vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, {}, {"VK_KHR_swapchain"} ); diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index 816fded86405cc36d997c2f48a57be18b36f6cab..761add2c9c0792bbf098c1f7f6122e84978a6735 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -36,7 +36,6 @@ namespace vkcv Context::~Context() noexcept { - std::cout<< " Context " << std::endl; m_Device.destroy(); m_Instance.destroy(); } diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 9635f2a4e1ae272f25ff4b642a43d955ae8cdadc..c4a473801b2558cb21cc0f958c84746efc145dc2 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -123,49 +123,169 @@ namespace vkcv /** - * @brief Creates a candidate list of queues that all meet the desired flags and then creates the maximum possible number - * of queues. If the number of desired queues is not sufficient, the remaining queues are created from the next - * candidate from the list. - * @param physicalDevice The physical device - * @param queueCount The amount of queues to be created - * @param qPriorities - * @param queueFlags The abilities which have to be supported by any created queue - * @return - */ - std::vector<vk::DeviceQueueCreateInfo> getQueueCreateInfos(vk::PhysicalDevice& physicalDevice, - uint32_t queueCount, - std::vector<float> &qPriorities, - std::vector<vk::QueueFlagBits>& queueFlags) + * Given the @p physicalDevice and the @p queuePriorities, the @p queueCreateInfos are computed. First, the requested + * queues are sorted by priority depending on the availability of queues in the queue families of the given + * @p physicalDevice. Then check, if all requested queues are creatable. If so, the @p queueCreateInfos will be computed. + * Furthermore, lists of index pairs (queueFamilyIndex, queueIndex) for later referencing of the separate queues will + * be computed. + * @param[in] physicalDevice The physical device + * @param[in] queuePriorities The queue priorities used for the computation of @p queueCreateInfos + * @param[in] queueFlags The queue flags requesting the queues + * @param[in,out] queueCreateInfos The queue create info structures to be created + * @param[in,out] queuePairsGraphics The list of index pairs (queueFamilyIndex, queueIndex) of queues of type + * vk::QueueFlagBits::eGraphics + * @param[in,out] queuePairsCompute The list of index pairs (queueFamilyIndex, queueIndex) of queues of type + * vk::QueueFlagBits::eCompute + * @param[in,out] queuePairsTransfer The list of index pairs (queueFamilyIndex, queueIndex) of queues of type + * vk::QueueFlagBits::eTransfer + * @throws std::runtime_error If the requested queues from @p queueFlags are not creatable due to insufficient availability. + */ + void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice, + std::vector<float> &queuePriorities, + std::vector<vk::QueueFlagBits> &queueFlags, + std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos, + std::vector<std::pair<int, int>> &queuePairsGraphics, + std::vector<std::pair<int, int>> &queuePairsCompute, + std::vector<std::pair<int, int>> &queuePairsTransfer) { - std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos; + queueCreateInfos = {}; + queuePairsGraphics = {}; + queuePairsCompute = {}; + queuePairsTransfer = {}; std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); - std::vector<vk::QueueFamilyProperties> qFamilyCandidates; - // search for queue families which support the desired queue flag bits - for (auto& qFamily : qFamilyProperties) { - bool supported = true; - for (auto qFlag : queueFlags) { - supported = supported && (static_cast<uint32_t>(qFlag & qFamily.queueFlags) != 0); + // DEBUG + std::cout << "Input queue flags:" << std::endl; + for (auto qFlag : queueFlags) { + std::cout << "\t" << to_string(qFlag) << std::endl; + } + + //check priorities of flags -> the lower prioCount the higher the priority + std::vector<int> prios; + for(auto flag: queueFlags){ + int prioCount = 0; + for (int i = 0; i < qFamilyProperties.size(); i++) { + prioCount += (static_cast<uint32_t>(flag & qFamilyProperties[i].queueFlags) != 0) * qFamilyProperties[i].queueCount; } - if (supported) { - qFamilyCandidates.push_back(qFamily); + prios.push_back(prioCount); + std::cout<< "prio Count: " << prioCount << std::endl; + } + //resort flags with heighest priority before allocating the queues + std::vector<vk::QueueFlagBits> newFlags; + for(int i = 0; i < prios.size(); i++){ + auto minElem = std::min_element(prios.begin(), prios.end()); + int index = minElem - prios.begin(); + std::cout << "index: "<< index << std::endl; + newFlags.push_back(queueFlags[index]); + prios[index] = std::numeric_limits<int>::max(); + } + + std::cout << "Sorted queue flags:" << std::endl; + for (auto qFlag : newFlags) { + std::cout << "\t" << to_string(qFlag) << std::endl; + } + + // create requested queues and check if more requested queues are supported + // herefore: create vector that updates available queues in each queue family + // structure: [qFamily_0, ..., qFamily_n] where + // - qFamily_i = [GraphicsCount, ComputeCount, TransferCount], 0 <= i <= n + std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus; + + for (auto qFamily : qFamilyProperties) { + int graphicsCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0) * qFamily.queueCount; + int computeCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0) * qFamily.queueCount;; + int transferCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0) * qFamily.queueCount;; + queueFamilyStatus.push_back({graphicsCount, computeCount, transferCount}); + } + + initialQueueFamilyStatus = queueFamilyStatus; + + // check if every queue with the specified queue flag can be created + // this automatically checks for queue flag support! + for (auto qFlag : newFlags) { + bool found; + switch (qFlag) { + case vk::QueueFlagBits::eGraphics: + found = false; + for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + if (queueFamilyStatus[i][0] > 0) { + queuePairsGraphics.push_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0])); + queueFamilyStatus[i][0]--; + queueFamilyStatus[i][1]--; + queueFamilyStatus[i][2]--; + std::cout << "Graphics queue available at queue family #" << i << std::endl; + found = true; + } + } + if (!found) { + throw std::runtime_error("Too many graphics queues were requested than being available!"); + } + break; + case vk::QueueFlagBits::eCompute: + found = false; + for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + if (queueFamilyStatus[i][1] > 0) { + queuePairsCompute.push_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1])); + queueFamilyStatus[i][0]--; + queueFamilyStatus[i][1]--; + queueFamilyStatus[i][2]--; + std::cout << "Compute queue available at queue family #" << i << std::endl; + found = true; + } + } + if (!found) { + throw std::runtime_error("Too many compute queues were requested than being available!"); + } + break; + case vk::QueueFlagBits::eTransfer: + found = false; + for (int i = 0; i < queueFamilyStatus.size() && !found; i++) { + if (queueFamilyStatus[i][2] > 0) { + queuePairsTransfer.push_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2])); + queueFamilyStatus[i][0]--; + queueFamilyStatus[i][1]--; + queueFamilyStatus[i][2]--; + std::cout << "Transfer queue available at queue family #" << i << std::endl; + found = true; + } + } + if (!found) { + throw std::runtime_error("Too many transfer queues were requested than being available!"); + } + break; + default: + throw std::runtime_error("Invalid input for queue flag bits. Valid inputs are 'vk::QueueFlagBits::eGraphics', 'vk::QueueFlagBits::eCompute' and 'vk::QueueFlagBits::eTransfer'."); } } - uint32_t create = queueCount; - for (uint32_t i = 0; i < qFamilyCandidates.size() && create > 0; i++) { - const uint32_t maxCreatableQueues = std::min(create, qFamilyCandidates[i].queueCount); - vk::DeviceQueueCreateInfo qCreateInfo( - vk::DeviceQueueCreateFlags(), - i, - maxCreatableQueues, - qPriorities.data() - ); - queueCreateInfos.push_back(qCreateInfo); - create -= maxCreatableQueues; + std::cout << "Initial queue status:" << std::endl; + int x = 0; + for (std::vector<int> e : initialQueueFamilyStatus) { + std::cout << "#" << x << ":\t[" << e[0] << ", " << e[1] << ", " << e[2] << "]" << std::endl; + x++; + } + + std::cout << "Actual queue status:" << std::endl; + x = 0; + for (std::vector<int> e : queueFamilyStatus) { + std::cout << "#" << x << ":\t[" << e[0] << ", " << e[1] << ", " << e[2] << "]" << std::endl; + x++; } - return queueCreateInfos; + // create all requested queues + for (int i = 0; i < qFamilyProperties.size(); i++) { + uint32_t create = std::abs(initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]); + std::cout << "For Queue Family #" << i << " create " << create << " queues" << std::endl; + if (create > 0) { + vk::DeviceQueueCreateInfo qCreateInfo( + vk::DeviceQueueCreateFlags(), + i, + create, + queuePriorities.data() + ); + queueCreateInfos.push_back(qCreateInfo); + } + } } /** @@ -205,28 +325,24 @@ namespace vkcv } /** - * @brief finds an queue family index that fits with the given queue flags to create a queue handle - * @param flag The given flag that specifies as which queue type the accessed queue should be treated - * @param createInfos The createInfos of the created queues depending on the logical device - * @param device The physical with which the queue families can be accessed - * @return a fitting queue family index + * Computes the queue handles from @p queuePairs + * @param queuePairs The queuePairs that were created separately for each queue type (e.g., vk::QueueFlagBits::eGraphics) + * @param device The device + * @return An array of queue handles based on the @p queuePairs */ - int findQueueFamilyIndex(vk::QueueFlagBits flag, std::vector<vk::DeviceQueueCreateInfo> &createInfos, vk::PhysicalDevice &device){ - std::vector<vk::QueueFamilyProperties> queueFamilyProperties = device.getQueueFamilyProperties(); - for (auto i = createInfos.begin(); i != createInfos.end(); ++i ) { - auto createInfo = *i; - int index = createInfo.queueFamilyIndex; - if(static_cast<uint32_t>(queueFamilyProperties[index].queueFlags & flag) != 0){ - return index; - } + std::vector<vk::Queue> getQueueHandles(const std::vector<std::pair<int, int>> queuePairs, const vk::Device device) { + std::vector<vk::Queue> queueHandles; + for (auto q : queuePairs) { + int queueFamilyIndex = q.first; // the queueIndex of the queue family + int queueIndex = q.second; // the queueIndex within a queue family + queueHandles.push_back(device.getQueue(queueFamilyIndex, queueIndex)); } - return -1; + return queueHandles; } Core Core::create(const Window &window, const char *applicationName, uint32_t applicationVersion, - uint32_t queueCount, std::vector<vk::QueueFlagBits> queueFlags, std::vector<const char *> instanceExtensions, std::vector<const char *> deviceExtensions) @@ -310,10 +426,12 @@ namespace vkcv //vector to define the queue priorities std::vector<float> qPriorities; - qPriorities.resize(queueCount, 1.f); // all queues have the same priorities + qPriorities.resize(queueFlags.size(), 1.f); // all queues have the same priorities // create required queues - std::vector<vk::DeviceQueueCreateInfo> qCreateInfos = getQueueCreateInfos(physicalDevice, queueCount, qPriorities,queueFlags); + std::vector<vk::DeviceQueueCreateInfo> qCreateInfos; + std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer; + queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); vk::DeviceCreateInfo deviceCreateInfo( vk::DeviceCreateFlags(), @@ -334,32 +452,24 @@ namespace vkcv vk::Device device = physicalDevice.createDevice(deviceCreateInfo); - uint32_t graphicsQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eGraphics}, qCreateInfos, physicalDevice); - if(graphicsQueueFamilyIndex == -1){ - throw std::runtime_error("It is not possible to access another queue as a graphics queue."); - } - uint32_t computeQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eCompute}, qCreateInfos, physicalDevice); - if(computeQueueFamilyIndex == -1){ - throw std::runtime_error("It is not possible to access another queue as a compute queue."); - } - uint32_t transferQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eTransfer}, qCreateInfos, physicalDevice); - if(transferQueueFamilyIndex == -1){ - throw std::runtime_error("It is not possible to access another queue as a transfer queue."); - } - vk::Queue graphicsQueue = device.getQueue( graphicsQueueFamilyIndex, 0 ); - vk::Queue computeQueue = device.getQueue(computeQueueFamilyIndex,1); - vk::Queue transferQueue = device.getQueue(transferQueueFamilyIndex,2); + // maybe it can be useful to store these lists as member variable of Core + std::vector<vk::Queue> graphicsQueues = getQueueHandles(queuePairsGraphics, device); + std::vector<vk::Queue> computeQueues = getQueueHandles(queuePairsCompute, device); + std::vector<vk::Queue> transferQueues = getQueueHandles(queuePairsTransfer, device); + + // examples for accessing queues + vk::Queue graphicsQueue = graphicsQueues[0]; + vk::Queue computeQueue = computeQueues[0]; + vk::Queue transferQueue = transferQueues[0]; Context context(instance, physicalDevice, device); SwapChain swapChain = SwapChain::create(window, context); - std::vector<vk::Image> swapChainImages = device.getSwapchainImagesKHR(swapChain.getSwapchain()); std::vector<vk::ImageView> imageViews; imageViews.reserve( swapChainImages.size() ); //here can be swizzled with vk::ComponentSwizzle if needed - // ToDo: we need the format from the surface object vk::ComponentMapping componentMapping( vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, @@ -600,38 +710,37 @@ namespace vkcv vk::AttachmentReference depthAttachmentReference{}; vk::AttachmentReference *pDepthAttachment = nullptr; //stays nullptr if no depth attachment used - for(uint32_t i = 0; i < pass.attachments.size(); i++) - { - // TODO: Renderpass struct should hold proper format information - vk::Format format; + for (uint32_t i = 0; i < pass.attachments.size(); i++) + { + // TODO: Renderpass struct should hold proper format information + vk::Format format; - if(pass.attachments[i].layout_in_pass == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) - { - format = vk::Format::eD16Unorm; // depth attachments; + if (pass.attachments[i].layout_in_pass == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) + { + format = vk::Format::eD16Unorm; // depth attachments; - depthAttachmentReference.attachment = i; - depthAttachmentReference.layout = getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass); + depthAttachmentReference.attachment = i; + depthAttachmentReference.layout = getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass); pDepthAttachment = &depthAttachmentReference; - } - else - { - format = vk::Format::eB8G8R8A8Srgb; // color attachments, compatible with swapchain - vk::AttachmentReference attachmentRef(i, getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass)); - colorAttachmentReferences.push_back(attachmentRef); - } - - vk::AttachmentDescription attachmentDesc({}, - format, - vk::SampleCountFlagBits::e1, - getVKLoadOpFromAttachOp(pass.attachments[i].load_operation), - getVkStoreOpFromAttachOp(pass.attachments[i].load_operation), - vk::AttachmentLoadOp::eDontCare, - vk::AttachmentStoreOp::eDontCare, - getVkLayoutFromAttachLayout(pass.attachments[i].layout_initial), - getVkLayoutFromAttachLayout(pass.attachments[i].layout_final)); - attachmentDescriptions.push_back(attachmentDesc); - } + } + else + { + format = vk::Format::eB8G8R8A8Srgb; // color attachments, compatible with swapchain + vk::AttachmentReference attachmentRef(i, getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass)); + colorAttachmentReferences.push_back(attachmentRef); + } + vk::AttachmentDescription attachmentDesc({}, + format, + vk::SampleCountFlagBits::e1, + getVKLoadOpFromAttachOp(pass.attachments[i].load_operation), + getVkStoreOpFromAttachOp(pass.attachments[i].load_operation), + vk::AttachmentLoadOp::eDontCare, + vk::AttachmentStoreOp::eDontCare, + getVkLayoutFromAttachLayout(pass.attachments[i].layout_initial), + getVkLayoutFromAttachLayout(pass.attachments[i].layout_final)); + attachmentDescriptions.push_back(attachmentDesc); + } vk::SubpassDescription subpassDescription({}, vk::PipelineBindPoint::eGraphics, 0, diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/SwapChain.cpp index 3a3209e79efa842f453cae255400718728e5f3d4..85f67b8d0fe252a2ab65d4e0d5baf388a7cfa862 100644 --- a/src/vkcv/SwapChain.cpp +++ b/src/vkcv/SwapChain.cpp @@ -3,33 +3,44 @@ namespace vkcv { - SwapChain::SwapChain(vk::SurfaceKHR surface, const vkcv::Context &context, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format ) - : m_surface(surface), m_context(context), m_swapchain(swapchain), m_format( format) + SwapChain::SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format ) + : m_surface(surface), m_swapchain(swapchain), m_format( format) {} vk::SwapchainKHR SwapChain::getSwapchain() { return m_swapchain; } + /** + * gets surface of the swapchain + * @return current surface + */ vk::SurfaceKHR SwapChain::getSurface() { return m_surface; } + /** + * gets the surface of the swapchain + * @return chosen format + */ vk::SurfaceFormatKHR SwapChain::getSurfaceFormat(){ return m_format; } + /** + * 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; - // 0 means VK_SUCCESS - //std::cout << "FAIL: " << glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &newSurface) << std::endl; if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) { throw std::runtime_error("failed to create a window surface!"); } vk::Bool32 surfaceSupport = false; - // ToDo: hierfuer brauchen wir jetzt den queuefamiliy Index -> siehe ToDo in Context.cpp - // frage: nimmt die Swapchain automatisch den 0'ten Index (Graphics Queue Family)? if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) { throw std::runtime_error("surface is not supported by the device!"); } @@ -37,7 +48,13 @@ namespace vkcv { return vk::SurfaceKHR(surface); } - + /** + * chooses Extent and clapms values to the available + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface of the swapchain + * @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::SurfaceCapabilitiesKHR surfaceCapabilities; if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){ @@ -60,6 +77,12 @@ namespace vkcv { return extent2D; } + /** + * chooses Surface Format for the current surface + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface of the swapchain + * @return available Format + */ vk::SurfaceFormatKHR chooseSwapSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { uint32_t formatCount; physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, nullptr); @@ -76,6 +99,12 @@ namespace vkcv { return availableFormats[0]; } + /** + * returns vk::PresentModeKHR::eMailbox if available or vk::PresentModeKHR::eFifo otherwise + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface of the swapchain + * @return available PresentationMode + */ vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { uint32_t modeCount; physicalDevice.getSurfacePresentModesKHR( surface, &modeCount, nullptr ); @@ -89,9 +118,16 @@ namespace vkcv { return availablePresentMode; } } + // The FIFO present mode is guaranteed by the spec to be supported return vk::PresentModeKHR::eFifo; } + /** + * returns the minImageCount +1 for at least doublebuffering, if it's greater than maxImageCount return maxImageCount + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface of the swapchain + * @return available ImageCount + */ uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { vk::SurfaceCapabilitiesKHR surfaceCapabilities; if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess){ @@ -106,7 +142,12 @@ namespace vkcv { return imageCount; } - + /** + * creates and returns a swapchain with default specs + * @param window of the current application + * @param context that keeps instance, physicalDevice and a device. + * @return swapchain + */ SwapChain SwapChain::create(const Window &window, const Context &context) { const vk::Instance& instance = context.getInstance(); const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); @@ -140,14 +181,12 @@ namespace vkcv { vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo); - return SwapChain(surface, context, swapchain, surfaceFormat); + return SwapChain(surface, swapchain, surfaceFormat); } SwapChain::~SwapChain() { - std::cout<< " Swap " << std::endl; -// m_context.getDevice().destroySwapchainKHR( m_swapchain ); -// m_context.getInstance().destroySurfaceKHR( m_surface ); + // needs to be destroyed by creator } }