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