Unhandled Exception Regarding vkWaitForFences

I am trying to follow a tutorial on creating my first triangle in Vulkan. This has been a pretty smooth and educational experience thus far, though I have now found myself at a roadblock. The tutorial I am following is the one at vulkan-tutorial dot com. The author of this tutorial explains things very well and has taught me a lot.

The roadblock in question is inside the draw loop, its the vkWaitForFences function and other fence related functions that throw an unhandled exception. This exception is complaining of a read access violation, which if I am correct, means there is a pointer to memory which is null. I have checks all along the way throughout the creation of the device, swapchain, fences, semaphores, etc. None of the checks fail all the way through to the draw loop.

The version of Vulkan I am using is 1.3, along with windows 11 pro, 32gb of ram and an rtx 3070 laptop graphics card. My graphics driver version is 535.98.0.0, api version 1.3.242. If there is more system information that is needed, please let me know and I will provide.

What makes me more stumped is that I was following the tutorial most of the time throughout this crucial process. I have received no errors from my validation layers, which appear to work, at least occasionally, but again they may not be perfect as well.

I am going to attach screenshots of the fence/semaphore creation as well as the error in the draw loop. I hope I was not horrible at describing my issue, as I hate posting questions about things, I have spent maybe 2 - 3 days looking for a solution and can’t find one. I appreciate any help I do get in advance!

I am not allowed to embed links since I am too new, so not sure what to do there. I will post the function code for fence/semaphore creation and the first relevant part of the draw loop instead.

Fence/Semaphore creation function

void Rendering::CreateVulkanSyncObjects()
	{
		VkSemaphoreCreateInfo SemaphoreInfo = {};
		SemaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
		

		VkFenceCreateInfo FenceInfo = {};
		FenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
		FenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
		FenceInfo.pNext = nullptr;

		VkResult result = vkCreateSemaphore(m_VulkanDevice, &SemaphoreInfo, nullptr, &m_VkImageAvailable);
		if (result != VkResult::VK_SUCCESS)
		{
			AD_ASSERT(L"Failed to create image availability semaphore sync object!")
		}

		result = vkCreateSemaphore(m_VulkanDevice, &SemaphoreInfo, nullptr, &m_VkRenderFinished);
		if (result != VkResult::VK_SUCCESS)
		{
			AD_ASSERT(L"Failed to create render semaphore sync object!")
		}

		result = vkCreateFence(m_VulkanDevice, &FenceInfo, nullptr, &m_VkInFlight);
		if (result != VkResult::VK_SUCCESS)
		{
			AD_ASSERT(L"Failed to create in flight fence sync object!")
		}
	}

Top section of draw loop containing the error

else if (isVulkan)
		{
			VkResult result = VkResult::VK_SUCCESS;
			// Waits for gpu to catch up // Seems fences are causing problems!
			result = vkWaitForFences(m_VulkanDevice, 1, &m_VkInFlight, VK_TRUE, UINT64_MAX); // ERROR
			if (result != VkResult::VK_SUCCESS)
			{
				AD_ASSERT(L"Failed to wait for fences!")
			}

			// After waiting, then reset the signal back to unsignaled for next time
			result = vkResetFences(m_VulkanDevice, 1, &m_VkInFlight); 
			if (result != VkResult::VK_SUCCESS)
			{
				AD_ASSERT(L"Failed to reset fence signals!")
			}
		}

Show me your full VK_LAYER_LUNARG_api_dump.

I am attempting to get an api dump for you, though its proving difficult for me. I tried to set the layer up internally through the source code, but seemed to not get any results. I then decided to try it through vkconfig and I am still getting no results.

Something to note here, I am getting a process terminated message as soon as I launch the program through vkconfig. I am positive this is due to the error that I am trying to solve, but still feel it should be giving me some sort of information to debug and find the root cause of the problem, no? I am sorry if I am a little frustrating to deal with but its quite a new journey for me and I will of course do my best to make things easy.

Here is a screenshot of vkconfig and the output
https://i.imgur.com/0CCmYYp.png

I have gone through the VkLayer_override json to see if there were settings I needed to enable and everything seemed to be fine. I will be actively working on this until further notice, this I am sure is a critical feature that should be used often. Let me know what your thoughts are and if you think I screwed this up somehow.

I believe by a stroke of luck, I managed to get the dump file. Had to have the vkconfig open with the settings I wanted and then simply ran the executable outside of vkconfig and voila! Anyways, seems I have so much to learn with all of this, seems to be extremely specific to get some things working and I never saw any documentation explaining that as the way to use vkconfig, but oh well. Not sure how to show you the full dump without an extremely long reply, so sorry about this.

VK_LAYER_LUNARG_api_dump

Hehe, newfangled utilities. You would just open command prompt and run your thing with VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_api_dump environment variable, and that’s it.

Nah, full log of tutorial-like app is fine. I can scan it quickly irrespective of perceived length.

