Skip to content

Instantly share code, notes, and snippets.

@RoryO
Created February 10, 2021 23:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RoryO/46530198f3791ccf8d3d22e671a23268 to your computer and use it in GitHub Desktop.
Save RoryO/46530198f3791ccf8d3d22e671a23268 to your computer and use it in GitHub Desktop.
Linux nvidia vulkan crash
// 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