1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief VkSurface Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktWsiSurfaceTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29 #include "vktNativeObjectsUtil.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkStrUtil.hpp"
34 #include "vkRef.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkDeviceUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkWsiPlatform.hpp"
42 #include "vkWsiUtil.hpp"
43 #include "vkAllocationCallbackUtil.hpp"
44 #include "vkQueryUtil.hpp"
45
46 #include "tcuTestLog.hpp"
47 #include "tcuFormatUtil.hpp"
48 #include "tcuPlatform.hpp"
49 #include "tcuResultCollector.hpp"
50 #include "tcuCommandLine.hpp"
51
52 #include "deUniquePtr.hpp"
53 #include "deStringUtil.hpp"
54 #include "deMemory.h"
55
56 namespace vk
57 {
58
operator !=(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)59 inline bool operator!=(const VkSurfaceFormatKHR &a, const VkSurfaceFormatKHR &b)
60 {
61 return (a.format != b.format) || (a.colorSpace != b.colorSpace);
62 }
63
operator ==(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)64 inline bool operator==(const VkSurfaceFormatKHR &a, const VkSurfaceFormatKHR &b)
65 {
66 return !(a != b);
67 }
68
operator !=(const VkExtent2D & a,const VkExtent2D & b)69 inline bool operator!=(const VkExtent2D &a, const VkExtent2D &b)
70 {
71 return (a.width != b.width) || (a.height != b.height);
72 }
73
operator !=(const VkSurfaceCapabilitiesKHR & a,const VkSurfaceCapabilitiesKHR & b)74 inline bool operator!=(const VkSurfaceCapabilitiesKHR &a, const VkSurfaceCapabilitiesKHR &b)
75 {
76 return (a.minImageCount != b.minImageCount) || (a.maxImageCount != b.maxImageCount) ||
77 (a.currentExtent != b.currentExtent) || (a.minImageExtent != b.minImageExtent) ||
78 (a.maxImageExtent != b.maxImageExtent) || (a.maxImageArrayLayers != b.maxImageArrayLayers) ||
79 (a.supportedTransforms != b.supportedTransforms) || (a.currentTransform != b.currentTransform) ||
80 (a.supportedCompositeAlpha != b.supportedCompositeAlpha) || (a.supportedUsageFlags != b.supportedUsageFlags);
81 }
82
83 } // namespace vk
84
85 namespace vkt
86 {
87 namespace wsi
88 {
89
90 namespace
91 {
92
93 using namespace vk;
94 using namespace vk::wsi;
95
96 using tcu::Maybe;
97 using tcu::TestLog;
98 using tcu::UVec2;
99
100 using de::MovePtr;
101 using de::UniquePtr;
102
103 using std::string;
104 using std::vector;
105
106 enum
107 {
108 SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC = 0xffffffff
109 };
110
111 enum
112 {
113 GUARD_SIZE = 0x20, //!< Number of bytes to check
114 GUARD_VALUE = 0xcd, //!< Data pattern
115 };
116
117 template <typename T>
118 class CheckIncompleteResult
119 {
120 public:
~CheckIncompleteResult(void)121 virtual ~CheckIncompleteResult(void)
122 {
123 }
124 virtual void getResult(const InstanceInterface &vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface,
125 T *data) = 0;
126
operator ()(tcu::ResultCollector & results,const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkSurfaceKHR surface,const std::size_t expectedCompleteSize)127 void operator()(tcu::ResultCollector &results, const InstanceInterface &vki, const VkPhysicalDevice physDevice,
128 const VkSurfaceKHR surface, const std::size_t expectedCompleteSize)
129 {
130 if (expectedCompleteSize == 0)
131 return;
132
133 vector<T> outputData(expectedCompleteSize);
134 const uint32_t usedSize = static_cast<uint32_t>(expectedCompleteSize / 3);
135
136 ValidateQueryBits::fillBits(outputData.begin(),
137 outputData.end()); // unused entries should have this pattern intact
138 m_count = usedSize;
139 m_result = VK_SUCCESS;
140
141 getResult(vki, physDevice, surface, &outputData[0]); // update m_count and m_result
142
143 if (m_count != usedSize || m_result != VK_INCOMPLETE ||
144 !ValidateQueryBits::checkBits(outputData.begin() + m_count, outputData.end()))
145 results.fail("Query didn't return VK_INCOMPLETE");
146 }
147
148 protected:
149 uint32_t m_count;
150 VkResult m_result;
151 };
152
153 struct CheckPhysicalDeviceSurfaceFormatsIncompleteResult : public CheckIncompleteResult<VkSurfaceFormatKHR>
154 {
getResultvkt::wsi::__anon2b710b1b0111::CheckPhysicalDeviceSurfaceFormatsIncompleteResult155 void getResult(const InstanceInterface &vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface,
156 VkSurfaceFormatKHR *data)
157 {
158 m_result = vki.getPhysicalDeviceSurfaceFormatsKHR(physDevice, surface, &m_count, data);
159 }
160 };
161
162 struct CheckPhysicalDeviceSurfacePresentModesIncompleteResult : public CheckIncompleteResult<VkPresentModeKHR>
163 {
getResultvkt::wsi::__anon2b710b1b0111::CheckPhysicalDeviceSurfacePresentModesIncompleteResult164 void getResult(const InstanceInterface &vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface,
165 VkPresentModeKHR *data)
166 {
167 m_result = vki.getPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &m_count, data);
168 }
169 };
170
171 typedef vector<VkExtensionProperties> Extensions;
172
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)173 CustomInstance createInstanceWithWsi(Context &context, Type wsiType, const vector<string> extraExtensions,
174 const VkAllocationCallbacks *pAllocator = DE_NULL)
175 {
176 const uint32_t version = context.getUsedApiVersion();
177 vector<string> extensions = extraExtensions;
178
179 extensions.push_back("VK_KHR_surface");
180 extensions.push_back(getExtensionName(wsiType));
181 if (isDisplaySurface(wsiType))
182 extensions.push_back("VK_KHR_display");
183
184 vector<string> instanceExtensions;
185 for (const auto &ext : extensions)
186 {
187 if (!context.isInstanceFunctionalitySupported(ext))
188 TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
189
190 if (!isCoreInstanceExtension(version, ext))
191 instanceExtensions.push_back(ext);
192 }
193
194 return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
195 }
196
197 struct InstanceHelper
198 {
199 const vector<VkExtensionProperties> supportedExtensions;
200 CustomInstance instance;
201 const InstanceDriver &vki;
202
InstanceHelpervkt::wsi::__anon2b710b1b0111::InstanceHelper203 InstanceHelper(Context &context, Type wsiType, const VkAllocationCallbacks *pAllocator = DE_NULL)
204 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
205 , instance(createInstanceWithWsi(context, wsiType, vector<string>(), pAllocator))
206 , vki(instance.getDriver())
207 {
208 }
209
InstanceHelpervkt::wsi::__anon2b710b1b0111::InstanceHelper210 InstanceHelper(Context &context, Type wsiType, const vector<string> &extensions,
211 const VkAllocationCallbacks *pAllocator = DE_NULL)
212 : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
213 , instance(createInstanceWithWsi(context, wsiType, extensions, pAllocator))
214 , vki(instance.getDriver())
215 {
216 }
217 };
218
createSurfaceTest(Context & context,Type wsiType)219 tcu::TestStatus createSurfaceTest(Context &context, Type wsiType)
220 {
221 const InstanceHelper instHelper(context, wsiType);
222 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
223 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
224 native.getWindow(), context.getTestContext().getCommandLine()));
225
226 return tcu::TestStatus::pass("Creating surface succeeded");
227 }
228
querySurfaceCounterTest(Context & context,Type wsiType)229 tcu::TestStatus querySurfaceCounterTest(Context &context, Type wsiType)
230 {
231 const InstanceHelper instHelper(context, wsiType, {"VK_KHR_display", "VK_EXT_display_surface_counter"});
232 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
233 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
234 native.getWindow(), context.getTestContext().getCommandLine()));
235 const vk::InstanceInterface &vki = instHelper.vki;
236 const tcu::CommandLine &cmdLine = context.getTestContext().getCommandLine();
237 const vk::VkPhysicalDevice physicalDevice = chooseDevice(vki, instHelper.instance, cmdLine);
238 const bool isDisplay = isDisplaySurface(wsiType);
239
240 if (!isInstanceExtensionSupported(context.getUsedApiVersion(), context.getInstanceExtensions(),
241 "VK_EXT_display_surface_counter"))
242 TCU_THROW(NotSupportedError, "VK_EXT_display_surface_counter not supported");
243
244 VkBool32 surfaceSupported;
245 vki.getPhysicalDeviceSurfaceSupportKHR(physicalDevice, 0u, surface.get(), &surfaceSupported);
246 if (!surfaceSupported)
247 TCU_THROW(NotSupportedError, "Surface is not supported by physical device");
248
249 const vk::VkSurfaceCapabilities2EXT capsExt =
250 getPhysicalDeviceSurfaceCapabilities2EXT(vki, physicalDevice, surface.get());
251 const vk::VkSurfaceCapabilitiesKHR capsKhr =
252 getPhysicalDeviceSurfaceCapabilities(vki, physicalDevice, surface.get());
253
254 if (!sameSurfaceCapabilities(capsKhr, capsExt))
255 {
256 return tcu::TestStatus::fail("KHR and EXT surface capabilities do not match");
257 }
258
259 if (!isDisplay && capsExt.supportedSurfaceCounters != 0)
260 {
261 return tcu::TestStatus::fail("supportedSurfaceCounters nonzero (" +
262 de::toString(capsExt.supportedSurfaceCounters) + ") for non-display surface");
263 }
264
265 return tcu::TestStatus::pass("Pass");
266 }
267
createSurfaceCustomAllocatorTest(Context & context,Type wsiType)268 tcu::TestStatus createSurfaceCustomAllocatorTest(Context &context, Type wsiType)
269 {
270 AllocationCallbackRecorder allocationRecorder(getSystemAllocator());
271 tcu::TestLog &log = context.getTestContext().getLog();
272
273 {
274 const InstanceHelper instHelper(context, wsiType, allocationRecorder.getCallbacks());
275 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
276 const Unique<VkSurfaceKHR> surface(
277 createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(),
278 context.getTestContext().getCommandLine(), allocationRecorder.getCallbacks()));
279
280 if (!validateAndLog(log, allocationRecorder,
281 (1u << VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) | (1u << VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
282 return tcu::TestStatus::fail("Detected invalid system allocation callback");
283 }
284
285 if (!validateAndLog(log, allocationRecorder, 0u))
286 return tcu::TestStatus::fail("Detected invalid system allocation callback");
287
288 if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
289 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
290 else
291 return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
292 }
293
createSurfaceSimulateOOMTest(Context & context,Type wsiType)294 tcu::TestStatus createSurfaceSimulateOOMTest(Context &context, Type wsiType)
295 {
296 tcu::TestLog &log = context.getTestContext().getLog();
297
298 for (uint32_t numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
299 {
300 AllocationCallbackRecorder allocationRecorder(getSystemAllocator());
301 DeterministicFailAllocator failingAllocator(allocationRecorder.getCallbacks(),
302 DeterministicFailAllocator::MODE_DO_NOT_COUNT, 0);
303 bool gotOOM = false;
304
305 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding"
306 << TestLog::EndMessage;
307
308 try
309 {
310 const InstanceHelper instHelper(context, wsiType, failingAllocator.getCallbacks());
311
312 // OOM is not simulated for VkInstance as we don't want to spend time
313 // testing OOM paths inside instance creation.
314 failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
315
316 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
317 const Unique<VkSurfaceKHR> surface(
318 createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(),
319 context.getTestContext().getCommandLine(), failingAllocator.getCallbacks()));
320
321 if (!validateAndLog(log, allocationRecorder,
322 (1u << VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) |
323 (1u << VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
324 return tcu::TestStatus::fail("Detected invalid system allocation callback");
325 }
326 catch (const OutOfMemoryError &e)
327 {
328 log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
329 gotOOM = true;
330 }
331
332 if (!validateAndLog(log, allocationRecorder, 0u))
333 return tcu::TestStatus::fail("Detected invalid system allocation callback");
334
335 if (!gotOOM)
336 {
337 log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
338
339 if (numPassingAllocs == 0)
340 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
341 else
342 return tcu::TestStatus::pass("OOM simulation completed");
343 }
344 }
345
346 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
347 }
348
getNumQueueFamilies(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)349 uint32_t getNumQueueFamilies(const InstanceInterface &vki, VkPhysicalDevice physicalDevice)
350 {
351 uint32_t numFamilies = 0;
352
353 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
354
355 return numFamilies;
356 }
357
querySurfaceSupportTest(Context & context,Type wsiType)358 tcu::TestStatus querySurfaceSupportTest(Context &context, Type wsiType)
359 {
360 tcu::TestLog &log = context.getTestContext().getLog();
361 tcu::ResultCollector results(log);
362
363 const InstanceHelper instHelper(context, wsiType);
364 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
365 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
366 native.getWindow(), context.getTestContext().getCommandLine()));
367 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
368
369 // On Android surface must be supported by all devices and queue families
370 const bool expectSupportedOnAll = wsiType == TYPE_ANDROID;
371
372 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
373 {
374 const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
375 const uint32_t numQueueFamilies = getNumQueueFamilies(instHelper.vki, physicalDevice);
376
377 for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
378 {
379 const VkBool32 isSupported =
380 getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
381
382 log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
383 << (isSupported == VK_FALSE ? "NOT " : "") << "supported" << TestLog::EndMessage;
384
385 if (expectSupportedOnAll && !isSupported)
386 results.fail("Surface must be supported by all devices and queue families");
387 }
388 }
389
390 return tcu::TestStatus(results.getResult(), results.getMessage());
391 }
392
queryPresentationSupportTest(Context & context,Type wsiType)393 tcu::TestStatus queryPresentationSupportTest(Context &context, Type wsiType)
394 {
395 // There is no implementation of getPhysicalDevicePresentationSupport for DRM.
396 if (wsiType == TYPE_DIRECT_DRM)
397 {
398 TCU_THROW(NotSupportedError, "No presentation support query for Drm.");
399 }
400
401 tcu::TestLog &log = context.getTestContext().getLog();
402 tcu::ResultCollector results(log);
403
404 const InstanceHelper instHelper(context, wsiType);
405 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
406 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
407 native.getWindow(), context.getTestContext().getCommandLine()));
408 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
409
410 native.getDisplay();
411 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
412 {
413 const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
414 const uint32_t numQueueFamilies = getNumQueueFamilies(instHelper.vki, physicalDevice);
415
416 for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
417 {
418 VkBool32 isPresentationSupported = getPhysicalDevicePresentationSupport(
419 instHelper.vki, physicalDevice, queueFamilyNdx, wsiType, native.getDisplay());
420 VkBool32 isSurfaceSupported =
421 getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
422
423 log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx
424 << ": presentation " << (isPresentationSupported == VK_FALSE ? "NOT " : "") << "supported. Surface "
425 << (isSurfaceSupported == VK_FALSE ? "NOT " : "") << "supported." << TestLog::EndMessage;
426
427 if (isPresentationSupported != isSurfaceSupported)
428 results.fail("Presentation support is different from surface support");
429 }
430 }
431
432 return tcu::TestStatus(results.getResult(), results.getMessage());
433 }
434
isSupportedByAnyQueue(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)435 bool isSupportedByAnyQueue(const InstanceInterface &vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
436 {
437 const uint32_t numQueueFamilies = getNumQueueFamilies(vki, physicalDevice);
438
439 for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
440 {
441 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
442 return true;
443 }
444
445 return false;
446 }
447
validateSurfaceCapabilities(tcu::ResultCollector & results,const VkSurfaceCapabilitiesKHR & capabilities)448 void validateSurfaceCapabilities(tcu::ResultCollector &results, const VkSurfaceCapabilitiesKHR &capabilities)
449 {
450 results.check(capabilities.minImageCount > 0, "minImageCount must be larger than 0");
451
452 results.check(capabilities.minImageExtent.width > 0 && capabilities.minImageExtent.height > 0,
453 "minImageExtent dimensions must be larger than 0");
454
455 results.check(capabilities.maxImageExtent.width > 0 && capabilities.maxImageExtent.height > 0,
456 "maxImageExtent dimensions must be larger than 0");
457
458 results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
459 capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
460 "maxImageExtent must be larger or equal to minImageExtent");
461
462 if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
463 capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
464 {
465 results.check(capabilities.currentExtent.width > 0 && capabilities.currentExtent.height > 0,
466 "currentExtent dimensions must be larger than 0");
467
468 results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width,
469 capabilities.maxImageExtent.width) &&
470 de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height,
471 capabilities.maxImageExtent.height),
472 "currentExtent is not in supported extent limits");
473 }
474
475 results.check(capabilities.maxImageArrayLayers > 0, "maxImageArrayLayers must be larger than 0");
476
477 results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
478 "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
479
480 results.check(capabilities.supportedTransforms != 0, "At least one transform must be supported");
481
482 results.check(dePop32(capabilities.currentTransform) != 0, "Invalid currentTransform");
483
484 results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
485 "currentTransform is not supported by surface");
486
487 results.check(capabilities.supportedCompositeAlpha != 0, "At least one alpha mode must be supported");
488 }
489
querySurfaceCapabilitiesTest(Context & context,Type wsiType)490 tcu::TestStatus querySurfaceCapabilitiesTest(Context &context, Type wsiType)
491 {
492 tcu::TestLog &log = context.getTestContext().getLog();
493 tcu::ResultCollector results(log);
494
495 const InstanceHelper instHelper(context, wsiType);
496 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
497 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
498 native.getWindow(), context.getTestContext().getCommandLine()));
499 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
500
501 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
502 {
503 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
504 {
505 const VkSurfaceCapabilitiesKHR capabilities =
506 getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
507
508 log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
509
510 validateSurfaceCapabilities(results, capabilities);
511 }
512 // else skip query as surface is not supported by the device
513 }
514
515 return tcu::TestStatus(results.getResult(), results.getMessage());
516 }
517
querySurfaceCapabilities2Test(Context & context,Type wsiType)518 tcu::TestStatus querySurfaceCapabilities2Test(Context &context, Type wsiType)
519 {
520 tcu::TestLog &log = context.getTestContext().getLog();
521 tcu::ResultCollector results(log);
522
523 const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
524 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
525 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
526 native.getWindow(), context.getTestContext().getCommandLine()));
527 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
528
529 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
530 {
531 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
532 {
533 const VkSurfaceCapabilitiesKHR refCapabilities =
534 getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
535 VkSurfaceCapabilities2KHR extCapabilities;
536
537 deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
538 extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
539 extCapabilities.pNext = DE_NULL;
540
541 {
542 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {
543 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, DE_NULL, *surface};
544 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
545
546 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
547
548 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx],
549 &surfaceInfo, &extCapabilities));
550
551 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == true,
552 "Driver wrote into input struct");
553 }
554
555 results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
556 extCapabilities.pNext == DE_NULL,
557 "sType/pNext modified");
558
559 if (refCapabilities != extCapabilities.surfaceCapabilities)
560 {
561 log << TestLog::Message << "Device " << deviceNdx << ": expected " << refCapabilities << ", got "
562 << extCapabilities.surfaceCapabilities << TestLog::EndMessage;
563 results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
564 }
565 }
566 }
567
568 return tcu::TestStatus(results.getResult(), results.getMessage());
569 }
570
querySurfaceProtectedCapabilitiesTest(Context & context,Type wsiType)571 tcu::TestStatus querySurfaceProtectedCapabilitiesTest(Context &context, Type wsiType)
572 {
573 tcu::TestLog &log = context.getTestContext().getLog();
574 tcu::ResultCollector results(log);
575
576 vector<string> requiredExtensions;
577 requiredExtensions.push_back("VK_KHR_get_surface_capabilities2");
578 requiredExtensions.push_back("VK_KHR_surface_protected_capabilities");
579 const InstanceHelper instHelper(context, wsiType, requiredExtensions);
580 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
581 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
582 native.getWindow(), context.getTestContext().getCommandLine()));
583 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
584
585 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
586 {
587 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
588 {
589 VkSurfaceCapabilities2KHR extCapabilities;
590 VkSurfaceProtectedCapabilitiesKHR extProtectedCapabilities;
591
592 deMemset(&extProtectedCapabilities, 0xcd, sizeof(VkSurfaceProtectedCapabilitiesKHR));
593 extProtectedCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR;
594 extProtectedCapabilities.pNext = DE_NULL;
595
596 deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
597 extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
598 extCapabilities.pNext = &extProtectedCapabilities;
599
600 {
601 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
602 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {
603 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, DE_NULL, *surface};
604
605 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
606
607 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx],
608 &surfaceInfo, &extCapabilities));
609
610 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == true,
611 "Driver wrote into input struct");
612 }
613
614 results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
615 extCapabilities.pNext == &extProtectedCapabilities,
616 "sType/pNext modified");
617
618 results.check(extProtectedCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR &&
619 extProtectedCapabilities.pNext == DE_NULL,
620 "sType/pNext modified");
621
622 results.check(extProtectedCapabilities.supportsProtected == 0 ||
623 extProtectedCapabilities.supportsProtected == 1,
624 "supportsProtected ");
625 }
626 }
627
628 return tcu::TestStatus(results.getResult(), results.getMessage());
629 }
630
validateSurfaceFormats(tcu::ResultCollector & results,Type wsiType,const vector<VkSurfaceFormatKHR> & formats)631 void validateSurfaceFormats(tcu::ResultCollector &results, Type wsiType, const vector<VkSurfaceFormatKHR> &formats)
632 {
633 const VkSurfaceFormatKHR *requiredFormats = DE_NULL;
634 size_t numRequiredFormats = 0;
635
636 if (wsiType == TYPE_ANDROID)
637 {
638 static const VkSurfaceFormatKHR s_androidFormats[] = {
639 {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
640 {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
641 {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
642
643 requiredFormats = &s_androidFormats[0];
644 numRequiredFormats = DE_LENGTH_OF_ARRAY(s_androidFormats);
645 }
646
647 for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
648 {
649 const VkSurfaceFormatKHR &requiredFormat = requiredFormats[ndx];
650
651 if (!de::contains(formats.begin(), formats.end(), requiredFormat))
652 results.fail(de::toString(requiredFormat) + " not supported");
653 }
654
655 // Check that there are no duplicates
656 for (size_t ndx = 1; ndx < formats.size(); ++ndx)
657 {
658 if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
659 results.fail("Found duplicate entry " + de::toString(formats[ndx]));
660 }
661 }
662
querySurfaceFormatsTest(Context & context,Type wsiType)663 tcu::TestStatus querySurfaceFormatsTest(Context &context, Type wsiType)
664 {
665 tcu::TestLog &log = context.getTestContext().getLog();
666 tcu::ResultCollector results(log);
667
668 const InstanceHelper instHelper(context, wsiType);
669 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
670 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
671 native.getWindow(), context.getTestContext().getCommandLine()));
672 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
673
674 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
675 {
676 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
677 {
678 uint32_t numFormats = 0;
679
680 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
681 &numFormats, DE_NULL));
682
683 std::vector<VkSurfaceFormatKHR> formats(numFormats + 1);
684
685 if (numFormats > 0)
686 {
687 const uint32_t numFormatsOrig = numFormats;
688
689 // check if below call properly overwrites formats count
690 numFormats++;
691
692 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
693 &numFormats, &formats[0]));
694
695 if (numFormats != numFormatsOrig)
696 results.fail("Format count changed between calls");
697 }
698
699 formats.pop_back();
700
701 log << TestLog::Message << "Device " << deviceNdx << ": "
702 << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
703
704 validateSurfaceFormats(results, wsiType, formats);
705 CheckPhysicalDeviceSurfaceFormatsIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx],
706 *surface, formats.size());
707 }
708 // else skip query as surface is not supported by the device
709 }
710
711 return tcu::TestStatus(results.getResult(), results.getMessage());
712 }
713
querySurfaceFormatsTestSurfaceless(Context & context,Type wsiType)714 tcu::TestStatus querySurfaceFormatsTestSurfaceless(Context &context, Type wsiType)
715 {
716 tcu::TestLog &log = context.getTestContext().getLog();
717 tcu::ResultCollector results(log);
718
719 const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_GOOGLE_surfaceless_query")));
720 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
721 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
722 native.getWindow(), context.getTestContext().getCommandLine()));
723 const VkSurfaceKHR nullSurface = 0;
724 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
725
726 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
727 {
728 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
729 {
730 uint32_t numFormatsSurface = 0;
731 uint32_t numFormatsNull = 0;
732
733 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
734 &numFormatsSurface, DE_NULL));
735 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], nullSurface,
736 &numFormatsNull, DE_NULL));
737
738 if (numFormatsSurface != numFormatsNull)
739 {
740 results.fail("Number of formats do not match");
741 continue;
742 }
743
744 std::vector<VkSurfaceFormatKHR> formatsSurface(numFormatsSurface + 1);
745 std::vector<VkSurfaceFormatKHR> formatsNull(numFormatsSurface + 1);
746
747 if (numFormatsSurface > 0)
748 {
749 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
750 &numFormatsSurface, &formatsSurface[0]));
751 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], nullSurface,
752 &numFormatsSurface, &formatsNull[0]));
753 }
754
755 formatsSurface.pop_back();
756 formatsNull.pop_back();
757
758 for (uint32_t i = 0; i < numFormatsSurface; i++)
759 {
760 if (formatsSurface[i].colorSpace != formatsNull[i].colorSpace ||
761 formatsSurface[i].format != formatsNull[i].format)
762 {
763 results.fail("Surface formats do not match");
764 }
765 }
766 }
767 }
768
769 return tcu::TestStatus(results.getResult(), results.getMessage());
770 }
771
querySurfaceFormats2Test(Context & context,Type wsiType)772 tcu::TestStatus querySurfaceFormats2Test(Context &context, Type wsiType)
773 {
774 tcu::TestLog &log = context.getTestContext().getLog();
775 tcu::ResultCollector results(log);
776
777 const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
778 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
779 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
780 native.getWindow(), context.getTestContext().getCommandLine()));
781 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
782
783 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
784 {
785 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
786 {
787 const vector<VkSurfaceFormatKHR> refFormats =
788 getPhysicalDeviceSurfaceFormats(instHelper.vki, physicalDevices[deviceNdx], *surface);
789 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
790 DE_NULL, *surface};
791 uint32_t numFormats = 0;
792
793 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
794 &numFormats, DE_NULL));
795
796 if ((size_t)numFormats != refFormats.size())
797 results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
798
799 if (numFormats > 0)
800 {
801 vector<VkSurfaceFormat2KHR> formats(numFormats + 1);
802
803 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
804 {
805 formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
806 formats[ndx].pNext = DE_NULL;
807 }
808
809 const uint32_t numFormatsOrig = numFormats;
810
811 // check if below call properly overwrites formats count
812 numFormats++;
813
814 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
815 &numFormats, &formats[0]));
816
817 if ((size_t)numFormats != numFormatsOrig)
818 results.fail("Format count changed between calls");
819
820 formats.pop_back();
821
822 {
823 vector<VkSurfaceFormatKHR> extFormats(formats.size());
824
825 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
826 {
827 results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
828 formats[ndx].pNext == DE_NULL,
829 "sType/pNext modified");
830 extFormats[ndx] = formats[ndx].surfaceFormat;
831 }
832
833 for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
834 {
835 if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
836 results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
837 }
838 }
839
840 // Check VK_INCOMPLETE
841 {
842 vector<VkSurfaceFormat2KHR> formatsClone(formats);
843 uint32_t numToSupply = numFormats / 2;
844 VkResult queryResult;
845
846 ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
847
848 queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(
849 physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
850
851 results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
852 results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
853 "Driver wrote past last element");
854
855 for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
856 {
857 results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
858 formatsClone[ndx].pNext == DE_NULL &&
859 formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
860 "Returned element " + de::toString(ndx) + " is different");
861 }
862 }
863 }
864 }
865 // else skip query as surface is not supported by the device
866 }
867
868 return tcu::TestStatus(results.getResult(), results.getMessage());
869 }
870
validateSurfacePresentModes(tcu::ResultCollector & results,Type wsiType,const vector<VkPresentModeKHR> & modes)871 void validateSurfacePresentModes(tcu::ResultCollector &results, Type wsiType, const vector<VkPresentModeKHR> &modes)
872 {
873 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
874 "VK_PRESENT_MODE_FIFO_KHR is not supported");
875
876 if (wsiType == TYPE_ANDROID)
877 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
878 "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
879 }
880
querySurfacePresentModes2Test(Context & context,Type wsiType)881 tcu::TestStatus querySurfacePresentModes2Test(Context &context, Type wsiType)
882 {
883 tcu::TestLog &log = context.getTestContext().getLog();
884 tcu::ResultCollector results(log);
885
886 const InstanceHelper instHelper(context, wsiType);
887 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
888 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
889 native.getWindow(), context.getTestContext().getCommandLine()));
890 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
891 const std::vector<VkExtensionProperties> deviceExtensions(
892 enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
893 if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
894 TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
895
896 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
897 {
898 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
899 {
900 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
901 DE_NULL, *surface};
902
903 uint32_t numModesRef = 0;
904 uint32_t numModes = 0;
905
906 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface,
907 &numModesRef, DE_NULL));
908 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo,
909 &numModes, DE_NULL));
910
911 if (numModes != numModesRef)
912 {
913 results.fail("Number of modes do not match");
914 continue;
915 }
916
917 vector<VkPresentModeKHR> modes(numModes + 1);
918
919 if (numModes > 0)
920 {
921 const uint32_t numModesOrig = numModes;
922
923 // check if below call properly overwrites mode count
924 numModes++;
925
926 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx],
927 &surfaceInfo, &numModes, &modes[0]));
928
929 if ((size_t)numModes != numModesOrig)
930 TCU_FAIL("Mode count changed between calls");
931 }
932
933 modes.pop_back();
934
935 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end())
936 << TestLog::EndMessage;
937
938 validateSurfacePresentModes(results, wsiType, modes);
939 if (numModes > 1)
940 {
941 numModes /= 2;
942 vk::VkResult res = instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(
943 physicalDevices[deviceNdx], &surfaceInfo, &numModes, &modes[0]);
944 if (res != VK_INCOMPLETE)
945 TCU_FAIL("Failed to fetch incomplete results");
946 }
947 }
948 // else skip query as surface is not supported by the device
949 }
950
951 return tcu::TestStatus(results.getResult(), results.getMessage());
952 }
953
querySurfacePresentModes2TestSurfaceless(Context & context,Type wsiType)954 tcu::TestStatus querySurfacePresentModes2TestSurfaceless(Context &context, Type wsiType)
955 {
956 tcu::TestLog &log = context.getTestContext().getLog();
957 tcu::ResultCollector results(log);
958
959 const std::string extensionName = "VK_GOOGLE_surfaceless_query";
960 const InstanceHelper instHelper(context, wsiType, vector<string>(1, extensionName), DE_NULL);
961 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
962 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
963 native.getWindow(), context.getTestContext().getCommandLine()));
964 const VkSurfaceKHR nullSurface = 0;
965 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
966 const std::vector<vk::VkExtensionProperties> deviceExtensions(
967 enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
968 const vector<VkPresentModeKHR> validPresentModes{VK_PRESENT_MODE_FIFO_KHR,
969 VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
970 VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR};
971
972 if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
973 return tcu::TestStatus(QP_TEST_RESULT_NOT_SUPPORTED, "Extension VK_EXT_full_screen_exclusive not supported");
974
975 // Ensure "VK_GOOGLE_surfaceless_query" extension's spec version is at least 2
976 {
977 uint32_t propertyCount = 0u;
978 std::vector<vk::VkExtensionProperties> extensionsProperties;
979 vk::VkResult extensionResult;
980
981 extensionResult =
982 context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, DE_NULL);
983 if (extensionResult != vk::VK_SUCCESS)
984 return tcu::TestStatus(QP_TEST_RESULT_FAIL,
985 "Failed to retrieve spec version for extension " + extensionName);
986
987 extensionsProperties.resize(propertyCount);
988
989 extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(
990 DE_NULL, &propertyCount, extensionsProperties.data());
991 if (extensionResult != vk::VK_SUCCESS)
992 return tcu::TestStatus(QP_TEST_RESULT_FAIL,
993 "Failed to retrieve spec version for extension " + extensionName);
994
995 for (const auto &property : extensionsProperties)
996 {
997 if (property.extensionName == extensionName)
998 {
999 if (property.specVersion < 2)
1000 return tcu::TestStatus(QP_TEST_RESULT_NOT_SUPPORTED,
1001 "VK_GOOGLE_surfaceless_query is version 1. Need version 2 or higher");
1002 break;
1003 }
1004 }
1005 }
1006
1007 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1008 {
1009 const VkPhysicalDeviceSurfaceInfo2KHR nullSurfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1010 DE_NULL, nullSurface};
1011 uint32_t numModesNull = 0u;
1012
1013 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo,
1014 &numModesNull, DE_NULL));
1015
1016 if (numModesNull == 0u)
1017 continue;
1018
1019 vector<VkPresentModeKHR> modesNull(numModesNull);
1020
1021 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo,
1022 &numModesNull, &modesNull[0]));
1023
1024 for (uint32_t i = 0; i < modesNull.size(); i++)
1025 {
1026 if (std::find(validPresentModes.begin(), validPresentModes.end(), modesNull[i]) == validPresentModes.end())
1027 {
1028 std::string error_string =
1029 std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1030 results.fail(error_string);
1031 break;
1032 }
1033 }
1034 }
1035
1036 return tcu::TestStatus(results.getResult(), results.getMessage());
1037 }
1038
querySurfaceFormats2TestSurfaceless(Context & context,Type wsiType)1039 tcu::TestStatus querySurfaceFormats2TestSurfaceless(Context &context, Type wsiType)
1040 {
1041 tcu::TestLog &log = context.getTestContext().getLog();
1042 tcu::ResultCollector results(log);
1043
1044 const vector<std::string> extensions({"VK_KHR_get_surface_capabilities2", "VK_GOOGLE_surfaceless_query"});
1045 const InstanceHelper instHelper(context, wsiType, extensions);
1046 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1047 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
1048 native.getWindow(), context.getTestContext().getCommandLine()));
1049 const VkSurfaceKHR nullSurface = 0;
1050 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1051
1052 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1053 {
1054 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1055 {
1056 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1057 DE_NULL, *surface};
1058 const VkPhysicalDeviceSurfaceInfo2KHR nullSurfaceInfo = {
1059 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, DE_NULL, nullSurface};
1060 uint32_t numFormatsSurface = 0;
1061 uint32_t numFormatsNull = 0;
1062
1063 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
1064 &numFormatsSurface, DE_NULL));
1065 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &nullSurfaceInfo,
1066 &numFormatsNull, DE_NULL));
1067
1068 if (numFormatsSurface != numFormatsNull)
1069 {
1070 results.fail("Number of formats do not match");
1071 continue;
1072 }
1073
1074 if (numFormatsSurface > 0)
1075 {
1076 vector<VkSurfaceFormat2KHR> formatsSurface(numFormatsSurface + 1);
1077 vector<VkSurfaceFormat2KHR> formatsNull(numFormatsSurface + 1);
1078
1079 for (size_t ndx = 0; ndx < formatsSurface.size(); ++ndx)
1080 {
1081 formatsSurface[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1082 formatsSurface[ndx].pNext = DE_NULL;
1083 formatsNull[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1084 formatsNull[ndx].pNext = DE_NULL;
1085 }
1086
1087 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
1088 &numFormatsSurface, &formatsSurface[0]));
1089 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(
1090 physicalDevices[deviceNdx], &nullSurfaceInfo, &numFormatsSurface, &formatsNull[0]));
1091
1092 formatsSurface.pop_back();
1093 formatsNull.pop_back();
1094
1095 for (uint32_t i = 0; i < numFormatsSurface; i++)
1096 {
1097 if (formatsSurface[i].surfaceFormat != formatsNull[i].surfaceFormat)
1098 {
1099 results.fail("Surface formats do not match");
1100 }
1101 }
1102 }
1103 }
1104 }
1105
1106 return tcu::TestStatus(results.getResult(), results.getMessage());
1107 }
1108
querySurfacePresentModesTest(Context & context,Type wsiType)1109 tcu::TestStatus querySurfacePresentModesTest(Context &context, Type wsiType)
1110 {
1111 tcu::TestLog &log = context.getTestContext().getLog();
1112 tcu::ResultCollector results(log);
1113
1114 const InstanceHelper instHelper(context, wsiType);
1115 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1116 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
1117 native.getWindow(), context.getTestContext().getCommandLine()));
1118 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1119
1120 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1121 {
1122 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1123 {
1124 uint32_t numModes = 0;
1125
1126 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface,
1127 &numModes, DE_NULL));
1128
1129 vector<VkPresentModeKHR> modes(numModes + 1);
1130
1131 if (numModes > 0)
1132 {
1133 const uint32_t numModesOrig = numModes;
1134
1135 // check if below call properly overwrites mode count
1136 numModes++;
1137
1138 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface,
1139 &numModes, &modes[0]));
1140
1141 if ((size_t)numModes != numModesOrig)
1142 TCU_FAIL("Mode count changed between calls");
1143 }
1144
1145 modes.pop_back();
1146
1147 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end())
1148 << TestLog::EndMessage;
1149
1150 validateSurfacePresentModes(results, wsiType, modes);
1151 CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(
1152 results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
1153 }
1154 // else skip query as surface is not supported by the device
1155 }
1156
1157 return tcu::TestStatus(results.getResult(), results.getMessage());
1158 }
1159
checkDeprecatedExtensionGoogleSurfacelessQuery(const vk::InstanceDriver & vk,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,tcu::ResultCollector & result)1160 void checkDeprecatedExtensionGoogleSurfacelessQuery(const vk::InstanceDriver &vk, VkPhysicalDevice physicalDevice,
1161 VkSurfaceKHR surface, tcu::ResultCollector &result)
1162 {
1163 const VkSurfaceKHR nullSurface = DE_NULL;
1164
1165 if (isSupportedByAnyQueue(vk, physicalDevice, surface))
1166 {
1167 uint32_t numModesSurface = 0;
1168 uint32_t numModesNull = 0;
1169
1170 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModesSurface, DE_NULL));
1171 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, DE_NULL));
1172
1173 if (numModesNull == 0)
1174 return;
1175
1176 // Actual surface needs to have at least the amount of modes that null surface has
1177 if (numModesSurface < numModesNull)
1178 {
1179 result.fail("Number of modes does not match");
1180 return;
1181 }
1182
1183 vector<VkPresentModeKHR> modesSurface(numModesSurface);
1184 vector<VkPresentModeKHR> modesNull(numModesNull);
1185
1186 VK_CHECK(
1187 vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModesSurface, &modesSurface[0]));
1188 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, &modesNull[0]));
1189
1190 // All modes present in null surface should also be present in actual surface
1191 for (uint32_t i = 0; i < modesNull.size(); i++)
1192 {
1193 if (std::find(modesSurface.begin(), modesSurface.end(), modesNull[i]) == modesSurface.end())
1194 {
1195 std::string error_string =
1196 std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1197 result.fail(error_string);
1198 break;
1199 }
1200 }
1201 }
1202 }
1203
checkExtensionGoogleSurfacelessQuery(const vk::InstanceDriver & vk,VkPhysicalDevice physicalDevice,tcu::ResultCollector & result)1204 void checkExtensionGoogleSurfacelessQuery(const vk::InstanceDriver &vk, VkPhysicalDevice physicalDevice,
1205 tcu::ResultCollector &result)
1206 {
1207 const VkSurfaceKHR nullSurface = DE_NULL;
1208 const vector<VkPresentModeKHR> validPresentModes{VK_PRESENT_MODE_FIFO_KHR,
1209 VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
1210 VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR};
1211
1212 uint32_t numModesNull = 0;
1213 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, DE_NULL));
1214
1215 if (numModesNull == 0u)
1216 return;
1217
1218 vector<VkPresentModeKHR> modesNull(numModesNull);
1219
1220 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, &modesNull[0]));
1221
1222 for (uint32_t i = 0; i < modesNull.size(); i++)
1223 {
1224 if (std::find(validPresentModes.begin(), validPresentModes.end(), modesNull[i]) == validPresentModes.end())
1225 {
1226 std::string error_string =
1227 std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1228 result.fail(error_string);
1229 break;
1230 }
1231 }
1232 }
1233
querySurfacePresentModesTestSurfaceless(Context & context,Type wsiType)1234 tcu::TestStatus querySurfacePresentModesTestSurfaceless(Context &context, Type wsiType)
1235 {
1236 tcu::TestLog &log = context.getTestContext().getLog();
1237 tcu::ResultCollector results(log);
1238
1239 const std::string extensionName = "VK_GOOGLE_surfaceless_query";
1240 const InstanceHelper instHelper(context, wsiType, vector<string>(1, extensionName), DE_NULL);
1241 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1242 const Unique<vk::VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType,
1243 native.getDisplay(), native.getWindow(),
1244 context.getTestContext().getCommandLine()));
1245
1246 uint32_t extensionVersion = 1u;
1247
1248 // Get "VK_GOOGLE_surfaceless_query" extension's spec version
1249 {
1250 uint32_t propertyCount = 0u;
1251 std::vector<vk::VkExtensionProperties> extensionsProperties;
1252 vk::VkResult extensionResult;
1253
1254 extensionResult =
1255 context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, DE_NULL);
1256 if (extensionResult != vk::VK_SUCCESS)
1257 return tcu::TestStatus(QP_TEST_RESULT_FAIL,
1258 "Failed to retrieve spec version for extension " + extensionName);
1259
1260 extensionsProperties.resize(propertyCount);
1261
1262 extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(
1263 DE_NULL, &propertyCount, extensionsProperties.data());
1264 if (extensionResult != vk::VK_SUCCESS)
1265 return tcu::TestStatus(QP_TEST_RESULT_FAIL,
1266 "Failed to retrieve spec version for extension " + extensionName);
1267
1268 for (const auto &property : extensionsProperties)
1269 {
1270 if (property.extensionName == extensionName)
1271 {
1272 extensionVersion = property.specVersion;
1273 break;
1274 }
1275 }
1276 }
1277
1278 log << TestLog::Message << "Checking spec version " << extensionVersion << " for VK_GOOGLE_surfaceless_query"
1279 << TestLog::EndMessage;
1280
1281 const bool checkDeprecatedVersion = extensionVersion < 2;
1282 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1283 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1284 {
1285 if (checkDeprecatedVersion)
1286 checkDeprecatedExtensionGoogleSurfacelessQuery(instHelper.vki, physicalDevices[deviceNdx], *surface,
1287 results);
1288 else
1289 checkExtensionGoogleSurfacelessQuery(instHelper.vki, physicalDevices[deviceNdx], results);
1290 }
1291
1292 return tcu::TestStatus(results.getResult(), results.getMessage());
1293 }
1294
queryDevGroupSurfacePresentCapabilitiesTest(Context & context,Type wsiType)1295 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest(Context &context, Type wsiType)
1296 {
1297 tcu::TestLog &log = context.getTestContext().getLog();
1298 const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1299 const float queuePriority = 1.0f;
1300 const tcu::CommandLine &cmdLine = context.getTestContext().getCommandLine();
1301 const uint32_t devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1302 const uint32_t deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1303 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1304 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag =
1305 VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1306 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1307 uint8_t buffer[sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
1308 uint32_t queueFamilyIndex = 0;
1309 VkDeviceGroupPresentCapabilitiesKHR *presentCapabilities;
1310 std::vector<const char *> deviceExtensions;
1311
1312 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1313 deviceExtensions.push_back("VK_KHR_device_group");
1314 deviceExtensions.push_back("VK_KHR_swapchain");
1315
1316 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1317 {
1318 if (!context.isDeviceFunctionalitySupported(deviceExtensions[ndx]))
1319 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1320 }
1321
1322 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps =
1323 enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1324
1325 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(
1326 instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1327 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1328 {
1329 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1330 queueFamilyIndex = (uint32_t)queueNdx;
1331 }
1332 const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
1333 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1334 DE_NULL, //pNext
1335 (VkDeviceQueueCreateFlags)0u, //flags
1336 queueFamilyIndex, //queueFamilyIndex;
1337 1u, //queueCount;
1338 &queuePriority, //pQueuePriorities;
1339 };
1340 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo = {
1341 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1342 DE_NULL, //pNext
1343 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
1344 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
1345 };
1346
1347 const VkDeviceCreateInfo deviceCreateInfo = {
1348 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
1349 &deviceGroupInfo, //pNext;
1350 (VkDeviceCreateFlags)0u, //flags
1351 1, //queueRecordCount;
1352 &deviceQueueCreateInfo, //pRequestedQueues;
1353 0, //layerCount;
1354 DE_NULL, //ppEnabledLayerNames;
1355 uint32_t(deviceExtensions.size()), //enabledExtensionCount;
1356 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1357 DE_NULL, //pEnabledFeatures;
1358 };
1359
1360 Move<VkDevice> deviceGroup =
1361 createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
1362 context.getPlatformInterface(), instHelper.instance, instHelper.vki,
1363 deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1364 const DeviceDriver vk(context.getPlatformInterface(), instHelper.instance, *deviceGroup,
1365 context.getUsedApiVersion(), context.getTestContext().getCommandLine());
1366
1367 presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR *>(buffer);
1368 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1369 presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
1370 presentCapabilities->pNext = DE_NULL;
1371 VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
1372
1373 // Guard check
1374 for (int32_t ndx = 0; ndx < GUARD_SIZE; ndx++)
1375 {
1376 if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
1377 {
1378 log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid"
1379 << TestLog::EndMessage;
1380 return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
1381 }
1382 }
1383
1384 // Check each physical device can present on itself
1385 for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE; physDevIdx++)
1386 {
1387 if (presentCapabilities->presentMask[physDevIdx])
1388 if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
1389 return tcu::TestStatus::fail(
1390 "deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
1391 }
1392
1393 // Check if flags are valid
1394 if ((!(presentCapabilities->modes & requiredFlag)) || presentCapabilities->modes > maxValidFlag)
1395 return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
1396
1397 return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
1398 }
1399
queryDevGroupSurfacePresentModesTest(Context & context,Type wsiType)1400 tcu::TestStatus queryDevGroupSurfacePresentModesTest(Context &context, Type wsiType)
1401 {
1402 tcu::TestLog &log = context.getTestContext().getLog();
1403 tcu::ResultCollector results(log);
1404 const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1405 const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1406 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
1407 native.getWindow(), context.getTestContext().getCommandLine()));
1408 const float queuePriority = 1.0f;
1409 const tcu::CommandLine &cmdLine = context.getTestContext().getCommandLine();
1410 const uint32_t devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1411 const uint32_t deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1412 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1413 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag =
1414 VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1415 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1416 VkResult result = VK_SUCCESS;
1417 uint8_t buffer[sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
1418 uint32_t rectCount = 0;
1419 uint32_t incompleteRectCount = 0;
1420 uint32_t queueFamilyIndex = 0;
1421 VkRect2D *presentRectangles;
1422 VkDeviceGroupPresentModeFlagsKHR *presentModeFlags;
1423 vector<uint8_t> rectanglesBuffer;
1424 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1425 const Extensions &supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1426 std::vector<const char *> deviceExtensions;
1427
1428 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1429 deviceExtensions.push_back("VK_KHR_device_group");
1430 deviceExtensions.push_back("VK_KHR_swapchain");
1431
1432 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1433 {
1434 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1435 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1436 }
1437
1438 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps =
1439 enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1440 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(
1441 instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1442 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1443 {
1444 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1445 queueFamilyIndex = (uint32_t)queueNdx;
1446 }
1447 const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
1448 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1449 DE_NULL, //pNext
1450 (VkDeviceQueueCreateFlags)0u, //flags
1451 queueFamilyIndex, //queueFamilyIndex;
1452 1u, //queueCount;
1453 &queuePriority, //pQueuePriorities;
1454 };
1455 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo = {
1456 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1457 DE_NULL, //pNext
1458 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
1459 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
1460 };
1461
1462 const VkDeviceCreateInfo deviceCreateInfo = {
1463 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
1464 &deviceGroupInfo, //pNext;
1465 (VkDeviceCreateFlags)0u, //flags
1466 1, //queueRecordCount;
1467 &deviceQueueCreateInfo, //pRequestedQueues;
1468 0, //layerCount;
1469 DE_NULL, //ppEnabledLayerNames;
1470 uint32_t(deviceExtensions.size()), //enabledExtensionCount;
1471 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1472 DE_NULL, //pEnabledFeatures;
1473 };
1474
1475 Move<VkDevice> deviceGroup =
1476 createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
1477 context.getPlatformInterface(), instHelper.instance, instHelper.vki,
1478 deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1479 const DeviceDriver vk(context.getPlatformInterface(), instHelper.instance, *deviceGroup,
1480 context.getUsedApiVersion(), context.getTestContext().getCommandLine());
1481 presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR *>(buffer);
1482 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1483
1484 VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
1485
1486 // Guard check
1487 for (int32_t ndx = 0; ndx < GUARD_SIZE; ndx++)
1488 {
1489 if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
1490 {
1491 log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid"
1492 << TestLog::EndMessage;
1493 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
1494 }
1495 }
1496
1497 // Check if flags are valid
1498 if ((!(*presentModeFlags & requiredFlag)) || *presentModeFlags > maxValidFlag)
1499 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1500
1501 // getPhysicalDevicePresentRectanglesKHR is supported only when VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR is set
1502 if ((*presentModeFlags & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR))
1503 {
1504 for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1505 {
1506 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(
1507 deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1508 rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1509 presentRectangles = reinterpret_cast<VkRect2D *>(rectanglesBuffer.data());
1510 deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1511
1512 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(
1513 deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1514
1515 // Guard check
1516 for (int32_t ndx = 0; ndx < GUARD_SIZE; ndx++)
1517 {
1518 if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1519 {
1520 log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx
1521 << " not valid" << TestLog::EndMessage;
1522 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1523 }
1524 }
1525
1526 // Check rectangles do not overlap
1527 for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1528 {
1529 for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1530 {
1531 if (rectIdx1 != rectIdx2)
1532 {
1533 uint32_t rectATop = presentRectangles[rectIdx1].offset.y;
1534 uint32_t rectALeft = presentRectangles[rectIdx1].offset.x;
1535 uint32_t rectABottom =
1536 presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1537 uint32_t rectARight =
1538 presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1539
1540 uint32_t rectBTop = presentRectangles[rectIdx2].offset.y;
1541 uint32_t rectBLeft = presentRectangles[rectIdx2].offset.x;
1542 uint32_t rectBBottom =
1543 presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1544 uint32_t rectBRight =
1545 presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1546
1547 if (rectALeft < rectBRight && rectARight > rectBLeft && rectATop < rectBBottom &&
1548 rectABottom > rectBTop)
1549 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1550 }
1551 }
1552 }
1553
1554 // Check incomplete
1555 incompleteRectCount = rectCount / 2;
1556 result = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(
1557 deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount,
1558 presentRectangles);
1559 results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1560 }
1561 }
1562
1563 return tcu::TestStatus(results.getResult(), results.getMessage());
1564 }
1565
createSurfaceInitialSizeTest(Context & context,Type wsiType)1566 tcu::TestStatus createSurfaceInitialSizeTest(Context &context, Type wsiType)
1567 {
1568 tcu::TestLog &log = context.getTestContext().getLog();
1569 tcu::ResultCollector results(log);
1570
1571 const InstanceHelper instHelper(context, wsiType);
1572
1573 const UniquePtr<Display> nativeDisplay(NativeObjects::createDisplay(
1574 context.getTestContext().getPlatform().getVulkanPlatform(), instHelper.supportedExtensions, wsiType));
1575
1576 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1577 const UVec2 sizes[] = {UVec2(64, 64), UVec2(124, 119), UVec2(256, 512)};
1578
1579 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1580
1581 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1582 {
1583 const UVec2 &testSize = sizes[sizeNdx];
1584 const UniquePtr<Window> nativeWindow(NativeObjects::createWindow(*nativeDisplay, tcu::just(testSize)));
1585 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay,
1586 *nativeWindow, context.getTestContext().getCommandLine()));
1587
1588 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1589 {
1590 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1591 {
1592 const VkSurfaceCapabilitiesKHR capabilities =
1593 getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1594
1595 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1596 results.check(capabilities.currentExtent.width == testSize.x() &&
1597 capabilities.currentExtent.height == testSize.y(),
1598 "currentExtent " + de::toString(capabilities.currentExtent) +
1599 " doesn't match requested size " + de::toString(testSize));
1600 }
1601 }
1602 }
1603
1604 return tcu::TestStatus(results.getResult(), results.getMessage());
1605 }
1606
resizeSurfaceTest(Context & context,Type wsiType)1607 tcu::TestStatus resizeSurfaceTest(Context &context, Type wsiType)
1608 {
1609 tcu::TestLog &log = context.getTestContext().getLog();
1610 tcu::ResultCollector results(log);
1611
1612 const InstanceHelper instHelper(context, wsiType);
1613
1614 const UniquePtr<Display> nativeDisplay(NativeObjects::createDisplay(
1615 context.getTestContext().getPlatform().getVulkanPlatform(), instHelper.supportedExtensions, wsiType));
1616 UniquePtr<Window> nativeWindow(NativeObjects::createWindow(*nativeDisplay, tcu::Nothing));
1617
1618 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1619 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay,
1620 *nativeWindow, context.getTestContext().getCommandLine()));
1621
1622 const UVec2 sizes[] = {UVec2(64, 64), UVec2(124, 119), UVec2(256, 512)};
1623
1624 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1625
1626 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1627 {
1628 const UVec2 testSize = sizes[sizeNdx];
1629
1630 try
1631 {
1632 nativeWindow->resize(testSize);
1633 }
1634 catch (const tcu::Exception &e)
1635 {
1636 // Make sure all exception types result in a test failure
1637 results.fail(e.getMessage());
1638 }
1639
1640 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1641 {
1642 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1643 {
1644 const VkSurfaceCapabilitiesKHR capabilities =
1645 getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1646
1647 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1648 results.check(capabilities.currentExtent.width == testSize.x() &&
1649 capabilities.currentExtent.height == testSize.y(),
1650 "currentExtent " + de::toString(capabilities.currentExtent) +
1651 " doesn't match requested size " + de::toString(testSize));
1652 }
1653 }
1654 }
1655
1656 return tcu::TestStatus(results.getResult(), results.getMessage());
1657 }
1658
destroyNullHandleSurfaceTest(Context & context,Type wsiType)1659 tcu::TestStatus destroyNullHandleSurfaceTest(Context &context, Type wsiType)
1660 {
1661 const InstanceHelper instHelper(context, wsiType);
1662 const VkSurfaceKHR nullHandle = DE_NULL;
1663
1664 // Default allocator
1665 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, DE_NULL);
1666
1667 // Custom allocator
1668 {
1669 AllocationCallbackRecorder recordingAllocator(getSystemAllocator(), 1u);
1670
1671 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1672
1673 if (recordingAllocator.getNumRecords() != 0u)
1674 return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1675 }
1676
1677 return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1678 }
1679
1680 } // namespace
1681
createSurfaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1682 void createSurfaceTests(tcu::TestCaseGroup *testGroup, vk::wsi::Type wsiType)
1683 {
1684 const PlatformProperties &platformProperties = getPlatformProperties(wsiType);
1685
1686 // Create surface
1687 addFunctionCase(testGroup, "create", createSurfaceTest, wsiType);
1688 // Create surface with custom allocator
1689 addFunctionCase(testGroup, "create_custom_allocator", createSurfaceCustomAllocatorTest, wsiType);
1690 // Create surface with simulating OOM
1691 addFunctionCase(testGroup, "create_simulate_oom", createSurfaceSimulateOOMTest, wsiType);
1692 // Query surface support
1693 addFunctionCase(testGroup, "query_support", querySurfaceSupportTest, wsiType);
1694 // Query native presentation support
1695 addFunctionCase(testGroup, "query_presentation_support", queryPresentationSupportTest, wsiType);
1696 // Query surface capabilities
1697 addFunctionCase(testGroup, "query_capabilities", querySurfaceCapabilitiesTest, wsiType);
1698 // Query extended surface capabilities
1699 addFunctionCase(testGroup, "query_capabilities2", querySurfaceCapabilities2Test, wsiType);
1700 // Query protected surface capabilities
1701 addFunctionCase(testGroup, "query_protected_capabilities", querySurfaceProtectedCapabilitiesTest, wsiType);
1702 // Query and check available surface counters
1703 addFunctionCase(testGroup, "query_surface_counters", querySurfaceCounterTest, wsiType);
1704 // Query surface formats
1705 addFunctionCase(testGroup, "query_formats", querySurfaceFormatsTest, wsiType);
1706 // Query extended surface formats
1707 addFunctionCase(testGroup, "query_formats2", querySurfaceFormats2Test, wsiType);
1708 // Query surface present modes
1709 addFunctionCase(testGroup, "query_present_modes", querySurfacePresentModesTest, wsiType);
1710 // Query extended surface present modes
1711 addFunctionCase(testGroup, "query_present_modes2", querySurfacePresentModes2Test, wsiType);
1712 // Query surface present modes capabilities in device groups
1713 addFunctionCase(testGroup, "query_devgroup_present_capabilities", queryDevGroupSurfacePresentCapabilitiesTest,
1714 wsiType);
1715 // Query surface present modes for device groups
1716 addFunctionCase(testGroup, "query_devgroup_present_modes", queryDevGroupSurfacePresentModesTest, wsiType);
1717 // Destroy VK_NULL_HANDLE surface
1718 addFunctionCase(testGroup, "destroy_null_handle", destroyNullHandleSurfaceTest, wsiType);
1719
1720 if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1721 // Create surface with initial window size set
1722 addFunctionCase(testGroup, "initial_size", createSurfaceInitialSizeTest, wsiType);
1723
1724 if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1725 // Resize window and surface
1726 addFunctionCase(testGroup, "resize", resizeSurfaceTest, wsiType);
1727
1728 // Query surface formats without surface
1729 addFunctionCase(testGroup, "query_formats_surfaceless", querySurfaceFormatsTestSurfaceless, wsiType);
1730 // Query surface present modes without surface
1731 addFunctionCase(testGroup, "query_present_modes_surfaceless", querySurfacePresentModesTestSurfaceless, wsiType);
1732 // Query extended surface present modes without surface
1733 addFunctionCase(testGroup, "query_present_modes2_surfaceless", querySurfacePresentModes2TestSurfaceless, wsiType);
1734 // Query extended surface formats without surface
1735 addFunctionCase(testGroup, "query_formats2_surfaceless", querySurfaceFormats2TestSurfaceless, wsiType);
1736 }
1737
1738 } // namespace wsi
1739 } // namespace vkt
1740