# Vulkan Vulkan Swapchain Unable To Create

This topic is 737 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi guys,

I'm currently having a problem with creating a swapchain. I've followed the 101 tutorial by jhenriques (it's posted in this forum), and apparently the swapchain is created just fine. Then I tried to redo the tutorial by Intel, and it triggers me an error when creating a swapchain. The app closes right away with validation layer enabled. I assume it's validation layer problem or whatev, so I tried to disable it. Now it throws an access violation error if I turned it off. It doesn't even have a chance to return a result for both situations. The only feedback I have from debugreportcallback is, it only says "Swapchain" given from pLayerPrefix, lol. So I assume it's related to one of the properties in the swapchainCreateInfo.

I have also visited Reddit for the almost same case. His case was he did not enable the VK_KHR_swapchain  in device extensions (he did it on instance extensions instead), and therefore throws the same problem as I am. I checked mine, but I have the swapchain extension enabled during device creation. I've checked the format, the image usage, surface formats, everything is there, nothing seems to be missing.

So I really have no idea what to look anymore. Does any of you have any case with swapchain that I may need to look for?

Thanks!

---

Swapchain creation:

	void _createSwapchain()
{
VkResult result;

if (_device != VK_NULL_HANDLE)
{
vkDeviceWaitIdle(_device);
}

// Get surface capabilities.
VkSurfaceCapabilitiesKHR surfaceCapabilities;

result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(_physicalDevice, _surface, &surfaceCapabilities);
KMA_VULKAN_CHECK_RESULT(result, "Unable to get physical device capabilities.");

// Get surface formats.
uint32_t surfaceFormatCount;

result = vkGetPhysicalDeviceSurfaceFormatsKHR(_physicalDevice, _surface, &surfaceFormatCount, nullptr);
KMA_VULKAN_CHECK_RESULT(result, "Unable to get physical device surface formats.");

std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);

result = vkGetPhysicalDeviceSurfaceFormatsKHR(_physicalDevice, _surface, &surfaceFormatCount, surfaceFormats.data());
KMA_VULKAN_CHECK_RESULT(result, "Unable to get physical device surface formats.");

// Get present modes.
uint32_t presentModeCount;

result = vkGetPhysicalDeviceSurfacePresentModesKHR(_physicalDevice, _surface, &presentModeCount, nullptr);
KMA_VULKAN_CHECK_RESULT(result, "Unable to get physical device present modes.");

std::vector<VkPresentModeKHR> presentModes(presentModeCount);

result = vkGetPhysicalDeviceSurfacePresentModesKHR(_physicalDevice, _surface, &presentModeCount, presentModes.data());
KMA_VULKAN_CHECK_RESULT(result, "Unable to get physical device present modes.");

// Get image count. 2 = double buffering, 3 triple buffering.
uint32_t imageCount = 2;

// Check if the surface is able to handle the image count we desire.
if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount)
{
imageCount = surfaceCapabilities.maxImageCount;
}

// Get surface format.
VkSurfaceFormatKHR surfaceFormat = surfaceFormats[0];

// If there is no preferred format, we can put anything.
if (surfaceFormats.size() == 1 && surfaceFormat.format == VK_FORMAT_UNDEFINED)
{
surfaceFormat.format = VK_FORMAT_R8G8B8A8_UNORM;
surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
}

// Get our preferred format.
for (int i = 0, size = surfaceFormats.size(); i < size; ++i)
{
if (surfaceFormats[i].format == VK_FORMAT_R8G8B8A8_UNORM)
{
surfaceFormat = surfaceFormats[i];
}
}

// Set swapchain extent. If surface capabilities has no width,
// just set it like our window size, as long as it fits the surface capabilities.
Window* window = Global::stage->getWindow();

VkExtent2D extent = {};

extent.width = window->width;
extent.height = window->height;

