首页 > 解决方案 > Vulkan vkCreateInstance - 访问冲突写入位置 0x0000000000000000

问题描述

我正在尝试使用 Vulkan 编写一个基本程序,但我不断收到运行时错误。

Exception thrown at 0x00007FFDC27A8DBE (vulkan-1.dll) in VulkanTest.exe: 0xC0000005: Access violation writing location 0x0000000000000000.

这似乎是一个相对常见的问题,原因是未能初始化 vkCreateInstance 函数的参数。我已经尝试了我发现向其他人提出的所有解决方案,甚至初始化了我相当确定我不需要的东西,但我仍然无法解决问题。该程序是使用 MSVC 编译器用 C 语言编写的。

#include "stdio.h"
#include "SDL.h"
#include "vulkan\vulkan.h"
#include "System.h"

int main(int argc, char *argv[])
{
    //Initialize SDL
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        printf("Error");
    }
    printf("Success");

    //Initialize Vulkan
    VkInstance VulkanInstance;

    VkApplicationInfo VulkanApplicationInfo;
    VulkanApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    VulkanApplicationInfo.pNext = 0;
    VulkanApplicationInfo.pApplicationName = "VulkanTest";
    VulkanApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    VulkanApplicationInfo.pEngineName = "VulkanTest";
    VulkanApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    VulkanApplicationInfo.apiVersion = VK_API_VERSION_1_0;


    VkInstanceCreateInfo VulkanCreateInfo = {0,0,0,0,0,0,0,0};
    VulkanCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    VulkanCreateInfo.pNext = 0;
    VulkanCreateInfo.pApplicationInfo = &VulkanApplicationInfo;
    VulkanCreateInfo.enabledLayerCount = 1;
    VulkanCreateInfo.ppEnabledLayerNames = "VK_LAYER_KHRONOS_validation";
    vkEnumerateInstanceExtensionProperties(0, VulkanCreateInfo.enabledExtensionCount,             
    VulkanCreateInfo.ppEnabledExtensionNames);

    //Create Vulkan Instance
    if(vkCreateInstance(&VulkanCreateInfo, 0, &VulkanInstance) != VK_SUCCESS)
    {
        printf("Vulkan instance was not created");
    }

    //Create SDL Window
    SDL_Window* window;
    window = SDL_CreateWindow("VulkanTest", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_VULKAN || SDL_WINDOW_FULLSCREEN_DESKTOP);

    SDL_Delay(10000);
    return 0;
}

标签: cexceptiongraphicsvulkan

解决方案


你确定调用vkCreateInstance()是什么崩溃了吗?我没有尝试调试您显示的代码(那是您的工作),但只是查看代码正在进行的调用,它应该vkEnumerateInstanceExtensionProperties()是崩溃的调用(如果它甚至可以编译!)。

的第二个参数vkEnumerateInstanceExtensionProperties()需要一个uint32_t*指针,但您传入的uint32_t值 ( VulkanCreateInfo.enabledExtensionCount) 已初始化为 0。因此,这将使pPropertyCount参数成为 NULL 指针(如果它甚至可以编译)。

您正在传递VulkanCreateInfo.ppEnabledExtensionNames第三个参数(如果它甚至可以编译),并且ppEnabledExtensionNames已被初始化为 NULL。根据以下文档vkEnumerateInstanceExtensionProperties()

如果pProperties为 NULL,则返回可用扩展属性的数量pPropertyCount。否则,pPropertyCount必须指向用户设置的变量,该变量指向pProperties数组中的元素数量,并在返回时用实际写入的结构数覆盖该变量pProperties

由于pPropertCount是NULL,vkEnumerateInstanceExtensionProperties()所以无处写入属性计数!这肯定会导致访问冲突试图写入地址 0x00000000000000000。

文档清除状态:

pPropertyCount 必须uint32_t是指向值的有效指针

最重要的是,无论如何,您的调用在vkEnumerateInstanceExtensionProperties()逻辑上都是错误的,因为第三个参数需要一个指向VkExtensionProperties结构数组的指针,而是VulkanCreateInfo.ppEnabledExtensionNames指向const char*UTF-8 字符串数组的指针。

换句话说,您不应该使用vkEnumerateInstanceExtensionProperties()来初始化调用的标准vkCreateInstance()。你完全在滥用vkEnumerateInstanceExtensionProperties(). 您可能打算SDL_Vulkan_GetInstanceExtensions()改用,例如:

uint32_t ExtensionCount = 0;
if (!SDL_Vulkan_GetInstanceExtensions(NULL, &ExtensionCount, NULL))
{
    ...
}

const char **ExtensionNames = (const char **) SDL_malloc(sizeof(const char *) * ExtensionCount);
if (!ExtensionNames)
{
    ...
}

if (!SDL_Vulkan_GetInstanceExtensions(NULL, &ExtensionCount, ExtensionNames))
{
    SDL_free(ExtensionNames);
    ...
}

VulkanCreateInfo.enabledExtensionCount = ExtensionCount;
VulkanCreateInfo.ppEnabledExtensionNames = ExtensionNames;

if (vkCreateInstance(&VulkanCreateInfo, 0, &VulkanInstance) != VK_SUCCESS)
{
    ...
}

SDL_free(ExtensionNames);
...

推荐阅读