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