首页 > 解决方案 > 从交换链呈现会导致段错误

问题描述

目前正在尝试创建一个显示交换链中图像的主循环:

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;
}

但是,看起来我以不正确的方式使用了交换链扩展,这会转换为来自验证层的以下错误消息,然后是分段错误:

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.

我的init函数很长,我不知道把它放在这里是否很有用,但我实际上在做的(并且不起作用)是:

我想知道我做错了什么以及如何解决它。随意要求任何额外的精度。

编辑:我使用的实例扩展是VK_KHR_surfaceVK_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
    };

我使用的唯一设备扩展是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
    };

标签: cvulkan

解决方案


对,所以这是一个 XY 问题。似乎您正在使用不适合您的情况的 Vulkan 功能。即VkImageSwapchainCreateInfoKHRVkBindImageMemorySwapchainInfoKHR。根据他们的描述,它们仅对 GPU 组有用。但是根据您的评论,您只想以旧的无聊方式使用 Swapchain。

Swapchain 需要以一种特殊的方式创建自己的镜像。这通常是对 Vulkan Swapchain 抽象的底层系统(例如 X、Wayland、GDI 或 DXGI)的限制。因此,您不会尝试自己创建这些图像(也不会尝试将内存绑定到它们),而是让vkCreateSwapchain您为您完成。

BTW Vulkan 交换链对深度图像没有用处。都是彩色图像。

因此,当 Swapchain 是vkCreated 时,您将获得它为您创建的图像vkGetSwapchainImagesKHR。用法类似于:

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";

注意:理论上你可能会得到比你要求的更多的图像vkCreateSwapchain

VkImage这些图像与s 定期获得的一样好vkCreateImage,除了两件事:

  • 你不被允许vkDestroyImage;当你调用它们时,它们会被销毁vkDestroySwapchainKHR
  • 它们已经绑定了内存(因此您不需要,也不允许将内存绑定到这些图像)。

这应该用于介绍,并解决这里的直接问题。


推荐阅读