There doesn’t seem to be no Wait executed there though. Also you are enabling VK_KHR_external_fence extension for something, which would imply there is larger complexity to this than it would seem.

Oh okay, gotcha! Yeah, since getting the validation and api dump to work, I have solved some errors and warnings that have showed up. I have taken the VK_KHR_external_fences out of the extensions. That was mainly there just as an attempt to fix what was happening. I wasn’t sure if it was needed to use fences, though the tutorial never showed of it. It however, did not fix the issue at hand unfortunately.

What do you mean by

“There doesn’t seem to be no Wait executed there though”

That is in fact where the application throws an exception so possibly its just not calling it. Not really sure why.

I will continue to report back on any findings I have and hopefully with a resolution sometime soon! Thanks again for looking into things for me.

Also a follow up, I am going to post the screenshots now that it seems that I have a higher trust level from searching for an answer on the forums here haha.

Draw Loop where the error happens on the first line of vkWaitForFences

Fence/Semaphore object creation

Well, if it had crashed with unhandled exception, then the log would just end there. But instead it seem to end properly, all the way to teardown.

Something is nullptr. The primary suspects would be one of the two parameters you pass.

Yeah, that was my assumption too. I guess I just overlooked a part of the tutorial, not really sure. I will attempt to find this pesky nullptr. I just feel that if it was in fact a nullptr, the validation should have called back with the device or whatever being nullptr. I believe in debugging inside of trampoline.c there is a callback message of "vkGetFenceStatus: Invalid device [VUID-vkGetFenceStatus-device-parameter]". Says its a loader log so maybe different from the validation messenger callback.

I will also attach a screenshot of the function that is in the call stack that seems to fail.

trampoline.c function fail

Is there a validation function to see if the VkDevice is in fact valid and not nullptr?

Before posting a question here in the first place I checked this using a breakpoint on the line but it did have an address. Not sure if the address can exist, even when the memory its holding doesn’t. This question here is more of a c++ question. I suppose if it was a pointer to memory that no longer existed it would make since but, isn’t the VkDevice an object, not a pointer?

No, it’s a pointer:

The devices, queues, and other entities in Vulkan are represented by Vulkan objects. At the API level, all objects are referred to by handles. There are two classes of handles, dispatchable and non-dispatchable. Dispatchable handle types are a pointer to an opaque type.

VkDevice is a dispatchable handle, and is therefore a pointer.

Oh okay, thank you for that information! Is there a simple way to hunt down a pointer to null memory? I just assumed that if the device creates with the result of VK_SUCCESS that the memory would be filled in properly until it is destroyed by the VkDestroyDevice function. How would it get this far as a pointer to null memory, or is it just because the pointer itself is technically not nullptr so it acts as if its not through all the other Vulkan creation functions?

So I believe in the tutorial just to render the simple triangle, the author said to create an initialized struct of VkPhysicalDeviceFeatures just as a placeholder until we decided to actually use the features. I just now decided to fetch the data to see if it somehow clears things up and now I am getting a unhandled exception to a new function inside of trampoline.c. Its now happening at vkResetFences. Not sure if its progress or not but its something new and the address that its complaining about is not 0x0000000000, its a legitimate address.

Screenshot

I have done absolutely nothing and its now failing at vkGetFenceStatus again. I am really scratching my head on this one. But its still an actual address that its trying to access at least.

And I am now getting fatal program exit requested instead of the previous exception.

While using vkconfig validation with the application, I get a different exception message. Its in the exact same spot as the others. Starting at vkWaitForFences.

Screenshot of exception
i1dpmpH2x4

The art of debugging is trying not to get dragged into pointless rabbit holes and specifics. My old mom always asks what was the problem, like it is meaningful. I always tell her I don’t know and don’t care, I just turned it off and on \ reinstalled \ resetted it and it just works now.

Hierarchy of blame starts with your code (then the driver, and so on). So we start with that assumption. Now you either do pass valid inputs, or you don’t. That is pretty binary situation. Unfortunatelly things may crash later down the road from the actual bug.

Now the API dump would allow us to see the full timeline of things, and it is a matter of 10 minutes tops to review it when roughly knowing what we are looking for. And I suspect the dump you provided is not proper. All that is done in it is fence is created and then destroyed, and the app seem terminated successfuly. Full code would be as good, though it is easier to miss things the more things are abstracted and indirect (while api dump should show the sequence as it actually is, and the parameter values as they actually are; including potential accidental nullptrs).

I know it’s a bit of a silly remark (you may have already checked) but as for that one call there isn’t a great deal of nullptr chance given parameters: vkWaitForFences(3).

I’d double check with a breakpoint before call whether pFences does in fact contain your previously created VkFence (at position 0 of the vector/array) given your count of 1

I am not using a vector of fences as of yet, going by the tutorial, but… I did place a breakpoint as you suggested just after creation of the VkFence and the memory address is 0xcccccccccccccccc. Which from what I just looked up, is essentially invalid memory filled in by the system to detect uninitialized values.

Why would that be? This is more than likely the issue lol