Hi,
I have few Vulkan games run well on numbers of Android devices. However, when I test them on HUAWEI P30 (not P30 Pro) with Mali-G76 MP10 GPU and Android 9.0, function vkCreateDevice() returns error VK_ERROR_FEATURE_NOT_PRESENT (VkResult:-8).
My app should have successfully loaded Vulkan dynamic lib since vkInstance has been created before creating vkDevice.
So what is the reason that vkCreateDevice() return VK_ERROR_FEATURE_NOT_PRESENT? Here is my code snippet:
// Create Logical Device, ensure that this device is connecte to graphics queue// Step 1 - Retrive the queue family that supports graphics pipelineuint32_t graphicQueueFamilyIndex;int i = 0;for (const auto& family : _queueFamilyProps){ // Check if the family has queues and that are Graphical and not Computational queues. if (family.queueCount > 0 && family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { graphicQueueFamilyIndex = i; //Found the family, record its index break; } i++;}// Step 2 - Get physical device featuresvkGetPhysicalDeviceFeatures(vkPhyDevice, &deviceFeatures); VkPhysicalDeviceFeatures enabledFeatures = {VK_FALSE};enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy;enabledFeatures.shaderSampledImageArrayDynamicIndexing = deviceFeatures.shaderSampledImageArrayDynamicIndexing;enabledFeatures.depthClamp = VK_TRUE;enabledFeatures.sampleRateShading = VK_TRUE;#if defined (NATIVE_LINEWIDTH_SUPPORT) enabledFeatures.wideLines = VK_TRUE; //MoltenVK (via Metal API) does not support line width#endif// Step 3 - Create the logical devicefloat queuePriorities[1] = { 0.0f };VkDeviceQueueCreateInfo queueCreateInfo { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //sType nullptr, //pNext 0, //flags graphicQueueFamilyIndex, //queueFamilyIndex 1, //queueCount queuePriorities //pQueuePriorities};std::vector<const char *> extensionNames { VK_KHR_SWAPCHAIN_EXTENSION_NAME };VkDeviceCreateInfo deviceInfo{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType nullptr, //pNext 0, //flags 1, //queueCreateInfoCount &queueCreateInfo, //pQueueCreateInfos 0, //enabledLayerCount nullptr, //ppEnabledLayerNames (uint32_t)extensionNames.size(), //enabledExtensionCount extensionNames.data(), //ppEnabledExtensionNames &enabledFeatures //pEnabledFeatures };VK_ASSERT(vkCreateDevice(vkPhyDevice, &deviceInfo, nullptr, &vkDevice));
// Create Logical Device, ensure that this device is connecte to graphics queue// Step 1 - Retrive the queue family that supports graphics pipelineuint32_t graphicQueueFamilyIndex;int i = 0;for (const auto& family : _queueFamilyProps){ // Check if the family has queues and that are Graphical and not Computational queues. if (family.queueCount > 0 && family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { graphicQueueFamilyIndex = i; //Found the family, record its index break; } i++;}// Step 2 - Get physical device featuresvkGetPhysicalDeviceFeatures(vkPhyDevice, &deviceFeatures); VkPhysicalDeviceFeatures enabledFeatures = {VK_FALSE};enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy;enabledFeatures.shaderSampledImageArrayDynamicIndexing = deviceFeatures.shaderSampledImageArrayDynamicIndexing;enabledFeatures.depthClamp = VK_TRUE;enabledFeatures.sampleRateShading = VK_TRUE;#if defined (NATIVE_LINEWIDTH_SUPPORT) enabledFeatures.wideLines = VK_TRUE; //MoltenVK (via Metal API) does not support line width#endif// Step 3 - Create the logical devicefloat queuePriorities[1] = { 0.0f };VkDeviceQueueCreateInfo queueCreateInfo { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //sType nullptr, //pNext 0, //flags graphicQueueFamilyIndex, //queueFamilyIndex 1, //queueCount queuePriorities //pQueuePriorities};std::vector<const char *> extensionNames { VK_KHR_SWAPCHAIN_EXTENSION_NAME };VkDeviceCreateInfo deviceInfo{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType nullptr, //pNext 0, //flags 1, //queueCreateInfoCount &queueCreateInfo, //pQueueCreateInfos 0, //enabledLayerCount nullptr, //ppEnabledLayerNames (uint32_t)extensionNames.size(), //enabledExtensionCount extensionNames.data(), //ppEnabledExtensionNames &enabledFeatures //pEnabledFeatures };VK_ASSERT(vkCreateDevice(vkPhyDevice, &deviceInfo, nullptr, &vkDevice
));
Thanks, we've raised this enhancement request with the product team.
Hi Pete,
I double checked my OpenGL ES sourc code, it is true that OpenGL ES 3.0 API does not natively support "glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);". I emulate wireframe rendering by drawing triangle's outlines through "glDrawElements(GL_LINE_LOOP, ...)". Sorry for the wrong information I provided. I will use them same emulation method for Vulkan on Mali GPUs.
However, having this feature on Mali in the future might be good since other competitors like Adreno and PowerVR do have this handy feature.
Regards,
Hongkun
I've just checked with the engineering team for this one, and it's not something we support natively in our driver for OpenGL ES (glPolygonMode is only available via an extension, which we don't support).
Are you using a game engine which is emulating this functionality? Could a similar emulation be used for Vulkan?
Cheers, Pete
Thanks for the feedback - I'll raise with the GPU product management team.
Hi Ben,
I also found that another Vulkan feature "fillModeNonSolid" is not support by Mali Vulkan Driver (I have tested on Mali-T880 and Mali-G76).
This feature is important when need to render 3D object in wireframe mode. Interestingly, when I switch the graphics back-end of my app back to OpenGL ES, the wireframe rendering works well by "glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);", which means the GPU is actually capable of doing wireframe rendering.
So why Mali vulkan driver disable this feature even if the GPU is capable of that? Wondering if this feature can be back in the future Vulkan driver.
Thanks.
Glad you fixed the issue.
King regards,
Ben
It turns out that "enabledFeatures.depthClamp = VK_TRUE;" should be removed from the enabled feature list. After that it is working.
I should have tried to remove some device features before I post this question, is now solved.
View all questions in Graphics and Gaming forum