Greetings everyone,
Is there any example on how to execute a Vulkan example, with Mali drivers, on Linux using the fbdev interface ?
I'm just wondering how the display initialisation and surface creation should be handled on such platforms, with Vulkan.
This is done through VK_KHR_display extension. Instead of creating a VkSurfaceKHR from X11/Wayland window handles, there is a special API to query display modes and you can create a VkSurfaceKHR directly from that API.
!! Thanks for the answer and these precious informations !
Will the code described in the aforementioned extension proposal text do the trick ?
The extension proposal text being :
http://vulkan-spec-chunked.ahcox.com/apes04.html
They seem to suggest using this code :
extern VkBool32 ModeMatchesMyCriteria(const VkDisplayModePropertiesKHR *m); extern VkInstance instance; extern VkPhysicalDevice physDevice; extern VkSurfaceKHR surface; uint32_t displayCount, planeCount, i, j, k; VkDisplayPropertiesKHR* pDisplayProps; VkDisplayPlanePropertiesKHR* pPlaneProps; VkDisplayModeKHR myMode = VK_NULL_HANDLE; VkDisplayKHR myDisplay = VK_NULL_HANDLE; uint32_t bestPlane = UINT32_MAX; VkDisplayPlaneAlphaFlagBitsKHR alphaMode = 0; PFN_vkGetPhysicalDeviceDisplayPropertiesKHR pfnGetPhysicalDeviceDisplayPropertiesKHR; PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR pfnGetPhysicalDeviceDisplayPlanePropertiesKHR; PFN_vkGetDisplayModePropertiesKHR pfnGetDisplayModePropertiesKHR; PFN_vkGetDisplayPlaneCapabilitiesKHR pfnGetDisplayPlaneCapabilitiesKHR; PFN_vkGetDisplayPlaneSupportedDisplaysKHR pfnGetDisplayPlaneSupportedDisplaysKHR; PFN_vkCreateDisplayPlaneSurfaceKHR pfnCreateDisplayPlaneSurfaceKHR; pfnGetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR) vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"); pfnGetPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR) vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"); pfnGetDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR) vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR"); pfnGetDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR) vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR"); pfnGetDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR) vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR"); pfnCreateDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR) vkGetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR"); // Get a list of displays on a physical device displayCount = 0; pfnGetPhysicalDeviceDisplayPropertiesKHR(physDevice, &displayCount, NULL); pDisplayProps = (VkDisplayPropertiesKHR*)malloc(sizeof(VkDisplayPropertiesKHR) * displayCount); pfnGetPhysicalDeviceDisplayPropertiesKHR(physDevice, &displayCount, pDisplayProps); // Get a list of display planes on a physical device planeCount = 0; pfnGetPhysicalDeviceDisplayPlanePropertiesKHR(physDevice, &planeCount, NULL); pPlaneProps = (VkDisplayPlanePropertiesKHR*)malloc(sizeof(VkDisplayPlanePropertiesKHR) * planeCount); pfnGetPhysicalDeviceDisplayPlanePropertiesKHR(physDevice, &planeCount, pPlaneProps); // Get the list of pModes each display supports for (i = 0; i < displayCount; ++i) { VkDisplayKHR display = pDisplayProps[i].display; VkDisplayModePropertiesKHR* pModes; uint32_t modeCount; vkGetDisplayModePropertiesKHR(physDevice, display, &modeCount, NULL); pModes = (VkDisplayModePropertiesKHR*)malloc(sizeof(VkDisplayModePropertiesKHR) * modeCount); vkGetDisplayModePropertiesKHR(physDevice, display, &modeCount, pModes); myMode = VK_NULL_HANDLE; for (j = 0; j < modeCount; ++j) { const VkDisplayModePropertiesKHR* mode = &pModes[i]; if (ModeMatchesMyCriteria(mode)) { myMode = mode->displayMode; break; } } free(pModes); // If there are no useable pModes found then check the next display. if (myMode == VK_NULL_HANDLE) continue; // Find a plane that matches these criteria, in order of preference: // -Is compatible with the chosen display + mode. // -Isn't currently bound to another display. // -Supports per-pixel alpha, if possible. for (j = 0; j < planeCount; ++j) { uint32_t supportedCount = 0; VkDisplayKHR* pSupportedDisplays; VkDisplayPlaneCapabilitiesKHR planeCaps; // See if the plane is compatible with the current display. pfnGetDisplayPlaneSupportedDisplaysKHR(physDevice, j, &supportedCount, NULL); // Plane doesn't support any displays. This might happen on a card // that has a fixed mapping between planes and connectors when no // displays are currently attached to this plane's conector, for // example. if (supportedCount == 0) continue; pSupportedDisplays = (VkDisplayKHR*)malloc(sizeof(VkDisplayKHR) * supportedCount); pfnGetDisplayPlaneSupportedDisplaysKHR(physDevice, j, &supportedCount, pSupportedDisplays); for (k = 0; k < supportedCount; ++k) if (pSupportedDisplays[k] == display) { // If no supported plane has yet been found, this is // currently the best available plane. if (bestPlane == UINT32_MAX) bestPlane = j; break; } // If the plane can't be used with the chosen display, keep looking. // Each display must have at least one compatible plane. if (k == supportedCount) continue; // If the plane passed the above test and is currently bound to the // desired display, or is not in use, it is the best plane found so // far. if ((pPlaneProps[j].currentDisplay == VK_NULL_HANDLE) && (pPlaneProps[j].currentDisplay == display)) bestPlane = j; else continue; pfnGetDisplayPlaneCapabilitiesKHR(physDevice, myMode, j, &planeCaps); // Prefer a plane that supports per-pixel alpha. if (planeCaps.supportedAlpha & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR) { // This is the perfect plane for the given criteria. Use it. bestPlane = j; alphaMode = VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR; break; } } } free(pDisplayProps); if (myDisplay == VK_NULL_HANDLE || myMode == VK_NULL_HANDLE) { // No suitable display + mode could be found. Abort. abort(); } else { // Success. Create a VkSurfaceKHR object for this plane. const VkDisplaySurfaceCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, // sType NULL, // pNext 0, // flags myMode, // displayMode bestPlane, // planeIndex pPlaneProps[bestPlane].currentStackIndex, // planeStackIndex VK_SURFACE_TRANSFORM_IDENTITY_KHR, // transform 1.0f, // globalAlpha alphaMode, // alphaMode ... } pfnCreateDisplayPlaneSurfaceKHR(instance, &createInfo, NULL, &surface); }
I guess that the key in creating the surface using this method is within vkCreateDisplayPlaneSurfaceKHR ?
Something like that, yes. We have a backend for it in our Vulkan SDK as well:
github.com/.../display.cpp
Alright, I'll take a look at that !
Thanks again for these informations. I might be able to get Vulkan working on Mali-T760 !