来自交换链的提示会引发段错误

时间:2018-11-25 12:22:32

标签: c vulkan

当前正在尝试创建一个主循环,以显示来自交换链的图像:

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函数很长,我不知道将其放在这里是否很有用,但是我实际上正在做的(并且不起作用)是:

  • 按如下方式创建交换链:

    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;
    
  • 创建彩色图像和深度图像。两个VkImageCreateInfo结构体都有一个指向以下结构体的指针作为其pNext值:

    VkImageSwapchainCreateInfoKHR swapchainImageInfo =
        { .sType     = VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR
        , .pNext     = NULL
        , .swapchain = ctx->objects.swapchain
        };
    
  • 为两个图像分配内存,然后尝试如下将它们绑定到交换链:

    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;
    
  • 执行两个所需的图像布局转换(从VK_IMAGE_LAYOUT_UNDEFINEDVK_IMAGE_LAYOUT_GENERAL

  • 创建两个所需的图像视图,即帧缓冲区和VkPresentInfoKHR结构

我想知道我在做错什么以及如何解决。随时要求其他精度。

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

1 个答案:

答案 0 :(得分:3)

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

交换链需要以特殊方式创建自己的图像。这通常是对Vulkan交换链摘要(例如X,Wayland,GDI或DXGI)的基础系统的限制。因此,您不会尝试自己创建这些图像(也不会尝试将内存绑定到它们),而是让vkCreateSwapchain为您完成。

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

因此,在vkCreate d交换链中,您将使用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定期获得的vkCreateImage一样好,除了以下两点:

  • 不允许您vkDestroyImage使用它们;而是当您致电vkDestroySwapchainKHR时将它们销毁。
  • 它们已经绑定了内存(因此,您既不需要,也不允许将内存绑定到这些图像)。

这应该做介绍,并在此处解决当前的问题。