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::VkDebugUtilsMessengerCreateInfoEXT;
45 using vk::VkDebugUtilsMessengerEXT;
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<VkDebugUtilsMessengerEXT>())
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<VkDebugUtilsMessengerEXT> 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(nullptr)
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 != nullptr) ? new InstanceDriver(context.getPlatformInterface(), m_instance) : nullptr)
217 , m_callback((m_driver && m_recorder) ? m_recorder->createCallback(*m_driver, m_instance) :
218 Move<VkDebugUtilsMessengerEXT>())
219 #else
220 , m_driver((m_instance != nullptr) ?
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 != nullptr)
236 {
237 #ifndef CTS_USES_VULKANSC
238 m_callback = vk::Move<vk::VkDebugUtilsMessengerEXT>();
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<VkDebugUtilsMessengerEXT> 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 != nullptr);
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, nullptr);
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_utils");
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 (!isDebugUtilsSupported(vkp))
386 TCU_THROW(NotSupportedError, "VK_EXT_debug_utils 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_utils");
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 VkDebugUtilsMessengerCreateInfoEXT 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() ? nullptr : 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(), nullptr);
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() ? nullptr : 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 VkDebugUtilsMessengerCreateInfoEXT 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(), nullptr);
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() ? nullptr : 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 nullptr, // 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() ? nullptr : 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 nullptr, // 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_ENCODE_AV1_BIT_KHR) != 0)
628 context.requireDeviceFunctionality("VK_KHR_video_encode_av1");
629
630 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0)
631 context.requireDeviceFunctionality("VK_KHR_video_decode_h264");
632
633 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0)
634 context.requireDeviceFunctionality("VK_KHR_video_decode_h265");
635
636 if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) != 0)
637 context.requireDeviceFunctionality("VK_KHR_video_decode_av1");
638 #else
639 DE_UNREF(context);
640 DE_UNREF(videoCodecOperation);
641 #endif
642 }
643
VideoDevice(Context & context)644 VideoDevice::VideoDevice(Context &context)
645 : m_context(context)
646 , m_logicalDevice()
647 , m_deviceDriver()
648 , m_allocator()
649 , m_queueFamilyTransfer(VK_QUEUE_FAMILY_IGNORED)
650 , m_queueFamilyDecode(VK_QUEUE_FAMILY_IGNORED)
651 , m_queueFamilyEncode(VK_QUEUE_FAMILY_IGNORED)
652 #ifndef CTS_USES_VULKANSC
653 , m_videoCodecOperation(vk::VK_VIDEO_CODEC_OPERATION_NONE_KHR)
654 #else
655 , m_videoCodecOperation(~0u)
656 #endif
657 {
658 }
659
VideoDevice(Context & context,const VideoCodecOperationFlags videoCodecOperation,const VideoDeviceFlags videoDeviceFlags)660 VideoDevice::VideoDevice(Context &context, const VideoCodecOperationFlags videoCodecOperation,
661 const VideoDeviceFlags videoDeviceFlags)
662 : VideoDevice(context)
663 {
664 #ifndef CTS_USES_VULKANSC
665
666 // TODO encode only device case
667 const vk::VkQueueFlags queueFlagsRequired = getQueueFlags(videoCodecOperation);
668 const vk::VkDevice result = getDeviceSupportingQueue(queueFlagsRequired, videoCodecOperation, videoDeviceFlags);
669
670 DE_ASSERT(result != nullptr);
671 DE_UNREF(result);
672 #else
673 DE_UNREF(videoCodecOperation);
674 DE_UNREF(videoDeviceFlags);
675 #endif
676 }
677
~VideoDevice(void)678 VideoDevice::~VideoDevice(void)
679 {
680 }
681
getQueueFlags(const VideoCodecOperationFlags videoCodecOperation)682 vk::VkQueueFlags VideoDevice::getQueueFlags(const VideoCodecOperationFlags videoCodecOperation)
683 {
684 #ifndef CTS_USES_VULKANSC
685 const vk::VkQueueFlags queueFlagsRequired =
686 (isVideoEncodeOperation(videoCodecOperation) ? vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR : 0) |
687 (isVideoDecodeOperation(videoCodecOperation) ? vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR : 0);
688
689 return queueFlagsRequired;
690 #else
691 DE_UNREF(videoCodecOperation);
692
693 return 0;
694 #endif
695 }
696
isVideoEncodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)697 bool VideoDevice::isVideoEncodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)
698 {
699 #ifndef CTS_USES_VULKANSC
700 const vk::VkVideoCodecOperationFlagsKHR encodeOperations = vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR |
701 vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR |
702 vk::VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR;
703
704 return (encodeOperations & videoCodecOperationFlags) != 0;
705 #else
706 DE_UNREF(videoCodecOperationFlags);
707
708 return false;
709 #endif
710 }
711
isVideoDecodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)712 bool VideoDevice::isVideoDecodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)
713 {
714 #ifndef CTS_USES_VULKANSC
715 const vk::VkVideoCodecOperationFlagsKHR decodeOperations = vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR |
716 vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR |
717 vk::VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR;
718
719 return (decodeOperations & videoCodecOperationFlags) != 0;
720 #else
721 DE_UNREF(videoCodecOperationFlags);
722
723 return false;
724 #endif
725 }
726
isVideoOperation(const VideoCodecOperationFlags videoCodecOperationFlags)727 bool VideoDevice::isVideoOperation(const VideoCodecOperationFlags videoCodecOperationFlags)
728 {
729 #ifndef CTS_USES_VULKANSC
730 return isVideoDecodeOperation(videoCodecOperationFlags) || isVideoEncodeOperation(videoCodecOperationFlags);
731 #else
732 DE_UNREF(videoCodecOperationFlags);
733
734 return false;
735 #endif
736 }
737
addVideoDeviceExtensions(std::vector<const char * > & deviceExtensions,const uint32_t apiVersion,const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags)738 void VideoDevice::addVideoDeviceExtensions(std::vector<const char *> &deviceExtensions, const uint32_t apiVersion,
739 const vk::VkQueueFlags queueFlagsRequired,
740 const VideoCodecOperationFlags videoCodecOperationFlags)
741 {
742 #ifndef CTS_USES_VULKANSC
743 static const char videoQueue[] = "VK_KHR_video_queue";
744 static const char videoEncodeQueue[] = "VK_KHR_video_encode_queue";
745 static const char videoDecodeQueue[] = "VK_KHR_video_decode_queue";
746 static const char videoEncodeH264[] = "VK_KHR_video_encode_h264";
747 static const char videoEncodeH265[] = "VK_KHR_video_encode_h265";
748 static const char videoDecodeH264[] = "VK_KHR_video_decode_h264";
749 static const char videoDecodeH265[] = "VK_KHR_video_decode_h265";
750
751 if (!vk::isCoreDeviceExtension(apiVersion, videoQueue))
752 deviceExtensions.push_back(videoQueue);
753
754 if ((queueFlagsRequired & vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0)
755 if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeQueue))
756 deviceExtensions.push_back(videoEncodeQueue);
757
758 if ((queueFlagsRequired & vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0)
759 if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeQueue))
760 deviceExtensions.push_back(videoDecodeQueue);
761
762 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) != 0)
763 if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeH264))
764 deviceExtensions.push_back(videoEncodeH264);
765
766 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) != 0)
767 if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeH265))
768 deviceExtensions.push_back(videoEncodeH265);
769
770 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0)
771 if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeH265))
772 deviceExtensions.push_back(videoDecodeH265);
773
774 if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0)
775 if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeH264))
776 deviceExtensions.push_back(videoDecodeH264);
777 #else
778 DE_UNREF(deviceExtensions);
779 DE_UNREF(apiVersion);
780 DE_UNREF(queueFlagsRequired);
781 DE_UNREF(videoCodecOperationFlags);
782 #endif
783 }
784
getDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags,const VideoDevice::VideoDeviceFlags videoDeviceFlags)785 vk::VkDevice VideoDevice::getDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,
786 const VideoCodecOperationFlags videoCodecOperationFlags,
787 const VideoDevice::VideoDeviceFlags videoDeviceFlags)
788 {
789 #ifndef CTS_USES_VULKANSC
790 if (*m_logicalDevice == nullptr)
791 {
792 DE_ASSERT(static_cast<uint32_t>(queueFlagsRequired) != 0u);
793 DE_ASSERT(static_cast<uint32_t>(videoCodecOperationFlags) != 0u);
794
795 if (!createDeviceSupportingQueue(queueFlagsRequired, videoCodecOperationFlags, videoDeviceFlags))
796 TCU_THROW(NotSupportedError, "Cannot create device with required parameters");
797 }
798
799 return *m_logicalDevice;
800 #else
801 DE_UNREF(queueFlagsRequired);
802 DE_UNREF(videoCodecOperationFlags);
803 DE_UNREF(videoDeviceFlags);
804
805 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
806 #endif
807 }
808
createDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags,const VideoDeviceFlags videoDeviceFlags)809 bool VideoDevice::createDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,
810 const VideoCodecOperationFlags videoCodecOperationFlags,
811 const VideoDeviceFlags videoDeviceFlags)
812 {
813 #ifndef CTS_USES_VULKANSC
814 const vk::PlatformInterface &vkp = m_context.getPlatformInterface();
815 const vk::InstanceInterface &vki = m_context.getInstanceInterface();
816 const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
817 const vk::VkInstance instance = m_context.getInstance();
818 const uint32_t apiVersion = m_context.getUsedApiVersion();
819 const bool validationEnabled = m_context.getTestContext().getCommandLine().isValidationEnabled();
820 const bool queryWithStatusForDecodeSupport =
821 (videoDeviceFlags & VIDEO_DEVICE_FLAG_QUERY_WITH_STATUS_FOR_DECODE_SUPPORT) != 0;
822 const bool queryWithStatusForEncodeSupport =
823 (videoDeviceFlags & VIDEO_DEVICE_FLAG_QUERY_WITH_STATUS_FOR_ENCODE_SUPPORT) != 0;
824 const bool requireMaintenance1 = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_MAINTENANCE_1) != 0;
825 const bool requireQuantizationMap = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_QUANTIZATION_MAP) != 0;
826 const bool requireYCBCRorNotSupported = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_YCBCR_OR_NOT_SUPPORTED) != 0;
827 const bool requireSync2orNotSupported = (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_SYNC2_OR_NOT_SUPPORTED) != 0;
828 const bool requireTimelineSemOrNotSupported =
829 (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_TIMELINE_OR_NOT_SUPPORTED) != 0;
830 const float queueFamilyPriority = 1.0f;
831 uint32_t queueFamilyPropertiesCount = 0u;
832 uint32_t queueFamilyTransfer = VK_QUEUE_FAMILY_IGNORED;
833 uint32_t queueFamilyDecode = VK_QUEUE_FAMILY_IGNORED;
834 uint32_t queueFamilyEncode = VK_QUEUE_FAMILY_IGNORED;
835 vk::VkQueueFlags queueFlagsFound = 0;
836 vector<vk::VkQueueFamilyProperties2> queueFamilyProperties2;
837 vector<vk::VkQueueFamilyVideoPropertiesKHR> videoQueueFamilyProperties2;
838 vector<vk::VkQueueFamilyQueryResultStatusPropertiesKHR> VkQueueFamilyQueryResultStatusPropertiesKHR;
839 vector<const char *> deviceExtensions;
840 vector<vk::VkDeviceQueueCreateInfo> queueInfos;
841
842 DE_ASSERT(queueFlagsRequired != 0);
843 DE_ASSERT(videoCodecOperationFlags != 0);
844
845 vki.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, nullptr);
846
847 if (queueFamilyPropertiesCount == 0u)
848 TCU_FAIL("Device reports an empty set of queue family properties");
849
850 queueFamilyProperties2.resize(queueFamilyPropertiesCount);
851 videoQueueFamilyProperties2.resize(queueFamilyPropertiesCount);
852 VkQueueFamilyQueryResultStatusPropertiesKHR.resize(queueFamilyPropertiesCount);
853
854 for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
855 {
856 queueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
857 queueFamilyProperties2[ndx].pNext = &videoQueueFamilyProperties2[ndx];
858 videoQueueFamilyProperties2[ndx].sType = vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
859 videoQueueFamilyProperties2[ndx].pNext = &VkQueueFamilyQueryResultStatusPropertiesKHR[ndx];
860 videoQueueFamilyProperties2[ndx].videoCodecOperations = 0;
861 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].sType =
862 vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR;
863 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].pNext = nullptr;
864 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport = false;
865 }
866
867 vki.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount,
868 queueFamilyProperties2.data());
869
870 if (queueFamilyPropertiesCount != queueFamilyProperties2.size())
871 TCU_FAIL("Device returns less queue families than initially reported");
872
873 for (uint32_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
874 {
875 const vk::VkQueueFamilyProperties &queueFamilyProperties = queueFamilyProperties2[ndx].queueFamilyProperties;
876 const vk::VkQueueFlags usefulQueueFlags =
877 queueFamilyProperties.queueFlags & queueFlagsRequired & ~queueFlagsFound;
878
879 if (usefulQueueFlags != 0)
880 {
881 bool assigned = false;
882
883 if ((usefulQueueFlags & vk::VK_QUEUE_TRANSFER_BIT) != 0 && queueFamilyTransfer == VK_QUEUE_FAMILY_IGNORED)
884 {
885 queueFamilyTransfer = ndx;
886 assigned = true;
887 }
888
889 if ((videoQueueFamilyProperties2[ndx].videoCodecOperations & videoCodecOperationFlags) != 0)
890 {
891 if ((usefulQueueFlags & vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0 &&
892 queueFamilyDecode == VK_QUEUE_FAMILY_IGNORED)
893 {
894 if (!queryWithStatusForDecodeSupport ||
895 (queryWithStatusForDecodeSupport &&
896 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport))
897 {
898 queueFamilyDecode = ndx;
899 assigned = true;
900 }
901 }
902
903 if ((usefulQueueFlags & vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0 &&
904 queueFamilyEncode == VK_QUEUE_FAMILY_IGNORED)
905 {
906 if (!queryWithStatusForEncodeSupport ||
907 (queryWithStatusForEncodeSupport &&
908 VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport))
909 {
910 queueFamilyEncode = ndx;
911 assigned = true;
912 }
913 }
914 }
915
916 if (assigned)
917 {
918 const vk::VkDeviceQueueCreateInfo queueInfo = {
919 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
920 nullptr, // const void* pNext;
921 (vk::VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
922 ndx, // uint32_t queueFamilyIndex;
923 1u, // uint32_t queueCount;
924 &queueFamilyPriority, // const float* pQueuePriorities;
925 };
926
927 if (queueFamilyProperties.queueCount == 0)
928 TCU_FAIL("Video queue returned queueCount is zero");
929
930 queueInfos.push_back(queueInfo);
931
932 queueFlagsFound |= usefulQueueFlags;
933
934 if (queueFlagsFound == queueFlagsRequired)
935 break;
936 }
937 }
938 }
939
940 if (queueFlagsFound != queueFlagsRequired)
941 return false;
942
943 addVideoDeviceExtensions(deviceExtensions, apiVersion, queueFlagsRequired, videoCodecOperationFlags);
944
945 if (requireYCBCRorNotSupported)
946 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
947 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
948
949 if (requireSync2orNotSupported)
950 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_synchronization2"))
951 deviceExtensions.push_back("VK_KHR_synchronization2");
952
953 if (requireMaintenance1)
954 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_video_maintenance1"))
955 deviceExtensions.push_back("VK_KHR_video_maintenance1");
956
957 if (requireQuantizationMap)
958 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_video_encode_quantization_map"))
959 deviceExtensions.push_back("VK_KHR_video_encode_quantization_map");
960
961 if (requireTimelineSemOrNotSupported)
962 if (m_context.isDeviceFunctionalitySupported("VK_KHR_timeline_semaphore"))
963 deviceExtensions.push_back("VK_KHR_timeline_semaphore");
964
965 vk::VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features = {
966 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, // VkStructureType sType;
967 nullptr, // void* pNext;
968 false, // VkBool32 synchronization2;
969 };
970 vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYcbcrConversionFeatures = {
971 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, // VkStructureType sType;
972 nullptr, // void* pNext;
973 false, // VkBool32 samplerYcbcrConversion;
974 };
975
976 vk::VkPhysicalDeviceVideoMaintenance1FeaturesKHR maintenance1Features = {
977 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR, // VkStructureType sType;
978 nullptr, // void* pNext;
979 false, // VkBool32 videoMaintenance1;
980 };
981
982 vk::VkPhysicalDeviceVideoEncodeQuantizationMapFeaturesKHR quantizationMapFeatures = {
983 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_QUANTIZATION_MAP_FEATURES_KHR, // VkStructureType sType;
984 nullptr, // void* pNext;
985 false, // VkBool32 videoEncodeQuantizationMap;
986 };
987
988 vk::VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures = {
989 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, // VkStructureType sType;
990 nullptr, // void* pNext;
991 true // VkBool32 timelineSemaphore;
992 };
993
994 vk::VkPhysicalDeviceFeatures2 features2 = {
995 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType sType;
996 nullptr, // void* pNext;
997 vk::VkPhysicalDeviceFeatures(), // VkPhysicalDeviceFeatures features;
998 };
999
1000 if (requireYCBCRorNotSupported)
1001 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &samplerYcbcrConversionFeatures);
1002
1003 if (requireSync2orNotSupported)
1004 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &synchronization2Features);
1005
1006 if (requireMaintenance1)
1007 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &maintenance1Features);
1008
1009 if (requireQuantizationMap)
1010 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &quantizationMapFeatures);
1011
1012 if (requireTimelineSemOrNotSupported)
1013 if (m_context.isDeviceFunctionalitySupported("VK_KHR_timeline_semaphore"))
1014 appendStructurePtrToVulkanChain((const void **)&features2.pNext, &timelineSemaphoreFeatures);
1015
1016 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1017
1018 if (requireYCBCRorNotSupported && samplerYcbcrConversionFeatures.samplerYcbcrConversion == false)
1019 TCU_THROW(NotSupportedError, "samplerYcbcrConversionFeatures.samplerYcbcrConversion is required");
1020
1021 if (requireSync2orNotSupported && synchronization2Features.synchronization2 == false)
1022 TCU_THROW(NotSupportedError, "synchronization2Features.synchronization2 is required");
1023
1024 if (requireTimelineSemOrNotSupported && timelineSemaphoreFeatures.timelineSemaphore == false)
1025 TCU_THROW(NotSupportedError, "timelineSemaphore extension is required");
1026
1027 if (requireMaintenance1 && maintenance1Features.videoMaintenance1 == false)
1028 TCU_THROW(NotSupportedError, "videoMaintenance1 feature is required");
1029
1030 features2.features.robustBufferAccess = false;
1031
1032 const vk::VkDeviceCreateInfo deviceCreateInfo = {
1033 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
1034 &features2, // const void* pNext;
1035 (vk::VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
1036 static_cast<uint32_t>(queueInfos.size()), // uint32_t queueCreateInfoCount;
1037 de::dataOrNull(queueInfos), // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
1038 0u, // uint32_t enabledLayerCount;
1039 nullptr, // const char* const* ppEnabledLayerNames;
1040 uint32_t(deviceExtensions.size()), // uint32_t enabledExtensionCount;
1041 de::dataOrNull(deviceExtensions), // const char* const* ppEnabledExtensionNames;
1042 nullptr, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
1043 };
1044
1045 m_logicalDevice = createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceCreateInfo);
1046 m_deviceDriver = de::MovePtr<vk::DeviceDriver>(
1047 new vk::DeviceDriver(vkp, instance, *m_logicalDevice, apiVersion, m_context.getTestContext().getCommandLine()));
1048 m_allocator = de::MovePtr<vk::Allocator>(new vk::SimpleAllocator(
1049 *m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
1050 m_queueFamilyTransfer = queueFamilyTransfer;
1051 m_queueFamilyDecode = queueFamilyDecode;
1052 m_queueFamilyEncode = queueFamilyEncode;
1053 m_videoCodecOperation = videoCodecOperationFlags;
1054
1055 return true;
1056 #else
1057 DE_UNREF(queueFlagsRequired);
1058 DE_UNREF(videoCodecOperationFlags);
1059 DE_UNREF(videoDeviceFlags);
1060
1061 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1062 #endif
1063 }
1064
getDeviceDriver(void)1065 const vk::DeviceDriver &VideoDevice::getDeviceDriver(void)
1066 {
1067 #ifndef CTS_USES_VULKANSC
1068 DE_ASSERT(m_deviceDriver.get() != nullptr);
1069
1070 return *m_deviceDriver;
1071 #else
1072 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1073 #endif
1074 }
1075
getQueueFamilyIndexTransfer(void) const1076 uint32_t VideoDevice::getQueueFamilyIndexTransfer(void) const
1077 {
1078 #ifndef CTS_USES_VULKANSC
1079 DE_ASSERT(m_queueFamilyTransfer != VK_QUEUE_FAMILY_IGNORED);
1080
1081 return m_queueFamilyTransfer;
1082 #else
1083 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1084 #endif
1085 }
1086
getQueueFamilyIndexDecode(void) const1087 uint32_t VideoDevice::getQueueFamilyIndexDecode(void) const
1088 {
1089 #ifndef CTS_USES_VULKANSC
1090 DE_ASSERT(m_queueFamilyDecode != VK_QUEUE_FAMILY_IGNORED);
1091
1092 return m_queueFamilyDecode;
1093 #else
1094 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1095 #endif
1096 }
1097
getQueueFamilyIndexEncode(void) const1098 uint32_t VideoDevice::getQueueFamilyIndexEncode(void) const
1099 {
1100 #ifndef CTS_USES_VULKANSC
1101 DE_ASSERT(m_queueFamilyEncode != VK_QUEUE_FAMILY_IGNORED);
1102
1103 return m_queueFamilyEncode;
1104 #else
1105 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1106 #endif
1107 }
1108
getQueueFamilyVideo(void) const1109 uint32_t VideoDevice::getQueueFamilyVideo(void) const
1110 {
1111 #ifndef CTS_USES_VULKANSC
1112 const bool encode = isVideoEncodeOperation(m_videoCodecOperation);
1113 const bool decode = isVideoDecodeOperation(m_videoCodecOperation);
1114
1115 DE_ASSERT((encode && !decode) || (!encode && decode));
1116 DE_UNREF(decode);
1117
1118 return encode ? getQueueFamilyIndexEncode() : getQueueFamilyIndexDecode();
1119 #else
1120 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1121 #endif
1122 }
1123
getAllocator(void)1124 vk::Allocator &VideoDevice::getAllocator(void)
1125 {
1126 #ifndef CTS_USES_VULKANSC
1127 DE_ASSERT(m_allocator);
1128
1129 return *m_allocator;
1130 #else
1131 TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
1132 #endif
1133 }
1134
1135 } // namespace vkt
1136