if (surfaceCapabilities.currentExtent.width == -1)
{
if (extent.width < surfaceCapabilities.minImageExtent.width)
{
extent.width = surfaceCapabilities.minImageExtent.width;
}

if (extent.height < surfaceCapabilities.minImageExtent.height)
{
extent.height = surfaceCapabilities.minImageExtent.height;
}

if (extent.width > surfaceCapabilities.maxImageExtent.width)
{
extent.width = surfaceCapabilities.maxImageExtent.width;
}

if (extent.height > surfaceCapabilities.maxImageExtent.height)
{
extent.height = surfaceCapabilities.maxImageExtent.height;
}
}

// Set image usage; how the image is used by Vulkan.
VkImageUsageFlags imageUsage;

// Just checking a bit, but color attachment is always supported.
if (surfaceCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
{
imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
else
{
KMA_ERROR("No image usage supported by the surface.");
}

// Select the pre-transformations. This is useful on phones/tablets to determine the default orientation.
VkSurfaceTransformFlagBitsKHR preTransform;

if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
{
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
}
else
{
preTransform = surfaceCapabilities.currentTransform;
}

// Select the present modes. By default we use FIFO method, but we prefer mailbox if it's supported.
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

for (int i = 0, size = presentModes.size(); i < size; ++i)
{
if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
{
presentMode = presentModes[i];
}
}

// If the window is minimized, we may want not want to recreate swapchain as there's nothing to render.
// Desktop only case.
if ((extent.width == 0) || (extent.height == 0))
{
return;
}

// Refer the current swapchain as old swapchain.
VkSwapchainKHR oldSwapchain = _swapchain;

// Finally create the swapchain.
VkSwapchainCreateInfoKHR swapchainCreateInfo = {};

swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.pNext = nullptr;
swapchainCreateInfo.flags = 0;
swapchainCreateInfo.surface = _surface;
swapchainCreateInfo.minImageCount = imageCount;
swapchainCreateInfo.imageFormat = surfaceFormat.format;
swapchainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
swapchainCreateInfo.imageExtent = extent;
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageUsage = imageUsage;

swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainCreateInfo.queueFamilyIndexCount = 0;
swapchainCreateInfo.pQueueFamilyIndices = nullptr;

swapchainCreateInfo.preTransform = preTransform;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapchainCreateInfo.presentMode = presentMode;
swapchainCreateInfo.clipped = VK_TRUE;
swapchainCreateInfo.oldSwapchain = oldSwapchain;

result = vkCreateSwapchainKHR(_device, &swapchainCreateInfo, nullptr, &_swapchain); // <-- WHERE THE ERROR HAPPENS.
KMA_VULKAN_CHECK_RESULT(result, "Unable to create swapchain.");

// Destroy the old swapchain.
if (oldSwapchain != VK_NULL_HANDLE)
{
vkDestroySwapchainKHR(_device, oldSwapchain, nullptr);
}
}

Edited by Alectora

##### Share on other sites

Oh geez. Apparently I made a mistake on matching the image extent. Since currentExtent already exists, I just need to refer it to the currentExtent by default and it solves the problem.

I can only define the extent when the currentExtent dimension is -1. If I define the dimension myself while the current extent exists (or not -1), it throws that error because they don't match! (Well, as jhenriques' tutorial said)

So this one:

Window* window = Global::stage->getWindow();

VkExtent2D extent = {};

extent.width = window->width;
extent.height = window->height;

if (surfaceCapabilities.currentExtent.width == -1)
{
... 

Should be roughly like this:

VkExtent2D extent = surfaceCapabilities.currentExtent;

if (extent.width == -1)
{
Window* window = Global::stage->getWindow();

extent.width = window->width;
extent.height = window->height;
...
Edited by Alectora

1. 1
2. 2
3. 3
Rutin
22
4. 4
JoeJ
17
5. 5

• 14
• 30
• 13
• 11
• 11
• ### Forum Statistics

• Total Topics
631774
• Total Posts
3002295
×