创建 Vulkan 实例会导致访问冲突

Creating Vulkan instance causes access violation

本文关键字:访问冲突 Vulkan 实例 创建      更新时间:2023-10-16

我正在尝试初始化 Vulkan API。
我遇到的问题是在调用vkCreateInstance后出现访问冲突错误,我认为问题来自扩展和层列表。
我正在使用 char buff[20][256] 将它们从字符串传输到 API 调用的结构中,我在调试器中看到的层和扩展名称(3 个扩展和 15 层)都比 256 个字符短得多,并且都是以 null 结尾的。
扩展名或层名称没有缓冲区溢出,但它会崩溃。

我事先使用vkEnumerateInstanceExtensionPropertiesvkEnumerateInstanceLayerProperties接收的字符串的层和扩展列表都是有效的以 null 结尾的字符串,如"VK_KHR_surface"等。

是否有可能即使它说我支持某些扩展,但我并不真正支持它们,并且 API 在尝试初始化我不支持的扩展时崩溃?

void InitializeInstance(void** instance, const vector<string>& layers, const vector<string>& extensions)
{
VkApplicationInfo applicationInfo;
VkInstanceCreateInfo instanceInfo;
VkInstance* instanceOut = (VkInstance*)instance;
applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
applicationInfo.pNext = nullptr;
applicationInfo.pApplicationName = "MyApp";
applicationInfo.pEngineName = "MyEngine";
applicationInfo.engineVersion = 1;
applicationInfo.apiVersion = VK_API_VERSION_1_0;
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pNext = null;
instanceInfo.flags = 0;
instanceInfo.pApplicationInfo = &applicationInfo;
char buffLayer[20][256];
char buffExt[20][256];
if(!layers.empty())
{
instanceInfo.enabledLayerCount = layers.size();
for(int i = 0; i < layers.size(); i++)
{
strcpy(buffLayer[i], layers[i].c_str());
}
instanceInfo.ppEnabledLayerNames = (char**)buffLayer;
}
else
{
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledLayerNames = nullptr;
}
if(!extensions.empty())
{
instanceInfo.enabledExtensionCount = extensions.size();
for(int i = 0; i < extensions.size(); i++)
{
strcpy(buffExt[i], extensions[i].c_str());
}
instanceInfo.ppEnabledExtensionNames = (char**)buffExt;
}
else
{
instanceInfo.enabledExtensionCount = 0;
instanceInfo.ppEnabledExtensionNames = nullptr;
}
vkCreateInstance(&instanceInfo, nullptr, instanceOut);
}

当我只有 0 个扩展名和 0 层时,它创建成功。如果其中任何一个不是 0,它将崩溃。

char buffLayer[20][256];
instanceInfo.ppEnabledLayerNames = (char**)buffLayer;

ppEnabledLayerNames 应该是指向字符数组的指针数组。但是你给它传递的是一个 2D 字符数组,它实际上只是一个 20*256 个字符的数组。

如果你使用的是具有 32 位指针的机器,则驱动程序将获取 buffLayer 中的前四个字节,并将它们视为指向字符数组的指针。但是您刚刚将图层名称的前四个字符存储在那里,并且"VK_K"可能不是:)的有效指针值。因此,加载程序在尝试取消引用该无效指针时将崩溃。

可能最简单的更改是添加:

char* layerNames[20];
for (int i = 0; i < 20; i++)
layerNames[i] = &buffLayer[i][0];

并将图层名称传递为 ppEnabledLayerNames。