Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qvkkhrdisplayvulkaninstance.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <QVarLengthArray>
6
8
14
16{
17 qDebug("Creating Vulkan instance for VK_KHR_display");
18
19 const QByteArray extName = QByteArrayLiteral("VK_KHR_display");
20 initInstance(m_instance, { extName });
21 if (!m_vkInst)
22 return;
23
24 if (!enabledExtensions().contains(extName)) {
25 qWarning("Failed to enable VK_KHR_display extension");
26 return;
27 }
28
29#if VK_KHR_display
30 m_getPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)
31 m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceDisplayPropertiesKHR");
32 m_getDisplayModePropertiesKHR = (PFN_vkGetDisplayModePropertiesKHR)
33 m_vkGetInstanceProcAddr(m_vkInst, "vkGetDisplayModePropertiesKHR");
34 m_getPhysicalDeviceDisplayPlanePropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)
35 m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
36
37 m_getDisplayPlaneSupportedDisplaysKHR = (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)
38 m_vkGetInstanceProcAddr(m_vkInst, "vkGetDisplayPlaneSupportedDisplaysKHR");
39 m_getDisplayPlaneCapabilitiesKHR = (PFN_vkGetDisplayPlaneCapabilitiesKHR)
40 m_vkGetInstanceProcAddr(m_vkInst, "vkGetDisplayPlaneCapabilitiesKHR");
41
42 m_createDisplayPlaneSurfaceKHR = (PFN_vkCreateDisplayPlaneSurfaceKHR)
43 m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDisplayPlaneSurfaceKHR");
44#endif
45
46 m_enumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)
47 m_vkGetInstanceProcAddr(m_vkInst, "vkEnumeratePhysicalDevices");
48
49 m_getPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
50 m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceSurfaceSupportKHR"));
51
52 // Use for first physical device, unless overridden by QT_VK_PHYSICAL_DEVICE_INDEX.
53 // This behavior matches what the Vulkan backend of QRhi would do.
54
55 uint32_t physDevCount = 0;
56 m_enumeratePhysicalDevices(m_vkInst, &physDevCount, nullptr);
57 if (!physDevCount) {
58 qWarning("No physical devices");
59 return;
60 }
61 QVarLengthArray<VkPhysicalDevice, 4> physDevs(physDevCount);
62 VkResult err = m_enumeratePhysicalDevices(m_vkInst, &physDevCount, physDevs.data());
63 if (err != VK_SUCCESS || !physDevCount) {
64 qWarning("Failed to enumerate physical devices: %d", err);
65 return;
66 }
67
68 if (qEnvironmentVariableIsSet("QT_VK_PHYSICAL_DEVICE_INDEX")) {
69 int requestedPhysDevIndex = qEnvironmentVariableIntValue("QT_VK_PHYSICAL_DEVICE_INDEX");
70 if (requestedPhysDevIndex >= 0 && uint32_t(requestedPhysDevIndex) < physDevCount)
71 m_physDev = physDevs[requestedPhysDevIndex];
72 }
73
74 if (m_physDev == VK_NULL_HANDLE)
75 m_physDev = physDevs[0];
76
77 if (chooseDisplay()) {
78 if (m_createdCallback)
79 m_createdCallback(this, m_createdCallbackUserData);
80 }
81}
82
83bool QVkKhrDisplayVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
84 uint32_t queueFamilyIndex,
86{
87 if (!m_getPhysicalDeviceSurfaceSupportKHR)
88 return true;
89
90 VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window);
91 VkBool32 supported = false;
92 m_getPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &supported);
93
94 return supported;
95}
96
97bool QVkKhrDisplayVulkanInstance::chooseDisplay()
98{
99#if VK_KHR_display
100 uint32_t displayCount = 0;
101 VkResult err = m_getPhysicalDeviceDisplayPropertiesKHR(m_physDev, &displayCount, nullptr);
102 if (err != VK_SUCCESS) {
103 qWarning("Failed to get display properties: %d", err);
104 return false;
105 }
106
107 qDebug("Display count: %u", displayCount);
108
109 QVarLengthArray<VkDisplayPropertiesKHR, 4> displayProps(displayCount);
110 m_getPhysicalDeviceDisplayPropertiesKHR(m_physDev, &displayCount, displayProps.data());
111
112 m_display = VK_NULL_HANDLE;
113 m_displayMode = VK_NULL_HANDLE;
114
115 // Pick the first display and the first mode, unless specified via env.vars.
116 uint32_t wantedDisplayIndex = 0;
117 uint32_t wantedModeIndex = 0;
118 if (qEnvironmentVariableIsSet("QT_VK_DISPLAY_INDEX"))
119 wantedDisplayIndex = uint32_t(qEnvironmentVariableIntValue("QT_VK_DISPLAY_INDEX"));
120 if (qEnvironmentVariableIsSet("QT_VK_MODE_INDEX"))
121 wantedModeIndex = uint32_t(qEnvironmentVariableIntValue("QT_VK_MODE_INDEX"));
122
123 for (uint32_t i = 0; i < displayCount; ++i) {
124 const VkDisplayPropertiesKHR &disp(displayProps[i]);
125 qDebug("Display #%u:\n display: %p\n name: %s\n dimensions: %ux%u\n resolution: %ux%u",
126 i, (void *) disp.display, disp.displayName,
127 disp.physicalDimensions.width, disp.physicalDimensions.height,
128 disp.physicalResolution.width, disp.physicalResolution.height);
129
130 if (i == wantedDisplayIndex)
131 m_display = disp.display;
132
133 uint32_t modeCount = 0;
134 if (m_getDisplayModePropertiesKHR(m_physDev, disp.display, &modeCount, nullptr) != VK_SUCCESS) {
135 qWarning("Failed to get modes for display");
136 continue;
137 }
138 QVarLengthArray<VkDisplayModePropertiesKHR, 16> modeProps(modeCount);
139 m_getDisplayModePropertiesKHR(m_physDev, disp.display, &modeCount, modeProps.data());
140 for (uint32_t j = 0; j < modeCount; ++j) {
141 const VkDisplayModePropertiesKHR &mode(modeProps[j]);
142 qDebug(" Mode #%u:\n mode: %p\n visibleRegion: %ux%u\n refreshRate: %u",
143 j, (void *) mode.displayMode,
144 mode.parameters.visibleRegion.width, mode.parameters.visibleRegion.height,
145 mode.parameters.refreshRate);
146 if (j == wantedModeIndex && i == wantedDisplayIndex) {
147 m_displayMode = mode.displayMode;
148 m_width = mode.parameters.visibleRegion.width;
149 m_height = mode.parameters.visibleRegion.height;
150 }
151 }
152 }
153
154 if (m_display == VK_NULL_HANDLE || m_displayMode == VK_NULL_HANDLE) {
155 qWarning("Failed to choose display and mode");
156 return false;
157 }
158
159 qDebug("Using display #%u with mode #%u", wantedDisplayIndex, wantedModeIndex);
160
161 uint32_t planeCount = 0;
162 err = m_getPhysicalDeviceDisplayPlanePropertiesKHR(m_physDev, &planeCount, nullptr);
163 if (err != VK_SUCCESS) {
164 qWarning("Failed to get plane properties: %d", err);
165 return false;
166 }
167
168 qDebug("Plane count: %u", planeCount);
169
170 QVarLengthArray<VkDisplayPlanePropertiesKHR, 4> planeProps(planeCount);
171 m_getPhysicalDeviceDisplayPlanePropertiesKHR(m_physDev, &planeCount, planeProps.data());
172
173 m_planeIndex = UINT_MAX;
174 for (uint32_t i = 0; i < planeCount; ++i) {
175 uint32_t supportedDisplayCount = 0;
176 err = m_getDisplayPlaneSupportedDisplaysKHR(m_physDev, i, &supportedDisplayCount, nullptr);
177 if (err != VK_SUCCESS) {
178 qWarning("Failed to query supported displays for plane: %d", err);
179 return false;
180 }
181
182 QVarLengthArray<VkDisplayKHR, 4> supportedDisplays(supportedDisplayCount);
183 m_getDisplayPlaneSupportedDisplaysKHR(m_physDev, i, &supportedDisplayCount, supportedDisplays.data());
184 qDebug("Plane #%u supports %u displays, currently bound to display %p",
185 i, supportedDisplayCount, (void *) planeProps[i].currentDisplay);
186
187 VkDisplayPlaneCapabilitiesKHR caps;
188 err = m_getDisplayPlaneCapabilitiesKHR(m_physDev, m_displayMode, i, &caps);
189 if (err != VK_SUCCESS) {
190 qWarning("Failed to query plane capabilities: %d", err);
191 return false;
192 }
193
194 qDebug(" supportedAlpha: %d (1=no, 2=global, 4=per pixel, 8=per pixel premul)\n"
195 " minSrc=%d, %d %ux%u\n"
196 " maxSrc=%d, %d %ux%u\n"
197 " minDst=%d, %d %ux%u\n"
198 " maxDst=%d, %d %ux%u",
199 int(caps.supportedAlpha),
200 caps.minSrcPosition.x, caps.minSrcPosition.y, caps.minSrcExtent.width, caps.minSrcExtent.height,
201 caps.maxSrcPosition.x, caps.maxSrcPosition.y, caps.maxSrcExtent.width, caps.maxSrcExtent.height,
202 caps.minDstPosition.x, caps.minDstPosition.y, caps.minDstExtent.width, caps.minDstExtent.height,
203 caps.maxDstPosition.x, caps.maxDstPosition.y, caps.maxDstExtent.width, caps.maxDstExtent.height);
204
205 // if the plane is not in use and supports our chosen display, use that plane
206 if (supportedDisplays.contains(m_display)
207 && (planeProps[i].currentDisplay == VK_NULL_HANDLE || planeProps[i].currentDisplay == m_display))
208 {
209 m_planeIndex = i;
210 m_planeStackIndex = planeProps[i].currentStackIndex;
211 }
212 }
213
214 if (m_planeIndex == UINT_MAX) {
215 qWarning("Failed to find a suitable plane");
216 return false;
217 }
218
219 qDebug("Using plane #%u", m_planeIndex);
220 return true;
221#else
222 return false;
223#endif
224}
225
227{
228#if VK_KHR_display
229 qDebug("Creating VkSurfaceKHR via VK_KHR_display for window %p", (void *) window);
230
231 if (!m_physDev) {
232 qWarning("No physical device, cannot create surface");
233 return VK_NULL_HANDLE;
234 }
235 if (!m_display || !m_displayMode) {
236 qWarning("No display mode chosen, cannot create surface");
237 return VK_NULL_HANDLE;
238 }
239
240 VkDisplaySurfaceCreateInfoKHR surfaceCreateInfo = {};
241 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR;
242 surfaceCreateInfo.displayMode = m_displayMode;
243 surfaceCreateInfo.planeIndex = m_planeIndex;
244 surfaceCreateInfo.planeStackIndex = m_planeStackIndex;
245 surfaceCreateInfo.transform = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
246 surfaceCreateInfo.globalAlpha = 1.0f;
247 surfaceCreateInfo.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
248 surfaceCreateInfo.imageExtent = { m_width, m_height };
249
250 VkSurfaceKHR surface = VK_NULL_HANDLE;
251 VkResult err = m_createDisplayPlaneSurfaceKHR(m_vkInst, &surfaceCreateInfo, nullptr, &surface);
252 if (err != VK_SUCCESS || surface == VK_NULL_HANDLE) {
253 qWarning("Failed to create surface: %d", err);
254 return VK_NULL_HANDLE;
255 }
256
257 qDebug("Created surface %p", (void *) surface);
258
259 return surface;
260#else
262 return VK_NULL_HANDLE;
263#endif
264}
265
270
PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr
void loadVulkanLibrary(const QString &defaultLibraryName, int defaultLibraryVersion=-1)
void initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts)
QByteArrayList enabledExtensions() const override
\inmodule QtCore
Definition qbytearray.h:57
VkSurfaceKHR createSurface(QWindow *window)
bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override
void presentAboutToBeQueued(QWindow *window) override
QVkKhrDisplayVulkanInstance(QVulkanInstance *instance)
The QVulkanInstance class represents a native Vulkan instance, enabling Vulkan rendering onto a QSurf...
\inmodule QtGui
Definition qwindow.h:63
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLenum mode
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define Q_UNUSED(x)
aWidget window() -> setWindowTitle("New Window Title")
[2]