Reputation: 672
Currently trying to create a main loop which presents images from a swapchain:
void loop(struct Context *ctx, void(*loopfn)(struct Context*)) {
VkQueue queue;
vkGetDeviceQueue(ctx->objects.device, 0, 0, &queue);
while (!glfwWindowShouldClose(ctx->window)) {
VkResult fenceStatus = vkGetFenceStatus(ctx->objects.device, ctx->objects.fence);
if (fenceStatus == VK_SUCCESS) {
// Reset fence and command buffer
if (vkQueuePresentKHR(queue, &ctx->objects.presentInfo) != VK_SUCCESS) {
fprintf(stderr, "Failed to present image\n");
break;
}
loopfn(ctx);
} else if (fenceStatus == VK_ERROR_DEVICE_LOST) {
fprintf(stderr, "Device lost\n");
break;
}
}
}
void loopfn(struct Context *ctx) {
// Clear color image
}
int main() {
struct Context *ctx = init(500, 500, "Test");
if (!ctx)
return -1;
loop(ctx, loopfn);
deinit(ctx);
return 0;
}
However, it looks like I'm using the swapchain extension in an incorrect way, which translates to the following error message from the validation layers, immediately followed by a segmentation fault:
UNASSIGNED-CoreValidation-DrawState-SwapchainInvalidImage(ERROR / SPEC): msgNum: 0 - vkQueuePresentKHR: Swapchain image index too large (0). There are only 0 images in this swapchain.
Objects: 1
[0] 0x7, type: 1000001000, name: (null)
Validation(ERROR): msg_code: 0: [ UNASSIGNED-CoreValidation-DrawState-SwapchainInvalidImage ] Object: 0x7 (Type = 27) | vkQueuePresentKHR: Swapchain image index too large (0). There are only 0 images in this swapchain.
My init
function is very long and I don't know if it'd be very useful to put it in here, but what I'm essentially doing (and which does not work) is:
Creating the swapchain as follows:
VkSwapchainCreateInfoKHR swapchainInfo =
{ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
, .pNext = NULL
, .flags = 0x00000000
, .surface = ctx->objects.surface
, .minImageCount = surfaceCapabilities.minImageCount
, .imageFormat = pSurfaceFormats[0].format
, .imageColorSpace = pSurfaceFormats[0].colorSpace
, .imageExtent = surfaceCapabilities.currentExtent
, .imageArrayLayers = 1
, .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
, .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE
, .queueFamilyIndexCount = 1
, .pQueueFamilyIndices = NULL
, .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
, .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
, .presentMode = VK_PRESENT_MODE_MAILBOX_KHR
, .clipped = VK_TRUE
, .oldSwapchain = VK_NULL_HANDLE
};
if (vkCreateSwapchainKHR(ctx->objects.device, &swapchainInfo, NULL, &ctx->objects.swapchain) != VK_SUCCESS)
goto failure;
Creating the color image and depth image. Both VkImageCreateInfo
structures have a pointer to the following struct as their pNext
value:
VkImageSwapchainCreateInfoKHR swapchainImageInfo =
{ .sType = VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR
, .pNext = NULL
, .swapchain = ctx->objects.swapchain
};
Allocating memory for both images, then attempting to bind them to the swapchain as follows:
VkBindImageMemorySwapchainInfoKHR colorSwapchainBindInfo =
{ .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR
, .pNext = NULL
, .swapchain = ctx->objects.swapchain
, .imageIndex = 0
};
VkBindImageMemoryInfo colorMemBindInfo =
{ .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO
, .pNext = &colorSwapchainBindInfo
, .image = ctx->objects.colorImage
, .memory = ctx->objects.colorMemory
, .memoryOffset = 0
};
// Pretty much the same thing for the depth image
VkBindImageMemoryInfo memBindInfos[] = { colorMemBindInfo, depthMemBindInfo };
if (vkBindImageMemory2(ctx->objects.device, 2, memBindInfos) != VK_SUCCESS)
goto failure;
Performing the two needed image layout transitions (from VK_IMAGE_LAYOUT_UNDEFINED
to VK_IMAGE_LAYOUT_GENERAL
)
VkPresentInfoKHR
structI'd like to know what I'm doing wrong and how to fix it. Feel free to ask for any additional precisions.
Edit: The instance extensions I'm using are VK_KHR_surface
and VK_KHR_xcb_surface
.
uint32_t count;
const char **extensions = glfwGetRequiredInstanceExtensions(&count);
VkInstanceCreateInfo instanceInfo =
{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
, .pNext = NULL
, .flags = 0x00000000
, .pApplicationInfo = NULL
, .enabledLayerCount = 0
, .ppEnabledLayerNames = NULL
, .enabledExtensionCount = count
, .ppEnabledExtensionNames = extensions
};
The only device extension I'm using is VK_KHR_swapchain
:
const char *deviceExtensions[] = { "VK_KHR_swapchain" };
VkDeviceCreateInfo deviceInfo =
{ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
, .pNext = NULL
, .flags = 0x00000000
, .queueCreateInfoCount = 1
, .pQueueCreateInfos = &queueInfo
, .enabledLayerCount = 0
, .ppEnabledLayerNames = NULL
, .enabledExtensionCount = sizeof(deviceExtensions) / sizeof(deviceExtensions[0])
, .ppEnabledExtensionNames = deviceExtensions
, .pEnabledFeatures = NULL
};
Upvotes: 1
Views: 941
Reputation: 1
.queueFamilyIndexCount = 1
.pQueueFamilyIndices = NULL
This can make segfault at vkCreateSwapchainKHR.
Upvotes: 0
Reputation: 13276
Right, so this is a XY problem. Seems you are using Vulkan functionality that is inappropriate for your situation. Namely VkImageSwapchainCreateInfoKHR
and VkBindImageMemorySwapchainInfoKHR
. Based on their descriptions they are only useful for GPU groups. But based on your comments you just want to use the Swapchain the old boring way.
Swapchain needs to create its own images in a special way. That is typically a restriction of the underlying system the Vulkan Swapchain abstracts (such as X, Wayland, GDI, or DXGI). So you would not try to create those images yourself (nor try to bind memory to them), but let vkCreateSwapchain
do that for you.
BTW Vulkan swapchain has no use for depth image. It is all color images.
So when the Swapchain is vkCreate
d you obtain the images it created for you with vkGetSwapchainImagesKHR
. The usage is something like:
uint32_t count;
VkResult errco = vkGetSwapchainImagesKHR( dev, swpch, &count, nullptr );
if( errco ) throw "error";
std::vector<VkImage> swapchainImages( count );
errco = vkGetSwapchainImagesKHR( dev, swpch, &count, swapchainImages.data() );
if( errco ) throw "error";
Note: theoretically you may get more images than you asked for with vkCreateSwapchain
.
Those images are as good as VkImage
s obtained regularly with vkCreateImage
, except two things:
vkDestroyImage
them; they are instead destroyed when you call vkDestroySwapchainKHR
.That should do for introduction, and addressing the immediate problem here.
Upvotes: 3