• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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