为什么vkCreateSwapchainKHR会导致0的访问冲突?

问题描述 投票:2回答:2

我正在尝试通过关注vulkan-tutorial.com的精彩教程来学习Vulkan,但是我在创建交换链方面遇到了一些麻烦。如标题所述,vkCreateSwapchainKHR产生以下错误:Access violation executing location 0x0000000000000000

该教程表明这可能与蒸汽覆盖层发生冲突。我不是这样,因为从教程中复制整个代码是有效的。

我试图找出我的代码出了什么问题,并学习如何调试这些问题,因为我将来不会有参考代码。有罪的线看起来像这样:

if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, nullptr, &swapChain) != VK_SUCCESS) {
    throw std::runtime_error("Could not create swap chain");
}

我在这一行设置了一个断点,将我的代码中的参数值与参考代码中的值进行比较。据我所知,没有区别。 (当然地址不同)

我应该在哪里查找代码中的问题?变量swapChain是预期的NULL。错误形成的swapChainCreateInfo不应该让vkCreateSwapchainKHR崩溃。它只会让它返回不是VK_SUCCESS的东西。设备创建没有问题:

if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
    throw std::runtime_error("Failed to create logical device");
}

编辑 - 我正在使用验证层VK_LAYER_LUNARG_standard_validation和我的createInfo设置如下。

// Useful functions and structures
VkPhysicalDevice physicalDevice;
VkSurfaceKHR surface;
VkSwapchainKHR swapChain;

struct QueueFamilyIndices {
    std::optional<uint32_t> graphicsFamily;
    std::optional<uint32_t> presentationFamily;
    bool isComplete() {
        return graphicsFamily.has_value() && presentationFamily.has_value();
    }
};

struct SwapChainSupportDetails {
    VkSurfaceCapabilitiesKHR surfaceCapabilities;
    std::vector<VkSurfaceFormatKHR> formats;
    std::vector<VkPresentModeKHR> presentModes;
};

SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice physicalDevice) {
    SwapChainSupportDetails swapChainSupportDetails;

    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &swapChainSupportDetails.surfaceCapabilities);

    uint32_t formatCount = 0;
    vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr);
    if (formatCount != 0) {
        swapChainSupportDetails.formats.resize(formatCount);
        vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, swapChainSupportDetails.formats.data());
    }

    uint32_t presentModeCount = 0;
    vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr);
    if (presentModeCount != 0) {
        swapChainSupportDetails.presentModes.resize(presentModeCount);
        vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, swapChainSupportDetails.presentModes.data());
    }

    return swapChainSupportDetails;
}

VkSurfaceFormatKHR chooseSwapChainSurfaceFormat(const std::vector<VkSurfaceFormatKHR> & availableFormats) {
    if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED) {
        return { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
    }

    for (const auto & availableFormat : availableFormats) {
        if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
            return availableFormat;
        }
    }

    return availableFormats[0];
}

VkPresentModeKHR chooseSwapChainPresentMode(const std::vector<VkPresentModeKHR> & availablePresentModes) {

    VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR;
    for (const auto & availablePresentMode : availablePresentModes) {
        if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
            return availablePresentMode;
        }
        else if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
            bestMode = availablePresentMode;
        }
    }

    return bestMode;
}

VkExtent2D chooseSwapChainExtent2D(const VkSurfaceCapabilitiesKHR & surfaceCapabilities) {
    if (surfaceCapabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
        return surfaceCapabilities.currentExtent;
    }
    else {
        VkExtent2D actualExtent = { WIDTH, HEIGHT };
        actualExtent.width = std::max(std::min(surfaceCapabilities.maxImageExtent.width, actualExtent.width), surfaceCapabilities.minImageExtent.width);
        actualExtent.height = std::max(std::min(surfaceCapabilities.maxImageExtent.height, actualExtent.height), surfaceCapabilities.minImageExtent.height);
        return actualExtent;
    }
}

// Swap Chain creation code

SwapChainSupportDetails swapChainSupportDetails = querySwapChainSupport(physicalDevice);

VkSurfaceFormatKHR surfaceFormat = chooseSwapChainSurfaceFormat(swapChainSupportDetails.formats);
VkPresentModeKHR presentMode = chooseSwapChainPresentMode(swapChainSupportDetails.presentModes);
VkExtent2D extent = chooseSwapChainExtent2D(swapChainSupportDetails.surfaceCapabilities);
uint32_t imageCount = swapChainSupportDetails.surfaceCapabilities.minImageCount + 1;
if (swapChainSupportDetails.surfaceCapabilities.maxImageCount > 0 && imageCount > swapChainSupportDetails.surfaceCapabilities.maxImageCount) {
    imageCount = swapChainSupportDetails.surfaceCapabilities.minImageCount;
}

