1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Google Inc.
6 * Copyright (c) 2020 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief VK_EXT_full_screen_exclusive extension Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktWsiFullScreenExclusiveTests.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkWsiPlatform.hpp"
36 #include "vkWsiUtil.hpp"
37
38 #include "tcuTestLog.hpp"
39 #include "tcuPlatform.hpp"
40 #include "tcuCommandLine.hpp"
41
42 #include <limits>
43
44 #if ( DE_OS == DE_OS_WIN32 )
45 #define NOMINMAX
46 #define WIN32_LEAN_AND_MEAN
47 #include <windows.h>
48 #endif
49
50 namespace vkt
51 {
52 namespace wsi
53 {
54
55 namespace
56 {
57
58 using namespace vk;
59 using namespace vk::wsi;
60
61 typedef std::vector<VkExtensionProperties> Extensions;
62
63 struct TestParams
64 {
65 vk::wsi::Type wsiType;
66 VkFullScreenExclusiveEXT fseType;
67 };
68
checkAllSupported(const Extensions& supportedExtensions, const std::vector<std::string>& requiredExtensions)69 void checkAllSupported (const Extensions& supportedExtensions,
70 const std::vector<std::string>& requiredExtensions)
71 {
72 for (std::vector<std::string>::const_iterator requiredExtName = requiredExtensions.begin();
73 requiredExtName != requiredExtensions.end();
74 ++requiredExtName)
75 {
76 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
77 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
78 }
79 }
80
createInstanceWithWsi(Context& context, const Extensions& supportedExtensions, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)81 CustomInstance createInstanceWithWsi (Context& context,
82 const Extensions& supportedExtensions,
83 Type wsiType,
84 const VkAllocationCallbacks* pAllocator = DE_NULL)
85 {
86 std::vector<std::string> extensions;
87
88 extensions.push_back("VK_KHR_surface");
89 extensions.push_back(getExtensionName(wsiType));
90 if (isDisplaySurface(wsiType))
91 extensions.push_back("VK_KHR_display");
92
93 if (isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_KHR_get_surface_capabilities2")))
94 extensions.push_back("VK_KHR_get_surface_capabilities2");
95
96 checkAllSupported(supportedExtensions, extensions);
97
98 return createCustomInstanceWithExtensions(context, extensions, pAllocator);
99 }
100
getDeviceFeaturesForWsi(void)101 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
102 {
103 VkPhysicalDeviceFeatures features;
104 deMemset(&features, 0, sizeof(features));
105 return features;
106 }
107
createDeviceWithWsi(const vk::PlatformInterface& vkp, vk::VkInstance instance, const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const Extensions& supportedExtensions, const deUint32 queueFamilyIndex, const VkAllocationCallbacks* pAllocator, bool validationEnabled)108 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp,
109 vk::VkInstance instance,
110 const InstanceInterface& vki,
111 VkPhysicalDevice physicalDevice,
112 const Extensions& supportedExtensions,
113 const deUint32 queueFamilyIndex,
114 const VkAllocationCallbacks* pAllocator,
115 bool validationEnabled)
116 {
117 const float queuePriorities[] = { 1.0f };
118 const VkDeviceQueueCreateInfo queueInfos[] =
119 {
120 {
121 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
122 DE_NULL,
123 (VkDeviceQueueCreateFlags)0,
124 queueFamilyIndex,
125 DE_LENGTH_OF_ARRAY(queuePriorities),
126 &queuePriorities[0]
127 }
128 };
129 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi();
130 std::vector<const char*> extensions;
131
132 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
133 TCU_THROW(NotSupportedError, "VK_KHR_swapchain is not supported");
134 extensions.push_back("VK_KHR_swapchain");
135
136 if (isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
137 {
138 extensions.push_back("VK_EXT_full_screen_exclusive");
139 }
140
141 VkDeviceCreateInfo deviceParams =
142 {
143 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
144 DE_NULL,
145 (VkDeviceCreateFlags)0,
146 DE_LENGTH_OF_ARRAY(queueInfos),
147 &queueInfos[0],
148 0u, // enabledLayerCount
149 DE_NULL, // ppEnabledLayerNames
150 (deUint32)extensions.size(),
151 extensions.empty() ? DE_NULL : &extensions[0],
152 &features
153 };
154
155 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
156 }
157
158 struct InstanceHelper
159 {
160 const std::vector<VkExtensionProperties> supportedExtensions;
161 const CustomInstance instance;
162 const InstanceDriver& vki;
163
InstanceHelpervkt::wsi::__anon30128::InstanceHelper164 InstanceHelper (Context& context,
165 Type wsiType,
166 const VkAllocationCallbacks* pAllocator = DE_NULL)
167 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
168 DE_NULL))
169 , instance (createInstanceWithWsi(context,
170 supportedExtensions,
171 wsiType,
172 pAllocator))
173 , vki (instance.getDriver())
174 {}
175 };
176
177 struct DeviceHelper
178 {
179 const VkPhysicalDevice physicalDevice;
180 const deUint32 queueFamilyIndex;
181 const Unique<VkDevice> device;
182 const DeviceDriver vkd;
183 const VkQueue queue;
184
DeviceHelpervkt::wsi::__anon30128::DeviceHelper185 DeviceHelper (Context& context,
186 const InstanceInterface& vki,
187 VkInstance instance,
188 VkSurfaceKHR surface,
189 const VkAllocationCallbacks* pAllocator = DE_NULL)
190 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
191 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface))
192 , device (createDeviceWithWsi(context.getPlatformInterface(),
193 instance,
194 vki,
195 physicalDevice,
196 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
197 queueFamilyIndex,
198 pAllocator,
199 context.getTestContext().getCommandLine().isValidationEnabled()))
200 , vkd (context.getPlatformInterface(), instance, *device)
201 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
202 {
203 }
204 };
205
createDisplay(const vk::Platform& platform, const Extensions& supportedExtensions, Type wsiType)206 de::MovePtr<Display> createDisplay (const vk::Platform& platform,
207 const Extensions& supportedExtensions,
208 Type wsiType)
209 {
210 try
211 {
212 return de::MovePtr<Display>(platform.createWsiDisplay(wsiType));
213 }
214 catch (const tcu::NotSupportedError& e)
215 {
216 if (isExtensionStructSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
217 platform.hasDisplay(wsiType))
218 {
219 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
220 // must support creating native display & window for that WSI type.
221 throw tcu::TestError(e.getMessage());
222 }
223 else
224 throw;
225 }
226 }
227
createWindow(const Display& display, const tcu::Maybe<tcu::UVec2>& initialSize)228 de::MovePtr<Window> createWindow (const Display& display,
229 const tcu::Maybe<tcu::UVec2>& initialSize)
230 {
231 try
232 {
233 return de::MovePtr<Window>(display.createWindow(initialSize));
234 }
235 catch (const tcu::NotSupportedError& e)
236 {
237 // See createDisplay - assuming that wsi::Display was supported platform port
238 // should also support creating a window.
239 throw tcu::TestError(e.getMessage());
240 }
241 }
242
243 struct NativeObjectsFS
244 {
245 const de::UniquePtr<Display> display;
246 tcu::UVec2 windowSize;
247 const de::UniquePtr<Window> window;
248
NativeObjectsFSvkt::wsi::__anon30128::NativeObjectsFS249 NativeObjectsFS (Context& context,
250 const Extensions& supportedExtensions,
251 Type wsiType)
252 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
253 , windowSize (getFullScreenSize(wsiType, *display.get(), tcu::UVec2(256U, 256U)))
254 , window (createWindow(*display, windowSize))
255 {}
256 };
257
getBasicSwapchainParameters(Type wsiType, const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceFormatKHR surfaceFormat, const tcu::UVec2& desiredSize, deUint32 desiredImageCount)258 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
259 const InstanceInterface& vki,
260 VkPhysicalDevice physicalDevice,
261 VkSurfaceKHR surface,
262 VkSurfaceFormatKHR surfaceFormat,
263 const tcu::UVec2& desiredSize,
264 deUint32 desiredImageCount)
265 {
266 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
267 physicalDevice,
268 surface);
269 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
270 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
271 const VkSwapchainCreateInfoKHR parameters =
272 {
273 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
274 DE_NULL,
275 (VkSwapchainCreateFlagsKHR)0,
276 surface,
277 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
278 surfaceFormat.format,
279 surfaceFormat.colorSpace,
280 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
281 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
282 1u, // imageArrayLayers
283 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
284 VK_SHARING_MODE_EXCLUSIVE,
285 0u,
286 (const deUint32*)DE_NULL,
287 transform,
288 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
289 VK_PRESENT_MODE_FIFO_KHR,
290 VK_FALSE, // clipped
291 (VkSwapchainKHR)0 // oldSwapchain
292 };
293
294 return parameters;
295 }
296
297 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
298 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
299 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
300
createFences(const DeviceInterface& vkd, const VkDevice device, size_t numFences)301 std::vector<FenceSp> createFences (const DeviceInterface& vkd,
302 const VkDevice device,
303 size_t numFences)
304 {
305 std::vector<FenceSp> fences(numFences);
306
307 for (size_t ndx = 0; ndx < numFences; ++ndx)
308 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
309
310 return fences;
311 }
312
createSemaphores(const DeviceInterface& vkd, const VkDevice device, size_t numSemaphores)313 std::vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
314 const VkDevice device,
315 size_t numSemaphores)
316 {
317 std::vector<SemaphoreSp> semaphores(numSemaphores);
318
319 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
320 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
321
322 return semaphores;
323 }
324
allocateCommandBuffers(const DeviceInterface& vkd, const VkDevice device, const VkCommandPool commandPool, const VkCommandBufferLevel level, const size_t numCommandBuffers)325 std::vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
326 const VkDevice device,
327 const VkCommandPool commandPool,
328 const VkCommandBufferLevel level,
329 const size_t numCommandBuffers)
330 {
331 std::vector<CommandBufferSp> buffers (numCommandBuffers);
332
333 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
334 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
335
336 return buffers;
337 }
338
fullScreenExclusiveTest(Context& context, TestParams testParams)339 tcu::TestStatus fullScreenExclusiveTest(Context& context,
340 TestParams testParams)
341 {
342 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_full_screen_exclusive"))
343 TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
344
345 const InstanceHelper instHelper(context, testParams.wsiType);
346 const NativeObjectsFS native(context, instHelper.supportedExtensions, testParams.wsiType);
347 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, testParams.wsiType, *native.display, *native.window, context.getTestContext().getCommandLine()));
348 const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface);
349 const std::vector<VkExtensionProperties> deviceExtensions(enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
350 if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
351 TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
352
353 native.window->setVisible(true);
354
355 if (testParams.wsiType == TYPE_WIN32)
356 {
357 native.window->setForeground();
358 }
359
360 // add information about full screen exclusive to VkSwapchainCreateInfoKHR
361 VkSurfaceFullScreenExclusiveInfoEXT fseInfo =
362 {
363 VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT, // VkStructureType sType;
364 DE_NULL, // void* pNext;
365 testParams.fseType // VkFullScreenExclusiveEXT fullScreenExclusive;
366 };
367
368 // for Win32 - create structure containing HMONITOR value
369 #if ( DE_OS == DE_OS_WIN32 )
370 VkSurfaceFullScreenExclusiveWin32InfoEXT fseWin32Info = {
371 VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT, // VkStructureType sType;
372 DE_NULL, // const void* pNext;
373 pt::Win32MonitorHandle(0) // HMONITOR hmonitor;
374 };
375 if (testParams.wsiType == TYPE_WIN32)
376 {
377 Win32WindowInterface* windowInterface = dynamic_cast<Win32WindowInterface*>(native.window.get());
378 fseWin32Info.hmonitor = (pt::Win32MonitorHandle)MonitorFromWindow((HWND)windowInterface->getNative().internal, MONITOR_DEFAULTTONEAREST);
379 }
380 #endif
381
382 // check surface capabilities
383 VkSurfaceCapabilitiesFullScreenExclusiveEXT surfaceCapabilitiesFSE = {
384 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT, // VkStructureType sType;
385 DE_NULL, // void* pNext;
386 DE_FALSE // VkBool32 fullScreenExclusiveSupported;
387 };
388 VkSurfaceCapabilities2KHR surfaceCapabilities2 = {
389 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, // VkStructureType sType;
390 &surfaceCapabilitiesFSE, // void* pNext;
391 VkSurfaceCapabilitiesKHR {} // VkSurfaceCapabilitiesKHR surfaceCapabilities;
392 };
393 VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {
394 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, // VkStructureType sType;
395 DE_NULL, // const void* pNext;
396 *surface // VkSurfaceKHR surface;
397 };
398
399 surfaceInfo.pNext = &fseInfo;
400
401 #if ( DE_OS == DE_OS_WIN32 )
402 if (testParams.wsiType == TYPE_WIN32)
403 {
404 fseInfo.pNext = &fseWin32Info;
405 }
406 #endif
407
408 instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo, &surfaceCapabilities2);
409 if (surfaceCapabilitiesFSE.fullScreenExclusiveSupported == DE_FALSE)
410 TCU_THROW(NotSupportedError, "VkSurfaceCapabilitiesFullScreenExclusiveEXT::fullScreenExclusiveSupported is set to false");
411
412 const DeviceInterface& vkd = devHelper.vkd;
413 const VkDevice device = *devHelper.device;
414 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
415
416 std::vector<VkSurfaceFormatKHR> surfaceFormats = vk::wsi::getPhysicalDeviceSurfaceFormats(instHelper.vki, devHelper.physicalDevice, *surface);
417 if(surfaceFormats.empty())
418 return tcu::TestStatus::fail("No VkSurfaceFormatKHR defined");
419
420 VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(testParams.wsiType, instHelper.vki, devHelper.physicalDevice, *surface, surfaceFormats[0], native.windowSize, 2);
421
422 swapchainInfo.pNext = &fseInfo;
423
424 #if ( DE_OS == DE_OS_WIN32 )
425 if (testParams.wsiType == TYPE_WIN32)
426 {
427 fseInfo.pNext = &fseWin32Info;
428 }
429 #endif
430
431 Move<VkSwapchainKHR> swapchain;
432 {
433 VkSwapchainKHR object = 0;
434 VkResult result = vkd.createSwapchainKHR(device, &swapchainInfo, DE_NULL, &object);
435 if (result == VK_ERROR_INITIALIZATION_FAILED && testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT)
436 {
437 // In some cases, swapchain creation may fail if exclusive full-screen mode is requested for application control,
438 // but for some implementation-specific reason exclusive full-screen access is unavailable for the particular combination
439 // of parameters provided. If this occurs, VK_ERROR_INITIALIZATION_FAILED will be returned.
440 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Failed to create swapchain with exclusive full-screen mode for application control.");
441 }
442 else
443 {
444 VK_CHECK(result);
445 }
446
447 swapchain = Move<VkSwapchainKHR>(check<VkSwapchainKHR>(object), Deleter<VkSwapchainKHR>(vkd, device, DE_NULL));
448 }
449 const std::vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
450
451 const WsiTriangleRenderer renderer (vkd,
452 device,
453 allocator,
454 context.getBinaryCollection(),
455 true,
456 swapchainImages,
457 swapchainImages,
458 swapchainInfo.imageFormat,
459 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
460
461 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
462
463 const size_t maxQueuedFrames = swapchainImages.size()*2;
464
465 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
466 // limit number of frames we allow to be queued.
467 const std::vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
468
469 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
470 // the semaphore in same time as the fence we use to meter rendering.
471 const std::vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
472
473 // For rest we simply need maxQueuedFrames as we will wait for image
474 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
475 // previous uses must have completed.
476 const std::vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
477 const std::vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
478
479 bool fullScreenAcquired = (testParams.fseType != VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT);
480
481 bool fullScreenLost = false;
482
483 try
484 {
485 const deUint32 numFramesToRender = 60;
486
487 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
488 {
489 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
490 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
491 deUint32 imageNdx = ~0u;
492
493 if (!fullScreenAcquired)
494 {
495 const VkResult acquireResult = vkd.acquireFullScreenExclusiveModeEXT(device, *swapchain);
496
497 switch (acquireResult)
498 {
499 case VK_SUCCESS:
500 {
501 fullScreenAcquired = true;
502 break;
503 }
504 case VK_ERROR_INITIALIZATION_FAILED:
505 {
506 break;
507 }
508 case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
509 {
510 context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkAcquireFullScreenExclusiveModeEXT. Frame " << frameNdx << tcu::TestLog::EndMessage;
511 break;
512 }
513 default:
514 {
515 VK_CHECK(acquireResult);
516 break;
517 }
518 }
519 }
520
521 if (frameNdx >= maxQueuedFrames)
522 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
523
524 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
525
526 VkResult acquireResult;
527
528 {
529 acquireResult = vkd.acquireNextImageKHR(device,
530 *swapchain,
531 std::numeric_limits<deUint64>::max(),
532 imageReadySemaphore,
533 (vk::VkFence)0,
534 &imageNdx);
535 if (acquireResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
536 {
537 context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkAcquireNextImageKHR" << tcu::TestLog::EndMessage;
538
539 fullScreenLost = true;
540 }
541 VK_CHECK_WSI(acquireResult);
542 }
543
544 if (acquireResult != VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
545 {
546 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
547
548 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
549 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
550 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
551 const VkSubmitInfo submitInfo =
552 {
553 VK_STRUCTURE_TYPE_SUBMIT_INFO,
554 DE_NULL,
555 1u,
556 &imageReadySemaphore,
557 &waitDstStage,
558 1u,
559 &commandBuffer,
560 1u,
561 &renderingCompleteSemaphore
562 };
563 const VkPresentInfoKHR presentInfo =
564 {
565 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
566 DE_NULL,
567 1u,
568 &renderingCompleteSemaphore,
569 1u,
570 &*swapchain,
571 &imageNdx,
572 (VkResult*)DE_NULL
573 };
574
575 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
576 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
577 const VkResult presentResult = vkd.queuePresentKHR(devHelper.queue, &presentInfo);
578 if (presentResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
579 {
580 context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkQueuePresentKHR" << tcu::TestLog::EndMessage;
581
582 fullScreenLost = true;
583 }
584 VK_CHECK_WSI(presentResult);
585 }
586 else
587 {
588 // image was not acquired, just roll the synchronization
589 VK_CHECK(vkd.queueSubmit(devHelper.queue, 0u, DE_NULL, imageReadyFence));
590 }
591 }
592
593 VK_CHECK(vkd.deviceWaitIdle(device));
594 }
595 catch (...)
596 {
597 // Make sure device is idle before destroying resources
598 vkd.deviceWaitIdle(device);
599 throw;
600 }
601
602 if (fullScreenAcquired && testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT)
603 {
604 const VkResult releaseResult = vkd.releaseFullScreenExclusiveModeEXT(device, *swapchain);
605 if (releaseResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
606 {
607 context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkReleaseFullScreenExclusiveModeEXT" << tcu::TestLog::EndMessage;
608
609 fullScreenLost = true;
610 }
611 VK_CHECK_WSI(releaseResult);
612 }
613
614 native.window->setVisible(false);
615
616 if (fullScreenAcquired && !fullScreenLost)
617 {
618 return tcu::TestStatus::pass("Rendering tests succeeded");
619 }
620 else
621 {
622 if (fullScreenLost)
623 {
624 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Full screen exclusive was lost during test, but did not end with an error.");
625 }
626 else
627 {
628 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Failed to acquire full screen exclusive, but did not end with an error.");
629 }
630 }
631 }
632
getBasicRenderPrograms(SourceCollections& dst, TestParams)633 void getBasicRenderPrograms (SourceCollections& dst, TestParams)
634 {
635 WsiTriangleRenderer::getPrograms(dst);
636 }
637
638 } // anonymous
639
createFullScreenExclusiveTests(tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)640 void createFullScreenExclusiveTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
641 {
642 struct
643 {
644 VkFullScreenExclusiveEXT testType;
645 const char* name;
646 } fullScreenTestTypes[] =
647 {
648 { VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT, "default" },
649 { VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT, "allowed" },
650 { VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT, "disallowed" },
651 { VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT, "application_controlled" },
652 };
653
654 for (size_t fseNdx = 0; fseNdx < DE_LENGTH_OF_ARRAY(fullScreenTestTypes); ++fseNdx)
655 {
656 TestParams testParams
657 {
658 wsiType,
659 fullScreenTestTypes[fseNdx].testType
660 };
661 addFunctionCaseWithPrograms(testGroup, fullScreenTestTypes[fseNdx].name, "", getBasicRenderPrograms, fullScreenExclusiveTest, testParams);
662 }
663 }
664
665 } // wsi
666
667 } // vkt
668