1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Valve Corporation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Auxiliar functions to help create custom devices and instances.
23 *//*--------------------------------------------------------------------*/
24
25 #include "vkRefUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "vkDeviceUtil.hpp"
28 #include "vkDebugReportUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "tcuCommandLine.hpp"
31 #include "vktCustomInstancesDevices.hpp"
32
33 #include <algorithm>
34 #include <memory>
35 #include <set>
36
37 using std::string;
38 using std::vector;
39 using vk::Move;
40 using vk::VkInstance;
41 #ifndef CTS_USES_VULKANSC
42 using vk::DebugReportRecorder;
43 using vk::InstanceDriver;
44 using vk::VkDebugReportCallbackCreateInfoEXT;
45 using vk::VkDebugReportCallbackEXT;
46 #else
47 using vk::InstanceDriverSC;
48 #endif // CTS_USES_VULKANSC
49
50 namespace vkt
51 {
52
53 namespace
54 {
55
getValidationLayers(const vector<vk::VkLayerProperties> & supportedLayers)56 vector<const char *> getValidationLayers(const vector<vk::VkLayerProperties> &supportedLayers)
57 {
58 static const char *s_magicLayer = "VK_LAYER_KHRONOS_validation";
59 static const char *s_defaultLayers[] = {
60 "VK_LAYER_LUNARG_standard_validation", // Deprecated by at least Vulkan SDK 1.1.121.
61 "VK_LAYER_GOOGLE_threading", // Deprecated by at least Vulkan SDK 1.1.121.
62 "VK_LAYER_LUNARG_parameter_validation", // Deprecated by at least Vulkan SDK 1.1.121.
63 "VK_LAYER_LUNARG_device_limits",
64 "VK_LAYER_LUNARG_object_tracker", // Deprecated by at least Vulkan SDK 1.1.121.
65 "VK_LAYER_LUNARG_image",
66 "VK_LAYER_LUNARG_core_validation", // Deprecated by at least Vulkan SDK 1.1.121.
67 "VK_LAYER_LUNARG_swapchain",
68 "VK_LAYER_GOOGLE_unique_objects" // Deprecated by at least Vulkan SDK 1.1.121.
69 };
70
71 vector<const char *> enabledLayers;
72
73 if (vk::isLayerSupported(supportedLayers, vk::RequiredLayer(s_magicLayer)))
74 enabledLayers.push_back(s_magicLayer);
75 else
76 {
77 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
78 {
79 if (isLayerSupported(supportedLayers, vk::RequiredLayer(s_defaultLayers[ndx])))
80 enabledLayers.push_back(s_defaultLayers[ndx]);
81 }
82 }
83
84 return enabledLayers;
85 }
86
87 } // namespace
88
getValidationLayers(const vk::PlatformInterface & vkp)89 vector<const char *> getValidationLayers(const vk::PlatformInterface &vkp)
90 {
91 return getValidationLayers(enumerateInstanceLayerProperties(vkp));
92 }
93
getValidationLayers(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)94 vector<const char *> getValidationLayers(const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice)
95 {
96 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
97 }
98
99 #ifndef CTS_USES_VULKANSC
CustomInstance(Context & context,Move<VkInstance> instance,std::unique_ptr<vk::DebugReportRecorder> & recorder)100 CustomInstance::CustomInstance(Context &context, Move<VkInstance> instance,
101 std::unique_ptr<vk::DebugReportRecorder> &recorder)
102 #else
103 CustomInstance::CustomInstance(Context &context, Move<VkInstance> instance)
104 #endif // CTS_USES_VULKANSC
105 : m_context(&context)
106 #ifndef CTS_USES_VULKANSC
107 , m_recorder(recorder.release())
108 #endif // CTS_USES_VULKANSC
109 , m_instance(instance)
110 #ifndef CTS_USES_VULKANSC
111 , m_driver(new InstanceDriver(context.getPlatformInterface(), *m_instance))
112 , m_callback(m_recorder ? m_recorder->createCallback(*m_driver, *m_instance) : Move<VkDebugReportCallbackEXT>())
113 #else
114 , m_driver(new InstanceDriverSC(context.getPlatformInterface(), *m_instance,
115 context.getTestContext().getCommandLine(), context.getResourceInterface()))
116 #endif // CTS_USES_VULKANSC
117 {
118 }
119
CustomInstance()120 CustomInstance::CustomInstance()
121 : m_context(nullptr)
122 #ifndef CTS_USES_VULKANSC
123 , m_recorder(nullptr)
124 #endif // CTS_USES_VULKANSC
125 , m_instance()
126 , m_driver(nullptr)
127 #ifndef CTS_USES_VULKANSC
128 , m_callback()
129 #endif // CTS_USES_VULKANSC
130 {
131 }
132
CustomInstance(CustomInstance && other)133 CustomInstance::CustomInstance(CustomInstance &&other) : CustomInstance()
134 {
135 this->swap(other);
136 }
137
~CustomInstance()138 CustomInstance::~CustomInstance()
139 {
140 collectMessages();
141 }
142
operator =(CustomInstance && other)143 CustomInstance &CustomInstance::operator=(CustomInstance &&other)
144 {
145 CustomInstance destroyer;
146 destroyer.swap(other);
147 this->swap(destroyer);
148 return *this;
149 }
150
swap(CustomInstance & other)151 void CustomInstance::swap(CustomInstance &other)
152 {
153 std::swap(m_context, other.m_context);
154 #ifndef CTS_USES_VULKANSC
155 m_recorder.swap(other.m_recorder);
156 #endif // CTS_USES_VULKANSC
157 Move<VkInstance> aux = m_instance;
158 m_instance = other.m_instance;
159 other.m_instance = aux;
160 m_driver.swap(other.m_driver);
161 #ifndef CTS_USES_VULKANSC
162 Move<VkDebugReportCallbackEXT> aux2 = m_callback;
163 m_callback = other.m_callback;
164 other.m_callback = aux2;
165 #endif // CTS_USES_VULKANSC
166 }
167
operator VkInstance() const168 CustomInstance::operator VkInstance() const
169 {
170 return *m_instance;
171 }
172
getDriver() const173 const vk::InstanceDriver &CustomInstance::getDriver() const
174 {
175 return *m_driver;
176 }
177
collectMessages()178 void CustomInstance::collectMessages()
179 {
180 #ifndef CTS_USES_VULKANSC
181 if (m_recorder)
182 collectAndReportDebugMessages(*m_recorder, *m_context);
183 #endif // CTS_USES_VULKANSC
184 }
185
UncheckedInstance()186 UncheckedInstance::UncheckedInstance()
187 : m_context(nullptr)
188 #ifndef CTS_USES_VULKANSC
189 , m_recorder(nullptr)
190 #endif // CTS_USES_VULKANSC
191 , m_allocator(nullptr)
192 , m_instance(DE_NULL)
193 , m_driver(nullptr)
194 #ifndef CTS_USES_VULKANSC
195 , m_callback()
196 #endif // CTS_USES_VULKANSC
197 {
198 }
199
200 #ifndef CTS_USES_VULKANSC
UncheckedInstance(Context & context,vk::VkInstance instance,const vk::VkAllocationCallbacks * pAllocator,std::unique_ptr<DebugReportRecorder> & recorder)201 UncheckedInstance::UncheckedInstance(Context &context, vk::VkInstance instance,
202 const vk::VkAllocationCallbacks *pAllocator,
203 std::unique_ptr<DebugReportRecorder> &recorder)
204 #else
205 UncheckedInstance::UncheckedInstance(Context &context, vk::VkInstance instance,
206 const vk::VkAllocationCallbacks *pAllocator)
207 #endif // CTS_USES_VULKANSC
208
209 : m_context(&context)
210 #ifndef CTS_USES_VULKANSC
211 , m_recorder(recorder.release())
212 #endif // CTS_USES_VULKANSC
213 , m_allocator(pAllocator)
214 , m_instance(instance)
215 #ifndef CTS_USES_VULKANSC
216 , m_driver((m_instance != DE_NULL) ? new InstanceDriver(context.getPlatformInterface(), m_instance) : nullptr)
217 , m_callback((m_driver && m_recorder) ? m_recorder->createCallback(*m_driver, m_instance) :
218 Move<VkDebugReportCallbackEXT>())
219 #else
220 , m_driver((m_instance != DE_NULL) ?
221 new InstanceDriverSC(context.getPlatformInterface(), m_instance,
222 context.getTestContext().getCommandLine(), context.getResourceInterface()) :
223 nullptr)
224 #endif // CTS_USES_VULKANSC
225 {
226 }
227
~UncheckedInstance()228 UncheckedInstance::~UncheckedInstance()
229 {
230 #ifndef CTS_USES_VULKANSC
231 if (m_recorder)
232 collectAndReportDebugMessages(*m_recorder, *m_context);
233 #endif // CTS_USES_VULKANSC
234
235 if (m_instance != DE_NULL)
236 {
237 #ifndef CTS_USES_VULKANSC
238 m_callback = vk::Move<vk::VkDebugReportCallbackEXT>();
239 m_recorder.reset(nullptr);
240 #endif // CTS_USES_VULKANSC
241 m_driver->destroyInstance(m_instance, m_allocator);
242 }
243 }
244
swap(UncheckedInstance & other)245 void UncheckedInstance::swap(UncheckedInstance &other)
246 {
247 std::swap(m_context, other.m_context);
248 #ifndef CTS_USES_VULKANSC
249 m_recorder.swap(other.m_recorder);
250 #endif // CTS_USES_VULKANSC
251 std::swap(m_allocator, other.m_allocator);
252 vk::VkInstance aux = m_instance;
253 m_instance = other.m_instance;
254 other.m_instance = aux;
255 m_driver.swap(other.m_driver);
256 #ifndef CTS_USES_VULKANSC
257 Move<VkDebugReportCallbackEXT> aux2 = m_callback;
258 m_callback = other.m_callback;
259 other.m_callback = aux2;
260 #endif // CTS_USES_VULKANSC
261 }
262
UncheckedInstance(UncheckedInstance && other)263 UncheckedInstance::UncheckedInstance(UncheckedInstance &&other) : UncheckedInstance()
264 {
265 this->swap(other);
266 }
267
operator =(UncheckedInstance && other)268 UncheckedInstance &UncheckedInstance::operator=(UncheckedInstance &&other)
269 {
270 UncheckedInstance destroyer;
271 destroyer.swap(other);
272 this->swap(destroyer);
273 return *this;
274 }
275
operator vk::VkInstance() const276 UncheckedInstance::operator vk::VkInstance() const
277 {
278 return m_instance;
279 }
operator bool() const280 UncheckedInstance::operator bool() const
281 {
282 return (m_instance != DE_NULL);
283 }
284
createCustomInstanceWithExtensions(Context & context,const std::vector<std::string> & extensions,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)285 CustomInstance createCustomInstanceWithExtensions(Context &context, const std::vector<std::string> &extensions,
286 const vk::VkAllocationCallbacks *pAllocator, bool allowLayers)
287 {
288 vector<const char *> enabledLayers;
289 vector<string> enabledLayersStr;
290 const auto &cmdLine = context.getTestContext().getCommandLine();
291 const bool validationRequested = (cmdLine.isValidationEnabled() && allowLayers);
292 #ifndef CTS_USES_VULKANSC
293 const bool printValidationErrors = cmdLine.printValidationErrors();
294 #endif // CTS_USES_VULKANSC
295
296 if (validationRequested)
297 {
298 enabledLayers = getValidationLayers(context.getPlatformInterface());
299 enabledLayersStr = vector<string>(begin(enabledLayers), end(enabledLayers));
300 }
301
302 const bool validationEnabled = !enabledLayers.empty();
303
304 // Filter extension list and throw NotSupported if a required extension is not supported.
305 const uint32_t apiVersion = context.getUsedApiVersion();
306 const vk::PlatformInterface &vkp = context.getPlatformInterface();
307 const vector<vk::VkExtensionProperties> availableExtensions =
308 vk::enumerateInstanceExtensionProperties(vkp, DE_NULL);
309 std::set<string> usedExtensions;
310
311 // Get list of available extension names.
312 vector<string> availableExtensionNames;
313 for (const auto &ext : availableExtensions)
314 availableExtensionNames.push_back(ext.extensionName);
315
316 // Filter duplicates and remove core extensions.
317 for (const auto &ext : extensions)
318 {
319 if (!vk::isCoreInstanceExtension(apiVersion, ext))
320 usedExtensions.insert(ext);
321 }
322
323 // Add debug extension if validation is enabled.
324 if (validationEnabled)
325 usedExtensions.insert("VK_EXT_debug_report");
326
327 // Check extension support.
328 for (const auto &ext : usedExtensions)
329 {
330 if (!vk::isInstanceExtensionSupported(apiVersion, availableExtensionNames, ext))
331 TCU_THROW(NotSupportedError, ext + " is not supported");
332 }
333
334 #ifndef CTS_USES_VULKANSC
335 std::unique_ptr<DebugReportRecorder> debugReportRecorder;
336 if (validationEnabled)
337 debugReportRecorder.reset(new DebugReportRecorder(printValidationErrors));
338 #endif // CTS_USES_VULKANSC
339
340 // Create custom instance.
341 const vector<string> usedExtensionsVec(begin(usedExtensions), end(usedExtensions));
342 #ifndef CTS_USES_VULKANSC
343 Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, cmdLine,
344 debugReportRecorder.get(), pAllocator);
345 return CustomInstance(context, instance, debugReportRecorder);
346 #else
347 Move<VkInstance> instance =
348 vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, cmdLine, pAllocator);
349 return CustomInstance(context, instance);
350 #endif // CTS_USES_VULKANSC
351 }
352
createCustomInstanceWithExtension(Context & context,const std::string & extension,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)353 CustomInstance createCustomInstanceWithExtension(Context &context, const std::string &extension,
354 const vk::VkAllocationCallbacks *pAllocator, bool allowLayers)
355 {
356 return createCustomInstanceWithExtensions(context, std::vector<std::string>(1, extension), pAllocator, allowLayers);
357 }
358
createCustomInstanceFromContext(Context & context,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)359 CustomInstance createCustomInstanceFromContext(Context &context, const vk::VkAllocationCallbacks *pAllocator,
360 bool allowLayers)
361 {
362 return createCustomInstanceWithExtensions(context, std::vector<std::string>(), pAllocator, allowLayers);
363 }
364
copyExtensions(const vk::VkInstanceCreateInfo & createInfo)365 static std::vector<const char *> copyExtensions(const vk::VkInstanceCreateInfo &createInfo)
366 {
367 std::vector<const char *> extensions(createInfo.enabledExtensionCount);
368 for (size_t i = 0u; i < extensions.size(); ++i)
369 extensions[i] = createInfo.ppEnabledExtensionNames[i];
370 return extensions;
371 }
372
addExtension(std::vector<const char * > & presentExtensions,const char * extension)373 static void addExtension(std::vector<const char *> &presentExtensions, const char *extension)
374 {
375 if (std::find_if(presentExtensions.cbegin(), presentExtensions.cend(),
376 [extension](const char *name)
377 { return (strcmp(name, extension) == 0); }) == presentExtensions.cend())
378 {
379 presentExtensions.emplace_back(extension);
380 }
381 }
382
addDebugReportExt(const vk::PlatformInterface & vkp,const vk::VkInstanceCreateInfo & createInfo)383 vector<const char *> addDebugReportExt(const vk::PlatformInterface &vkp, const vk::VkInstanceCreateInfo &createInfo)
384 {
385 if (!isDebugReportSupported(vkp))
386 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
387
388 vector<const char *> actualExtensions;
389 if (createInfo.enabledExtensionCount != 0u)
390 actualExtensions = copyExtensions(createInfo);
391
392 addExtension(actualExtensions, "VK_EXT_debug_report");
393
394 return actualExtensions;
395 }
396
createCustomInstanceFromInfo(Context & context,const vk::VkInstanceCreateInfo * instanceCreateInfo,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)397 CustomInstance createCustomInstanceFromInfo(Context &context, const vk::VkInstanceCreateInfo *instanceCreateInfo,
398 const vk::VkAllocationCallbacks *pAllocator, bool allowLayers)
399 {
400 vector<const char *> enabledLayers;
401 vector<const char *> enabledExtensions;
402 vk::VkInstanceCreateInfo createInfo = *instanceCreateInfo;
403 const auto &cmdLine = context.getTestContext().getCommandLine();
404 const bool validationEnabled = cmdLine.isValidationEnabled();
405 #ifndef CTS_USES_VULKANSC
406 const bool printValidationErrors = cmdLine.printValidationErrors();
407 #endif // CTS_USES_VULKANSC
408 const vk::PlatformInterface &vkp = context.getPlatformInterface();
409 #ifndef CTS_USES_VULKANSC
410 std::unique_ptr<DebugReportRecorder> recorder;
411 VkDebugReportCallbackCreateInfoEXT callbackInfo;
412 #endif // CTS_USES_VULKANSC
413
414 if (validationEnabled && allowLayers)
415 {
416 // Activate some layers if requested.
417 if (createInfo.enabledLayerCount == 0u)
418 {
419 enabledLayers = getValidationLayers(vkp);
420 createInfo.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size());
421 createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
422 }
423
424 // Make sure the debug report extension is enabled when validation is enabled.
425 enabledExtensions = addDebugReportExt(vkp, createInfo);
426 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
427 createInfo.ppEnabledExtensionNames = enabledExtensions.data();
428
429 #ifndef CTS_USES_VULKANSC
430 recorder.reset(new DebugReportRecorder(printValidationErrors));
431 callbackInfo = recorder->makeCreateInfo();
432 callbackInfo.pNext = createInfo.pNext;
433 createInfo.pNext = &callbackInfo;
434 #endif // CTS_USES_VULKANSC
435 }
436
437 #ifndef CTS_USES_VULKANSC
438 // Enable portability if available. Needed for portability drivers, otherwise loader will complain and make tests fail
439 std::vector<vk::VkExtensionProperties> availableExtensions =
440 vk::enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL);
441 if (vk::isExtensionStructSupported(availableExtensions, vk::RequiredExtension("VK_KHR_portability_enumeration")))
442 {
443 if (enabledExtensions.empty() && createInfo.enabledExtensionCount != 0u)
444 enabledExtensions = copyExtensions(createInfo);
445
446 addExtension(enabledExtensions, "VK_KHR_portability_enumeration");
447 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
448 createInfo.ppEnabledExtensionNames = enabledExtensions.data();
449 createInfo.flags |= vk::VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
450 }
451
452 return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator), recorder);
453 #else
454 return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator));
455 #endif // CTS_USES_VULKANSC
456 }
457
createUncheckedInstance(Context & context,const vk::VkInstanceCreateInfo * instanceCreateInfo,const vk::VkAllocationCallbacks * pAllocator,UncheckedInstance * instance,bool allowLayers)458 vk::VkResult createUncheckedInstance(Context &context, const vk::VkInstanceCreateInfo *instanceCreateInfo,
459 const vk::VkAllocationCallbacks *pAllocator, UncheckedInstance *instance,
460 bool allowLayers)
461 {
462 vector<const char *> enabledLayers;
463 vector<const char *> enabledExtensions;
464 vk::VkInstanceCreateInfo createInfo = *instanceCreateInfo;
465 const auto &cmdLine = context.getTestContext().getCommandLine();
466 const bool validationEnabled = cmdLine.isValidationEnabled();
467 #ifndef CTS_USES_VULKANSC
468 const bool printValidationErrors = cmdLine.printValidationErrors();
469 #endif // CTS_USES_VULKANSC
470 const vk::PlatformInterface &vkp = context.getPlatformInterface();
471 const bool addLayers = (validationEnabled && allowLayers);
472 #ifndef CTS_USES_VULKANSC
473 std::unique_ptr<DebugReportRecorder> recorder;
474 #endif // CTS_USES_VULKANSC
475
476 if (addLayers)
477 {
478 // Activate some layers if requested.
479 if (createInfo.enabledLayerCount == 0u)
480 {
481 enabledLayers = getValidationLayers(vkp);
482 createInfo.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size());
483 createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
484 }
485
486 // Make sure the debug report extension is enabled when validation is enabled.
487 enabledExtensions = addDebugReportExt(vkp, createInfo);
488 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
489 createInfo.ppEnabledExtensionNames = enabledExtensions.data();
490
491 #ifndef CTS_USES_VULKANSC
492 recorder.reset(new DebugReportRecorder(printValidationErrors));
493 // No need to add VkDebugReportCallbackCreateInfoEXT to VkInstanceCreateInfo since we
494 // don't want to check for errors at instance creation. This is intended since we use
495 // UncheckedInstance to try to create invalid instances for driver stability
496 #endif // CTS_USES_VULKANSC
497 }
498
499 #ifndef CTS_USES_VULKANSC
500 // Enable portability if available. Needed for portability drivers, otherwise loader will complain and make tests fail
501 std::vector<vk::VkExtensionProperties> availableExtensions =
502 vk::enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL);
503 if (vk::isExtensionStructSupported(availableExtensions, vk::RequiredExtension("VK_KHR_portability_enumeration")))
504 {
505 if (enabledExtensions.empty() && createInfo.enabledExtensionCount != 0u)
506 enabledExtensions = copyExtensions(createInfo);
507
508 addExtension(enabledExtensions, "VK_KHR_portability_enumeration");
509 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
510 createInfo.ppEnabledExtensionNames = enabledExtensions.data();
511 createInfo.flags |= vk::VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
512 }
513 #endif // CTS_USES_VULKANSC
514
515 vk::VkInstance raw_instance = DE_NULL;
516 vk::VkResult result = vkp.createInstance(&createInfo, pAllocator, &raw_instance);
517
518 #ifndef CTS_USES_VULKANSC
519 *instance = UncheckedInstance(context, raw_instance, pAllocator, recorder);
520 #else
521 *instance = UncheckedInstance(context, raw_instance, pAllocator);
522 #endif // CTS_USES_VULKANSC
523
524 return result;
525 }
526
createCustomDevice(bool validationEnabled,const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkDeviceCreateInfo * pCreateInfo,const vk::VkAllocationCallbacks * pAllocator)527 vk::Move<vk::VkDevice> createCustomDevice(bool validationEnabled, const vk::PlatformInterface &vkp,
528 vk::VkInstance instance, const vk::InstanceInterface &vki,
529 vk::VkPhysicalDevice physicalDevice,
530 const vk::VkDeviceCreateInfo *pCreateInfo,
531 const vk::VkAllocationCallbacks *pAllocator)
532 {
533 vector<const char *> enabledLayers;
534 vk::VkDeviceCreateInfo createInfo = *pCreateInfo;
535
536 if (createInfo.enabledLayerCount == 0u && validationEnabled)
537 {
538 enabledLayers = getValidationLayers(vki, physicalDevice);
539 createInfo.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size());
540 createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
541 }
542
543 #ifdef CTS_USES_VULKANSC
544 // Add fault callback if there isn't one already.
545 VkFaultCallbackInfo faultCallbackInfo = {
546 VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO, // VkStructureType sType;
547 DE_NULL, // void* pNext;
548 0U, // uint32_t faultCount;
549 nullptr, // VkFaultData* pFaults;
550 Context::faultCallbackFunction // PFN_vkFaultCallbackFunction pfnFaultCallback;
551 };
552
553 if (!findStructureInChain(createInfo.pNext, getStructureType<VkFaultCallbackInfo>()))
554 {
555 // XXX workaround incorrect constness on faultCallbackInfo.pNext.
556 faultCallbackInfo.pNext = const_cast<void *>(createInfo.pNext);
557 createInfo.pNext = &faultCallbackInfo;
558 }
559 #endif // CTS_USES_VULKANSC
560
561 return createDevice(vkp, instance, vki, physicalDevice, &createInfo, pAllocator);
562 }
563
createUncheckedDevice(bool validationEnabled,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkDeviceCreateInfo * pCreateInfo,const vk::VkAllocationCallbacks * pAllocator,vk::VkDevice * pDevice)564 vk::VkResult createUncheckedDevice(bool validationEnabled, const vk::InstanceInterface &vki,
565 vk::VkPhysicalDevice physicalDevice, const vk::VkDeviceCreateInfo *pCreateInfo,
566 const vk::VkAllocationCallbacks *pAllocator, vk::VkDevice *pDevice)
567 {
568 vector<const char *> enabledLayers;
569 vk::VkDeviceCreateInfo createInfo = *pCreateInfo;
570
571 if (createInfo.enabledLayerCount == 0u && validationEnabled)
572 {
573 enabledLayers = getValidationLayers(vki, physicalDevice);
574 createInfo.enabledLayerCount = static_cast<uint32_t>(enabledLayers.size());
575 createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
576 }
577
578 #ifdef CTS_USES_VULKANSC
579 // Add fault callback if there isn't one already.
580 VkFaultCallbackInfo faultCallbackInfo = {
581 VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO, // VkStructureType sType;
582 DE_NULL, // void* pNext;
583 0U, // uint32_t faultCount;
584 nullptr, // VkFaultData* pFaults;
585 Context::faultCallbackFunction // PFN_vkFaultCallbackFunction pfnFaultCallback;
586 };
587
588 if (!findStructureInChain(createInfo.pNext, getStructureType<VkFaultCallbackInfo>()))
589 {
590 // XXX workaround incorrect constness on faultCallbackInfo.pNext.
591 faultCallbackInfo.pNext = const_cast<void *>(createInfo.pNext);
592 createInfo.pNext = &faultCallbackInfo;
593 }
594 #endif // CTS_USES_VULKANSC
595
596 return vki.createDevice(physicalDevice, &createInfo, pAllocator, pDevice);
597 }
598
CustomInstanceWrapper(Context & context)599 CustomInstanceWrapper::CustomInstanceWrapper(Context &context) : instance(vkt::createCustomInstanceFromContext(context))
600 {
601 }
602
CustomInstanceWrapper(Context & context,const std::vector<std::string> extensions)603 CustomInstanceWrapper::CustomInstanceWrapper(Context &context, const std::vector<std::string> extensions)
604 : instance(vkt::createCustomInstanceWithExtensions(context, extensions))
605 {
606 }
checkSupport(Context & context,const VideoCodecOperationFlags videoCodecOperation)607 void VideoDevice::checkSupport(Context &context, const VideoCodecOperationFlags videoCodecOperation)
608 {
609 #ifndef CTS_USES_VULKANSC
610 DE_ASSERT(videoCodecOperation != 0 && isVideoOperation(videoCodecOperation));
611
612 if (isVideoOperation(videoCodecOperation))
613 context.requireDeviceFunctionality("VK_KHR_video_queue");
614
615 if (isVideoEncodeOperation(videoCodecOperation))
616 context.requireDeviceFunctionality("VK_KHR_video_encode_queue");
617
618 if (isVideoDecodeOperation(videoCodecOperation))
619 context.requireDeviceFunctionality("VK_KHR_video_decode_queue");
620
621 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) != 0)
622 context.requireDeviceFunctionality("VK_KHR_video_encode_h264");
623
624 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) != 0)
625 context.requireDeviceFunctionality("VK_KHR_video_encode_h265");
626
627 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0)
628 context.requireDeviceFunctionality("VK_KHR_video_decode_h264");
629
630 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0)
631 context.requireDeviceFunctionality("VK_KHR_video_decode_h265");
632 #else
633 DE_UNREF(context);
634 DE_UNREF(videoCodecOperation);
635 #endif
636 }
637
VideoDevice(Context & context)638 VideoDevice::VideoDevice(Context &context)
639 : m_context(context)
640 , m_logicalDevice()
641 , m_deviceDriver()
642 , m_allocator()
643 , m_queueFamilyTransfer(VK_QUEUE_FAMILY_IGNORED)
644 , m_queueFamilyDecode(VK_QUEUE_FAMILY_IGNORED)
645 , m_queueFamilyEncode(VK_QUEUE_FAMILY_IGNORED)
646 #ifndef CTS_USES_VULKANSC
647 , m_videoCodecOperation(vk::VK_VIDEO_CODEC_OPERATION_NONE_KHR)
648 #else
649 , m_videoCodecOperation(~0u)
650 #endif
651 {
652 }
653
VideoDevice(Context & context,const VideoCodecOperationFlags videoCodecOperation,const VideoDeviceFlags videoDeviceFlags)654 VideoDevice::VideoDevice(Context &context, const VideoCodecOperationFlags videoCodecOperation,
655 const VideoDeviceFlags videoDeviceFlags)
656 : VideoDevice(context)
657 {
658 #ifndef CTS_USES_VULKANSC
659
660 // TODO encode only device case
661 const vk::VkQueueFlags queueFlagsRequired = getQueueFlags(videoCodecOperation);
662 const vk::VkDevice result = getDeviceSupportingQueue(queueFlagsRequired, videoCodecOperation, videoDeviceFlags);
663
664 DE_ASSERT(result != DE_NULL);
665 DE_UNREF(result);
666 #else
667 DE_UNREF(videoCodecOperation);
668 DE_UNREF(videoDeviceFlags);
669 #endif
670 }
671
~VideoDevice(void)672 VideoDevice::~VideoDevice(void)
673 {
674 }
675
getQueueFlags(const VideoCodecOperationFlags videoCodecOperation)676 vk::VkQueueFlags VideoDevice::getQueueFlags(const VideoCodecOperationFlags videoCodecOperation)
677 {
678 #ifndef CTS_USES_VULKANSC
679 const vk::VkQueueFlags queueFlagsRequired =
680 (isVideoEncodeOperation(videoCodecOperation) ? vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR : 0) |
681 (isVideoDecodeOperation(videoCodecOperation) ? vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR : 0);
682
683 return queueFlagsRequired;
684 #else
685 DE_UNREF(videoCodecOperation);
686
687 return 0;
688 #endif
689 }
690
isVideoEncodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)691 bool VideoDevice::isVideoEncodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)
692 {
693 #ifndef CTS_USES_VULKANSC
694 const vk::VkVideoCodecOperationFlagsKHR encodeOperations =
695 vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR | vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR;
696
697 return (encodeOperations & videoCodecOperationFlags) != 0;
698 #else
699 DE_UNREF(videoCodecOperationFlags);
700
701 return false;
702 #endif
703 }
704
isVideoDecodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)705 bool VideoDevice::isVideoDecodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)
706 {
707 #ifndef CTS_USES_VULKANSC
708 const vk::VkVideoCodecOperationFlagsKHR decodeOperations =
709 vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR | vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR;
710
711 return (decodeOperations & videoCodecOperationFlags) != 0;
712 #else
713 DE_UNREF(videoCodecOperationFlags);
714
715 return false;
716 #endif
717 }
718
isVideoOperation(const VideoCodecOperationFlags videoCodecOperationFlags)719 bool VideoDevice::isVideoOperation(const VideoCodecOperationFlags videoCodecOperationFlags)
720 {
721 #ifndef CTS_USES_VULKANSC
722 return isVideoDecodeOperation(videoCodecOperationFlags) || isVideoEncodeOperation(videoCodecOperationFlags);
723 #else
724 DE_UNREF(videoCodecOperationFlags);
725
726 return false;
727 #endif
728 }
729
addVideoDeviceExtensions(std::vector<const char * > & deviceExtensions,const uint32_t apiVersion,const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags)730 void VideoDevice::addVideoDeviceExtensions(std::vector<const char *> &deviceExtensions, const uint32_t apiVersion,
731 const vk::VkQueueFlags queueFlagsRequired,
732 const VideoCodecOperationFlags videoCodecOperationFlags)
733 {
734 #ifndef CTS_USES_VULKANSC
735 static const char videoQueue[] = "VK_KHR_video_queue";
736 static const char videoEncodeQueue[] = "VK_KHR_video_encode_queue";
737 static const char videoDecodeQueue[] = "VK_KHR_video_decode_queue";
738 static const char videoEncodeH264[] = "VK_KHR_video_encode_h264";
739 static const char videoEncodeH265[] = "VK_KHR_video_encode_h265";
740 static const char videoDecodeH264[] = "VK_KHR_video_decode_h264";
741 static const char videoDecodeH265[] = "VK_KHR_video_decode_h265";
742
743 if (!vk::isCoreDeviceExtension(apiVersion, videoQueue))
744 deviceExtensions.push_back(videoQueue);
745
746 if ((queueFlagsRequired & vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0)
747 if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeQueue))
748 deviceExtensions.push_back(videoEncodeQueue);
749
750 if ((queueFlagsRequired & vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0)
751 if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeQueue))
752 deviceExtensions.push_back(videoDecodeQueue);
753
754 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) != 0)
755 if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeH264))
756 deviceExtensions.push_back(videoEncodeH264);
757
758 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) != 0)
759 if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeH265))
760 deviceExtensions.push_back(videoEncodeH265);
761
762 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0)
763 if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeH265))
764 deviceExtensions.push_back(videoDecodeH265);
765
766 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0)
767 if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeH264))
768 deviceExtensions.push_back(videoDecodeH264);
769 #else
770 DE_UNREF(deviceExtensions);
771 DE_UNREF(apiVersion);
772 DE_UNREF(queueFlagsRequired);
773 DE_UNREF(videoCodecOperationFlags);
774 #endif
775 }
776
getDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags,const VideoDevice::VideoDeviceFlags videoDeviceFlags)777 vk::VkDevice VideoDevice::getDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,
778 const VideoCodecOperationFlags videoCodecOperationFlags,
779 const VideoDevice::VideoDeviceFlags videoDeviceFlags)
780 {
781 #ifndef CTS_USES_VULKANSC
782 if (*m_logicalDevice == DE_NULL)
783 {
784 DE_ASSERT(static_cast<uint32_t>(queueFlagsRequired) != 0u);
785 DE_ASSERT(static_cast<uint32_t>(videoCodecOperationFlags) != 0u);
786
787 if (!createDeviceSupportingQueue(queueFlagsRequired, videoCodecOperationFlags, videoDeviceFlags))
788 TCU_THROW(NotSupportedError, "Cannot create device with required parameters");
789 }
790
791 return *m_logicalDevice;
792 #else
793 DE_UNREF(queueFlagsRequired);
794 DE_UNREF(videoCodecOperationFlags);
795 DE_UNREF(videoDeviceFlags);
796
797 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
798 #endif
799 }
800
createDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags,const VideoDeviceFlags videoDeviceFlags)801 bool VideoDevice::createDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,
802 const VideoCodecOperationFlags videoCodecOperationFlags,
803 const VideoDeviceFlags videoDeviceFlags)
804 {
805 #ifndef CTS_USES_VULKANSC
806 const vk::PlatformInterface &vkp = m_context.getPlatformInterface();
807 const vk::InstanceInterface &vki = m_context.getInstanceInterface();
808 const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
809 const vk::VkInstance instance = m_context.getInstance();
810 const uint32_t apiVersion = m_context.getUsedApiVersion();
811 const bool validationEnabled = m_context.getTestContext().getCommandLine().isValidationEnabled();
812 const bool queryWithStatusForDecodeSupport =
813 (videoDeviceFlags & VIDEO_DEVICE_FLAG_QUERY_WITH_STATUS_FOR_DECODE_SUPPORT) != 0;
814 const bool queryWithStatusForEncodeSupport =
815 (videoDeviceFlags & VIDEO_DEVICE_FLAG_QUERY_WITH_STATUS_FOR_ENCODE_SUPPORT) != 0;
816 const bool requireMaintenance1 = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_MAINTENANCE_1) != 0;
817 const bool requireYCBCRorNotSupported = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_YCBCR_OR_NOT_SUPPORTED) != 0;
818 const bool requireSync2orNotSupported = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_SYNC2_OR_NOT_SUPPORTED) != 0;
819 const bool requireTimelineSemOrNotSupported =
820 (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_TIMELINE_OR_NOT_SUPPORTED) != 0;
821 const float queueFamilyPriority = 1.0f;
822 uint32_t queueFamilyPropertiesCount = 0u;
823 uint32_t queueFamilyTransfer = VK_QUEUE_FAMILY_IGNORED;
824 uint32_t queueFamilyDecode = VK_QUEUE_FAMILY_IGNORED;
825 uint32_t queueFamilyEncode = VK_QUEUE_FAMILY_IGNORED;
826 vk::VkQueueFlags queueFlagsFound = 0;
827 vector<vk::VkQueueFamilyProperties2> queueFamilyProperties2;
828 vector<vk::VkQueueFamilyVideoPropertiesKHR> videoQueueFamilyProperties2;
829 vector<vk::VkQueueFamilyQueryResultStatusPropertiesKHR> VkQueueFamilyQueryResultStatusPropertiesKHR;
830 vector<const char *> deviceExtensions;
831 vector<vk::VkDeviceQueueCreateInfo> queueInfos;
832
833 DE_ASSERT(queueFlagsRequired != 0);
834 DE_ASSERT(videoCodecOperationFlags != 0);
835
836 vki.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
837
838 if (queueFamilyPropertiesCount == 0u)
839 TCU_FAIL("Device reports an empty set of queue family properties");
840
841 queueFamilyProperties2.resize(queueFamilyPropertiesCount);
842 videoQueueFamilyProperties2.resize(queueFamilyPropertiesCount);
843 VkQueueFamilyQueryResultStatusPropertiesKHR.resize(queueFamilyPropertiesCount);
844
845 for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
846 {
847 queueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
848 queueFamilyProperties2[ndx].pNext = &videoQueueFamilyProperties2[ndx];
849 videoQueueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
850 videoQueueFamilyProperties2[ndx].pNext = &VkQueueFamilyQueryResultStatusPropertiesKHR[ndx];
851 videoQueueFamilyProperties2[ndx].videoCodecOperations = 0;
852 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].sType =
853 vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR;
854 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].pNext = DE_NULL;
855 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport = false;
856 }
857
858 vki.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount,
859 queueFamilyProperties2.data());
860
861 if (queueFamilyPropertiesCount != queueFamilyProperties2.size())
862 TCU_FAIL("Device returns less queue families than initially reported");
863
864 for (uint32_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
865 {
866 const vk::VkQueueFamilyProperties &queueFamilyProperties = queueFamilyProperties2[ndx].queueFamilyProperties;
867 const vk::VkQueueFlags usefulQueueFlags =
868 queueFamilyProperties.queueFlags & queueFlagsRequired & ~queueFlagsFound;
869
870 if (usefulQueueFlags != 0)
871 {
872 bool assigned = false;
873
874 if ((usefulQueueFlags & vk::VK_QUEUE_TRANSFER_BIT) != 0 && queueFamilyTransfer == VK_QUEUE_FAMILY_IGNORED)
875 {
876 queueFamilyTransfer = ndx;
877 assigned = true;
878 }
879
880 if ((videoQueueFamilyProperties2[ndx].videoCodecOperations & videoCodecOperationFlags) != 0)
881 {
882 if ((usefulQueueFlags & vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0 &&
883 queueFamilyDecode == VK_QUEUE_FAMILY_IGNORED)
884 {
885 if (!queryWithStatusForDecodeSupport ||
886 (queryWithStatusForDecodeSupport &&
887 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport))
888 {
889 queueFamilyDecode = ndx;
890 assigned = true;
891 }
892 }
893
894 if ((usefulQueueFlags & vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0 &&
895 queueFamilyEncode == VK_QUEUE_FAMILY_IGNORED)
896 {
897 if (!queryWithStatusForEncodeSupport ||
898 (queryWithStatusForEncodeSupport &&
899 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport))
900 {
901 queueFamilyEncode = ndx;
902 assigned = true;
903 }
904 }
905 }
906
907 if (assigned)
908 {
909 const vk::VkDeviceQueueCreateInfo queueInfo = {
910 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
911 DE_NULL, // const void* pNext;
912 (vk::VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
913 ndx, // uint32_t queueFamilyIndex;
914 1u, // uint32_t queueCount;
915 &queueFamilyPriority, // const float* pQueuePriorities;
916 };
917
918 if (queueFamilyProperties.queueCount == 0)
919 TCU_FAIL("Video queue returned queueCount is zero");
920
921 queueInfos.push_back(queueInfo);
922
923 queueFlagsFound |= usefulQueueFlags;
924
925 if (queueFlagsFound == queueFlagsRequired)
926 break;
927 }
928 }
929 }
930
931 if (queueFlagsFound != queueFlagsRequired)
932 return false;
933
934 addVideoDeviceExtensions(deviceExtensions, apiVersion, queueFlagsRequired, videoCodecOperationFlags);
935
936 if (requireYCBCRorNotSupported)
937 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
938 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
939
940 if (requireSync2orNotSupported)
941 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_synchronization2"))
942 deviceExtensions.push_back("VK_KHR_synchronization2");
943
944 if (requireMaintenance1)
945 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_video_maintenance1"))
946 deviceExtensions.push_back("VK_KHR_video_maintenance1");
947
948 if (requireTimelineSemOrNotSupported)
949 if (m_context.isDeviceFunctionalitySupported("VK_KHR_timeline_semaphore"))
950 deviceExtensions.push_back("VK_KHR_timeline_semaphore");
951
952 vk::VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features = {
953 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, // VkStructureType sType;
954 DE_NULL, // void* pNext;
955 false, // VkBool32 synchronization2;
956 };
957 vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYcbcrConversionFeatures = {
958 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, // VkStructureType sType;
959 DE_NULL, // void* pNext;
960 false, // VkBool32 samplerYcbcrConversion;
961 };
962
963 vk::VkPhysicalDeviceVideoMaintenance1FeaturesKHR maintenance1Features = {
964 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR, // VkStructureType sType;
965 DE_NULL, // void* pNext;
966 false, // VkBool32 videoMaintenance1;
967 };
968
969 vk::VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures = {
970 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, // VkStructureType sType;
971 DE_NULL, // void* pNext;
972 true // VkBool32 timelineSemaphore;
973 };
974
975 vk::VkPhysicalDeviceFeatures2 features2 = {
976 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType sType;
977 DE_NULL, // void* pNext;
978 vk::VkPhysicalDeviceFeatures(), // VkPhysicalDeviceFeatures features;
979 };
980
981 if (requireYCBCRorNotSupported)
982 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &samplerYcbcrConversionFeatures);
983
984 if (requireSync2orNotSupported)
985 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &synchronization2Features);
986
987 if (requireMaintenance1)
988 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &maintenance1Features);
989
990 if (requireTimelineSemOrNotSupported)
991 if (m_context.isDeviceFunctionalitySupported("VK_KHR_timeline_semaphore"))
992 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &timelineSemaphoreFeatures);
993
994 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
995
996 if (requireYCBCRorNotSupported && samplerYcbcrConversionFeatures.samplerYcbcrConversion == false)
997 TCU_THROW(NotSupportedError, "samplerYcbcrConversionFeatures.samplerYcbcrConversion is required");
998
999 if (requireSync2orNotSupported && synchronization2Features.synchronization2 == false)
1000 TCU_THROW(NotSupportedError, "synchronization2Features.synchronization2 is required");
1001
1002 if (requireTimelineSemOrNotSupported && timelineSemaphoreFeatures.timelineSemaphore == false)
1003 TCU_THROW(NotSupportedError, "timelineSemaphore extension is required");
1004
1005 if (requireMaintenance1 && maintenance1Features.videoMaintenance1 == false)
1006 TCU_THROW(NotSupportedError, "videoMaintenance1 feature is required");
1007
1008 features2.features.robustBufferAccess = false;
1009
1010 const vk::VkDeviceCreateInfo deviceCreateInfo = {
1011 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
1012 &features2, // const void* pNext;
1013 (vk::VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
1014 static_cast<uint32_t>(queueInfos.size()), // uint32_t queueCreateInfoCount;
1015 de::dataOrNull(queueInfos), // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
1016 0u, // uint32_t enabledLayerCount;
1017 DE_NULL, // const char* const* ppEnabledLayerNames;
1018 uint32_t(deviceExtensions.size()), // uint32_t enabledExtensionCount;
1019 de::dataOrNull(deviceExtensions), // const char* const* ppEnabledExtensionNames;
1020 DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
1021 };
1022
1023 m_logicalDevice = createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceCreateInfo);
1024 m_deviceDriver = de::MovePtr<vk::DeviceDriver>(
1025 new vk::DeviceDriver(vkp, instance, *m_logicalDevice, apiVersion, m_context.getTestContext().getCommandLine()));
1026 m_allocator = de::MovePtr<vk::Allocator>(new vk::SimpleAllocator(
1027 *m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
1028 m_queueFamilyTransfer = queueFamilyTransfer;
1029 m_queueFamilyDecode = queueFamilyDecode;
1030 m_queueFamilyEncode = queueFamilyEncode;
1031 m_videoCodecOperation = videoCodecOperationFlags;
1032
1033 return true;
1034 #else
1035 DE_UNREF(queueFlagsRequired);
1036 DE_UNREF(videoCodecOperationFlags);
1037 DE_UNREF(videoDeviceFlags);
1038
1039 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1040 #endif
1041 }
1042
getDeviceDriver(void)1043 const vk::DeviceDriver &VideoDevice::getDeviceDriver(void)
1044 {
1045 #ifndef CTS_USES_VULKANSC
1046 DE_ASSERT(m_deviceDriver.get() != DE_NULL);
1047
1048 return *m_deviceDriver;
1049 #else
1050 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1051 #endif
1052 }
1053
getQueueFamilyIndexTransfer(void) const1054 uint32_t VideoDevice::getQueueFamilyIndexTransfer(void) const
1055 {
1056 #ifndef CTS_USES_VULKANSC
1057 DE_ASSERT(m_queueFamilyTransfer != VK_QUEUE_FAMILY_IGNORED);
1058
1059 return m_queueFamilyTransfer;
1060 #else
1061 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1062 #endif
1063 }
1064
getQueueFamilyIndexDecode(void) const1065 uint32_t VideoDevice::getQueueFamilyIndexDecode(void) const
1066 {
1067 #ifndef CTS_USES_VULKANSC
1068 DE_ASSERT(m_queueFamilyDecode != VK_QUEUE_FAMILY_IGNORED);
1069
1070 return m_queueFamilyDecode;
1071 #else
1072 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1073 #endif
1074 }
1075
getQueueFamilyIndexEncode(void) const1076 uint32_t VideoDevice::getQueueFamilyIndexEncode(void) const
1077 {
1078 #ifndef CTS_USES_VULKANSC
1079 DE_ASSERT(m_queueFamilyEncode != VK_QUEUE_FAMILY_IGNORED);
1080
1081 return m_queueFamilyEncode;
1082 #else
1083 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1084 #endif
1085 }
1086
getQueueFamilyVideo(void) const1087 uint32_t VideoDevice::getQueueFamilyVideo(void) const
1088 {
1089 #ifndef CTS_USES_VULKANSC
1090 const bool encode = isVideoEncodeOperation(m_videoCodecOperation);
1091 const bool decode = isVideoDecodeOperation(m_videoCodecOperation);
1092
1093 DE_ASSERT((encode && !decode) || (!encode && decode));
1094 DE_UNREF(decode);
1095
1096 return encode ? getQueueFamilyIndexEncode() : getQueueFamilyIndexDecode();
1097 #else
1098 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1099 #endif
1100 }
1101
getAllocator(void)1102 vk::Allocator &VideoDevice::getAllocator(void)
1103 {
1104 #ifndef CTS_USES_VULKANSC
1105 DE_ASSERT(m_allocator != DE_NULL);
1106
1107 return *m_allocator;
1108 #else
1109 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1110 #endif
1111 }
1112
1113 } // namespace vkt
1114