VkSwapchainCreateInfoKHR swapChainCreateInfo = {};
swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapChainCreateInfo.surface = surface;
swapChainCreateInfo.minImageCount = imageCount;
swapChainCreateInfo.imageFormat = surfaceFormat.format;
swapChainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
swapChainCreateInfo.imageExtent = extent;
swapChainCreateInfo.imageArrayLayers = 1;
swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

QueueFamilyIndices familyIndices = findQueueFamilies(physicalDevice);
uint32_t queueFamilyIndices[] = { familyIndices.graphicsFamily.value(), familyIndices.presentationFamily.value() };
if (familyIndices.graphicsFamily != familyIndices.presentationFamily) {
    swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
    swapChainCreateInfo.queueFamilyIndexCount = 2;
    swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else {
    swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    swapChainCreateInfo.queueFamilyIndexCount = 0;
    swapChainCreateInfo.pQueueFamilyIndices = nullptr;
}

swapChainCreateInfo.preTransform = swapChainSupportDetails.surfaceCapabilities.currentTransform;
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapChainCreateInfo.presentMode = presentMode;
swapChainCreateInfo.clipped = VK_TRUE;
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;

if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, nullptr, &swapChain) != VK_SUCCESS) {
    throw std::runtime_error("Could not create swap chain");
}

我得到了结果:enter image description here

c++ access-violation vulkan
2个回答
1
投票

好吧,在创建逻辑设备时,需要将enabledExtensionCount设置为实际所需的扩展数,如果需要扩展可以工作则不需要为0。就我而言,这是一个简单的编辑失败。这是我的代码中的gem:

createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data();

createInfo.enabledExtensionCount = 0;

我通过将代码中的每个函数替换为参考代码中的函数直到它起作用来解决这个问题。我有点失望,验证层没有抓住这一点。我弄错了吗?这是他们应该抓住的东西吗?

编辑:正如LIANG LIU所指出的,这是deviceExtensions的初始化:

const std::vector<const char*> deviceExtensions = {
    VK_KHR_SWAPCHAIN_EXTENSION_NAME
};

0
投票

看起来您在代码段的末尾调用vkCreateDevice来创建交换链并将VkSwapchainCreateInfo传入其中。也许您想要调用vkCreateSwapchainKHR,例如:

if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, nullptr, &swapChain) !=
    VK_SUCCESS) {
    throw std::runtime_error("failed to create swap chain");
}

如果您实际上正在调用vkCreateSwapchainKHR,是否可以编辑您的问题以表明这一点?


0
投票

创建VkDevice时启用VK_KHR_SWAPCHAIN_EXTENSION_NAME

    void VKRenderer::createVkLogicalDevice()
    {
        // device extensions
        vector<const char*>::type deviceExtensionNames = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };

        // priorities
        float queuePrioritys[2] = { 1.f, 1.f};

        // graphics queue
        VkDeviceQueueCreateInfo queueCreateInfos;
        queueCreateInfos.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfos.pNext = nullptr;
        queueCreateInfos.queueFamilyIndex = getGraphicsQueueFamilyIndex();
        queueCreateInfos.queueCount = 1;
        queueCreateInfos.pQueuePriorities = &queuePrioritys[0];

        // device features
        VkPhysicalDeviceFeatures deviceFeatures = {};

        VkDeviceCreateInfo createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
        createInfo.pNext = nullptr;
        createInfo.pQueueCreateInfos = &queueCreateInfos;
        createInfo.queueCreateInfoCount = 1;
        createInfo.pEnabledFeatures = &deviceFeatures;
        createInfo.enabledExtensionCount = deviceExtensionNames.size();
        createInfo.ppEnabledExtensionNames = deviceExtensionNames.data();

        // create logical device and retirve graphics queue
        if (VK_SUCCESS == vkCreateDevice(m_vkPhysicalDevice, &createInfo, nullptr, &m_vkDevice))
        {
            vkGetDeviceQueue(m_vkDevice, getGraphicsQueueFamilyIndex(), 0, &m_vkGraphicsQueue);
            vkGetDeviceQueue(m_vkDevice, getPresentQueueFamilyIndex(), 0, &m_vkPresentQueue);
        }
        else
        {
            EchoLogError("Failed to create vulkan logical device!");
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.