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