Algorythmis
Algorythmis

Reputation: 672

Presenting from swapchain induces segfault

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:

I'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

Answers (2)

tarosuke
tarosuke

Reputation: 1

.queueFamilyIndexCount = 1
.pQueueFamilyIndices   = NULL

This can make segfault at vkCreateSwapchainKHR.

Upvotes: 0

krOoze
krOoze

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 vkCreated 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 VkImages obtained regularly with vkCreateImage, except two things:

  • you are not allowed to vkDestroyImage them; they are instead destroyed when you call vkDestroySwapchainKHR.
  • they already have memory bound to them (so you do not need to, nor are you allowed to bind memory to those images).

That should do for introduction, and addressing the immediate problem here.

Upvotes: 3

Related Questions