VkPresentModeKHR SwapChain::ChoosePresentMode() { uint32_t presentModeCount; K3D_VK_VERIFY(fpGetPhysicalDeviceSurfacePresentModesKHR(GetPhysicalDevice(), m_Surface, &presentModeCount, NULL)); std::vector<VkPresentModeKHR> presentModes(presentModeCount); K3D_VK_VERIFY(fpGetPhysicalDeviceSurfacePresentModesKHR(GetPhysicalDevice(), m_Surface, &presentModeCount, presentModes.data())); VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; for (size_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) { swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } return swapchainPresentMode; }
static std::vector<VkPresentModeKHR> GetPresentModes(VkPhysicalDevice physDevice, VkSurfaceKHR surface) { uint32_t presentModeCount; VkResult error; error = GetPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &presentModeCount, nullptr); Assert(error, "could not get surface present modes"); Assert(presentModeCount > 0, "present mode count is zero!!"); std::vector<VkPresentModeKHR> presentModes(presentModeCount); error = GetPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &presentModeCount, presentModes.data()); Assert(error, "could not get the present Modes"); return presentModes; }
int XdevLSwapChainVulkan::create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height) { VkResult result; VkSwapchainKHR oldSwapchain = m_swapChain; // Get physical device surface properties and formats. VkSurfaceCapabilitiesKHR surfCaps; result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfCaps); if(VK_SUCCESS != result) { std::cerr << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } // ------------------------------------------------------------------------- // Get available present modes. // // Get the number of modes. uint32_t presentModeCount; result = fpGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr); if(VK_SUCCESS != result) { std::cerr << "vkGetPhysicalDeviceSurfacePresentModesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } // Use the number of modes and create an array of modes. std::vector<VkPresentModeKHR> presentModes(presentModeCount); result = fpGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data()); if(VK_SUCCESS != result) { std::cerr << "vkGetPhysicalDeviceSurfacePresentModesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } // ------------------------------------------------------------------------- VkExtent2D swapchainExtent = {}; // width and height are either both -1, or both not -1. if(surfCaps.currentExtent.width == UINT32_MAX) { // If the surface size is undefined, the size is set to // the size of the images requested. swapchainExtent.width = *width; swapchainExtent.height = *height; } else { // If the surface size is defined, the swap chain size must match swapchainExtent = surfCaps.currentExtent; *width = surfCaps.currentExtent.width; *height = surfCaps.currentExtent.height; } VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; for(size_t i = 0; i < presentModeCount; i++) { if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) { swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } // Determine the number of images uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; if((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) { desiredNumberOfSwapchainImages = surfCaps.maxImageCount; } VkSurfaceTransformFlagsKHR preTransform; if(surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = surfCaps.currentTransform; } VkSwapchainCreateInfoKHR swapchainCI = {}; swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCI.pNext = NULL; swapchainCI.surface = m_surface; swapchainCI.minImageCount = desiredNumberOfSwapchainImages; swapchainCI.imageFormat = m_colorFormat; swapchainCI.imageColorSpace = m_colorSpace; swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height }; swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapchainCI.imageArrayLayers = 1; swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCI.queueFamilyIndexCount = 0; swapchainCI.pQueueFamilyIndices = NULL; swapchainCI.presentMode = swapchainPresentMode; swapchainCI.oldSwapchain = oldSwapchain; swapchainCI.clipped = true; swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // If we recreate a SwapChain we have to destroy the previous one. // Note: destroying the swapchain also cleans up all its associated // presentable images once the platform is done with them. if(m_oldSwapChain != VK_NULL_HANDLE) { fpDestroySwapchainKHR(m_device, m_oldSwapChain, nullptr); } result = fpCreateSwapchainKHR(m_device, &swapchainCI, nullptr, &m_swapChain); if(VK_SUCCESS != result) { std::cerr << "vkCreateSwapchainKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } result = fpGetSwapchainImagesKHR(m_device, m_swapChain, &m_imageCount, nullptr); if(VK_SUCCESS != result) { std::cerr << "vkGetSwapchainImagesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } m_images.reserve(m_imageCount); m_images.resize(m_imageCount); result = fpGetSwapchainImagesKHR(m_device, m_swapChain, &m_imageCount, m_images.data()); if(VK_SUCCESS != result) { std::cerr << "vkGetSwapchainImagesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } m_buffers.reserve(m_imageCount); m_buffers.resize(m_imageCount); for(uint32_t i = 0; i < m_imageCount; i++) { VkImageViewCreateInfo colorAttachmentView = {}; colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; colorAttachmentView.pNext = NULL; colorAttachmentView.format = m_colorFormat; colorAttachmentView.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorAttachmentView.subresourceRange.baseMipLevel = 0; colorAttachmentView.subresourceRange.levelCount = 1; colorAttachmentView.subresourceRange.baseArrayLayer = 0; colorAttachmentView.subresourceRange.layerCount = 1; colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorAttachmentView.flags = 0; m_buffers[i].image = m_images[i]; // Transform images from initial (undefined) to present layout setImageLayout( cmdBuffer, m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); colorAttachmentView.image = m_buffers[i].image; result = vkCreateImageView(m_device, &colorAttachmentView, nullptr, &m_buffers[i].view); assert(!result); } return 0; }
void create(VkCommandBuffer cmdBuffer) { VkSurfaceCapabilitiesKHR caps = {}; VkResult result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &caps); if (result != VK_SUCCESS) VulkanTools::exitOnError( "Failed to get physical device surface capabilities"); VkExtent2D swapchainExtent = {}; if (caps.currentExtent.width == -1 || caps.currentExtent.height == -1) { swapchainExtent.width = WINDOW_WIDTH; swapchainExtent.height = WINDOW_HEIGHT; } else { swapchainExtent = caps.currentExtent; } uint32_t presentModeCount = 0; result = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL); assert(result == VK_SUCCESS); assert(presentModeCount >= 1); std::vector<VkPresentModeKHR> presentModes(presentModeCount); result = fpGetPhysicalDeviceSurfacePresentModesKHR( physicalDevice, surface, &presentModeCount, presentModes.data()); assert(result == VK_SUCCESS); VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; for (uint32_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } assert(caps.maxImageCount >= 1); imageCount = caps.minImageCount + 1; if (imageCount > caps.maxImageCount) imageCount = caps.maxImageCount; VkSwapchainCreateInfoKHR swapchainCreateInfo = {}; swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCreateInfo.surface = surface; swapchainCreateInfo.minImageCount = imageCount; swapchainCreateInfo.imageFormat = colorFormat; swapchainCreateInfo.imageColorSpace = colorSpace; swapchainCreateInfo.imageExtent = {swapchainExtent.width, swapchainExtent.height}; swapchainCreateInfo.imageArrayLayers = 1; swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCreateInfo.queueFamilyIndexCount = 1; swapchainCreateInfo.pQueueFamilyIndices = {0}; swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainCreateInfo.presentMode = presentMode; result = fpCreateSwapchainKHR(device, &swapchainCreateInfo, NULL, &swapchain); assert(result == VK_SUCCESS); result = fpGetSwapchainImagesKHR(device, swapchain, &imageCount, NULL); assert(result == VK_SUCCESS); images.resize(imageCount); buffers.resize(imageCount); result = fpGetSwapchainImagesKHR(device, swapchain, &imageCount, images.data()); assert(result == VK_SUCCESS); }
// Create the swap chain and get images with given width and height void create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height) { VkResult err; VkSwapchainKHR oldSwapchain = swapChain; // Get physical device surface properties and formats VkSurfaceCapabilitiesKHR surfCaps; err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps); assert(!err); // Get available present modes uint32_t presentModeCount; err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL); assert(!err); assert(presentModeCount > 0); std::vector<VkPresentModeKHR> presentModes(presentModeCount); err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data()); assert(!err); VkExtent2D swapchainExtent = {}; // width and height are either both -1, or both not -1. if (surfCaps.currentExtent.width == -1) { // If the surface size is undefined, the size is set to // the size of the images requested. swapchainExtent.width = *width; swapchainExtent.height = *height; } else { // If the surface size is defined, the swap chain size must match swapchainExtent = surfCaps.currentExtent; *width = surfCaps.currentExtent.width; *height = surfCaps.currentExtent.height; } // Prefer mailbox mode if present, it's the lowest latency non-tearing present mode VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; for (size_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) { swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } // Determine the number of images uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) { desiredNumberOfSwapchainImages = surfCaps.maxImageCount; } VkSurfaceTransformFlagsKHR preTransform; if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = surfCaps.currentTransform; } VkSwapchainCreateInfoKHR swapchainCI = {}; swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCI.pNext = NULL; swapchainCI.surface = surface; swapchainCI.minImageCount = desiredNumberOfSwapchainImages; swapchainCI.imageFormat = colorFormat; swapchainCI.imageColorSpace = colorSpace; swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height }; swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapchainCI.imageArrayLayers = 1; swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCI.queueFamilyIndexCount = 0; swapchainCI.pQueueFamilyIndices = NULL; swapchainCI.presentMode = swapchainPresentMode; swapchainCI.oldSwapchain = oldSwapchain; swapchainCI.clipped = true; swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain); assert(!err); // If an existing sawp chain is re-created, destroy the old swap chain // This also cleans up all the presentable images if (oldSwapchain != VK_NULL_HANDLE) { fpDestroySwapchainKHR(device, oldSwapchain, nullptr); } err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL); assert(!err); // Get the swap chain images images.resize(imageCount); err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, images.data()); assert(!err); // Get the swap chain buffers containing the image and imageview buffers.resize(imageCount); for (uint32_t i = 0; i < imageCount; i++) { VkImageViewCreateInfo colorAttachmentView = {}; colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; colorAttachmentView.pNext = NULL; colorAttachmentView.format = colorFormat; colorAttachmentView.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorAttachmentView.subresourceRange.baseMipLevel = 0; colorAttachmentView.subresourceRange.levelCount = 1; colorAttachmentView.subresourceRange.baseArrayLayer = 0; colorAttachmentView.subresourceRange.layerCount = 1; colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorAttachmentView.flags = 0; buffers[i].image = images[i]; // Transform images from initial (undefined) to present layout feather::vulkan::tools::setImageLayout( cmdBuffer, buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); colorAttachmentView.image = buffers[i].image; err = vkCreateImageView(device, &colorAttachmentView, nullptr, &buffers[i].view); assert(!err); } }
bool VkContext::CreateSwapchain(int width, int height) { // Get surface capabilities VkSurfaceCapabilitiesKHR surfaceCapabilities; CheckVkResult(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDev, surf, &surfaceCapabilities)); // Get surface formats u32 formatCount = 0; CheckVkResult(vkGetPhysicalDeviceSurfaceFormatsKHR(physDev, surf, &formatCount, nullptr)); std::vector<VkSurfaceFormatKHR> formats(formatCount); CheckVkResult(vkGetPhysicalDeviceSurfaceFormatsKHR(physDev, surf, &formatCount, formats.data())); // Get present modes u32 presentModeCount; CheckVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(physDev, surf, &presentModeCount, nullptr)); std::vector<VkPresentModeKHR> presentModes(presentModeCount); CheckVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(physDev, surf, &presentModeCount, presentModes.data())); // Select number of swapchain images u32 imageCount = surfaceCapabilities.minImageCount + 1; if (surfaceCapabilities.maxImageCount != 0 && imageCount > surfaceCapabilities.maxImageCount) { imageCount = surfaceCapabilities.maxImageCount; } // Select format VkSurfaceFormatKHR format; if (formats.size() == 1 && formats[0].format == VK_FORMAT_UNDEFINED) { format.format = VK_FORMAT_R8G8B8A8_UNORM; format.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; } else { for (u32 i = 0; i < formats.size(); i++) { if (formats[i].format == VK_FORMAT_R8G8B8A8_UNORM) { format = formats[i]; } } format = formats[0]; } // Select extent VkExtent2D extent; if (surfaceCapabilities.currentExtent.width == -1) { extent.width = min(max((u32)width, surfaceCapabilities.minImageExtent.width), surfaceCapabilities.maxImageExtent.width); extent.height = min(max((u32)height, surfaceCapabilities.minImageExtent.height), surfaceCapabilities.maxImageExtent.height); } else { extent = surfaceCapabilities.currentExtent; } // Select present mode (FIFO by default) VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; // Choose mailbox if possible for (u32 i = 0; i < presentModes.size(); i++) { if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = presentModes[i]; } } // Select transformation VkSurfaceTransformFlagBitsKHR transform; if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { transform = surfaceCapabilities.currentTransform; } // Check if image transfer destination is supported if (!(surfaceCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) { std::cout << "Image transfer destination not supported" << std::endl; return false; } // Create swapchian VkSwapchainCreateInfoKHR swapchainInfo = {}; swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainInfo.surface = surf; swapchainInfo.minImageCount = imageCount; swapchainInfo.imageFormat = format.format; swapchainInfo.imageColorSpace = format.colorSpace; swapchainInfo.imageExtent = extent; swapchainInfo.imageArrayLayers = 1; swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainInfo.queueFamilyIndexCount = 0; swapchainInfo.pQueueFamilyIndices = nullptr; swapchainInfo.preTransform = transform; swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainInfo.presentMode = presentMode; swapchainInfo.clipped = VK_TRUE; swapchainInfo.oldSwapchain = VK_NULL_HANDLE; CheckVkResult(vkCreateSwapchainKHR(dev, &swapchainInfo, nullptr, &swapchain)); // Get swapchain images u32 swapchainImageCount = 0; CheckVkResult(vkGetSwapchainImagesKHR(dev, swapchain, &swapchainImageCount, nullptr)); swapchainImages.resize(swapchainImageCount); CheckVkResult(vkGetSwapchainImagesKHR(dev, swapchain, &swapchainImageCount, swapchainImages.data())); // Create swapchain image views swapchainImageViews.resize(imageCount); for (u32 i = 0; i < imageCount; i++) { VkImageViewCreateInfo imageViewCreateInfo = {}; imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewCreateInfo.image = swapchainImages[i]; imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewCreateInfo.format = format.format; imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageViewCreateInfo.subresourceRange.baseMipLevel = 0; imageViewCreateInfo.subresourceRange.levelCount = 1; imageViewCreateInfo.subresourceRange.baseArrayLayer = 0; imageViewCreateInfo.subresourceRange.layerCount = 1; CheckVkResult(vkCreateImageView(dev, &imageViewCreateInfo, nullptr, &swapchainImageViews[i])); } return true; }
void create(VkCommandBuffer cmdBuffer) { VkSurfaceCapabilitiesKHR caps = {}; VkResult result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &caps); if (result != VK_SUCCESS) VulkanTools::exitOnError( "Failed to get physical device surface capabilities"); VkExtent2D swapchainExtent = {}; if (caps.currentExtent.width == -1 || caps.currentExtent.height == -1) { swapchainExtent.width = WINDOW_WIDTH; swapchainExtent.height = WINDOW_HEIGHT; } else { swapchainExtent = caps.currentExtent; } uint32_t presentModeCount = 0; result = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL); assert(result == VK_SUCCESS); assert(presentModeCount >= 1); std::vector<VkPresentModeKHR> presentModes(presentModeCount); result = fpGetPhysicalDeviceSurfacePresentModesKHR( physicalDevice, surface, &presentModeCount, presentModes.data()); assert(result == VK_SUCCESS); VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; for (uint32_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } assert(caps.maxImageCount >= 1); imageCount = caps.minImageCount + 1; if (imageCount > caps.maxImageCount) imageCount = caps.maxImageCount; VkSwapchainCreateInfoKHR swapchainCreateInfo = {}; swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCreateInfo.surface = surface; swapchainCreateInfo.minImageCount = imageCount; swapchainCreateInfo.imageFormat = colorFormat; swapchainCreateInfo.imageColorSpace = colorSpace; swapchainCreateInfo.imageExtent = {swapchainExtent.width, swapchainExtent.height}; swapchainCreateInfo.imageArrayLayers = 1; swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCreateInfo.queueFamilyIndexCount = 1; swapchainCreateInfo.pQueueFamilyIndices = {0}; swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainCreateInfo.presentMode = presentMode; result = fpCreateSwapchainKHR(device, &swapchainCreateInfo, NULL, &swapchain); assert(result == VK_SUCCESS); result = fpGetSwapchainImagesKHR(device, swapchain, &imageCount, NULL); assert(result == VK_SUCCESS); images.resize(imageCount); buffers.resize(imageCount); result = fpGetSwapchainImagesKHR(device, swapchain, &imageCount, images.data()); assert(result == VK_SUCCESS); for (uint32_t i = 0; i < imageCount; i++) { VkImageViewCreateInfo imageCreateInfo = {}; imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageCreateInfo.pNext = NULL; imageCreateInfo.format = colorFormat; imageCreateInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; imageCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageCreateInfo.subresourceRange.baseMipLevel = 0; imageCreateInfo.subresourceRange.levelCount = 1; imageCreateInfo.subresourceRange.baseArrayLayer = 0; imageCreateInfo.subresourceRange.layerCount = 1; imageCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageCreateInfo.flags = 0; buffers[i].image = images[i]; VulkanTools::setImageLayout( cmdBuffer, buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); imageCreateInfo.image = buffers[i].image; result = vkCreateImageView(device, &imageCreateInfo, NULL, &buffers[i].view); assert(result == VK_SUCCESS); VkFramebufferCreateInfo fbCreateInfo = {}; fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; fbCreateInfo.attachmentCount = 1; fbCreateInfo.pAttachments = &buffers[i].view; fbCreateInfo.width = swapchainExtent.width; fbCreateInfo.height = swapchainExtent.height; fbCreateInfo.layers = 1; result = vkCreateFramebuffer(device, &fbCreateInfo, NULL, &buffers[i].frameBuffer); assert(result == VK_SUCCESS); } }
bool _agpu_swap_chain::initialize(agpu_swap_chain_create_info *createInfo) { swapChainWidth = createInfo->width; swapChainHeight = createInfo->height; VkSurfaceCapabilitiesKHR surfaceCapabilities; auto error = device->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physicalDevice, surface, &surfaceCapabilities); if (error) return false; uint32_t presentModeCount; error = device->fpGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, surface, &presentModeCount, nullptr); if (error) return false; std::vector<VkPresentModeKHR> presentModes(presentModeCount); error = device->fpGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, surface, &presentModeCount, &presentModes[0]); if (error) return false; VkExtent2D swapchainExtent; if (surfaceCapabilities.currentExtent.width == (uint32_t)-1) { swapchainExtent.width = swapChainWidth; swapchainExtent.height = swapChainHeight; } else { swapchainExtent = surfaceCapabilities.currentExtent; swapChainWidth = swapchainExtent.width; swapChainHeight = swapchainExtent.height; } VkPresentModeKHR swapchainPresentMode = presentModes[0]; for (size_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_FIFO_KHR) { swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; } if (presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { swapchainPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; break; } } uint32_t desiredNumberOfSwapchainImages = std::max(surfaceCapabilities.minImageCount, createInfo->buffer_count); if ((surfaceCapabilities.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfaceCapabilities.maxImageCount)) desiredNumberOfSwapchainImages = surfaceCapabilities.maxImageCount; VkSurfaceTransformFlagsKHR preTransform; if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = surfaceCapabilities.currentTransform; } VkSwapchainCreateInfoKHR swapchainInfo; memset(&swapchainInfo, 0, sizeof(swapchainInfo)); swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainInfo.surface = surface; swapchainInfo.minImageCount = desiredNumberOfSwapchainImages; swapchainInfo.imageFormat = format; swapchainInfo.imageColorSpace = colorSpace; swapchainInfo.imageExtent = swapchainExtent; swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; swapchainInfo.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainInfo.imageArrayLayers = 1; swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainInfo.presentMode = swapchainPresentMode; swapchainInfo.oldSwapchain = handle; error = device->fpCreateSwapchainKHR(device->device, &swapchainInfo, nullptr, &handle); if (error) return false; error = device->fpGetSwapchainImagesKHR(device->device, handle, &imageCount, nullptr); if (error) return false; std::vector<VkImage> swapChainImages(imageCount); error = device->fpGetSwapchainImagesKHR(device->device, handle, &imageCount, &swapChainImages[0]); if (error) return false; // Color buffers descriptions agpu_texture_description colorDesc; memset(&colorDesc, 0, sizeof(colorDesc)); colorDesc.type = AGPU_TEXTURE_2D; colorDesc.width = createInfo->width; colorDesc.height = createInfo->height; colorDesc.depthOrArraySize = 1; colorDesc.format = agpuFormat; colorDesc.flags = agpu_texture_flags(AGPU_TEXTURE_FLAG_RENDER_TARGET | AGPU_TEXTURE_FLAG_RENDERBUFFER_ONLY); colorDesc.miplevels = 1; colorDesc.sample_count = 1; // Depth stencil buffer descriptions. agpu_texture_description depthStencilDesc; memset(&depthStencilDesc, 0, sizeof(depthStencilDesc)); depthStencilDesc.type = AGPU_TEXTURE_2D; depthStencilDesc.width = createInfo->width; depthStencilDesc.height = createInfo->height; depthStencilDesc.depthOrArraySize = 1; depthStencilDesc.format = createInfo->depth_stencil_format; depthStencilDesc.flags = agpu_texture_flags(AGPU_TEXTURE_FLAG_RENDERBUFFER_ONLY); depthStencilDesc.miplevels = 1; bool hasDepth = hasDepthComponent(createInfo->depth_stencil_format); bool hasStencil = hasStencilComponent(createInfo->depth_stencil_format); if (hasDepth) depthStencilDesc.flags = agpu_texture_flags(depthStencilDesc.flags | AGPU_TEXTURE_FLAG_DEPTH); if (hasStencil) depthStencilDesc.flags = agpu_texture_flags(depthStencilDesc.flags | AGPU_TEXTURE_FLAG_STENCIL); agpu_texture_view_description colorViewDesc; agpu_texture_view_description depthStencilViewDesc; auto depthStencilViewPointer = &depthStencilViewDesc; if (!hasDepth && !hasStencil) depthStencilViewPointer = nullptr; // Create the semaphores VkSemaphoreCreateInfo semaphoreInfo; memset(&semaphoreInfo, 0, sizeof(semaphoreInfo)); semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphores.resize(imageCount, VK_NULL_HANDLE); currentSemaphoreIndex = 0; for (size_t i = 0; i < imageCount; ++i) { error = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &semaphores[i]); if(error) return false; } VkClearColorValue clearColor; memset(&clearColor, 0, sizeof(clearColor)); framebuffers.resize(imageCount); for (size_t i = 0; i < imageCount; ++i) { auto colorImage = swapChainImages[i]; VkImageSubresourceRange range; memset(&range, 0, sizeof(range)); range.layerCount = 1; range.levelCount = 1; if (!device->clearImageWithColor(colorImage, range, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VkAccessFlagBits(0), &clearColor)) return false; agpu_texture *colorBuffer = nullptr; agpu_texture *depthStencilBuffer = nullptr; { colorBuffer = agpu_texture::createFromImage(device, &colorDesc, colorImage); if (!colorBuffer) return false; // Get the color buffer view description. colorBuffer->getFullViewDescription(&colorViewDesc); } { depthStencilBuffer = agpu_texture::create(device, &depthStencilDesc); if (!depthStencilBuffer) { colorBuffer->release(); return false; } // Get the depth stencil buffer view description. depthStencilBuffer->getFullViewDescription(&depthStencilViewDesc); } auto framebuffer = agpu_framebuffer::create(device, swapChainWidth, swapChainHeight, 1, &colorViewDesc, depthStencilViewPointer); framebuffer->swapChainFramebuffer = true; framebuffers[i] = framebuffer; // Release the references to the buffers. colorBuffer->release(); depthStencilBuffer->release(); if (!framebuffer) return false; } if (!getNextBackBufferIndex()) return false; return true; }