Render while loading from a thread not working on Android

#1

What’s interesting is that this works fine on my PC running Arch Linux, but the same code compiled on Android is throwing an odd error. vkQueueSubmit is returning VK_ERROR_INITIALIZATION_FAILED (-3) and it’s not an error listed to be returned by vkQueueSubmit. This all works on Android if I don’t load from a thread. I’m currently rendering graphics on the screen when I try to load more.

I have a separate command pool specifically for loading from a thread where I create a primary command buffer from the loading thread.

The main process thread is where the rendering command pool, primary and secondary command buffers are allocated and used. Been doing a lot of tests but I’m stumped.

Any thoughts would be appreciated.

#2

It’s not clear what you mean by “loading from a thread” or how this differs from the alternative. What are you “loading”? Is this thread that you’re “loading” from just building the CB or is it submitting to a queue? If so, is that a different queue from the one the other thread(s) presumably are using (most Android-capable GPUs don’t allow for multiple queues)? If not, how are you synchronizing access to the queue? Because that’s a thing you have to do.

You cannot call vkQueueSubmit at the same time from multiple threads on the same queue.

#3

What I mean by “loading from a thread” is loading images. My code for loading images has it’s own queue (transfer queue) as well as it’s own command pool and buffer. The vkQueueSubmit that’s throwing the error uses the graphics queue.

I’ll take a closer look at the two different queues and make sure Android didn’t give me the same queue for both queues.

#4

That’s not really possible for the API to give you the same queue (not unless you haven’t turned on validation layers, which you should always be using during development). When you create a device, you do so in part by specifying a number of VkDeviceQueueCreateInfo objects. In order to get multiple queues from a device, you have to ask for them. Which means that either you checked the device properties to see if that device supports multiple queues for a particular family or which families it supports, or you assumed that it supported multiple queues.

And in the latter case, the validation layer should have given an error when you asked for more queues than the device offers, since VkDeviceQueueCreateInfo::queueCount would be larger than the number of queues supported by that family.

From a cursory examination of the Vulkan hardware database, it seems clear that the only Android-capable GPUs that support multiple queues at all are from NVIDIA. So unless you’re developing on an NVIDIA GPU, there’s no way you created a device with a separate “transfer queue”. Or at least, not correctly.

Indeed, the fact that you got VK_ERROR_INITIALIZATION_FAILED, which is an error returned by vkCreateDevice, makes it seem likely that you never got a working device to begin with.

#5

Well you totally clued me in. My Android which is a Galaxy Note 9 only has one queue family and doesn’t have a separate graphics and transfer queue. I totally forgot about the possibility of not having a separate transfer queue. As for the validation layers, Android doesn’t support validation layers.

In my game engine, I’ll now need to figure out how I’m going handle not having a separate transfer queue. I did a test using a mutex but it didn’t completely work.

#6

Hey, so Android does indeed support Validation Layers!

You might mixing up that they do not support “implicit layers” on release builds, but if you are the developer of the app, you have the ability to easily add them in.

As for separate transfer queue, it’s not because the device is Android, it’s because mobile phones have a UMA (Unified Memory Architecture) and this means you don’t have the long transfer latency which PC cards have going over the PCIe bus since the GPU and CPU share the same memory of the SoC. This also means you will find that you can map HOST_VISABLE memory to DEVICE_LOCAL memory without having to send a command buffer over to transfer it

#7

Thanks, you are correct! A year or more ago when I started trying to get my Vulkan game engine running on Android, the info online was that Android didn’t support Validation Layers. Since then I’ve put my Vulkan game engine aside (forgot some Vulkan concepts while updating WebGL engine) since I was waiting for my phone to get Pie 9 because that came with Vulkan 1.5. I was using a feature available in 1.0 but was broken on 1.0.

All is good now and I can load graphics and animate at the same time. Updated my logic to use one of the available graphics queues if a transfer bit was not found.