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) ||
77 (a.maxImageCount != b.maxImageCount) ||
78 (a.currentExtent != b.currentExtent) ||
79 (a.minImageExtent != b.minImageExtent) ||
80 (a.maxImageExtent != b.maxImageExtent) ||
81 (a.maxImageArrayLayers != b.maxImageArrayLayers) ||
82 (a.supportedTransforms != b.supportedTransforms) ||
83 (a.currentTransform != b.currentTransform) ||
84 (a.supportedCompositeAlpha != b.supportedCompositeAlpha) ||
85 (a.supportedUsageFlags != b.supportedUsageFlags);
86 }
87
88 } // vk
89
90 namespace vkt
91 {
92 namespace wsi
93 {
94
95 namespace
96 {
97
98 using namespace vk;
99 using namespace vk::wsi;
100
101 using tcu::TestLog;
102 using tcu::Maybe;
103 using tcu::UVec2;
104
105 using de::MovePtr;
106 using de::UniquePtr;
107
108 using std::string;
109 using std::vector;
110
111 enum
112 {
113 SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC = 0xffffffff
114 };
115
116 enum
117 {
118 GUARD_SIZE = 0x20, //!< Number of bytes to check
119 GUARD_VALUE = 0xcd, //!< Data pattern
120 };
121
122 template<typename T>
123 class CheckIncompleteResult
124 {
125 public:
~CheckIncompleteResult(void)126 virtual ~CheckIncompleteResult (void) {}
127 virtual void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, T* data) = 0;
128
operator ()(tcu::ResultCollector & results,const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkSurfaceKHR surface,const std::size_t expectedCompleteSize)129 void operator() (tcu::ResultCollector& results,
130 const InstanceInterface& vki,
131 const VkPhysicalDevice physDevice,
132 const VkSurfaceKHR surface,
133 const std::size_t expectedCompleteSize)
134 {
135 if (expectedCompleteSize == 0)
136 return;
137
138 vector<T> outputData (expectedCompleteSize);
139 const deUint32 usedSize = static_cast<deUint32>(expectedCompleteSize / 3);
140
141 ValidateQueryBits::fillBits(outputData.begin(), outputData.end()); // unused entries should have this pattern intact
142 m_count = usedSize;
143 m_result = VK_SUCCESS;
144
145 getResult(vki, physDevice, surface, &outputData[0]); // update m_count and m_result
146
147 if (m_count != usedSize || m_result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(outputData.begin() + m_count, outputData.end()))
148 results.fail("Query didn't return VK_INCOMPLETE");
149 }
150
151 protected:
152 deUint32 m_count;
153 VkResult m_result;
154 };
155
156 struct CheckPhysicalDeviceSurfaceFormatsIncompleteResult : public CheckIncompleteResult<VkSurfaceFormatKHR>
157 {
getResultvkt::wsi::__anon7534b2240111::CheckPhysicalDeviceSurfaceFormatsIncompleteResult158 void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkSurfaceFormatKHR* data)
159 {
160 m_result = vki.getPhysicalDeviceSurfaceFormatsKHR(physDevice, surface, &m_count, data);
161 }
162 };
163
164 struct CheckPhysicalDeviceSurfacePresentModesIncompleteResult : public CheckIncompleteResult<VkPresentModeKHR>
165 {
getResultvkt::wsi::__anon7534b2240111::CheckPhysicalDeviceSurfacePresentModesIncompleteResult166 void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkPresentModeKHR* data)
167 {
168 m_result = vki.getPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &m_count, data);
169 }
170 };
171
172 typedef vector<VkExtensionProperties> Extensions;
173
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)174 CustomInstance createInstanceWithWsi (Context& context,
175 Type wsiType,
176 const vector<string> extraExtensions,
177 const VkAllocationCallbacks* pAllocator = DE_NULL)
178 {
179 const deUint32 version = context.getUsedApiVersion();
180 vector<string> extensions = extraExtensions;
181
182 extensions.push_back("VK_KHR_surface");
183 extensions.push_back(getExtensionName(wsiType));
184
185 vector<string> instanceExtensions;
186 for (const auto& ext : extensions)
187 {
188 if (!context.isInstanceFunctionalitySupported(ext))
189 TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
190
191 if (!isCoreInstanceExtension(version, ext))
192 instanceExtensions.push_back(ext);
193 }
194
195 return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
196 }
197
198 struct InstanceHelper
199 {
200 const vector<VkExtensionProperties> supportedExtensions;
201 CustomInstance instance;
202 const InstanceDriver& vki;
203
InstanceHelpervkt::wsi::__anon7534b2240111::InstanceHelper204 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
205 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
206 DE_NULL))
207 , instance (createInstanceWithWsi(context,
208 wsiType,
209 vector<string>(),
210 pAllocator))
211 , vki (instance.getDriver())
212 {}
213
InstanceHelpervkt::wsi::__anon7534b2240111::InstanceHelper214 InstanceHelper (Context& context, Type wsiType, const vector<string>& extensions, const VkAllocationCallbacks* pAllocator = DE_NULL)
215 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
216 DE_NULL))
217 , instance (createInstanceWithWsi(context,
218 wsiType,
219 extensions,
220 pAllocator))
221 , vki (instance.getDriver())
222 {}
223 };
224
createSurfaceTest(Context & context,Type wsiType)225 tcu::TestStatus createSurfaceTest (Context& context, Type wsiType)
226 {
227 const InstanceHelper instHelper (context, wsiType);
228 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
229 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
230
231 return tcu::TestStatus::pass("Creating surface succeeded");
232 }
233
querySurfaceCounterTest(Context & context,Type wsiType)234 tcu::TestStatus querySurfaceCounterTest (Context& context, Type wsiType)
235 {
236 const InstanceHelper instHelper (context, wsiType);
237 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
238 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
239 const vk::InstanceInterface& vki = context.getInstanceInterface();
240 const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
241
242 if (!isInstanceExtensionSupported(context.getUsedApiVersion(), context.getInstanceExtensions(), "VK_EXT_display_surface_counter"))
243 TCU_THROW(NotSupportedError, "VK_EXT_display_surface_counter not supported");
244
245 const vk::VkSurfaceCapabilities2EXT capsExt = getPhysicalDeviceSurfaceCapabilities2EXT (vki, physicalDevice, surface.get());
246 const vk::VkSurfaceCapabilitiesKHR capsKhr = getPhysicalDeviceSurfaceCapabilities (vki, physicalDevice, surface.get());
247
248 if (!sameSurfaceCapabilities(capsKhr, capsExt))
249 {
250 return tcu::TestStatus::fail("KHR and EXT surface capabilities do not match");
251 }
252
253 if (capsExt.supportedSurfaceCounters != 0)
254 {
255 return tcu::TestStatus::fail("supportedSurfaceCounters nonzero (" + de::toString(capsExt.supportedSurfaceCounters) + ") for non-display surface");
256 }
257
258 return tcu::TestStatus::pass("Pass");
259 }
260
createSurfaceCustomAllocatorTest(Context & context,Type wsiType)261 tcu::TestStatus createSurfaceCustomAllocatorTest (Context& context, Type wsiType)
262 {
263 AllocationCallbackRecorder allocationRecorder (getSystemAllocator());
264 tcu::TestLog& log = context.getTestContext().getLog();
265
266 {
267 const InstanceHelper instHelper (context, wsiType, allocationRecorder.getCallbacks());
268 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
269 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki,
270 instHelper.instance,
271 wsiType,
272 native.getDisplay(),
273 native.getWindow(),
274 allocationRecorder.getCallbacks()));
275
276 if (!validateAndLog(log,
277 allocationRecorder,
278 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) |
279 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
280 return tcu::TestStatus::fail("Detected invalid system allocation callback");
281 }
282
283 if (!validateAndLog(log, allocationRecorder, 0u))
284 return tcu::TestStatus::fail("Detected invalid system allocation callback");
285
286 if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
287 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
288 else
289 return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
290 }
291
createSurfaceSimulateOOMTest(Context & context,Type wsiType)292 tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
293 {
294 tcu::TestLog& log = context.getTestContext().getLog();
295
296 for (deUint32 numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
297 {
298 AllocationCallbackRecorder allocationRecorder (getSystemAllocator());
299 DeterministicFailAllocator failingAllocator (allocationRecorder.getCallbacks(),
300 DeterministicFailAllocator::MODE_DO_NOT_COUNT,
301 0);
302 bool gotOOM = false;
303
304 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
305
306 try
307 {
308 const InstanceHelper instHelper (context, wsiType, failingAllocator.getCallbacks());
309
310 // OOM is not simulated for VkInstance as we don't want to spend time
311 // testing OOM paths inside instance creation.
312 failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
313
314 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
315 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki,
316 instHelper.instance,
317 wsiType,
318 native.getDisplay(),
319 native.getWindow(),
320 failingAllocator.getCallbacks()));
321
322 if (!validateAndLog(log,
323 allocationRecorder,
324 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) |
325 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
326 return tcu::TestStatus::fail("Detected invalid system allocation callback");
327 }
328 catch (const OutOfMemoryError& e)
329 {
330 log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
331 gotOOM = true;
332 }
333
334 if (!validateAndLog(log, allocationRecorder, 0u))
335 return tcu::TestStatus::fail("Detected invalid system allocation callback");
336
337 if (!gotOOM)
338 {
339 log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
340
341 if (numPassingAllocs == 0)
342 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
343 else
344 return tcu::TestStatus::pass("OOM simulation completed");
345 }
346 }
347
348 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
349 }
350
getNumQueueFamilies(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)351 deUint32 getNumQueueFamilies (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
352 {
353 deUint32 numFamilies = 0;
354
355 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
356
357 return numFamilies;
358 }
359
querySurfaceSupportTest(Context & context,Type wsiType)360 tcu::TestStatus querySurfaceSupportTest (Context& context, Type wsiType)
361 {
362 tcu::TestLog& log = context.getTestContext().getLog();
363 tcu::ResultCollector results (log);
364
365 const InstanceHelper instHelper (context, wsiType);
366 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
367 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
368 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
369
370 // On Android surface must be supported by all devices and queue families
371 const bool expectSupportedOnAll = wsiType == TYPE_ANDROID;
372
373 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
374 {
375 const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
376 const deUint32 numQueueFamilies = getNumQueueFamilies(instHelper.vki, physicalDevice);
377
378 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
379 {
380 const VkBool32 isSupported = getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
381
382 log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
383 << (isSupported == VK_FALSE ? "NOT " : "") << "supported"
384 << TestLog::EndMessage;
385
386 if (expectSupportedOnAll && !isSupported)
387 results.fail("Surface must be supported by all devices and queue families");
388 }
389 }
390
391 return tcu::TestStatus(results.getResult(), results.getMessage());
392 }
393
queryPresentationSupportTest(Context & context,Type wsiType)394 tcu::TestStatus queryPresentationSupportTest(Context& context, Type wsiType)
395 {
396 tcu::TestLog& log = context.getTestContext().getLog();
397 tcu::ResultCollector results (log);
398
399 const InstanceHelper instHelper (context, wsiType);
400 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
401 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
402 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
403
404 native.getDisplay();
405 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
406 {
407 const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
408 const deUint32 numQueueFamilies = getNumQueueFamilies(instHelper.vki, physicalDevice);
409
410 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
411 {
412 VkBool32 isPresentationSupported = getPhysicalDevicePresentationSupport(instHelper.vki, physicalDevice, queueFamilyNdx, wsiType, native.getDisplay());
413 VkBool32 isSurfaceSupported = getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
414
415 log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": presentation "
416 << (isPresentationSupported == VK_FALSE ? "NOT " : "") << "supported. Surface "
417 << (isSurfaceSupported == VK_FALSE ? "NOT " : "") << "supported."
418 << TestLog::EndMessage;
419
420 if (isPresentationSupported != isSurfaceSupported)
421 results.fail("Presentation support is different from surface support");
422 }
423 }
424
425 return tcu::TestStatus(results.getResult(), results.getMessage());
426 }
427
isSupportedByAnyQueue(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)428 bool isSupportedByAnyQueue (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
429 {
430 const deUint32 numQueueFamilies = getNumQueueFamilies(vki, physicalDevice);
431
432 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
433 {
434 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
435 return true;
436 }
437
438 return false;
439 }
440
validateSurfaceCapabilities(tcu::ResultCollector & results,const VkSurfaceCapabilitiesKHR & capabilities)441 void validateSurfaceCapabilities (tcu::ResultCollector& results, const VkSurfaceCapabilitiesKHR& capabilities)
442 {
443 results.check(capabilities.minImageCount > 0,
444 "minImageCount must be larger than 0");
445
446 results.check(capabilities.minImageExtent.width > 0 &&
447 capabilities.minImageExtent.height > 0,
448 "minImageExtent dimensions must be larger than 0");
449
450 results.check(capabilities.maxImageExtent.width > 0 &&
451 capabilities.maxImageExtent.height > 0,
452 "maxImageExtent dimensions must be larger than 0");
453
454 results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
455 capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
456 "maxImageExtent must be larger or equal to minImageExtent");
457
458 if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
459 capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
460 {
461 results.check(capabilities.currentExtent.width > 0 &&
462 capabilities.currentExtent.height > 0,
463 "currentExtent dimensions must be larger than 0");
464
465 results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width) &&
466 de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height),
467 "currentExtent is not in supported extent limits");
468 }
469
470 results.check(capabilities.maxImageArrayLayers > 0,
471 "maxImageArrayLayers must be larger than 0");
472
473 results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
474 "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
475
476 results.check(capabilities.supportedTransforms != 0,
477 "At least one transform must be supported");
478
479 results.check(dePop32(capabilities.currentTransform) != 0,
480 "Invalid currentTransform");
481
482 results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
483 "currentTransform is not supported by surface");
484
485 results.check(capabilities.supportedCompositeAlpha != 0,
486 "At least one alpha mode must be supported");
487 }
488
querySurfaceCapabilitiesTest(Context & context,Type wsiType)489 tcu::TestStatus querySurfaceCapabilitiesTest (Context& context, Type wsiType)
490 {
491 tcu::TestLog& log = context.getTestContext().getLog();
492 tcu::ResultCollector results (log);
493
494 const InstanceHelper instHelper (context, wsiType);
495 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
496 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
497 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
498
499 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
500 {
501 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
502 {
503 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
504 physicalDevices[deviceNdx],
505 *surface);
506
507 log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
508
509 validateSurfaceCapabilities(results, capabilities);
510 }
511 // else skip query as surface is not supported by the device
512 }
513
514 return tcu::TestStatus(results.getResult(), results.getMessage());
515 }
516
querySurfaceCapabilities2Test(Context & context,Type wsiType)517 tcu::TestStatus querySurfaceCapabilities2Test (Context& context, Type wsiType)
518 {
519 tcu::TestLog& log = context.getTestContext().getLog();
520 tcu::ResultCollector results (log);
521
522 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
523 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
524 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
525 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
526
527 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
528 {
529 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
530 {
531 const VkSurfaceCapabilitiesKHR refCapabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
532 physicalDevices[deviceNdx],
533 *surface);
534 VkSurfaceCapabilities2KHR extCapabilities;
535
536 deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
537 extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
538 extCapabilities.pNext = DE_NULL;
539
540 {
541 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
542 {
543 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
544 DE_NULL,
545 *surface
546 };
547 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
548
549 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
550
551 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
552
553 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
554 }
555
556 results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
557 extCapabilities.pNext == DE_NULL,
558 "sType/pNext modified");
559
560 if (refCapabilities != extCapabilities.surfaceCapabilities)
561 {
562 log << TestLog::Message
563 << "Device " << deviceNdx
564 << ": expected " << refCapabilities
565 << ", got " << extCapabilities.surfaceCapabilities
566 << TestLog::EndMessage;
567 results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
568 }
569 }
570 }
571
572 return tcu::TestStatus(results.getResult(), results.getMessage());
573 }
574
querySurfaceProtectedCapabilitiesTest(Context & context,Type wsiType)575 tcu::TestStatus querySurfaceProtectedCapabilitiesTest (Context& context, Type wsiType)
576 {
577 tcu::TestLog& log = context.getTestContext().getLog();
578 tcu::ResultCollector results (log);
579
580 vector<string> requiredExtensions;
581 requiredExtensions.push_back("VK_KHR_get_surface_capabilities2");
582 requiredExtensions.push_back("VK_KHR_surface_protected_capabilities");
583 const InstanceHelper instHelper (context, wsiType, requiredExtensions);
584 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
585 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
586 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
587
588 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
589 {
590 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
591 {
592 VkSurfaceCapabilities2KHR extCapabilities;
593 VkSurfaceProtectedCapabilitiesKHR extProtectedCapabilities;
594
595 deMemset(&extProtectedCapabilities, 0xcd, sizeof(VkSurfaceProtectedCapabilitiesKHR));
596 extProtectedCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR;
597 extProtectedCapabilities.pNext = DE_NULL;
598
599 deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
600 extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
601 extCapabilities.pNext = &extProtectedCapabilities;
602
603 {
604 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
605 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
606 {
607 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
608 DE_NULL,
609 *surface
610 };
611
612
613 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
614
615 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
616
617 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
618 }
619
620 results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
621 extCapabilities.pNext == &extProtectedCapabilities,
622 "sType/pNext modified");
623
624 results.check(extProtectedCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR &&
625 extProtectedCapabilities.pNext == DE_NULL,
626 "sType/pNext modified");
627
628 results.check(extProtectedCapabilities.supportsProtected == 0 ||
629 extProtectedCapabilities.supportsProtected == 1,
630 "supportsProtected ");
631 }
632 }
633
634 return tcu::TestStatus(results.getResult(), results.getMessage());
635 }
636
validateSurfaceFormats(tcu::ResultCollector & results,Type wsiType,const vector<VkSurfaceFormatKHR> & formats)637 void validateSurfaceFormats (tcu::ResultCollector& results, Type wsiType, const vector<VkSurfaceFormatKHR>& formats)
638 {
639 const VkSurfaceFormatKHR* requiredFormats = DE_NULL;
640 size_t numRequiredFormats = 0;
641
642 if (wsiType == TYPE_ANDROID)
643 {
644 static const VkSurfaceFormatKHR s_androidFormats[] =
645 {
646 { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
647 { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
648 { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }
649 };
650
651 requiredFormats = &s_androidFormats[0];
652 numRequiredFormats = DE_LENGTH_OF_ARRAY(s_androidFormats);
653 }
654
655 for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
656 {
657 const VkSurfaceFormatKHR& requiredFormat = requiredFormats[ndx];
658
659 if (!de::contains(formats.begin(), formats.end(), requiredFormat))
660 results.fail(de::toString(requiredFormat) + " not supported");
661 }
662
663 // Check that there are no duplicates
664 for (size_t ndx = 1; ndx < formats.size(); ++ndx)
665 {
666 if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
667 results.fail("Found duplicate entry " + de::toString(formats[ndx]));
668 }
669 }
670
querySurfaceFormatsTest(Context & context,Type wsiType)671 tcu::TestStatus querySurfaceFormatsTest (Context& context, Type wsiType)
672 {
673 tcu::TestLog& log = context.getTestContext().getLog();
674 tcu::ResultCollector results (log);
675
676 const InstanceHelper instHelper (context, wsiType);
677 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
678 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
679 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
680
681 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
682 {
683 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
684 {
685 deUint32 numFormats = 0;
686
687 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, DE_NULL));
688
689 std::vector<VkSurfaceFormatKHR> formats (numFormats + 1);
690
691 if (numFormats > 0)
692 {
693 const deUint32 numFormatsOrig = numFormats;
694
695 // check if below call properly overwrites formats count
696 numFormats++;
697
698 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, &formats[0]));
699
700 if (numFormats != numFormatsOrig)
701 results.fail("Format count changed between calls");
702 }
703
704 formats.pop_back();
705
706 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
707
708 validateSurfaceFormats(results, wsiType, formats);
709 CheckPhysicalDeviceSurfaceFormatsIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, formats.size());
710 }
711 // else skip query as surface is not supported by the device
712 }
713
714 return tcu::TestStatus(results.getResult(), results.getMessage());
715 }
716
querySurfaceFormats2Test(Context & context,Type wsiType)717 tcu::TestStatus querySurfaceFormats2Test (Context& context, Type wsiType)
718 {
719 tcu::TestLog& log = context.getTestContext().getLog();
720 tcu::ResultCollector results (log);
721
722 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
723 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
724 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
725 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
726
727 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
728 {
729 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
730 {
731 const vector<VkSurfaceFormatKHR> refFormats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
732 physicalDevices[deviceNdx],
733 *surface);
734 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
735 {
736 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
737 DE_NULL,
738 *surface
739 };
740 deUint32 numFormats = 0;
741
742 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, DE_NULL));
743
744 if ((size_t)numFormats != refFormats.size())
745 results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
746
747 if (numFormats > 0)
748 {
749 vector<VkSurfaceFormat2KHR> formats (numFormats + 1);
750
751 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
752 {
753 formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
754 formats[ndx].pNext = DE_NULL;
755 }
756
757 const deUint32 numFormatsOrig = numFormats;
758
759 // check if below call properly overwrites formats count
760 numFormats++;
761
762 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, &formats[0]));
763
764 if ((size_t)numFormats != numFormatsOrig)
765 results.fail("Format count changed between calls");
766
767 formats.pop_back();
768
769 {
770 vector<VkSurfaceFormatKHR> extFormats (formats.size());
771
772 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
773 {
774 results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
775 formats[ndx].pNext == DE_NULL,
776 "sType/pNext modified");
777 extFormats[ndx] = formats[ndx].surfaceFormat;
778 }
779
780 for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
781 {
782 if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
783 results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
784 }
785 }
786
787 // Check VK_INCOMPLETE
788 {
789 vector<VkSurfaceFormat2KHR> formatsClone (formats);
790 deUint32 numToSupply = numFormats/2;
791 VkResult queryResult;
792
793 ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
794
795 queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
796
797 results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
798 results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
799 "Driver wrote past last element");
800
801 for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
802 {
803 results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
804 formatsClone[ndx].pNext == DE_NULL &&
805 formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
806 "Returned element " + de::toString(ndx) + " is different");
807 }
808 }
809 }
810 }
811 // else skip query as surface is not supported by the device
812 }
813
814 return tcu::TestStatus(results.getResult(), results.getMessage());
815 }
816
validateSurfacePresentModes(tcu::ResultCollector & results,Type wsiType,const vector<VkPresentModeKHR> & modes)817 void validateSurfacePresentModes (tcu::ResultCollector& results, Type wsiType, const vector<VkPresentModeKHR>& modes)
818 {
819 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
820 "VK_PRESENT_MODE_FIFO_KHR is not supported");
821
822 if (wsiType == TYPE_ANDROID)
823 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
824 "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
825 }
826
querySurfacePresentModesTest(Context & context,Type wsiType)827 tcu::TestStatus querySurfacePresentModesTest (Context& context, Type wsiType)
828 {
829 tcu::TestLog& log = context.getTestContext().getLog();
830 tcu::ResultCollector results (log);
831
832 const InstanceHelper instHelper (context, wsiType);
833 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
834 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
835 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
836
837 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
838 {
839 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
840 {
841 deUint32 numModes = 0;
842
843 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, DE_NULL));
844
845 vector<VkPresentModeKHR> modes (numModes + 1);
846
847 if (numModes > 0)
848 {
849 const deUint32 numModesOrig = numModes;
850
851 // check if below call properly overwrites mode count
852 numModes++;
853
854 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, &modes[0]));
855
856 if ((size_t)numModes != numModesOrig)
857 TCU_FAIL("Mode count changed between calls");
858 }
859
860 modes.pop_back();
861
862 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
863
864 validateSurfacePresentModes(results, wsiType, modes);
865 CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
866 }
867 // else skip query as surface is not supported by the device
868 }
869
870 return tcu::TestStatus(results.getResult(), results.getMessage());
871 }
872
queryDevGroupSurfacePresentCapabilitiesTest(Context & context,Type wsiType)873 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest (Context& context, Type wsiType)
874 {
875 tcu::TestLog& log = context.getTestContext().getLog();
876 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
877 const float queuePriority = 1.0f;
878 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
879 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
880 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
881 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
882 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
883 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
884 deUint8 buffer [sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
885 deUint32 queueFamilyIndex = 0;
886 VkDeviceGroupPresentCapabilitiesKHR* presentCapabilities;
887 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
888 const Extensions& supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
889 std::vector<const char*> deviceExtensions;
890
891 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
892 deviceExtensions.push_back("VK_KHR_device_group");
893 deviceExtensions.push_back("VK_KHR_swapchain");
894
895 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
896 {
897 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
898 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
899 }
900
901 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
902
903 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
904 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
905 {
906 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
907 queueFamilyIndex = (deUint32)queueNdx;
908 }
909 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
910 {
911 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
912 DE_NULL, //pNext
913 (VkDeviceQueueCreateFlags)0u, //flags
914 queueFamilyIndex, //queueFamilyIndex;
915 1u, //queueCount;
916 &queuePriority, //pQueuePriorities;
917 };
918 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
919 {
920 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
921 DE_NULL, //pNext
922 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
923 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
924 };
925
926 const VkDeviceCreateInfo deviceCreateInfo =
927 {
928 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
929 &deviceGroupInfo, //pNext;
930 (VkDeviceCreateFlags)0u, //flags
931 1, //queueRecordCount;
932 &deviceQueueCreateInfo, //pRequestedQueues;
933 0, //layerCount;
934 DE_NULL, //ppEnabledLayerNames;
935 deUint32(deviceExtensions.size()), //enabledExtensionCount;
936 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
937 DE_NULL, //pEnabledFeatures;
938 };
939
940 Move<VkDevice> deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
941 const DeviceDriver vk (context.getPlatformInterface(), instHelper.instance, *deviceGroup);
942
943
944 presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>(buffer);
945 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
946 presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
947 presentCapabilities->pNext = DE_NULL;
948 VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
949
950 // Guard check
951 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
952 {
953 if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
954 {
955 log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
956 return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
957 }
958 }
959
960 // Check each physical device can present on itself
961 for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE_KHR; physDevIdx++)
962 {
963 if (presentCapabilities->presentMask[physDevIdx])
964 if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
965 return tcu::TestStatus::fail("deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
966 }
967
968 // Check if flags are valid
969 if ((!(presentCapabilities->modes & requiredFlag)) ||
970 presentCapabilities->modes > maxValidFlag)
971 return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
972
973 return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
974 }
975
queryDevGroupSurfacePresentModesTest(Context & context,Type wsiType)976 tcu::TestStatus queryDevGroupSurfacePresentModesTest (Context& context, Type wsiType)
977 {
978 tcu::TestLog& log = context.getTestContext().getLog();
979 tcu::ResultCollector results (log);
980 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
981 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
982 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
983 const float queuePriority = 1.0f;
984 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
985 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
986 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
987 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
988 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
989 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
990 VkResult result = VK_SUCCESS;
991 deUint8 buffer [sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
992 deUint32 rectCount = 0;
993 deUint32 incompleteRectCount = 0;
994 deUint32 queueFamilyIndex = 0;
995 VkRect2D* presentRectangles;
996 VkDeviceGroupPresentModeFlagsKHR* presentModeFlags;
997 vector<deUint8> rectanglesBuffer;
998 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
999 const Extensions& supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1000 std::vector<const char*> deviceExtensions;
1001
1002 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1003 deviceExtensions.push_back("VK_KHR_device_group");
1004 deviceExtensions.push_back("VK_KHR_swapchain");
1005
1006 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1007 {
1008 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1009 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1010 }
1011
1012 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1013 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1014 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1015 {
1016 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1017 queueFamilyIndex = (deUint32)queueNdx;
1018 }
1019 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
1020 {
1021 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1022 DE_NULL, //pNext
1023 (VkDeviceQueueCreateFlags)0u, //flags
1024 queueFamilyIndex, //queueFamilyIndex;
1025 1u, //queueCount;
1026 &queuePriority, //pQueuePriorities;
1027 };
1028 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
1029 {
1030 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1031 DE_NULL, //pNext
1032 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
1033 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
1034 };
1035
1036 const VkDeviceCreateInfo deviceCreateInfo =
1037 {
1038 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
1039 &deviceGroupInfo, //pNext;
1040 (VkDeviceCreateFlags)0u, //flags
1041 1, //queueRecordCount;
1042 &deviceQueueCreateInfo, //pRequestedQueues;
1043 0, //layerCount;
1044 DE_NULL, //ppEnabledLayerNames;
1045 deUint32(deviceExtensions.size()), //enabledExtensionCount;
1046 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1047 DE_NULL, //pEnabledFeatures;
1048 };
1049
1050 Move<VkDevice> deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1051 const DeviceDriver vk (context.getPlatformInterface(), instHelper.instance, *deviceGroup);
1052 presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>(buffer);
1053 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1054
1055 VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
1056
1057 // Guard check
1058 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1059 {
1060 if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
1061 {
1062 log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1063 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
1064 }
1065 }
1066
1067 // Check if flags are valid
1068 if ((!(*presentModeFlags & requiredFlag)) ||
1069 *presentModeFlags > maxValidFlag)
1070 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1071
1072 // getPhysicalDevicePresentRectanglesKHR is supported only when VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR is set
1073 if ((*presentModeFlags & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR))
1074 {
1075 for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1076 {
1077 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1078 rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1079 presentRectangles = reinterpret_cast<VkRect2D*>(rectanglesBuffer.data());
1080 deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1081
1082 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1083
1084 // Guard check
1085 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1086 {
1087 if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1088 {
1089 log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1090 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1091 }
1092 }
1093
1094 // Check rectangles do not overlap
1095 for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1096 {
1097 for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1098 {
1099 if (rectIdx1 != rectIdx2)
1100 {
1101 deUint32 rectATop = presentRectangles[rectIdx1].offset.y;
1102 deUint32 rectALeft = presentRectangles[rectIdx1].offset.x;
1103 deUint32 rectABottom = presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1104 deUint32 rectARight = presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1105
1106 deUint32 rectBTop = presentRectangles[rectIdx2].offset.y;
1107 deUint32 rectBLeft = presentRectangles[rectIdx2].offset.x;
1108 deUint32 rectBBottom = presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1109 deUint32 rectBRight = presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1110
1111 if (rectALeft < rectBRight && rectARight > rectBLeft &&
1112 rectATop < rectBBottom && rectABottom > rectBTop)
1113 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1114 }
1115 }
1116 }
1117
1118 // Check incomplete
1119 incompleteRectCount = rectCount / 2;
1120 result = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount, presentRectangles);
1121 results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1122 }
1123 }
1124
1125 return tcu::TestStatus(results.getResult(), results.getMessage());
1126 }
1127
createSurfaceInitialSizeTest(Context & context,Type wsiType)1128 tcu::TestStatus createSurfaceInitialSizeTest (Context& context, Type wsiType)
1129 {
1130 tcu::TestLog& log = context.getTestContext().getLog();
1131 tcu::ResultCollector results (log);
1132
1133 const InstanceHelper instHelper (context, wsiType);
1134
1135 const UniquePtr<Display> nativeDisplay (NativeObjects::createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1136 instHelper.supportedExtensions,
1137 wsiType));
1138
1139 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1140 const UVec2 sizes[] =
1141 {
1142 UVec2(64, 64),
1143 UVec2(124, 119),
1144 UVec2(256, 512)
1145 };
1146
1147 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1148
1149 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1150 {
1151 const UVec2& testSize = sizes[sizeNdx];
1152 const UniquePtr<Window> nativeWindow (NativeObjects::createWindow(*nativeDisplay, tcu::just(testSize)));
1153 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
1154
1155 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1156 {
1157 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1158 {
1159 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1160
1161 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1162 results.check(capabilities.currentExtent.width == testSize.x() &&
1163 capabilities.currentExtent.height == testSize.y(),
1164 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1165 }
1166 }
1167 }
1168
1169 return tcu::TestStatus(results.getResult(), results.getMessage());
1170 }
1171
resizeSurfaceTest(Context & context,Type wsiType)1172 tcu::TestStatus resizeSurfaceTest (Context& context, Type wsiType)
1173 {
1174 tcu::TestLog& log = context.getTestContext().getLog();
1175 tcu::ResultCollector results (log);
1176
1177 const InstanceHelper instHelper (context, wsiType);
1178
1179 const UniquePtr<Display> nativeDisplay (NativeObjects::createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1180 instHelper.supportedExtensions,
1181 wsiType));
1182 UniquePtr<Window> nativeWindow (NativeObjects::createWindow(*nativeDisplay, tcu::Nothing));
1183
1184 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1185 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
1186
1187 const UVec2 sizes[] =
1188 {
1189 UVec2(64, 64),
1190 UVec2(124, 119),
1191 UVec2(256, 512)
1192 };
1193
1194 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1195
1196 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1197 {
1198 const UVec2 testSize = sizes[sizeNdx];
1199
1200 try
1201 {
1202 nativeWindow->resize(testSize);
1203 }
1204 catch (const tcu::Exception& e)
1205 {
1206 // Make sure all exception types result in a test failure
1207 results.fail(e.getMessage());
1208 }
1209
1210 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1211 {
1212 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1213 {
1214 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1215
1216 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1217 results.check(capabilities.currentExtent.width == testSize.x() &&
1218 capabilities.currentExtent.height == testSize.y(),
1219 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1220 }
1221 }
1222 }
1223
1224 return tcu::TestStatus(results.getResult(), results.getMessage());
1225 }
1226
destroyNullHandleSurfaceTest(Context & context,Type wsiType)1227 tcu::TestStatus destroyNullHandleSurfaceTest (Context& context, Type wsiType)
1228 {
1229 const InstanceHelper instHelper (context, wsiType);
1230 const VkSurfaceKHR nullHandle = DE_NULL;
1231
1232 // Default allocator
1233 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, DE_NULL);
1234
1235 // Custom allocator
1236 {
1237 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u);
1238
1239 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1240
1241 if (recordingAllocator.getNumRecords() != 0u)
1242 return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1243 }
1244
1245 return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1246 }
1247
1248 } // anonymous
1249
createSurfaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1250 void createSurfaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1251 {
1252 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
1253
1254 addFunctionCase(testGroup, "create", "Create surface", createSurfaceTest, wsiType);
1255 addFunctionCase(testGroup, "create_custom_allocator", "Create surface with custom allocator", createSurfaceCustomAllocatorTest, wsiType);
1256 addFunctionCase(testGroup, "create_simulate_oom", "Create surface with simulating OOM", createSurfaceSimulateOOMTest, wsiType);
1257 addFunctionCase(testGroup, "query_support", "Query surface support", querySurfaceSupportTest, wsiType);
1258 addFunctionCase(testGroup, "query_presentation_support", "Query native presentation support", queryPresentationSupportTest, wsiType);
1259 addFunctionCase(testGroup, "query_capabilities", "Query surface capabilities", querySurfaceCapabilitiesTest, wsiType);
1260 addFunctionCase(testGroup, "query_capabilities2", "Query extended surface capabilities", querySurfaceCapabilities2Test, wsiType);
1261 addFunctionCase(testGroup, "query_protected_capabilities", "Query protected surface capabilities", querySurfaceProtectedCapabilitiesTest, wsiType);
1262 addFunctionCase(testGroup, "query_surface_counters", "Query and check available surface counters", querySurfaceCounterTest, wsiType);
1263 addFunctionCase(testGroup, "query_formats", "Query surface formats", querySurfaceFormatsTest, wsiType);
1264 addFunctionCase(testGroup, "query_formats2", "Query extended surface formats", querySurfaceFormats2Test, wsiType);
1265 addFunctionCase(testGroup, "query_present_modes", "Query surface present modes", querySurfacePresentModesTest, wsiType);
1266 addFunctionCase(testGroup, "query_devgroup_present_capabilities", "Query surface present modes capabilities in device groups",queryDevGroupSurfacePresentCapabilitiesTest,wsiType);
1267 addFunctionCase(testGroup, "query_devgroup_present_modes", "Query surface present modes for device groups", queryDevGroupSurfacePresentModesTest, wsiType);
1268 addFunctionCase(testGroup, "destroy_null_handle", "Destroy VK_NULL_HANDLE surface", destroyNullHandleSurfaceTest, wsiType);
1269
1270 if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1271 addFunctionCase(testGroup, "initial_size", "Create surface with initial window size set", createSurfaceInitialSizeTest, wsiType);
1272
1273 if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1274 addFunctionCase(testGroup, "resize", "Resize window and surface", resizeSurfaceTest, wsiType);
1275 }
1276
1277 } // wsi
1278 } // vkt
1279