分段错误在 Vulkan 实例创建期间的原因是什么?

huangapple go评论79阅读模式
英文:

What is the cause of the segmentation fault during the vulkan instance creation?

问题

我正在编写一个使用Vulkan的应用程序,但我注意到它不起作用。我一直在删除代码,直到我达到了这个点:

#include <vulkan/vulkan.h>
#include <iostream>

int main()
{
  VkApplicationInfo info{};
  info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  info.pNext = nullptr;
  info.apiVersion = VK_VERSION_1_3;
  info.applicationVersion = 1;
  info.engineVersion = 0;
  info.pApplicationName = "App";
  info.pEngineName = nullptr;

  VkInstanceCreateInfo instanceInfo{};
  instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  instanceInfo.pNext = nullptr;
  instanceInfo.flags = 0;
  instanceInfo.enabledExtensionCount = 0;
  instanceInfo.enabledLayerCount = 0;
  instanceInfo.ppEnabledExtensionNames = nullptr;
  instanceInfo.ppEnabledLayerNames = nullptr;
  instanceInfo.pApplicationInfo = &info;

  VkInstance instance;
  auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);

  if (code != VK_SUCCESS)
  {
    std::cout << "failed to create instance" << std::endl;
    return -1;
  }
  else vkDestroyInstance(instance, nullptr);
  return 0;
}

我正在使用FreeBSD 13.2和Clang 16.0.6进行编译。我已经安装了Vulkan软件包:

$ pkg info vulkan*
vulkan-caps-viewer-3.31
vulkan-extension-layer-1.3.254
vulkan-headers-1.3.254
vulkan-loader-1.3.254
vulkan-tools-1.3.254
vulkan-validation-layers-1.3.254

使用带有调试符号的可执行文件运行GDB时,出现以下错误:

程序收到信号SIGSEGV,分段错误。
地址未映射到对象。
0x0000000800595300 in ?? () from /lib/libc.so.7
(gdb) backtrace
#0  0x0000000800595300 in ?? () from /lib/libc.so.7
#1  0x00000008005a04b6 in vsnprintf () from /lib/libc.so.7
#2  0x00000008002e3dec in ?? () from /usr/local/lib/libvulkan.so.1
#3  0x00000008002c1278 in ?? () from /usr/local/lib/libvulkan.so.1
#4  0x00000008002ded9f in ?? () from /usr/local/lib/libvulkan.so.1
#5  0x00000008002e1579 in ?? () from /usr/local/lib/libvulkan.so.1
#6  0x00000008002e7ca6 in vkCreateInstance () from /usr/local/lib/libvulkan.so.1
#7  0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
(gdb) frame 7
#7  0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
26	  auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
(gdb) p instanceInfo
$1 = {sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, pNext = 0x0, flags = 0, pApplicationInfo = 0x7fffffffe6f8, enabledLayerCount = 0,
  ppEnabledLayerNames = 0x0, enabledExtensionCount = 0, ppEnabledExtensionNames = 0x0}

我预期实例应该成功创建。

英文:

I am writing a vulkan powered app, and I noticed it wasn't working. I kept on removing code until i reached this:

#include &lt;vulkan/vulkan.h&gt;                                                        
#include &lt;iostream&gt;                                                               
                                                                                  
int main()                                                                        
{                                                                                 
  VkApplicationInfo info{};                                                       
  info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;                                
  info.pNext = nullptr;                                                           
  info.apiVersion = VK_VERSION_1_3;                                               
  info.applicationVersion = 1;                                                    
  info.engineVersion = 0;                                                         
  info.pApplicationName = &quot;App&quot;;                                                  
  info.pEngineName = nullptr;                                                     
                                                                                  
  VkInstanceCreateInfo instanceInfo{};                                            
  instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;                    
  instanceInfo.pNext = nullptr;                                                   
  instanceInfo.flags = 0;                                                         
  instanceInfo.enabledExtensionCount = 0;                                         
  instanceInfo.enabledLayerCount = 0;                                             
  instanceInfo.ppEnabledExtensionNames = nullptr;                                 
  instanceInfo.ppEnabledLayerNames = nullptr;                                     
  instanceInfo.pApplicationInfo = &amp;info;                                          
                                                                                  
  VkInstance instance;                                                            
  auto code = vkCreateInstance(&amp;instanceInfo, nullptr, &amp;instance);                
                                                                                  
  if (code != VK_SUCCESS)                                                         
  {                                                                               
    std::cout &lt;&lt; &quot;failed to create instance&quot; &lt;&lt; std::endl;                        
    return -1;                                                                    
  }                                                                               
  else vkDestroyInstance(instance, nullptr);                                      
  return 0;                                                                       
}                                     

I am using freebsd 13.2 with clang 16.0.6 to compile this.
I have installed the vulkan packages:

$ pkg info vulkan*<br>
vulkan-caps-viewer-3.31
vulkan-extension-layer-1.3.254
vulkan-headers-1.3.254
vulkan-loader-1.3.254
vulkan-tools-1.3.254
vulkan-validation-layers-1.3.254<br>

Running gdb on the executable with debugging symbols gives:

Program received signal SIGSEGV, Segmentation fault.
Address not mapped to object.
0x0000000800595300 in ?? () from /lib/libc.so.7
(gdb) backtrace
#0  0x0000000800595300 in ?? () from /lib/libc.so.7
#1  0x00000008005a04b6 in vsnprintf () from /lib/libc.so.7
#2  0x00000008002e3dec in ?? () from /usr/local/lib/libvulkan.so.1
#3  0x00000008002c1278 in ?? () from /usr/local/lib/libvulkan.so.1
#4  0x00000008002ded9f in ?? () from /usr/local/lib/libvulkan.so.1
#5  0x00000008002e1579 in ?? () from /usr/local/lib/libvulkan.so.1
#6  0x00000008002e7ca6 in vkCreateInstance () from /usr/local/lib/libvulkan.so.1
#7  0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
(gdb) frame 7
#7  0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
26	  auto code = vkCreateInstance(&amp;instanceInfo, nullptr, &amp;instance);
(gdb) p instanceInfo
$1 = {sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, pNext = 0x0, flags = 0, pApplicationInfo = 0x7fffffffe6f8, enabledLayerCount = 0, 
  ppEnabledLayerNames = 0x0, enabledExtensionCount = 0, ppEnabledExtensionNames = 0x0}

I expected the instance to get created successfully.

答案1

得分: 0

我认为这只是在您的 VkApplicationInfo 结构中使用了错误的宏的简单情况。我不确定在您的系统上 VK_VERSION_1_3 展开为什么,因为我只有 VK_VERSION_1_2,但它只展开为 1

在我的代码中,我仅仅是将那个宏替换为看似正确的宏。请注意,我通过运行 /usr/bin/vulkaninfo | head 并注意输出来获取正确的版本号来填充该宏。例如:

Vulkan Instance Version: 1.2.131

你的版本可能会不同。为了完整起见,这是我没有再发生段错误的代码(我在ubuntu上使用了稍微不同版本的vulkan,因此有额外的头文件):

#include <iostream>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan.hpp>

int main(){
  VkApplicationInfo info{};
  info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  info.pNext = nullptr;
  info.apiVersion = VK_MAKE_VERSION(1, 2, 131);
  info.applicationVersion = 1;
  info.engineVersion = 0;
  info.pApplicationName = "App";
  info.pEngineName = nullptr;

  VkInstanceCreateInfo instanceInfo{};
  instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  instanceInfo.pNext = nullptr;
  instanceInfo.flags = 0;
  instanceInfo.enabledExtensionCount = 0;
  instanceInfo.enabledLayerCount = 0;
  instanceInfo.ppEnabledExtensionNames = nullptr;
  instanceInfo.ppEnabledLayerNames = nullptr;
  instanceInfo.pApplicationInfo = &info;

  VkInstance instance;
  auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);

  if (code != VK_SUCCESS){
    std::cout << "failed to create instance" << std::endl;
    return -1;
  } else vkDestroyInstance(instance, nullptr);
  return 0;
}

补充说明,看起来您也可以通过以下方式轻松地以编程方式获取此信息,从这个答案中偷来:

通过代码检查(无论使用哪种语言,只要您有头文件),可以通过使用 vkGetPhysicalDeviceProperties 查询设备属性来完成。VkPhysicalDeviceProperties 结构的 apiVersion 成员包含该设备的最大支持版本。只需移位位或使用头文件中的版本宏即可获得可读的版本号(主要版本.次要版本.修订版本)。

英文:

I think its a simple case of using the wrong macro in your VkApplicationInfo struct. I am not sure what VK_VERSION_1_3 expands to on your system as I only have VK_VERSION_1_2, but that only expands to 1.

In my code here, I have done nothing but replace that macro with the seemingly correct macro. Note that I obtained the correct version numbers to fill the macro with by running /usr/bin/vulkaninfo | head and noting the output

Vulkan Instance Version: 1.2.131

And yours will likely be different. For completeness, this is the code I have which no longer segfaults (I am on ubuntu with a slightly different version of vulkan, hence the extra headers):

#include &lt;iostream&gt;
#include &lt;vulkan/vulkan.h&gt;
#include &lt;vulkan/vulkan_core.h&gt;
#include &lt;vulkan/vulkan.hpp&gt;

int main(){
  VkApplicationInfo info{};
  info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  info.pNext = nullptr;
  info.apiVersion = VK_MAKE_VERSION(1, 2, 131);
  info.applicationVersion = 1;
  info.engineVersion = 0;
  info.pApplicationName = &quot;App&quot;;
  info.pEngineName = nullptr;

  VkInstanceCreateInfo instanceInfo{};
  instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  instanceInfo.pNext = nullptr;
  instanceInfo.flags = 0;
  instanceInfo.enabledExtensionCount = 0;
  instanceInfo.enabledLayerCount = 0;
  instanceInfo.ppEnabledExtensionNames = nullptr;
  instanceInfo.ppEnabledLayerNames = nullptr;
  instanceInfo.pApplicationInfo = &amp;info;

  VkInstance instance;
  auto code = vkCreateInstance(&amp;instanceInfo, nullptr, &amp;instance);

  if (code != VK_SUCCESS){
    std::cout &lt;&lt; &quot;failed to create instance&quot; &lt;&lt; std::endl;
    return -1;
  } else vkDestroyInstance(instance, nullptr);
  return 0;
}

Editing to note that it seems like you could also easily get this information programatically by doing the following, stolen from this answer:

> Checking via code (no matter what language, as long as you got headers) can be done by querying device properties via vkGetPhysicalDeviceProperties. The apiVersion member of the VkPhysicalDeviceProperties struct contains the maximum supported version for that device. Just shift the bits or use the version macros from the headers to get a humnan readable version (major.minor.patch).

huangapple
  • 本文由 发表于 2023年6月29日 02:50:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575947.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定