-
-
Save RoryO/46530198f3791ccf8d3d22e671a23268 to your computer and use it in GitHub Desktop.
Linux nvidia vulkan crash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// build with | |
// cc -g nvidia-driver-crash.cpp -lm -lxcb -lvulkan | |
#define VK_USE_PLATFORM_XCB_KHR | |
#define STB_IMAGE_IMPLEMENTATION | |
#include <xcb/xcb.h> | |
#include <cstdlib> | |
#include <assert.h> | |
#include <vulkan/vulkan.h> | |
int | |
main() { | |
xcb_connection_t *xcb_connection = xcb_connect(nullptr, nullptr); | |
xcb_window_t xcb_window = xcb_generate_id(xcb_connection); | |
xcb_screen_t *xcb_screen = xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)).data; | |
uint32_t values[2]; | |
values[0] = xcb_screen->black_pixel; | |
values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | | |
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | | |
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | | |
XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_MOTION; | |
xcb_create_window(xcb_connection, | |
XCB_COPY_FROM_PARENT, | |
xcb_window, | |
xcb_screen->root, | |
0, 0, | |
1024, 768, | |
10, | |
XCB_WINDOW_CLASS_INPUT_OUTPUT, | |
xcb_screen->root_visual, | |
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, | |
values); | |
xcb_map_window(xcb_connection, xcb_window); | |
xcb_flush(xcb_connection); | |
xcb_generic_error_t *xcb_err = nullptr; | |
xcb_intern_atom_reply_t *atom_reply; | |
atom_reply = xcb_intern_atom_reply(xcb_connection, | |
xcb_intern_atom(xcb_connection, 1, 12, "WM_PROTOCOLS"), | |
&xcb_err); | |
xcb_atom_t wm_protocols = atom_reply->atom; | |
free(atom_reply); | |
atom_reply = xcb_intern_atom_reply(xcb_connection, | |
xcb_intern_atom(xcb_connection, 0, 16, "WM_DELETE_WINDOW"), | |
&xcb_err); | |
xcb_atom_t wm_delete_window = atom_reply->atom; | |
free(atom_reply); | |
xcb_discard_reply(xcb_connection, | |
xcb_change_property(xcb_connection, XCB_PROP_MODE_REPLACE, xcb_window, | |
wm_protocols, 4, 32, 1, &wm_delete_window).sequence); | |
const char *enabled_layer_names[] = { | |
"VK_LAYER_KHRONOS_validation", | |
}; | |
uint32_t enabled_layer_count = sizeof(enabled_layer_names) / | |
sizeof(enabled_layer_names[0]); | |
const char *enabled_instance_extension_names[] = { | |
"VK_KHR_surface", | |
#ifdef _WIN32 | |
"VK_KHR_win32_surface", | |
#elif __linux__ | |
"VK_KHR_xcb_surface", | |
#else | |
#endif | |
}; | |
uint32_t enabled_instance_extension_count = sizeof(enabled_instance_extension_names) / | |
sizeof(enabled_instance_extension_names[0]); | |
VkApplicationInfo application_info = {}; | |
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; | |
application_info.apiVersion = VK_MAKE_VERSION(1, 2, 0); | |
VkInstanceCreateInfo create_info = {}; | |
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; | |
create_info.pApplicationInfo = &application_info; | |
create_info.ppEnabledLayerNames = enabled_layer_names; | |
create_info.enabledLayerCount = enabled_layer_count; | |
create_info.ppEnabledExtensionNames = enabled_instance_extension_names; | |
create_info.enabledExtensionCount = enabled_instance_extension_count; | |
VkInstance instance = {}; | |
assert(vkCreateInstance(&create_info, nullptr, &instance) == VK_SUCCESS); | |
VkXcbSurfaceCreateInfoKHR surface_create_info = {}; | |
surface_create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; | |
surface_create_info.connection = xcb_connection; | |
surface_create_info.window = xcb_window; | |
VkSurfaceKHR surface = {}; | |
assert(vkCreateXcbSurfaceKHR(instance, &surface_create_info, nullptr, &surface) == VK_SUCCESS); | |
const uint8_t MAX_PHYSICAL_DEVICES = 5; | |
uint32_t physical_device_count = MAX_PHYSICAL_DEVICES; | |
VkPhysicalDevice physical_devices[MAX_PHYSICAL_DEVICES] = {}; | |
vkEnumeratePhysicalDevices(instance, &physical_device_count, physical_devices); | |
uint32_t selected_physical_device = 0; | |
if(physical_device_count > 1) { | |
for(uint32_t i = 0; i < physical_device_count; ++i) { | |
VkPhysicalDeviceProperties physical_device_properties = {}; | |
vkGetPhysicalDeviceProperties(physical_devices[i], &physical_device_properties); | |
if(physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { | |
selected_physical_device = i; | |
break; | |
} | |
} | |
assert(false); | |
} | |
VkPhysicalDevice physical_device = physical_devices[selected_physical_device]; | |
const uint8_t MAX_QUEUES = 10; | |
uint32_t num_queue_families = MAX_QUEUES; | |
VkQueueFamilyProperties queue_properties[MAX_QUEUES] = {}; | |
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, queue_properties); | |
uint32_t queue_family_index = 0; | |
for(uint32_t i = 0; i < num_queue_families; ++i) { | |
if((queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT) { | |
VkBool32 surface_supported = VK_FALSE; | |
assert(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, | |
surface, &surface_supported) == VK_SUCCESS); | |
if(surface_supported) { | |
queue_family_index = i; | |
break; | |
} | |
} | |
} | |
VkDeviceQueueCreateInfo queue_create_info = {}; | |
const float queue_priorities[] = { 1.0 }; | |
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; | |
queue_create_info.queueFamilyIndex = queue_family_index; | |
queue_create_info.queueCount = 1; | |
queue_create_info.pQueuePriorities = queue_priorities; | |
const char *enabled_device_extension_names[] = { | |
"VK_KHR_swapchain", | |
}; | |
uint32_t enabled_device_extension_count = sizeof(enabled_device_extension_names) / | |
sizeof(enabled_device_extension_names[0]); | |
VkDeviceCreateInfo device_create_info = {}; | |
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; | |
device_create_info.queueCreateInfoCount = 1; | |
device_create_info.pQueueCreateInfos = &queue_create_info; | |
device_create_info.enabledExtensionCount = enabled_device_extension_count; | |
device_create_info.ppEnabledExtensionNames = enabled_device_extension_names; | |
VkDevice device = {}; | |
assert(vkCreateDevice(physical_devices[selected_physical_device], &device_create_info, nullptr, &device) == VK_SUCCESS); | |
uint32_t n_surface_formats = 0; | |
assert(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices[selected_physical_device], | |
surface, &n_surface_formats, nullptr) == VK_SUCCESS); | |
VkSurfaceFormatKHR *surface_formats = reinterpret_cast<VkSurfaceFormatKHR*>(malloc(sizeof(VkSurfaceFormatKHR) * n_surface_formats)); | |
assert(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_devices[selected_physical_device], | |
surface, &n_surface_formats, surface_formats) == VK_SUCCESS); | |
VkSurfaceFormatKHR surface_format = surface_formats[0]; | |
free(surface_formats); | |
VkSurfaceCapabilitiesKHR surface_capabilities = {}; | |
assert(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices[selected_physical_device], | |
surface, &surface_capabilities) == VK_SUCCESS); | |
VkSwapchainCreateInfoKHR swapchain_create_info = {}; | |
// when imageFormat is not a valid VkSurfaceFormat, the nvidia X server crashes at vkCreateSwapchainKHR | |
// on Windows using Win32, the program crashes with a divide by zero error deep in | |
// nvogl.dll with the stack trace starting at vkCreateSwapchainKHR | |
// remove comment and the program functions fine | |
// swapchain_create_info.imageFormat = surface_format.format; | |
swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; | |
swapchain_create_info.surface = surface; | |
swapchain_create_info.minImageCount = 2; | |
swapchain_create_info.imageColorSpace = surface_format.colorSpace; | |
swapchain_create_info.imageExtent.width = surface_capabilities.currentExtent.width; | |
swapchain_create_info.imageExtent.height = surface_capabilities.currentExtent.height; | |
swapchain_create_info.imageArrayLayers = 1; | |
swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | |
swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; | |
swapchain_create_info.preTransform = surface_capabilities.currentTransform; | |
swapchain_create_info.compositeAlpha = static_cast<VkCompositeAlphaFlagBitsKHR> | |
(surface_capabilities.supportedCompositeAlpha); | |
swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; | |
swapchain_create_info.clipped = VK_TRUE; | |
VkSwapchainKHR swapchain = {}; | |
assert(vkCreateSwapchainKHR(device, &swapchain_create_info, nullptr, &swapchain) == VK_SUCCESS); | |
bool should_quit = false; | |
while(!should_quit) { | |
while(xcb_generic_event_t* event = xcb_poll_for_event(xcb_connection)) { | |
switch (event->response_type & ~0x80) { | |
case XCB_EXPOSE: { | |
xcb_flush(xcb_connection); | |
break; | |
} | |
case XCB_CLIENT_MESSAGE: { | |
if(((xcb_client_message_event_t*)event)->data.data32[0] == wm_delete_window) { | |
should_quit = true; | |
} | |
break; | |
} | |
} | |
free(event); | |
} | |
} | |
vkDestroySwapchainKHR(device, swapchain, nullptr); | |
vkDestroySurfaceKHR(instance, surface, nullptr); | |
vkDestroyDevice(device, nullptr); | |
vkDestroyInstance(instance, nullptr); | |
free(xcb_err); | |
xcb_destroy_window(xcb_connection, xcb_window); | |
xcb_flush(xcb_connection); | |
xcb_disconnect(xcb_connection); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment