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