2

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

#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;                                                                       
}                                     

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

$ 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

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(&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 expected the instance to get created successfully.

  • Unrelated: Save yourself some code and take advantage of aggregate initialization. `VkInstanceCreateInfo instanceInfo{};` and the block of assignments could be `VkInstanceCreateInfo instanceInfo{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0, &info, ... };` – user4581301 Jun 28 '23 at 18:56
  • @user4581301 my code completer suggests the member names in alphabetical order, while according to cppref, one must "Initialize each element of the aggregate in the element order. That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order (since C++11).". This makes it too cumbersome for me to look up the order in the spec every time I have to pass a struct. As for the ordinary initializer list, it isn't explicit enough, in my opinion. It is easy to mistake a member name by looking at a value like nullptr. – Christopher Weronski Jun 28 '23 at 19:11
  • I can appreciate that, and with a simple POD structure you lose little (`VkInstanceCreateInfo instanceInfo{};` is zeroing the structure. If you're setting all of the members, you might as well `VkInstanceCreateInfo instanceInfo;` and initialize nothing) by spelling it out explicitly. [As of C++20 you can get the best of both worlds](https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers) – user4581301 Jun 28 '23 at 19:22

1 Answers1

0

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 <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;
}

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).

Douglas B
  • 585
  • 2
  • 13
  • I knew I never should have trusted those macros xD I'll be much more careful around them, from now on. – Christopher Weronski Jun 28 '23 at 19:35
  • 1
    You don't need to include the patch version for the apiVersion. The loader ignores it. You can also just use the correct macro rather than redefining it with a magic value; The correct macro is `VK_API_VERSION_1_3`. `VK_VERSION_X_Y` are feature macros for determining if the API you're compiling against supports that vulkan version, the `VK_API_VERSION_X_Y` contain the actual version number. – vandench Jun 28 '23 at 22:36