1 #ifndef _VKTVIDEOTESTUTILS_HPP
2 #define _VKTVIDEOTESTUTILS_HPP
3 /*------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2021 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Video Encoding and Decoding Utility Functions
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktVideoTestUtils.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktCustomInstancesDevices.hpp"
34 
35 #include "ycbcr/vktYCbCrUtil.hpp"
36 #include "vkMd5Sum.hpp"
37 
38 namespace vkt
39 {
40 namespace video
41 {
42 
43 using namespace vk;
44 using namespace std;
45 
46 typedef de::MovePtr<Allocation> AllocationPtr;
47 
48 bool videoLoggingEnabled();
49 
50 bool												imageMatchesReferenceChecksum(const ycbcr::MultiPlaneImageData& multiPlaneImageData, const std::string& referenceChecksums);
51 
52 VkVideoDecodeH264ProfileInfoKHR						getProfileOperationH264Decode			(StdVideoH264ProfileIdc						stdProfileIdc				= STD_VIDEO_H264_PROFILE_IDC_MAIN,
53 																							 VkVideoDecodeH264PictureLayoutFlagBitsKHR	pictureLayout				= VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR);
54 VkVideoEncodeH264ProfileInfoEXT						getProfileOperationH264Encode			(StdVideoH264ProfileIdc						stdProfileIdc				= STD_VIDEO_H264_PROFILE_IDC_MAIN);
55 VkVideoDecodeH265ProfileInfoKHR						getProfileOperationH265Decode			(StdVideoH265ProfileIdc					stdProfileIdc					= STD_VIDEO_H265_PROFILE_IDC_MAIN);
56 VkVideoEncodeH265ProfileInfoEXT						getProfileOperationH265Encode			(StdVideoH265ProfileIdc					stdProfileIdc					= STD_VIDEO_H265_PROFILE_IDC_MAIN);
57 
58 const VkExtensionProperties*						getVideoExtensionProperties				(const VkVideoCodecOperationFlagBitsKHR	codecOperation);
59 
60 de::MovePtr<vector<VkFormat>>						getSupportedFormats						(const InstanceInterface& vk,
61 																							const VkPhysicalDevice					physicalDevice,
62 																							const VkImageUsageFlags					imageUsageFlags,
63 																							const VkVideoProfileListInfoKHR*		videoProfileList);
64 
65 
66 VkImageCreateInfo									makeImageCreateInfo						(VkFormat								format,
67 																							 const VkExtent2D&						extent,
68 																							 const deUint32*						queueFamilyIndex,
69 																							 const VkImageUsageFlags				usage,
70 																							 void*									pNext,
71 																							 const deUint32							arrayLayers = 1);
72 
73 
74 void												cmdPipelineImageMemoryBarrier2			(const DeviceInterface&					vk,
75 																							 const VkCommandBuffer					commandBuffer,
76 																							 const VkImageMemoryBarrier2KHR*		pImageMemoryBarriers,
77 																							 const size_t							imageMemoryBarrierCount = 1u,
78 																							 const VkDependencyFlags				dependencyFlags = 0);
79 
80 void validateVideoProfileList (const InstanceInterface&				vk,
81 																			 VkPhysicalDevice						physicalDevice,
82 																			 const VkVideoProfileListInfoKHR*		videoProfileList,
83 																			 const VkFormat						format,
84 																			 const VkImageUsageFlags				usage);
85 
86 struct DeviceContext
87 {
88 	Context*				 context{};
89 	VideoDevice*			 vd{};
90 	VkPhysicalDevice		 phys{VK_NULL_HANDLE};
91 	VkDevice				 device{VK_NULL_HANDLE};
92 	VkQueue					 decodeQueue{VK_NULL_HANDLE};
93 	VkQueue					 transferQueue{VK_NULL_HANDLE};
94 
getInstanceInterfacevkt::video::DeviceContext95 	const InstanceInterface& getInstanceInterface() const
96 	{
97 		return context->getInstanceInterface();
98 	}
getDeviceDrivervkt::video::DeviceContext99 	const DeviceDriver& getDeviceDriver() const
100 	{
101 		return vd->getDeviceDriver();
102 	}
decodeQueueFamilyIdxvkt::video::DeviceContext103 	deUint32 decodeQueueFamilyIdx() const
104 	{
105 		return vd->getQueueFamilyIndexDecode();
106 	}
transferQueueFamilyIdxvkt::video::DeviceContext107 	deUint32 transferQueueFamilyIdx() const
108 	{
109 		return vd->getQueueFamilyIndexTransfer();
110 	}
allocatorvkt::video::DeviceContext111 	Allocator& allocator() const
112 	{
113 		return vd->getAllocator();
114 	}
waitDecodeQueuevkt::video::DeviceContext115 	void waitDecodeQueue() const
116 	{
117 		VK_CHECK(getDeviceDriver().queueWaitIdle(decodeQueue));
118 	}
deviceWaitIdlevkt::video::DeviceContext119 	void deviceWaitIdle() const
120 	{
121 		VK_CHECK(getDeviceDriver().deviceWaitIdle(device));
122 	}
123 };
124 
125 class VideoBaseTestInstance : public TestInstance
126 {
127 public:
VideoBaseTestInstance(Context& context)128 	explicit VideoBaseTestInstance(Context& context)
129 		: TestInstance(context)
130 		, m_videoDevice(context)
131 	{
132 	}
133 
134 	~VideoBaseTestInstance() override = default;
135 
136 	VkDevice			getDeviceSupportingQueue(VkQueueFlags				   queueFlagsRequired		= 0,
137 												 VkVideoCodecOperationFlagsKHR videoCodecOperationFlags = 0,
138 												 VideoDevice::VideoDeviceFlags videoDeviceFlags			= VideoDevice::VIDEO_DEVICE_FLAG_NONE);
139 	bool				createDeviceSupportingQueue(VkQueueFlags				  queueFlagsRequired,
140 													VkVideoCodecOperationFlagsKHR videoCodecOperationFlags,
141 													VideoDevice::VideoDeviceFlags videoDeviceFlags = VideoDevice::VIDEO_DEVICE_FLAG_NONE);
142 	const DeviceDriver& getDeviceDriver();
143 	deUint32			getQueueFamilyIndexTransfer();
144 	deUint32			getQueueFamilyIndexDecode();
145 	deUint32			getQueueFamilyIndexEncode();
146 	Allocator&			getAllocator();
147 
148 	std::string			getVideoDataClipA();
149 	std::string			getVideoDataClipB();
150 	std::string			getVideoDataClipC();
151 	std::string			getVideoDataClipD();
152 	std::string			getVideoDataClipH264G13();
153 	std::string			getVideoDataClipH265G13();
154 
155 protected:
156 	de::MovePtr<vector<deUint8>> loadVideoData(const string& filename);
157 	VideoDevice					 m_videoDevice;
158 };
159 
160 typedef enum StdChromaFormatIdc
161 {
162 	chroma_format_idc_monochrome = STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME,
163 	chroma_format_idc_420		 = STD_VIDEO_H264_CHROMA_FORMAT_IDC_420,
164 	chroma_format_idc_422		 = STD_VIDEO_H264_CHROMA_FORMAT_IDC_422,
165 	chroma_format_idc_444		 = STD_VIDEO_H264_CHROMA_FORMAT_IDC_444,
166 } StdChromaFormatIdc;
167 
168 class VkVideoCoreProfile
169 {
170 public:
isValidCodec(VkVideoCodecOperationFlagsKHR videoCodecOperations)171 	static bool isValidCodec(VkVideoCodecOperationFlagsKHR videoCodecOperations)
172 	{
173 		return (videoCodecOperations & (VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR |
174 										VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR |
175 										VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT |
176 										VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT));
177 	}
178 
PopulateProfileExt(VkBaseInStructure const* pVideoProfileExt)179 	bool PopulateProfileExt(VkBaseInStructure const* pVideoProfileExt)
180 	{
181 		if (m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
182 		{
183 			VkVideoDecodeH264ProfileInfoKHR const* pProfileExt = (VkVideoDecodeH264ProfileInfoKHR const*)pVideoProfileExt;
184 			if (pProfileExt && (pProfileExt->sType != VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR))
185 			{
186 				m_profile.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
187 				return false;
188 			}
189 			if (pProfileExt)
190 			{
191 				m_h264DecodeProfile = *pProfileExt;
192 			}
193 			else
194 			{
195 				//  Use default ext profile parameters
196 				m_h264DecodeProfile.sType		  = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
197 				m_h264DecodeProfile.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN;
198 				m_h264DecodeProfile.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
199 			}
200 			m_profile.pNext			  = &m_h264DecodeProfile;
201 			m_h264DecodeProfile.pNext = NULL;
202 		}
203 		else if (m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR)
204 		{
205 			VkVideoDecodeH265ProfileInfoKHR const* pProfileExt = (VkVideoDecodeH265ProfileInfoKHR const*)pVideoProfileExt;
206 			if (pProfileExt && (pProfileExt->sType != VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR))
207 			{
208 				m_profile.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
209 				return false;
210 			}
211 			if (pProfileExt)
212 			{
213 				m_h265DecodeProfile = *pProfileExt;
214 			}
215 			else
216 			{
217 				//  Use default ext profile parameters
218 				m_h265DecodeProfile.sType		  = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
219 				m_h265DecodeProfile.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN;
220 			}
221 			m_profile.pNext			  = &m_h265DecodeProfile;
222 			m_h265DecodeProfile.pNext = NULL;
223 		}
224 		else if (m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT)
225 		{
226 			VkVideoEncodeH264ProfileInfoEXT const* pProfileExt = (VkVideoEncodeH264ProfileInfoEXT const*)pVideoProfileExt;
227 			if (pProfileExt && (pProfileExt->sType != VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT))
228 			{
229 				m_profile.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
230 				return false;
231 			}
232 			if (pProfileExt)
233 			{
234 				m_h264EncodeProfile = *pProfileExt;
235 			}
236 			else
237 			{
238 				//  Use default ext profile parameters
239 				m_h264DecodeProfile.sType		  = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT;
240 				m_h264DecodeProfile.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN;
241 			}
242 			m_profile.pNext			  = &m_h264EncodeProfile;
243 			m_h264EncodeProfile.pNext = NULL;
244 		}
245 		else if (m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT)
246 		{
247 			VkVideoEncodeH265ProfileInfoEXT const* pProfileExt = (VkVideoEncodeH265ProfileInfoEXT const*)pVideoProfileExt;
248 			if (pProfileExt && (pProfileExt->sType != VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT))
249 			{
250 				m_profile.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
251 				return false;
252 			}
253 			if (pProfileExt)
254 			{
255 				m_h265EncodeProfile = *pProfileExt;
256 			}
257 			else
258 			{
259 				//  Use default ext profile parameters
260 				m_h265EncodeProfile.sType		  = VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT;
261 				m_h265EncodeProfile.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN;
262 			}
263 			m_profile.pNext			  = &m_h265EncodeProfile;
264 			m_h265EncodeProfile.pNext = NULL;
265 		}
266 		else
267 		{
268 			DE_ASSERT(false && "Unknown codec!");
269 			return false;
270 		}
271 
272 		return true;
273 	}
274 
InitFromProfile(const VkVideoProfileInfoKHR* pVideoProfile)275 	bool InitFromProfile(const VkVideoProfileInfoKHR* pVideoProfile)
276 	{
277 		m_profile		= *pVideoProfile;
278 		m_profile.pNext = NULL;
279 		return PopulateProfileExt((VkBaseInStructure const*)pVideoProfile->pNext);
280 	}
281 
VkVideoCoreProfile(const VkVideoProfileInfoKHR* pVideoProfile)282 	VkVideoCoreProfile(const VkVideoProfileInfoKHR* pVideoProfile)
283 		: m_profile(*pVideoProfile)
284 	{
285 
286 		PopulateProfileExt((VkBaseInStructure const*)pVideoProfile->pNext);
287 	}
288 
VkVideoCoreProfile(VkVideoCodecOperationFlagBitsKHR videoCodecOperation = VK_VIDEO_CODEC_OPERATION_NONE_KHR, VkVideoChromaSubsamplingFlagsKHR chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR, VkVideoComponentBitDepthFlagsKHR lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR, VkVideoComponentBitDepthFlagsKHR chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR, deUint32 videoH26xProfileIdc = 0)289 	VkVideoCoreProfile(VkVideoCodecOperationFlagBitsKHR videoCodecOperation = VK_VIDEO_CODEC_OPERATION_NONE_KHR,
290 					   VkVideoChromaSubsamplingFlagsKHR chromaSubsampling	= VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR,
291 					   VkVideoComponentBitDepthFlagsKHR lumaBitDepth		= VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR,
292 					   VkVideoComponentBitDepthFlagsKHR chromaBitDepth		= VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR,
293 					   deUint32							videoH26xProfileIdc = 0)
294 		: m_profile({VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR, NULL, videoCodecOperation, chromaSubsampling, lumaBitDepth, chromaBitDepth}), m_profileList({VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR, NULL, 1, &m_profile})
295 	{
296 		if (!isValidCodec(videoCodecOperation))
297 		{
298 			return;
299 		}
300 
301 		VkVideoDecodeH264ProfileInfoKHR decodeH264ProfilesRequest;
302 		VkVideoDecodeH265ProfileInfoKHR decodeH265ProfilesRequest;
303 		VkVideoEncodeH264ProfileInfoEXT encodeH264ProfilesRequest;
304 		VkVideoEncodeH265ProfileInfoEXT encodeH265ProfilesRequest;
305 		VkBaseInStructure*				pVideoProfileExt = NULL;
306 
307 		if (videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
308 		{
309 			decodeH264ProfilesRequest.sType			= VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
310 			decodeH264ProfilesRequest.pNext			= NULL;
311 			decodeH264ProfilesRequest.stdProfileIdc = (videoH26xProfileIdc == 0) ?
312 														  STD_VIDEO_H264_PROFILE_IDC_INVALID :
313 														  (StdVideoH264ProfileIdc)videoH26xProfileIdc;
314 			decodeH264ProfilesRequest.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
315 			pVideoProfileExt						= (VkBaseInStructure*)&decodeH264ProfilesRequest;
316 		}
317 		else if (videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR)
318 		{
319 			decodeH265ProfilesRequest.sType			= VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
320 			decodeH265ProfilesRequest.pNext			= NULL;
321 			decodeH265ProfilesRequest.stdProfileIdc = (videoH26xProfileIdc == 0) ?
322 														  STD_VIDEO_H265_PROFILE_IDC_INVALID :
323 														  (StdVideoH265ProfileIdc)videoH26xProfileIdc;
324 			pVideoProfileExt						= (VkBaseInStructure*)&decodeH265ProfilesRequest;
325 		}
326 		else if (videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT)
327 		{
328 			encodeH264ProfilesRequest.sType			= VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT;
329 			encodeH264ProfilesRequest.pNext			= NULL;
330 			encodeH264ProfilesRequest.stdProfileIdc = (videoH26xProfileIdc == 0) ?
331 														  STD_VIDEO_H264_PROFILE_IDC_INVALID :
332 														  (StdVideoH264ProfileIdc)videoH26xProfileIdc;
333 			pVideoProfileExt						= (VkBaseInStructure*)&encodeH264ProfilesRequest;
334 		}
335 		else if (videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT)
336 		{
337 			encodeH265ProfilesRequest.sType			= VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT;
338 			encodeH265ProfilesRequest.pNext			= NULL;
339 			encodeH265ProfilesRequest.stdProfileIdc = (videoH26xProfileIdc == 0) ?
340 														  STD_VIDEO_H265_PROFILE_IDC_INVALID :
341 														  (StdVideoH265ProfileIdc)videoH26xProfileIdc;
342 			pVideoProfileExt						= (VkBaseInStructure*)&encodeH265ProfilesRequest;
343 		}
344 		else
345 		{
346 			DE_ASSERT(false && "Unknown codec!");
347 			return;
348 		}
349 
350 		PopulateProfileExt(pVideoProfileExt);
351 	}
352 
GetCodecType() const353 	VkVideoCodecOperationFlagBitsKHR GetCodecType() const
354 	{
355 		return m_profile.videoCodecOperation;
356 	}
357 
IsEncodeCodecType() const358 	bool IsEncodeCodecType() const
359 	{
360 		return ((m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT) ||
361 				(m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT));
362 	}
363 
IsDecodeCodecType() const364 	bool IsDecodeCodecType() const
365 	{
366 		return ((m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) ||
367 				(m_profile.videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR));
368 	}
369 
operator bool() const370 	operator bool() const
371 	{
372 		return (m_profile.sType == VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR);
373 	}
374 
GetProfile() const375 	const VkVideoProfileInfoKHR* GetProfile() const
376 	{
377 		if (m_profile.sType == VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR)
378 		{
379 			return &m_profile;
380 		}
381 		else
382 		{
383 			return NULL;
384 		}
385 	}
386 
GetProfileListInfo() const387 	const VkVideoProfileListInfoKHR* GetProfileListInfo() const
388 	{
389 		if (m_profileList.sType == VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR)
390 		{
391 			return &m_profileList;
392 		}
393 		else
394 		{
395 			return NULL;
396 		}
397 	}
398 
GetDecodeH264Profile() const399 	const VkVideoDecodeH264ProfileInfoKHR* GetDecodeH264Profile() const
400 	{
401 		if (m_h264DecodeProfile.sType == VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR)
402 		{
403 			return &m_h264DecodeProfile;
404 		}
405 		else
406 		{
407 			return NULL;
408 		}
409 	}
410 
GetDecodeH265Profile() const411 	const VkVideoDecodeH265ProfileInfoKHR* GetDecodeH265Profile() const
412 	{
413 		if (m_h265DecodeProfile.sType == VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR)
414 		{
415 			return &m_h265DecodeProfile;
416 		}
417 		else
418 		{
419 			return NULL;
420 		}
421 	}
422 
GetEncodeH264Profile() const423 	const VkVideoEncodeH264ProfileInfoEXT* GetEncodeH264Profile() const
424 	{
425 		if (m_h264DecodeProfile.sType == VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT)
426 		{
427 			return &m_h264EncodeProfile;
428 		}
429 		else
430 		{
431 			return NULL;
432 		}
433 	}
434 
GetEncodeH265Profile() const435 	const VkVideoEncodeH265ProfileInfoEXT* GetEncodeH265Profile() const
436 	{
437 		if (m_h265DecodeProfile.sType == VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_EXT)
438 		{
439 			return &m_h265EncodeProfile;
440 		}
441 		else
442 		{
443 			return NULL;
444 		}
445 	}
446 
copyProfile(const VkVideoCoreProfile& src)447 	bool copyProfile(const VkVideoCoreProfile& src)
448 	{
449 		if (!src)
450 		{
451 			return false;
452 		}
453 
454 		m_profile				= src.m_profile;
455 		m_profile.pNext			= nullptr;
456 
457 		m_profileList			= src.m_profileList;
458 		m_profileList.pNext		= nullptr;
459 
460 		m_profileList.pProfiles = &m_profile;
461 
462 		PopulateProfileExt((VkBaseInStructure const*)src.m_profile.pNext);
463 
464 		return true;
465 	}
466 
VkVideoCoreProfile(const VkVideoCoreProfile& other)467 	VkVideoCoreProfile(const VkVideoCoreProfile& other)
468 	{
469 		copyProfile(other);
470 	}
471 
operator =(const VkVideoCoreProfile& other)472 	VkVideoCoreProfile& operator=(const VkVideoCoreProfile& other)
473 	{
474 		copyProfile(other);
475 		return *this;
476 	}
477 
operator ==(const VkVideoCoreProfile& other) const478 	bool operator==(const VkVideoCoreProfile& other) const
479 	{
480 		if (m_profile.videoCodecOperation != other.m_profile.videoCodecOperation)
481 		{
482 			return false;
483 		}
484 
485 		if (m_profile.chromaSubsampling != other.m_profile.chromaSubsampling)
486 		{
487 			return false;
488 		}
489 
490 		if (m_profile.lumaBitDepth != other.m_profile.lumaBitDepth)
491 		{
492 			return false;
493 		}
494 
495 		if (m_profile.chromaBitDepth != other.m_profile.chromaBitDepth)
496 		{
497 			return false;
498 		}
499 
500 		if (m_profile.pNext != nullptr)
501 		{
502 			switch (m_profile.videoCodecOperation) {
503 				case vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
504 				{
505 					auto* ours	 = (VkVideoDecodeH264ProfileInfoKHR*)m_profile.pNext;
506 					auto* theirs = (VkVideoDecodeH264ProfileInfoKHR*)other.m_profile.pNext;
507 					if (ours->sType != theirs->sType)
508 						return false;
509 					if (ours->stdProfileIdc != theirs->stdProfileIdc)
510 						return false;
511 					if (ours->pictureLayout != theirs->pictureLayout)
512 						return false;
513 					break;
514 				}
515 				case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
516 				{
517 					auto* ours	 = (VkVideoDecodeH265ProfileInfoKHR*)m_profile.pNext;
518 					auto* theirs = (VkVideoDecodeH265ProfileInfoKHR*)other.m_profile.pNext;
519 					if (ours->sType != theirs->sType)
520 						return false;
521 					if (ours->stdProfileIdc != theirs->stdProfileIdc)
522 						return false;
523 					break;
524 				}
525 				default:
526 					tcu::die("Unknown codec");
527 			}
528 		}
529 
530 
531 		return true;
532 	}
533 
operator !=(const VkVideoCoreProfile& other) const534 	bool operator!=(const VkVideoCoreProfile& other) const
535 	{
536 		return !(*this == other);
537 	}
538 
GetColorSubsampling() const539 	VkVideoChromaSubsamplingFlagsKHR GetColorSubsampling() const
540 	{
541 		return m_profile.chromaSubsampling;
542 	}
543 
GetNvColorSubsampling() const544 	StdChromaFormatIdc GetNvColorSubsampling() const
545 	{
546 		if (m_profile.chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR)
547 		{
548 			return chroma_format_idc_monochrome;
549 		}
550 		else if (m_profile.chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR)
551 		{
552 			return chroma_format_idc_420;
553 		}
554 		else if (m_profile.chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR)
555 		{
556 			return chroma_format_idc_422;
557 		}
558 		else if (m_profile.chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR)
559 		{
560 			return chroma_format_idc_444;
561 		}
562 
563 		return chroma_format_idc_monochrome;
564 	}
565 
GetLumaBitDepthMinus8() const566 	deUint32 GetLumaBitDepthMinus8() const
567 	{
568 		if (m_profile.lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
569 		{
570 			return 8 - 8;
571 		}
572 		else if (m_profile.lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
573 		{
574 			return 10 - 8;
575 		}
576 		else if (m_profile.lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR)
577 		{
578 			return 12 - 8;
579 		}
580 		return 0;
581 	}
582 
GetChromaBitDepthMinus8() const583 	deUint32 GetChromaBitDepthMinus8() const
584 	{
585 		if (m_profile.chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
586 		{
587 			return 8 - 8;
588 		}
589 		else if (m_profile.chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
590 		{
591 			return 10 - 8;
592 		}
593 		else if (m_profile.chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR)
594 		{
595 			return 12 - 8;
596 		}
597 		return 0;
598 	}
599 
is16BitFormat() const600 	bool is16BitFormat() const
601 	{
602 		return !!GetLumaBitDepthMinus8() || !!GetChromaBitDepthMinus8();
603 	}
604 
CodecGetVkFormat(VkVideoChromaSubsamplingFlagBitsKHR chromaFormatIdc, VkVideoComponentBitDepthFlagBitsKHR lumaBitDepth, bool isSemiPlanar)605 	static VkFormat CodecGetVkFormat(VkVideoChromaSubsamplingFlagBitsKHR chromaFormatIdc,
606 									 VkVideoComponentBitDepthFlagBitsKHR lumaBitDepth,
607 									 bool								 isSemiPlanar)
608 	{
609 		VkFormat vkFormat = VK_FORMAT_UNDEFINED;
610 		switch (chromaFormatIdc)
611 		{
612 			case VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR:
613 				switch (lumaBitDepth)
614 				{
615 					case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
616 						vkFormat = VK_FORMAT_R8_UNORM;
617 						break;
618 					case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
619 						vkFormat = VK_FORMAT_R10X6_UNORM_PACK16;
620 						break;
621 					case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
622 						vkFormat = VK_FORMAT_R12X4_UNORM_PACK16;
623 						break;
624 					default:
625 						DE_ASSERT(false);
626 				}
627 				break;
628 			case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
629 				switch (lumaBitDepth)
630 				{
631 					case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
632 						vkFormat = isSemiPlanar ? VK_FORMAT_G8_B8R8_2PLANE_420_UNORM : VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
633 						break;
634 					case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
635 						vkFormat = isSemiPlanar ? VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 : VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16;
636 						break;
637 					case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
638 						vkFormat = isSemiPlanar ? VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 : VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16;
639 						break;
640 					default:
641 						DE_ASSERT(false);
642 				}
643 				break;
644 			case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
645 				switch (lumaBitDepth)
646 				{
647 					case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
648 						vkFormat = isSemiPlanar ? VK_FORMAT_G8_B8R8_2PLANE_422_UNORM : VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM;
649 						break;
650 					case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
651 						vkFormat = isSemiPlanar ? VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 : VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16;
652 						break;
653 					case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
654 						vkFormat = isSemiPlanar ? VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 : VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16;
655 						break;
656 					default:
657 						DE_ASSERT(false);
658 				}
659 				break;
660 			case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
661 				switch (lumaBitDepth)
662 				{
663 					case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
664 						vkFormat = isSemiPlanar ? VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT : VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM;
665 						break;
666 					case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
667 						vkFormat = isSemiPlanar ? VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT : VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16;
668 						break;
669 					case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
670 						vkFormat = isSemiPlanar ? VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT : VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16;
671 						break;
672 					default:
673 						DE_ASSERT(false);
674 				}
675 				break;
676 			default:
677 				DE_ASSERT(false);
678 		}
679 
680 		return vkFormat;
681 	}
682 
GetVideoChromaFormatFromVkFormat(VkFormat format)683 	static StdChromaFormatIdc GetVideoChromaFormatFromVkFormat(VkFormat format)
684 	{
685 		StdChromaFormatIdc videoChromaFormat = chroma_format_idc_420;
686 		switch ((deUint32)format)
687 		{
688 			case VK_FORMAT_R8_UNORM:
689 			case VK_FORMAT_R10X6_UNORM_PACK16:
690 			case VK_FORMAT_R12X4_UNORM_PACK16:
691 				videoChromaFormat = chroma_format_idc_monochrome;
692 				break;
693 
694 			case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
695 			case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
696 			case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
697 			case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
698 			case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
699 			case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
700 				videoChromaFormat = chroma_format_idc_420;
701 				break;
702 
703 			case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
704 			case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
705 			case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
706 			case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
707 			case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
708 			case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
709 				videoChromaFormat = chroma_format_idc_422;
710 				break;
711 
712 			case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
713 			case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
714 			case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
715 			case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT:
716 			case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:
717 			case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:
718 			case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT:
719 				videoChromaFormat = chroma_format_idc_444;
720 				break;
721 			default:
722 				DE_ASSERT(false);
723 		}
724 
725 		return videoChromaFormat;
726 	}
727 
CodecToName(VkVideoCodecOperationFlagBitsKHR codec)728 	static const char* CodecToName(VkVideoCodecOperationFlagBitsKHR codec)
729 	{
730 		switch ((int32_t)codec)
731 		{
732 			case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
733 				return "decode h.264";
734 			case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
735 				return "decode h.265";
736 			case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT:
737 				return "encode h.264";
738 			case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT:
739 				return "encode h.265";
740 			default:;
741 		}
742 		DE_ASSERT(false && "Unknown codec");
743 		return "UNKNON";
744 	}
745 
DumpFormatProfiles(VkVideoProfileInfoKHR* pVideoProfile)746 	static void DumpFormatProfiles(VkVideoProfileInfoKHR* pVideoProfile)
747 	{
748 		// formatProfile info based on supported chroma_format_idc
749 		if (pVideoProfile->chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR)
750 		{
751 			std::cout << "MONO, ";
752 		}
753 		if (pVideoProfile->chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR)
754 		{
755 			std::cout << " 420, ";
756 		}
757 		if (pVideoProfile->chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR)
758 		{
759 			std::cout << " 422, ";
760 		}
761 		if (pVideoProfile->chromaSubsampling & VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR)
762 		{
763 			std::cout << " 444, ";
764 		}
765 
766 		// Profile info based on max bit_depth_luma_minus8
767 		if (pVideoProfile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
768 		{
769 			std::cout << "LUMA:   8-bit, ";
770 		}
771 		if (pVideoProfile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
772 		{
773 			std::cout << "LUMA:  10-bit, ";
774 		}
775 		if (pVideoProfile->lumaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR)
776 		{
777 			std::cout << "LUMA:  12-bit, ";
778 		}
779 
780 		// Profile info based on max bit_depth_chroma_minus8
781 		if (pVideoProfile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR)
782 		{
783 			std::cout << "CHROMA: 8-bit, ";
784 		}
785 		if (pVideoProfile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
786 		{
787 			std::cout << "CHROMA:10-bit, ";
788 		}
789 		if (pVideoProfile->chromaBitDepth & VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR)
790 		{
791 			std::cout << "CHROMA:12-bit,";
792 		}
793 	}
794 
DumpH264Profiles(VkVideoDecodeH264ProfileInfoKHR* pH264Profiles)795 	static void DumpH264Profiles(VkVideoDecodeH264ProfileInfoKHR* pH264Profiles)
796 	{
797 		switch (pH264Profiles->stdProfileIdc)
798 		{
799 			case STD_VIDEO_H264_PROFILE_IDC_BASELINE:
800 				std::cout << "BASELINE, ";
801 				break;
802 			case STD_VIDEO_H264_PROFILE_IDC_MAIN:
803 				std::cout << "MAIN, ";
804 				break;
805 			case STD_VIDEO_H264_PROFILE_IDC_HIGH:
806 				std::cout << "HIGH, ";
807 				break;
808 			case STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE:
809 				std::cout << "HIGH_444_PREDICTIVE, ";
810 				break;
811 			default:
812 				std::cout << "UNKNOWN PROFILE, ";
813 				break;
814 		}
815 	}
816 
DumpH265Profiles(VkVideoDecodeH265ProfileInfoKHR* pH265Profiles)817 	static void DumpH265Profiles(VkVideoDecodeH265ProfileInfoKHR* pH265Profiles)
818 	{
819 		switch (pH265Profiles->stdProfileIdc)
820 		{
821 			case STD_VIDEO_H265_PROFILE_IDC_MAIN:
822 				std::cout << "MAIN, ";
823 				break;
824 			case STD_VIDEO_H265_PROFILE_IDC_MAIN_10:
825 				std::cout << "MAIN_10, ";
826 				break;
827 			case STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE:
828 				std::cout << "MAIN_STILL_PICTURE, ";
829 				break;
830 			case STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS:
831 				std::cout << "FORMAT_RANGE_EXTENSIONS, ";
832 				break;
833 			case STD_VIDEO_H265_PROFILE_IDC_SCC_EXTENSIONS:
834 				std::cout << "SCC_EXTENSIONS, ";
835 				break;
836 			default:
837 				std::cout << "UNKNOWN PROFILE, ";
838 				break;
839 		}
840 	}
841 
842 private:
843 	VkVideoProfileInfoKHR	  m_profile;
844 	VkVideoProfileListInfoKHR m_profileList;
845 	union
846 	{
847 		VkVideoDecodeH264ProfileInfoKHR m_h264DecodeProfile;
848 		VkVideoDecodeH265ProfileInfoKHR m_h265DecodeProfile;
849 		VkVideoEncodeH264ProfileInfoEXT m_h264EncodeProfile;
850 		VkVideoEncodeH265ProfileInfoEXT m_h265EncodeProfile;
851 	};
852 };
853 
854 namespace util
855 {
856 const char*					  getVideoCodecString(VkVideoCodecOperationFlagBitsKHR codec);
857 
858 const char*					  getVideoChromaFormatString(VkVideoChromaSubsamplingFlagBitsKHR chromaFormat);
859 
860 VkVideoCodecOperationFlagsKHR getSupportedCodecs(DeviceContext&				   devCtx,
861 												 deUint32					   selectedVideoQueueFamily,
862 												 VkQueueFlags				   queueFlagsRequired = (VK_QUEUE_VIDEO_DECODE_BIT_KHR | VK_QUEUE_VIDEO_ENCODE_BIT_KHR),
863 												 VkVideoCodecOperationFlagsKHR videoCodeOperations =
864 													 (VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR | VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR |
865 													  VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT | VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT));
866 
867 VkResult					  getVideoFormats(DeviceContext&			devCtx,
868 											  const VkVideoCoreProfile& videoProfile,
869 											  VkImageUsageFlags			imageUsage,
870 											  deUint32&					formatCount,
871 											  VkFormat*					formats,
872 											  bool						dumpData = false);
873 
874 VkResult					  getSupportedVideoFormats(DeviceContext&				   devCtx,
875 													   const VkVideoCoreProfile&	   videoProfile,
876 													   VkVideoDecodeCapabilityFlagsKHR capabilityFlags,
877 													   VkFormat&					   pictureFormat,
878 													   VkFormat&					   referencePicturesFormat);
879 
880 const char*					  codecToName(VkVideoCodecOperationFlagBitsKHR codec);
881 
882 VkResult					  getVideoCapabilities(DeviceContext&			 devCtx,
883 												   const VkVideoCoreProfile& videoProfile,
884 												   VkVideoCapabilitiesKHR*	 pVideoCapabilities);
885 
886 VkResult					  getVideoDecodeCapabilities(DeviceContext&				   devCtx,
887 														 const VkVideoCoreProfile&	   videoProfile,
888 														 VkVideoCapabilitiesKHR&	   videoCapabilities,
889 														 VkVideoDecodeCapabilitiesKHR& videoDecodeCapabilities);
890 } // namespace util
891 
892 std::vector<deUint8> semiplanarToYV12(const ycbcr::MultiPlaneImageData& multiPlaneImageData);
893 
894 } // video
895 } // vkt
896 
897 #endif // _VKTVIDEOTESTUTILS_HPP
898