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::__anonce9e24fd0111::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::__anonce9e24fd0111::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::__anonce9e24fd0111::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 bool isForeground = true;
319
320 if (testParams.wsiType == TYPE_WIN32)
321 {
322 isForeground = native.window->setForeground();
323 }
324
325 // add information about full screen exclusive to VkSwapchainCreateInfoKHR
326 VkSurfaceFullScreenExclusiveInfoEXT fseInfo = {
327 VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT, // VkStructureType sType;
328 DE_NULL, // void* pNext;
329 testParams.fseType // VkFullScreenExclusiveEXT fullScreenExclusive;
330 };
331
332 // for Win32 - create structure containing HMONITOR value
333 #if (DE_OS == DE_OS_WIN32)
334 VkSurfaceFullScreenExclusiveWin32InfoEXT fseWin32Info = {
335 VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT, // VkStructureType sType;
336 DE_NULL, // const void* pNext;
337 pt::Win32MonitorHandle(0) // HMONITOR hmonitor;
338 };
339 if (testParams.wsiType == TYPE_WIN32)
340 {
341 Win32WindowInterface *windowInterface = dynamic_cast<Win32WindowInterface *>(native.window.get());
342 fseWin32Info.hmonitor = (pt::Win32MonitorHandle)MonitorFromWindow((HWND)windowInterface->getNative().internal,
343 MONITOR_DEFAULTTONEAREST);
344 }
345 #endif
346
347 // check surface capabilities
348 VkSurfaceCapabilitiesFullScreenExclusiveEXT surfaceCapabilitiesFSE = {
349 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT, // VkStructureType sType;
350 DE_NULL, // void* pNext;
351 false // VkBool32 fullScreenExclusiveSupported;
352 };
353 VkSurfaceCapabilities2KHR surfaceCapabilities2 = {
354 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, // VkStructureType sType;
355 &surfaceCapabilitiesFSE, // void* pNext;
356 VkSurfaceCapabilitiesKHR{} // VkSurfaceCapabilitiesKHR surfaceCapabilities;
357 };
358 VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {
359 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, // VkStructureType sType;
360 DE_NULL, // const void* pNext;
361 *surface // VkSurfaceKHR surface;
362 };
363
364 surfaceInfo.pNext = &fseInfo;
365
366 #if (DE_OS == DE_OS_WIN32)
367 if (testParams.wsiType == TYPE_WIN32)
368 {
369 fseInfo.pNext = &fseWin32Info;
370 }
371 #endif
372
373 instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo,
374 &surfaceCapabilities2);
375 if (surfaceCapabilitiesFSE.fullScreenExclusiveSupported == false)
376 TCU_THROW(NotSupportedError,
377 "VkSurfaceCapabilitiesFullScreenExclusiveEXT::fullScreenExclusiveSupported is set to false");
378
379 const DeviceInterface &vkd = devHelper.vkd;
380 const VkDevice device = *devHelper.device;
381 SimpleAllocator allocator(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
382
383 std::vector<VkSurfaceFormatKHR> surfaceFormats =
384 vk::wsi::getPhysicalDeviceSurfaceFormats(instHelper.vki, devHelper.physicalDevice, *surface);
385 if (surfaceFormats.empty())
386 return tcu::TestStatus::fail("No VkSurfaceFormatKHR defined");
387
388 VkSwapchainCreateInfoKHR swapchainInfo =
389 getBasicSwapchainParameters(testParams.wsiType, instHelper.vki, devHelper.physicalDevice, *surface,
390 surfaceFormats[0], native.windowSize, 2);
391
392 swapchainInfo.pNext = &fseInfo;
393
394 #if (DE_OS == DE_OS_WIN32)
395 if (testParams.wsiType == TYPE_WIN32)
396 {
397 fseInfo.pNext = &fseWin32Info;
398 }
399 #endif
400
401 Move<VkSwapchainKHR> swapchain;
402 {
403 VkSwapchainKHR object = 0;
404 VkResult result = vkd.createSwapchainKHR(device, &swapchainInfo, DE_NULL, &object);
405 if (result == VK_ERROR_INITIALIZATION_FAILED &&
406 testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT)
407 {
408 // In some cases, swapchain creation may fail if exclusive full-screen mode is requested for application control,
409 // but for some implementation-specific reason exclusive full-screen access is unavailable for the particular combination
410 // of parameters provided. If this occurs, VK_ERROR_INITIALIZATION_FAILED will be returned.
411 return tcu::TestStatus(
412 QP_TEST_RESULT_QUALITY_WARNING,
413 "Failed to create swapchain with exclusive full-screen mode for application control.");
414 }
415 else
416 {
417 VK_CHECK(result);
418 }
419
420 swapchain = Move<VkSwapchainKHR>(check<VkSwapchainKHR>(object), Deleter<VkSwapchainKHR>(vkd, device, DE_NULL));
421 }
422 const std::vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
423
424 const WsiTriangleRenderer renderer(vkd, device, allocator, context.getBinaryCollection(), true, swapchainImages,
425 swapchainImages, swapchainInfo.imageFormat,
426 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
427
428 const Unique<VkCommandPool> commandPool(
429 createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
430
431 const size_t maxQueuedFrames = swapchainImages.size() * 2;
432
433 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
434 // limit number of frames we allow to be queued.
435 const std::vector<FenceSp> imageReadyFences(createFences(vkd, device, maxQueuedFrames));
436
437 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
438 // the semaphore in same time as the fence we use to meter rendering.
439 const std::vector<SemaphoreSp> imageReadySemaphores(createSemaphores(vkd, device, maxQueuedFrames + 1));
440
441 // For rest we simply need maxQueuedFrames as we will wait for image
442 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
443 // previous uses must have completed.
444 const std::vector<SemaphoreSp> renderingCompleteSemaphores(createSemaphores(vkd, device, maxQueuedFrames));
445 const std::vector<CommandBufferSp> commandBuffers(
446 allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
447
448 bool fullScreenAcquired = (testParams.fseType != VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT);
449
450 bool fullScreenLost = false;
451
452 try
453 {
454 const uint32_t numFramesToRender = 60;
455
456 for (uint32_t frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
457 {
458 const VkFence imageReadyFence = **imageReadyFences[frameNdx % imageReadyFences.size()];
459 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx % imageReadySemaphores.size()];
460 uint32_t imageNdx = ~0u;
461
462 if (!fullScreenAcquired)
463 {
464 const VkResult acquireResult = vkd.acquireFullScreenExclusiveModeEXT(device, *swapchain);
465
466 switch (acquireResult)
467 {
468 case VK_SUCCESS:
469 {
470 fullScreenAcquired = true;
471 break;
472 }
473 case VK_ERROR_INITIALIZATION_FAILED:
474 {
475 break;
476 }
477 case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
478 {
479 context.getTestContext().getLog() << tcu::TestLog::Message
480 << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at "
481 "vkAcquireFullScreenExclusiveModeEXT. Frame "
482 << frameNdx << tcu::TestLog::EndMessage;
483 break;
484 }
485 default:
486 {
487 VK_CHECK(acquireResult);
488 break;
489 }
490 }
491 }
492
493 if (frameNdx >= maxQueuedFrames)
494 VK_CHECK(
495 vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<uint64_t>::max()));
496
497 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
498
499 VkResult acquireResult;
500
501 {
502 acquireResult = vkd.acquireNextImageKHR(device, *swapchain, std::numeric_limits<uint64_t>::max(),
503 imageReadySemaphore, (vk::VkFence)0, &imageNdx);
504 if (acquireResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
505 {
506 context.getTestContext().getLog()
507 << tcu::TestLog::Message
508 << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkAcquireNextImageKHR"
509 << tcu::TestLog::EndMessage;
510
511 fullScreenLost = true;
512 }
513 VK_CHECK_WSI(acquireResult);
514 }
515
516 if (acquireResult != VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
517 {
518 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
519
520 const VkSemaphore renderingCompleteSemaphore =
521 **renderingCompleteSemaphores[frameNdx % renderingCompleteSemaphores.size()];
522 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx % commandBuffers.size()];
523 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
524 const VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO,
525 DE_NULL,
526 1u,
527 &imageReadySemaphore,
528 &waitDstStage,
529 1u,
530 &commandBuffer,
531 1u,
532 &renderingCompleteSemaphore};
533 const VkPresentInfoKHR presentInfo = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
534 DE_NULL,
535 1u,
536 &renderingCompleteSemaphore,
537 1u,
538 &*swapchain,
539 &imageNdx,
540 (VkResult *)DE_NULL};
541
542 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
543 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
544 const VkResult presentResult = vkd.queuePresentKHR(devHelper.queue, &presentInfo);
545 if (presentResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
546 {
547 context.getTestContext().getLog()
548 << tcu::TestLog::Message
549 << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkQueuePresentKHR"
550 << tcu::TestLog::EndMessage;
551
552 fullScreenLost = true;
553 }
554 VK_CHECK_WSI(presentResult);
555 }
556 else
557 {
558 // image was not acquired, just roll the synchronization
559 VK_CHECK(vkd.queueSubmit(devHelper.queue, 0u, DE_NULL, imageReadyFence));
560 }
561 }
562
563 VK_CHECK(vkd.deviceWaitIdle(device));
564 }
565 catch (...)
566 {
567 // Make sure device is idle before destroying resources
568 vkd.deviceWaitIdle(device);
569 throw;
570 }
571
572 if (fullScreenAcquired && testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT)
573 {
574 const VkResult releaseResult = vkd.releaseFullScreenExclusiveModeEXT(device, *swapchain);
575 if (releaseResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
576 {
577 context.getTestContext().getLog()
578 << tcu::TestLog::Message
579 << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkReleaseFullScreenExclusiveModeEXT"
580 << tcu::TestLog::EndMessage;
581
582 fullScreenLost = true;
583 }
584 VK_CHECK_WSI(releaseResult);
585 }
586
587 native.window->setVisible(false);
588
589 if ((fullScreenAcquired && !fullScreenLost) ||
590 (!isForeground && testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT))
591 {
592 return tcu::TestStatus::pass("Rendering tests succeeded");
593 }
594 else
595 {
596 if (fullScreenLost)
597 {
598 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING,
599 "Full screen exclusive was lost during test, but did not end with an error.");
600 }
601 else
602 {
603 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING,
604 "Failed to acquire full screen exclusive, but did not end with an error.");
605 }
606 }
607 }
608
getBasicRenderPrograms(SourceCollections & dst,TestParams)609 void getBasicRenderPrograms(SourceCollections &dst, TestParams)
610 {
611 WsiTriangleRenderer::getPrograms(dst);
612 }
613
614 } // namespace
615
createFullScreenExclusiveTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)616 void createFullScreenExclusiveTests(tcu::TestCaseGroup *testGroup, vk::wsi::Type wsiType)
617 {
618 struct
619 {
620 VkFullScreenExclusiveEXT testType;
621 const char *name;
622 } fullScreenTestTypes[] = {
623 {VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT, "default"},
624 {VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT, "allowed"},
625 {VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT, "disallowed"},
626 {VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT, "application_controlled"},
627 };
628
629 for (size_t fseNdx = 0; fseNdx < DE_LENGTH_OF_ARRAY(fullScreenTestTypes); ++fseNdx)
630 {
631 TestParams testParams{wsiType, fullScreenTestTypes[fseNdx].testType};
632 addFunctionCaseWithPrograms(testGroup, fullScreenTestTypes[fseNdx].name, getBasicRenderPrograms,
633 fullScreenExclusiveTest, testParams);
634 }
635 }
636
637 } // namespace wsi
638
639 } // namespace vkt
640