Results 1 to 6 of 6

Thread: vkCreateDevice Exception thrown at 0x0000000000000000

  1. #1
    Junior Member
    Join Date
    Jun 2018
    Posts
    3

    vkCreateDevice Exception thrown at 0x0000000000000000

    Hello,

    In my setup I have 2 'video cards', when enumerating the devices they show up in this order
    - GeForce GTX 1080
    - Intel(R) UHD Graphics 630

    I have a piece of code that selects the physical device to run on and (for testing purposes) I sometimes run on the 630 (as a low end card). However it seems that when I try to create a device for the Intel(R) UHD Graphics 630, it crashes in VkCreateDevice. Now this only happens if the GeForce GTX 1080 is enabled, since then the vulkan instance enumerates 2 devices. if I disable the 1080 through device manager, the same code works. Vulkan then only enumerates 1 device and it works as you think it would.

    I expected the validation layer to give some more information, but unfortunately it does not. I can see the callstack in the crash:

    0000000000000000() Unknown
    igvk64.dll!00007fff0876aec6() Unknown
    igvk64.dll!00007fff0874e11e() Unknown
    igvk64.dll!00007fff0873af5a() Unknown
    vulkan-1.dll!00007fff23249dbb() Unknown
    VkLayer_unique_objects.dll!unique_objects::CreateD evice(VkPhysicalDevice_T * gpu, const VkDeviceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDevice_T * * pDevice) Line 207 C++
    VkLayer_threading.dll!threading::CreateDevice(VkPh ysicalDevice_T * gpu, const VkDeviceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDevice_T * * pDevice) Line 163 C++
    VkLayer_parameter_validation.dll!parameter_validat ion::vkCreateDevice(VkPhysicalDevice_T * physicalDevice, const VkDeviceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDevice_T * * pDevice) Line 552 C++
    VkLayer_object_tracker.dll!object_tracker::CreateD evice(VkPhysicalDevice_T * physicalDevice, const VkDeviceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDevice_T * * pDevice) Line 834 C++
    VkLayer_core_validation.dll!core_validation::Creat eDevice(VkPhysicalDevice_T * gpu, const VkDeviceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDevice_T * * pDevice) Line 2242 C++

    Which seems to indicate that the problem is somewhere in the Intel driver (igvk64.dll)

    To make it easy to reproduce I have put together a small piece of code that tries to create a device for each enumerated physical device (attachments seem to not work, so code is copy/pasted below)

    I am running Vulkan runtime 1.1.73.0
    I am running NVIDIA driver 397.93
    I am running Intel UHD Graphics Driver 22.20.16.4758 (supports vulkan version 1.0.50)

    Another interesting thing, which does not cause crashes but triggers the validation layer, seems to be that when using the NVIDIA driver you are required to call vkGetPhysicalDeviceQueueFamilyProperties, as just setting the queueFamilyIndex to 0 will trigger validation errors.


    Code :
    #define WIN32_LEAN_AND_MEAN			/// vulkan.h includes windows.h, so the Windows defines need to happen before including vulkan.h
    #define NOMINMAX
    #define VK_USE_PLATFORM_WIN32_KHR
    #include <vulkan/vulkan.h>
    #include <assert.h>
     
    #include <malloc.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    #define VK_CHECK_RESULT(x)										do { VkResult result = (x); assert(result == VK_SUCCESS); } while(0)
    #define VK_CHECK_RESULT_RETURN(x)								do { VkResult result = (x); assert(result == VK_SUCCESS); if(result != VK_SUCCESS) return; } while(0)
    #define sizeof_array(x)											(sizeof(x) / sizeof(x[0]))
     
    void Print(const char* text)
    {
    	printf("%s\n", text);
     
    	OutputDebugStringA(text);
    	OutputDebugStringA("\n");
    }
     
    class TestCreateDevices
    {
    public:
     
    	TestCreateDevices()
    	{
    		CreateInstance("");
    		CreateDevices();
    		DestroyInstance();
    	}
     
    private:
     
    	void CreateInstance(const char* applicationName)
    	{
    		// Enabled Extensions
    		const char* enabledExtensions[] =
    		{
    			"VK_KHR_surface",
    			"VK_KHR_win32_surface",
    		};
     
    		// Enabled Layers
    		const char* enabledLayers[] =
    		{
    			"VK_LAYER_LUNARG_assistant_layer",
    			"VK_LAYER_LUNARG_core_validation",
    			"VK_LAYER_LUNARG_object_tracker",
    			"VK_LAYER_LUNARG_parameter_validation",
    			"VK_LAYER_LUNARG_standard_validation",
    		};
     
    		VkApplicationInfo applicationInfo = {};
    		applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    		applicationInfo.pApplicationName = applicationName;
    		applicationInfo.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
    		applicationInfo.pEngineName = applicationName;
    		applicationInfo.engineVersion = VK_MAKE_VERSION(0, 1, 0);
    		applicationInfo.apiVersion = VK_API_VERSION_1_1;
     
    		VkInstanceCreateInfo instanceCI = {};
    		instanceCI.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    		instanceCI.pApplicationInfo = &applicationInfo;
    		instanceCI.ppEnabledExtensionNames = enabledExtensions;
    		instanceCI.enabledExtensionCount = static_cast<uint32_t>(sizeof_array(enabledExtensions));
    		instanceCI.ppEnabledLayerNames = enabledLayers;
    		instanceCI.enabledLayerCount = static_cast<uint32_t>(sizeof_array(enabledLayers));
     
    		VK_CHECK_RESULT(vkCreateInstance(&instanceCI, mAllocationCallbacks, &mInstance));
    	}
     
    	void DestroyInstance()
    	{
    		vkDestroyInstance(mInstance, mAllocationCallbacks);
    		mInstance = VK_NULL_HANDLE;
    	}
     
    	void CreateDevices()
    	{
    		uint32_t physicalDeviceCount = 0;
    		VK_CHECK_RESULT_RETURN(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
     
    		VkPhysicalDevice* physicalDevices = (VkPhysicalDevice*)alloca(sizeof(VkPhysicalDevice) * physicalDeviceCount);
    		VK_CHECK_RESULT_RETURN(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, physicalDevices));
     
    		Print("Devices:"); 
    		for (uint32_t i = 0; i < physicalDeviceCount; ++i)
    		{
    			VkPhysicalDeviceProperties physicalDeviceProperties;
    			vkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties);
    			Print(physicalDeviceProperties.deviceName);
     
    			VkPhysicalDeviceFeatures physicalDeviceFeatures;
    			vkGetPhysicalDeviceFeatures(physicalDevices[i], &physicalDeviceFeatures);
     
    			// queueFamilyIndex
    			uint32_t queueFamilyIndex = 0;
    			uint32_t queueFamilyPropertyCount;
    			vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i], &queueFamilyPropertyCount, nullptr);
    			assert(queueFamilyPropertyCount > 0);
     
    			VkQueueFamilyProperties* queueFamilyProperties = (VkQueueFamilyProperties*)alloca(sizeof(VkQueueFamilyProperties) * queueFamilyPropertyCount);
    			vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i], &queueFamilyPropertyCount, queueFamilyProperties);
     
    			// queue
    			float queuePriority = 1.0f;
    			VkDeviceQueueCreateInfo queueCI = {};
    			queueCI.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    			queueCI.pNext = nullptr;
    			queueCI.flags = 0;
    			queueCI.queueFamilyIndex = queueFamilyIndex;
    			queueCI.queueCount = 1;
    			queueCI.pQueuePriorities = &queuePriority;
     
    			const char* enabledExtensions[] =
    			{
    				"VK_KHR_swapchain",
    			};
     
    			VkDeviceCreateInfo deviceCI = {};
    			deviceCI.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    			deviceCI.pNext = nullptr;
    			deviceCI.flags = 0;
    			deviceCI.queueCreateInfoCount = 1;
    			deviceCI.pQueueCreateInfos = &queueCI;
    			deviceCI.enabledLayerCount = 0;
    			deviceCI.ppEnabledLayerNames = nullptr;
    			deviceCI.ppEnabledExtensionNames = enabledExtensions;
    			deviceCI.enabledExtensionCount = static_cast<uint32_t>(sizeof_array(enabledExtensions));
    			deviceCI.pEnabledFeatures = &physicalDeviceFeatures;
     
    			VkDevice device;
    			VK_CHECK_RESULT(vkCreateDevice(physicalDevices[i], &deviceCI, mAllocationCallbacks, &device));
    			vkDestroyDevice(device, mAllocationCallbacks);
    		}
    	}
     
    	VkAllocationCallbacks*				mAllocationCallbacks = nullptr;
    	VkInstance							mInstance = VK_NULL_HANDLE;
    };
     
     
    int main(int argc, char* argv[])
    {
    	TestCreateDevices();
    	return 0;
    }
    Last edited by efolkertsma; 06-03-2018 at 02:56 PM.

  2. #2
    Senior Member
    Join Date
    Mar 2016
    Posts
    314
    You are enabling layers twice, and in weird order. Remove the VK_LAYER_LUNARG_core_validation, VK_LAYER_LUNARG_object_tracker and VK_LAYER_LUNARG_parameter_validation.
    VK_LAYER_LUNARG_assistant_layer should probably be last, as to first catch errors before potentially crashing.
    Should also enable identical set in vkCreateDevice for compatibility.

  3. #3
    Junior Member
    Join Date
    Jun 2018
    Posts
    3
    Thank you for the suggestions.

    I am not 100% clear what you mean by "you are enabling layers twice", to my understanding there are instance layers and device layers and the set is not necessarily the same.

    That said... I tried your approach of reorder/remove and I tried to disable all layers/extensions both on the vkInstance and the vkDevice and the crash remains the same.

  4. #4
    Senior Member
    Join Date
    Mar 2016
    Posts
    314
    Quote Originally Posted by efolkertsma View Post
    I am not 100% clear what you mean by "you are enabling layers twice", to my understanding there are instance layers and device layers and the set is not necessarily the same.
    Your enable set is:

    Code :
    		const char* enabledLayers[] =
    		{
    			"VK_LAYER_LUNARG_assistant_layer",
    			"VK_LAYER_LUNARG_core_validation",
    			"VK_LAYER_LUNARG_object_tracker",
    			"VK_LAYER_LUNARG_parameter_validation",
    			"VK_LAYER_LUNARG_standard_validation",
    		};

    The VK_LAYER_LUNARG_standard_validation is a meta-layer which expands to:

    Code :
    VK_LAYER_GOOGLE_threading
    VK_LAYER_LUNARG_parameter_validation
    VK_LAYER_LUNARG_object_tracker
    VK_LAYER_LUNARG_core_validation
    VK_LAYER_GOOGLE_unique_objects

    (in this order; BTW the order matters too).
    Therefore, as you can see, you are practically enabling the VK_LAYER_LUNARG_core_validation, VK_LAYER_LUNARG_object_tracker and VK_LAYER_LUNARG_parameter_validation twice.

    Also as you can see, even if you removed VK_LAYER_LUNARG_standard_validation from the list, the remaining layers are in different order than how canonical VK_LAYER_LUNARG_standard_validation meta-layer would enable them.

    Errors that would be otherwisely caught by the Validation Layers, can crash other types of layers (without error message). Therefore it usually (not always) makes sense to have the Validation Layers first in the list, and others last (such as the VK_LAYER_LUNARG_assistant_layer), so it first prints an error message then crashes, not other way around.

    As for the device layers, they were deprecated. But for backwards-compatibility you are supposed to pretend they are not. My preferred way to do so is just to pass to the vkCreateDevice the exact same enabledLayers you gave to vkCreateInstance

    As for your crash, I would suggest updating the drivers. There seems to be v24 (with 1.1.73).
    I previously had problems with this kind of "multi-monitor" setup -- in Linux distro though. I kinda hope it works though. Everybody gets shoved the iGPUs their throats, so it is quite common setup (though it has to be enabled in BIOS).

  5. #5
    Senior Member
    Join Date
    Mar 2016
    Posts
    314
    PS:
    Check if your Queue Family actually has >0 queues.

    For NVIDIA there seems to be v398 driver available.
    Last edited by krOoze; 06-07-2018 at 02:53 AM.

  6. #6
    Junior Member
    Join Date
    Jun 2018
    Posts
    3
    Updated both Intel + NVIDIA drivers now it works... thank you for the suggestions!

    I am running NVIDIA driver 398.11
    I am running Intel UHD Graphics Driver 24.20.100.6136

    PS1: When I originally tried to update the Intel Driver I got errors from the installer that the driver was not validated for the OS. Turns out that some vendors have their own driver vetting and block driver versions they didn't vet yet. Fortunately this is something that can be overridden by manually selecting the driver through the .inf file. Not very user friendly, but does the trick.
    PS2: When I first installed just the Intel driver then it failed to create device for the GTX 1080, then I updated that driver... success.
    PS3: After the updated drivers I did get warnings on a layer not being supported, fortunately the real code (not the sample) checks the layers I'm trying to enable against the layers supported (as queried by the device)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean