• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *	  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Video Decoding Base Classe Functionality
22  *//*--------------------------------------------------------------------*/
23  /*
24  * Copyright 2020 NVIDIA Corporation.
25  *
26  * Licensed under the Apache License, Version 2.0 (the "License");
27  * you may not use this file except in compliance with the License.
28  * You may obtain a copy of the License at
29  *
30  *    http://www.apache.org/licenses/LICENSE-2.0
31  *
32  * Unless required by applicable law or agreed to in writing, software
33  * distributed under the License is distributed on an "AS IS" BASIS,
34  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35  * See the License for the specific language governing permissions and
36  * limitations under the License.
37  */
38 
39 #include "vktVideoBaseDecodeUtils.hpp"
40 
41 #include "tcuPlatform.hpp"
42 #include "vkDefs.hpp"
43 #include "vkQueryUtil.hpp"
44 #include "vkMemUtil.hpp"
45 #include "vkStrUtil.hpp"
46 #include "deRandom.hpp"
47 
48 #include <iostream>
49 #include <algorithm>
50 #include <numeric>
51 #include <random>
52 
53 namespace vkt
54 {
55 namespace video
56 {
57 using namespace vk;
58 using namespace std;
59 using de::MovePtr;
60 using de::SharedPtr;
61 
62 static const deUint32 topFieldShift		   = 0;
63 static const deUint32 topFieldMask		   = (1 << topFieldShift);
64 static const deUint32 bottomFieldShift	   = 1;
65 static const deUint32 bottomFieldMask	   = (1 << bottomFieldShift);
66 static const deUint32 fieldIsReferenceMask = (topFieldMask | bottomFieldMask);
67 
68 #define HEVC_MAX_DPB_SLOTS 16
69 #define AVC_MAX_DPB_SLOTS 17
70 
GetPic(VkPicIf * pPicBuf)71 inline vkPicBuffBase *GetPic(VkPicIf *pPicBuf)
72 {
73 	return (vkPicBuffBase *) pPicBuf;
74 }
75 
ConvertStdH264ChromaFormatToVulkan(StdVideoH264ChromaFormatIdc stdFormat)76 inline VkVideoChromaSubsamplingFlagBitsKHR ConvertStdH264ChromaFormatToVulkan(StdVideoH264ChromaFormatIdc stdFormat)
77 {
78 	switch (stdFormat)
79 	{
80 		case STD_VIDEO_H264_CHROMA_FORMAT_IDC_420:
81 			return VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR;
82 		case STD_VIDEO_H264_CHROMA_FORMAT_IDC_422:
83 			return VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR;
84 		case STD_VIDEO_H264_CHROMA_FORMAT_IDC_444:
85 			return VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR;
86 		default:
87 			TCU_THROW(InternalError, "Invalid chroma sub-sampling format");
88 	}
89 }
90 
codecGetVkFormat(VkVideoChromaSubsamplingFlagBitsKHR chromaFormatIdc,int bitDepthLuma,bool isSemiPlanar)91 VkFormat codecGetVkFormat(VkVideoChromaSubsamplingFlagBitsKHR chromaFormatIdc,
92 						  int bitDepthLuma,
93 						  bool isSemiPlanar)
94 {
95 	switch (chromaFormatIdc)
96 	{
97 		case VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR:
98 		{
99 			switch (bitDepthLuma)
100 			{
101 				case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
102 					return VK_FORMAT_R8_UNORM;
103 				case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
104 					return VK_FORMAT_R10X6_UNORM_PACK16;
105 				case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
106 					return VK_FORMAT_R12X4_UNORM_PACK16;
107 				default:
108 					TCU_THROW(InternalError, "Cannot map monochrome format to VkFormat");
109 			}
110 		}
111 		case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR:
112 		{
113 			switch (bitDepthLuma)
114 			{
115 				case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
116 					return (isSemiPlanar ? VK_FORMAT_G8_B8R8_2PLANE_420_UNORM : VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM);
117 				case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
118 					return (isSemiPlanar ? VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 : VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16);
119 				case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
120 					return (isSemiPlanar ? VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 : VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16);
121 				default:
122 					TCU_THROW(InternalError, "Cannot map 420 format to VkFormat");
123 			}
124 		}
125 		case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR:
126 		{
127 			switch (bitDepthLuma)
128 			{
129 				case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
130 					return (isSemiPlanar ? VK_FORMAT_G8_B8R8_2PLANE_422_UNORM : VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM);
131 				case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
132 					return (isSemiPlanar ? VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 : VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16);
133 				case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
134 					return (isSemiPlanar ? VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 : VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16);
135 				default:
136 					TCU_THROW(InternalError, "Cannot map 422 format to VkFormat");
137 			}
138 		}
139 		case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR:
140 		{
141 			switch (bitDepthLuma)
142 			{
143 				case VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR:
144 					return (isSemiPlanar ? VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT : VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM);
145 				case VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR:
146 					return (isSemiPlanar ? VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT : VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16);
147 				case VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR:
148 					return (isSemiPlanar ? VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT : VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16);
149 				default:
150 					TCU_THROW(InternalError, "Cannot map 444 format to VkFormat");
151 			}
152 		}
153 		default:
154 			TCU_THROW(InternalError, "Unknown input idc format");
155 	}
156 }
157 
getLumaBitDepth(deUint8 lumaBitDepthMinus8)158 VkVideoComponentBitDepthFlagsKHR getLumaBitDepth(deUint8 lumaBitDepthMinus8)
159 {
160 	switch (lumaBitDepthMinus8)
161 	{
162 		case 0:
163 			return VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
164 		case 2:
165 			return VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
166 		case 4:
167 			return VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
168 		default:
169 			TCU_THROW(InternalError, "Unhandler lumaBitDepthMinus8");
170 	}
171 }
172 
getChromaBitDepth(deUint8 chromaBitDepthMinus8)173 VkVideoComponentBitDepthFlagsKHR getChromaBitDepth(deUint8 chromaBitDepthMinus8)
174 {
175 	switch (chromaBitDepthMinus8)
176 	{
177 		case 0:
178 			return VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
179 		case 2:
180 			return VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
181 		case 4:
182 			return VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
183 		default:
184 			TCU_THROW(InternalError, "Unhandler chromaBitDepthMinus8");
185 	}
186 }
187 
setImageLayout(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,VkImage image,VkImageLayout oldImageLayout,VkImageLayout newImageLayout,VkPipelineStageFlags2KHR srcStages,VkPipelineStageFlags2KHR dstStages,VkImageAspectFlags aspectMask=VK_IMAGE_ASPECT_COLOR_BIT)188 void setImageLayout(const DeviceInterface &vkd,
189 					VkCommandBuffer cmdBuffer,
190 					VkImage image,
191 					VkImageLayout oldImageLayout,
192 					VkImageLayout newImageLayout,
193 					VkPipelineStageFlags2KHR srcStages,
194 					VkPipelineStageFlags2KHR dstStages,
195 					VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT)
196 {
197 	VkAccessFlags2KHR srcAccessMask = 0;
198 	VkAccessFlags2KHR dstAccessMask = 0;
199 
200 	switch (static_cast<VkImageLayout>(oldImageLayout))
201 	{
202 		case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
203 			srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
204 			break;
205 		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
206 			srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
207 			break;
208 		case VK_IMAGE_LAYOUT_PREINITIALIZED:
209 			srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
210 			break;
211 		case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
212 			srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
213 			break;
214 		case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR:
215 			srcAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR;
216 			break;
217 		default:
218 			srcAccessMask = 0;
219 			break;
220 	}
221 
222 	switch (static_cast<VkImageLayout>(newImageLayout))
223 	{
224 		case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
225 			dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
226 			break;
227 		case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
228 			dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
229 			break;
230 		case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
231 			dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
232 			break;
233 		case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
234 			dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
235 			break;
236 		case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
237 			dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
238 			break;
239 		case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR:
240 			dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR;
241 			break;
242 		case VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR:
243 			dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR;
244 			break;
245 		case VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR:
246 			dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR;
247 			break;
248 		case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR:
249 			dstAccessMask = VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR | VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR;
250 			break;
251 		case VK_IMAGE_LAYOUT_GENERAL:
252 			dstAccessMask = VK_ACCESS_HOST_WRITE_BIT;
253 			break;
254 		default:
255 			dstAccessMask = 0;
256 			break;
257 	}
258 
259 	const VkImageMemoryBarrier2KHR imageMemoryBarrier =
260 			{
261 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR,    //  VkStructureType				sType;
262 					DE_NULL,                                        //  const void*					pNext;
263 					srcStages,                                        //  VkPipelineStageFlags2KHR	srcStageMask;
264 					srcAccessMask,                                    //  VkAccessFlags2KHR			srcAccessMask;
265 					dstStages,                                        //  VkPipelineStageFlags2KHR	dstStageMask;
266 					dstAccessMask,                                    //  VkAccessFlags2KHR			dstAccessMask;
267 					oldImageLayout,                                    //  VkImageLayout				oldLayout;
268 					newImageLayout,                                    //  VkImageLayout				newLayout;
269 					VK_QUEUE_FAMILY_IGNORED,                        //  deUint32					srcQueueFamilyIndex;
270 					VK_QUEUE_FAMILY_IGNORED,                        //  deUint32					dstQueueFamilyIndex;
271 					image,                                            //  VkImage						image;
272 					{aspectMask, 0, 1, 0, 1},                        //  VkImageSubresourceRange		subresourceRange;
273 			};
274 
275 	const VkDependencyInfoKHR dependencyInfo =
276 			{
277 					VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,    //  VkStructureType						sType;
278 					DE_NULL,                                //  const void*							pNext;
279 					VK_DEPENDENCY_BY_REGION_BIT,            //  VkDependencyFlags					dependencyFlags;
280 					0,                                        //  deUint32							memoryBarrierCount;
281 					DE_NULL,                                //  const VkMemoryBarrier2KHR*			pMemoryBarriers;
282 					0,                                        //  deUint32							bufferMemoryBarrierCount;
283 					DE_NULL,                                //  const VkBufferMemoryBarrier2KHR*	pBufferMemoryBarriers;
284 					1,                                        //  deUint32							imageMemoryBarrierCount;
285 					&imageMemoryBarrier,                    //  const VkImageMemoryBarrier2KHR*		pImageMemoryBarriers;
286 			};
287 
288 	vkd.cmdPipelineBarrier2(cmdBuffer, &dependencyInfo);
289 }
290 
291 typedef struct dpbH264Entry {
292 	int8_t dpbSlot;
293 	// bit0(used_for_reference)=1: top field used for reference,
294 	// bit1(used_for_reference)=1: bottom field used for reference
295 	deUint32 used_for_reference : 2;
296 	deUint32 is_long_term : 1; // 0 = short-term, 1 = long-term
297 	deUint32 is_non_existing : 1; // 1 = marked as non-existing
298 	deUint32 is_field_ref : 1; // set if unpaired field or complementary field pair
299 	union {
300 		int16_t FieldOrderCnt[2]; // h.264 : 2*32 [top/bottom].
301 		int32_t PicOrderCnt; // HEVC PicOrderCnt
302 	};
303 	union {
304 		int16_t FrameIdx; // : 16   short-term: FrameNum (16 bits), long-term:
305 		// LongTermFrameIdx (4 bits)
306 		int8_t originalDpbIndex; // Original Dpb source Index.
307 	};
308 	vkPicBuffBase* m_picBuff; // internal picture reference
309 
setReferenceAndTopBottomFieldvkt::video::dpbH264Entry310 	void setReferenceAndTopBottomField(
311 			bool isReference, bool nonExisting, bool isLongTerm, bool isFieldRef,
312 			bool topFieldIsReference, bool bottomFieldIsReference, int16_t frameIdx,
313 			const int16_t fieldOrderCntList[2], vkPicBuffBase* picBuff)
314 	{
315 		is_non_existing = nonExisting;
316 		is_long_term = isLongTerm;
317 		is_field_ref = isFieldRef;
318 		if (isReference && isFieldRef) {
319 			used_for_reference = (bottomFieldIsReference << bottomFieldShift) | (topFieldIsReference << topFieldShift);
320 		} else {
321 			used_for_reference = isReference ? 3 : 0;
322 		}
323 
324 		FrameIdx = frameIdx;
325 
326 		FieldOrderCnt[0] = fieldOrderCntList[used_for_reference == 2]; // 0: for progressive and top reference; 1: for
327 		// bottom reference only.
328 		FieldOrderCnt[1] = fieldOrderCntList[used_for_reference != 1]; // 0: for top reference only;  1: for bottom
329 		// reference and progressive.
330 
331 		dpbSlot = -1;
332 		m_picBuff = picBuff;
333 	}
334 
setReferencevkt::video::dpbH264Entry335 	void setReference(bool isLongTerm, int32_t picOrderCnt,
336 					  vkPicBuffBase* picBuff)
337 	{
338 		is_non_existing = (picBuff == NULL);
339 		is_long_term = isLongTerm;
340 		is_field_ref = false;
341 		used_for_reference = (picBuff != NULL) ? 3 : 0;
342 
343 		PicOrderCnt = picOrderCnt;
344 
345 		dpbSlot = -1;
346 		m_picBuff = picBuff;
347 		originalDpbIndex = -1;
348 	}
349 
isRefvkt::video::dpbH264Entry350 	bool isRef() { return (used_for_reference != 0); }
351 
getPictureFlagvkt::video::dpbH264Entry352 	StdVideoDecodeH264ReferenceInfoFlags getPictureFlag(bool currentPictureIsProgressive)
353 	{
354 		StdVideoDecodeH264ReferenceInfoFlags picFlags = StdVideoDecodeH264ReferenceInfoFlags();
355 		if (videoLoggingEnabled())
356 			std::cout << "\t\t Flags: ";
357 
358 		if (used_for_reference) {
359 			if (videoLoggingEnabled())
360 				std::cout << "FRAME_IS_REFERENCE ";
361 			// picFlags.is_reference = true;
362 		}
363 
364 		if (is_long_term) {
365 			if (videoLoggingEnabled())
366 				std::cout << "IS_LONG_TERM ";
367 			picFlags.used_for_long_term_reference = true;
368 		}
369 		if (is_non_existing) {
370 			if (videoLoggingEnabled())
371 				std::cout << "IS_NON_EXISTING ";
372 			picFlags.is_non_existing = true;
373 		}
374 
375 		if (is_field_ref) {
376 			if (videoLoggingEnabled())
377 				std::cout << "IS_FIELD ";
378 			// picFlags.field_pic_flag = true;
379 		}
380 
381 		if (!currentPictureIsProgressive && (used_for_reference & topFieldMask)) {
382 			if (videoLoggingEnabled())
383 				std::cout << "TOP_FIELD_IS_REF ";
384 			picFlags.top_field_flag = true;
385 		}
386 		if (!currentPictureIsProgressive && (used_for_reference & bottomFieldMask)) {
387 			if (videoLoggingEnabled())
388 				std::cout << "BOTTOM_FIELD_IS_REF ";
389 			picFlags.bottom_field_flag = true;
390 		}
391 
392 		return picFlags;
393 	}
394 
setH264PictureDatavkt::video::dpbH264Entry395 	void setH264PictureData(nvVideoDecodeH264DpbSlotInfo* pDpbRefList,
396 							VkVideoReferenceSlotInfoKHR* pReferenceSlots,
397 							deUint32 dpbEntryIdx, deUint32 dpbSlotIndex,
398 							bool currentPictureIsProgressive)
399 	{
400 		DE_ASSERT(dpbEntryIdx < AVC_MAX_DPB_SLOTS);
401 		DE_ASSERT(dpbSlotIndex < AVC_MAX_DPB_SLOTS);
402 
403 		DE_ASSERT((dpbSlotIndex == (deUint32)dpbSlot) || is_non_existing);
404 		pReferenceSlots[dpbEntryIdx].sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR;
405 		pReferenceSlots[dpbEntryIdx].slotIndex = dpbSlotIndex;
406 		pReferenceSlots[dpbEntryIdx].pNext = pDpbRefList[dpbEntryIdx].Init(dpbSlotIndex);
407 
408 		StdVideoDecodeH264ReferenceInfo* pRefPicInfo = &pDpbRefList[dpbEntryIdx].stdReferenceInfo;
409 		pRefPicInfo->FrameNum = FrameIdx;
410 		if (videoLoggingEnabled()) {
411 			std::cout << "\tdpbEntryIdx: " << dpbEntryIdx
412 					  << "dpbSlotIndex: " << dpbSlotIndex
413 					  << " FrameIdx: " << (int32_t)FrameIdx;
414 		}
415 		pRefPicInfo->flags = getPictureFlag(currentPictureIsProgressive);
416 		pRefPicInfo->PicOrderCnt[0] = FieldOrderCnt[0];
417 		pRefPicInfo->PicOrderCnt[1] = FieldOrderCnt[1];
418 		if (videoLoggingEnabled())
419 			std::cout << " fieldOrderCnt[0]: " << pRefPicInfo->PicOrderCnt[0]
420 					  << " fieldOrderCnt[1]: " << pRefPicInfo->PicOrderCnt[1]
421 					  << std::endl;
422 	}
423 
setH265PictureDatavkt::video::dpbH264Entry424 	void setH265PictureData(nvVideoDecodeH265DpbSlotInfo* pDpbSlotInfo,
425 							VkVideoReferenceSlotInfoKHR* pReferenceSlots,
426 							deUint32 dpbEntryIdx, deUint32 dpbSlotIndex)
427 	{
428 		DE_ASSERT(dpbEntryIdx < HEVC_MAX_DPB_SLOTS);
429 		DE_ASSERT(dpbSlotIndex < HEVC_MAX_DPB_SLOTS);
430 		DE_ASSERT(isRef());
431 
432 		DE_ASSERT((dpbSlotIndex == (deUint32)dpbSlot) || is_non_existing);
433 		pReferenceSlots[dpbEntryIdx].sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR;
434 		pReferenceSlots[dpbEntryIdx].slotIndex = dpbSlotIndex;
435 		pReferenceSlots[dpbEntryIdx].pNext = pDpbSlotInfo[dpbEntryIdx].Init(dpbSlotIndex);
436 
437 		StdVideoDecodeH265ReferenceInfo* pRefPicInfo = &pDpbSlotInfo[dpbEntryIdx].stdReferenceInfo;
438 		pRefPicInfo->PicOrderCntVal = PicOrderCnt;
439 		pRefPicInfo->flags.used_for_long_term_reference = is_long_term;
440 
441 		if (videoLoggingEnabled()) {
442 			std::cout << "\tdpbIndex: " << dpbSlotIndex
443 					  << " picOrderCntValList: " << PicOrderCnt;
444 
445 			std::cout << "\t\t Flags: ";
446 			std::cout << "FRAME IS REFERENCE ";
447 			if (pRefPicInfo->flags.used_for_long_term_reference) {
448 				std::cout << "IS LONG TERM ";
449 			}
450 			std::cout << std::endl;
451 		}
452 	}
453 
454 } dpbH264Entry;
455 
GetPicIdx(vkPicBuffBase * pPicBuf)456 int8_t VideoBaseDecoder::GetPicIdx(vkPicBuffBase *pPicBuf)
457 {
458 	if (pPicBuf)
459 	{
460 		int32_t picIndex = pPicBuf->m_picIdx;
461 
462 		if ((picIndex >= 0) && ((deUint32) picIndex < m_maxNumDecodeSurfaces))
463 		{
464 			return (int8_t) picIndex;
465 		}
466 	}
467 
468 	return -1;
469 }
470 
GetPicIdx(VkPicIf * pPicBuf)471 int8_t VideoBaseDecoder::GetPicIdx(VkPicIf *pPicBuf)
472 {
473 	return GetPicIdx(GetPic(pPicBuf));
474 }
475 
GetPicDpbSlot(int8_t picIndex)476 int8_t VideoBaseDecoder::GetPicDpbSlot(int8_t picIndex)
477 {
478 	return m_pictureToDpbSlotMap[picIndex];
479 }
480 
GetFieldPicFlag(int8_t picIndex)481 bool VideoBaseDecoder::GetFieldPicFlag(int8_t picIndex)
482 {
483 	DE_ASSERT((picIndex >= 0) && ((deUint32) picIndex < m_maxNumDecodeSurfaces));
484 
485 	return !!(m_fieldPicFlagMask & (1 << (deUint32) picIndex));
486 }
487 
SetFieldPicFlag(int8_t picIndex,bool fieldPicFlag)488 bool VideoBaseDecoder::SetFieldPicFlag(int8_t picIndex, bool fieldPicFlag)
489 {
490 	DE_ASSERT((picIndex >= 0) && ((deUint32) picIndex < m_maxNumDecodeSurfaces));
491 
492 	bool oldFieldPicFlag = GetFieldPicFlag(picIndex);
493 
494 	if (fieldPicFlag)
495 	{
496 		m_fieldPicFlagMask |= (1 << (deUint32) picIndex);
497 	}
498 	else
499 	{
500 		m_fieldPicFlagMask &= ~(1 << (deUint32) picIndex);
501 	}
502 
503 	return oldFieldPicFlag;
504 }
505 
SetPicDpbSlot(int8_t picIndex,int8_t dpbSlot)506 int8_t VideoBaseDecoder::SetPicDpbSlot(int8_t picIndex, int8_t dpbSlot)
507 {
508 	int8_t oldDpbSlot = m_pictureToDpbSlotMap[picIndex];
509 
510 	m_pictureToDpbSlotMap[picIndex] = dpbSlot;
511 
512 	if (dpbSlot >= 0)
513 	{
514 		m_dpbSlotsMask |= (1 << picIndex);
515 	}
516 	else
517 	{
518 		m_dpbSlotsMask &= ~(1 << picIndex);
519 
520 		if (oldDpbSlot >= 0)
521 		{
522 			m_dpb.FreeSlot(oldDpbSlot);
523 		}
524 	}
525 
526 	return oldDpbSlot;
527 }
528 
ResetPicDpbSlots(deUint32 picIndexSlotValidMask)529 deUint32 VideoBaseDecoder::ResetPicDpbSlots(deUint32 picIndexSlotValidMask)
530 {
531 	deUint32 resetSlotsMask = ~(picIndexSlotValidMask | ~m_dpbSlotsMask);
532 
533 	for (deUint32 picIdx = 0; (picIdx < m_maxNumDecodeSurfaces) && resetSlotsMask; picIdx++)
534 	{
535 		if (resetSlotsMask & (1 << picIdx))
536 		{
537 			resetSlotsMask &= ~(1 << picIdx);
538 
539 			SetPicDpbSlot((int8_t) picIdx, -1);
540 		}
541 	}
542 
543 	return m_dpbSlotsMask;
544 }
545 
VideoBaseDecoder(Parameters && params)546 VideoBaseDecoder::VideoBaseDecoder(Parameters&& params)
547 	: m_deviceContext(params.context)
548 	, m_profile(*params.profile)
549 	, m_framesToCheck(params.framesToCheck)
550 	, m_dpb(3)
551 	, m_videoFrameBuffer(params.framebuffer)
552 	// TODO: interface cleanup
553 	, m_decodeFramesData(params.context->getDeviceDriver(), params.context->device, params.context->decodeQueueFamilyIdx())
554 	, m_resetPictureParametersFrameTriggerHack(params.pictureParameterUpdateTriggerHack)
555 	, m_queryResultWithStatus(params.queryDecodeStatus)
556 	, m_outOfOrderDecoding(params.outOfOrderDecoding)
557 	, m_alwaysRecreateDPB(params.alwaysRecreateDPB)
558 {
559 	std::fill(m_pictureToDpbSlotMap.begin(), m_pictureToDpbSlotMap.end(), -1);
560 
561 	VK_CHECK(util::getVideoDecodeCapabilities(*m_deviceContext, *params.profile, m_videoCaps, m_decodeCaps));
562 
563 	VK_CHECK(util::getSupportedVideoFormats(*m_deviceContext, m_profile, m_decodeCaps.flags,
564 											 m_outImageFormat,
565 											 m_dpbImageFormat));
566 
567 	m_supportedVideoCodecs = util::getSupportedCodecs(*m_deviceContext,
568 													  m_deviceContext->decodeQueueFamilyIdx(),
569 													 VK_QUEUE_VIDEO_DECODE_BIT_KHR,
570 													  VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR | VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
571 	DE_ASSERT(m_supportedVideoCodecs != VK_VIDEO_CODEC_OPERATION_NONE_KHR);
572 }
573 
Deinitialize()574 void VideoBaseDecoder::Deinitialize()
575 {
576 	const DeviceInterface& vkd			 = m_deviceContext->getDeviceDriver();
577 	VkDevice			   device		 = m_deviceContext->device;
578 	VkQueue				   queueDecode	 = m_deviceContext->decodeQueue;
579 	VkQueue				   queueTransfer = m_deviceContext->transferQueue;
580 
581 	if (queueDecode)
582 		vkd.queueWaitIdle(queueDecode);
583 
584 	if (queueTransfer)
585 		vkd.queueWaitIdle(queueTransfer);
586 
587 	vkd.deviceWaitIdle(device);
588 
589 	m_dpb.Deinit();
590 	m_videoFrameBuffer = nullptr;
591 	m_decodeFramesData.deinit();
592 	m_videoSession = nullptr;
593 }
594 
StartVideoSequence(const VkParserDetectedVideoFormat * pVideoFormat)595 int32_t VideoBaseDecoder::StartVideoSequence (const VkParserDetectedVideoFormat* pVideoFormat)
596 {
597 	VkExtent2D codedExtent = { pVideoFormat->coded_width, pVideoFormat->coded_height };
598 
599 	// Width and height of the image surface
600 	VkExtent2D imageExtent = VkExtent2D { std::max((deUint32)(pVideoFormat->display_area.right  - pVideoFormat->display_area.left), pVideoFormat->coded_width),
601 										  std::max((deUint32)(pVideoFormat->display_area.bottom - pVideoFormat->display_area.top),  pVideoFormat->coded_height) };
602 
603 	// REVIEW: There is some inflexibility in the parser regarding this parameter. For the Jellyfish content, it continues wanting to allocate buffers
604 	// well past what is advertises here. The tangential problem with that content is that the second GOP doesn't start with an IDR frame like all the
605 	// other test content. Should look more ino this problem, but for now cheese it by always allocating the total number of frames we might need
606 	// to allocate, even if many of them could be recycled if the parser output pictures earlier (which would be legal but isn't happening for some
607 	// reason)
608 	m_numDecodeSurfaces = std::max(4u, m_framesToCheck); // N.B. pVideoFormat->minNumDecodeSurfaces is NOT advertised correctly!
609 	VkResult result = VK_SUCCESS;
610 
611 	if (videoLoggingEnabled()) {
612 		std::cout << "\t" << std::hex << m_supportedVideoCodecs << " HW codec types are available: " << std::dec << std::endl;
613 	}
614 
615 	VkVideoCodecOperationFlagBitsKHR detectedVideoCodec = pVideoFormat->codec;
616 
617 	VkVideoCoreProfile videoProfile(detectedVideoCodec, pVideoFormat->chromaSubsampling, pVideoFormat->lumaBitDepth, pVideoFormat->chromaBitDepth,
618 									pVideoFormat->codecProfile);
619 	DE_ASSERT(videoProfile == m_profile);
620 
621 	// Check the detected profile is the same as the specified test profile.
622 	DE_ASSERT(m_profile == videoProfile);
623 
624 	DE_ASSERT(((detectedVideoCodec & m_supportedVideoCodecs) != 0) && (detectedVideoCodec == m_profile.GetCodecType()));
625 
626 	if (m_videoFormat.coded_width && m_videoFormat.coded_height) {
627 		// CreateDecoder() has been called before, and now there's possible config change
628 		m_deviceContext->waitDecodeQueue();
629 		m_deviceContext->deviceWaitIdle();
630 	}
631 
632 	deUint32 maxDpbSlotCount = pVideoFormat->maxNumDpbSlots;
633 
634 	if (videoLoggingEnabled())
635 	{
636 		// TODO: Tidy up all the logging stuff copied from NVIDIA...
637 		std::cout << std::dec << "Video Input Information" << std::endl
638 				  << "\tCodec        : " << util::getVideoCodecString(pVideoFormat->codec) << std::endl
639 				  << "\tFrame rate   : " << pVideoFormat->frame_rate.numerator << "/" << pVideoFormat->frame_rate.denominator << " = " << ((pVideoFormat->frame_rate.denominator != 0) ? (1.0 * pVideoFormat->frame_rate.numerator / pVideoFormat->frame_rate.denominator) : 0.0) << " fps" << std::endl
640 				  << "\tSequence     : " << (pVideoFormat->progressive_sequence ? "Progressive" : "Interlaced") << std::endl
641 				  << "\tCoded size   : [" << codedExtent.width << ", " << codedExtent.height << "]" << std::endl
642 				  << "\tDisplay area : [" << pVideoFormat->display_area.left << ", " << pVideoFormat->display_area.top << ", " << pVideoFormat->display_area.right << ", " << pVideoFormat->display_area.bottom << "]" << std::endl
643 				  << "\tChroma       : " << util::getVideoChromaFormatString(pVideoFormat->chromaSubsampling) << std::endl
644 				  << "\tBit depth    : " << pVideoFormat->bit_depth_luma_minus8 + 8 << std::endl
645 				  << "\tCodec        : " << VkVideoCoreProfile::CodecToName(detectedVideoCodec) << std::endl
646 				  << "\t#Decode surf : " << m_numDecodeSurfaces << std::endl
647 				  << "\tCoded extent : " << codedExtent.width << " x " << codedExtent.height << std::endl
648 				  << "\tMax DPB slots : " << maxDpbSlotCount << std::endl;
649 	}
650 
651 	DE_ASSERT(VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR == pVideoFormat->chromaSubsampling ||
652 		   VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR == pVideoFormat->chromaSubsampling ||
653 		   VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR == pVideoFormat->chromaSubsampling ||
654 		   VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR == pVideoFormat->chromaSubsampling);
655 	DE_ASSERT(pVideoFormat->chromaSubsampling == m_profile.GetColorSubsampling());
656 
657 	imageExtent.width  = std::max(imageExtent.width, m_videoCaps.minCodedExtent.width);
658 	imageExtent.height = std::max(imageExtent.height, m_videoCaps.minCodedExtent.height);
659 
660 	imageExtent.width = deAlign32(imageExtent.width,  m_videoCaps.pictureAccessGranularity.width);
661 	imageExtent.height = deAlign32(imageExtent.height,  m_videoCaps.pictureAccessGranularity.height);
662 
663 	if (!m_videoSession ||
664 		!m_videoSession->IsCompatible(m_deviceContext->device,
665 									  m_deviceContext->decodeQueueFamilyIdx(),
666 									  &videoProfile,
667 									  m_outImageFormat,
668 									  imageExtent,
669 									  m_dpbImageFormat,
670 									  maxDpbSlotCount,
671 									  maxDpbSlotCount) ||
672 		m_alwaysRecreateDPB)
673 	{
674 
675 		VK_CHECK(VulkanVideoSession::Create(*m_deviceContext,
676 											m_deviceContext->decodeQueueFamilyIdx(),
677 											&videoProfile,
678 											m_outImageFormat,
679 											imageExtent,
680 											m_dpbImageFormat,
681 											maxDpbSlotCount,
682 											std::min<deUint32>(maxDpbSlotCount, m_videoCaps.maxActiveReferencePictures),
683 											m_videoSession));
684 
685 		// after creating a new video session, we need codec reset.
686 		m_resetDecoder = true;
687 		DE_ASSERT(result == VK_SUCCESS);
688 	}
689 
690 	if (m_currentPictureParameters)
691 	{
692 		m_currentPictureParameters->FlushPictureParametersQueue(m_videoSession);
693 	}
694 
695 	VkImageUsageFlags outImageUsage = (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
696 									   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
697 									   VK_IMAGE_USAGE_TRANSFER_DST_BIT);
698 	VkImageUsageFlags dpbImageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
699 
700 	if (dpbAndOutputCoincide()) {
701 		dpbImageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
702 	} else {
703 		// The implementation does not support dpbAndOutputCoincide
704 		m_useSeparateOutputImages = true;
705 	}
706 
707 	if(!(m_videoCaps.flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
708 		// The implementation does not support individual images for DPB and so must use arrays
709 		m_useImageArray = true;
710 		m_useImageViewArray = true;
711 	}
712 
713 	bool useLinearOutput = false;
714 	int32_t ret = m_videoFrameBuffer->InitImagePool(videoProfile.GetProfile(),
715 													m_numDecodeSurfaces,
716 													m_dpbImageFormat,
717 													m_outImageFormat,
718 													codedExtent,
719 													imageExtent,
720 													dpbImageUsage,
721 													outImageUsage,
722 													m_deviceContext->decodeQueueFamilyIdx(),
723 													m_useImageArray, m_useImageViewArray,
724 													m_useSeparateOutputImages, useLinearOutput);
725 
726 	DE_ASSERT((deUint32)ret >= m_numDecodeSurfaces);
727 	if ((deUint32)ret != m_numDecodeSurfaces) {
728 		fprintf(stderr, "\nERROR: InitImagePool() ret(%d) != m_numDecodeSurfaces(%d)\n", ret, m_numDecodeSurfaces);
729 	}
730 
731 	if (videoLoggingEnabled()) {
732 		std::cout << "Allocating Video Device Memory" << std::endl
733 				  << "Allocating " << m_numDecodeSurfaces << " Num Decode Surfaces and "
734 				  << maxDpbSlotCount << " Video Device Memory Images for DPB " << std::endl
735 				  << imageExtent.width << " x " << imageExtent.height << std::endl;
736 	}
737 
738 	// There will be no more than 32 frames in the queue.
739 	m_decodeFramesData.resize(m_numDecodeSurfaces);
740 
741 	int32_t availableBuffers = (int32_t)m_decodeFramesData.GetBitstreamBuffersQueue().GetAvailableNodesNumber();
742 	if (availableBuffers < m_numBitstreamBuffersToPreallocate) {
743 		deUint32 allocateNumBuffers = std::min<deUint32>(
744 				m_decodeFramesData.GetBitstreamBuffersQueue().GetMaxNodes(),
745 				(m_numBitstreamBuffersToPreallocate - availableBuffers));
746 
747 		allocateNumBuffers = std::min<deUint32>(allocateNumBuffers,
748 												m_decodeFramesData.GetBitstreamBuffersQueue().GetFreeNodesNumber());
749 
750 		for (deUint32 i = 0; i < 1; i++) {
751 
752 			VkSharedBaseObj<BitstreamBufferImpl> bitstreamBuffer;
753 			VkDeviceSize allocSize = 2 * 1024 * 1024;
754 
755 			result = BitstreamBufferImpl::Create(m_deviceContext,
756 													   m_deviceContext->decodeQueueFamilyIdx(),
757 													   allocSize,
758 													   m_videoCaps.minBitstreamBufferOffsetAlignment,
759 													   m_videoCaps.minBitstreamBufferSizeAlignment,
760 													   bitstreamBuffer,
761 													   m_profile.GetProfileListInfo());
762 			DE_ASSERT(result == VK_SUCCESS);
763 			if (result != VK_SUCCESS) {
764 				fprintf(stderr, "\nERROR: CreateVideoBitstreamBuffer() result: 0x%x\n", result);
765 				break;
766 			}
767 
768 			int32_t nodeAddedWithIndex = m_decodeFramesData.GetBitstreamBuffersQueue().
769 					AddNodeToPool(bitstreamBuffer, false);
770 			if (nodeAddedWithIndex < 0) {
771 				DE_ASSERT("Could not add the new node to the pool");
772 				break;
773 			}
774 		}
775 	}
776 
777 	// Save the original config
778 	m_videoFormat = *pVideoFormat;
779 	return m_numDecodeSurfaces;
780 }
781 
BeginSequence(const VkParserSequenceInfo * pnvsi)782 int32_t VideoBaseDecoder::BeginSequence (const VkParserSequenceInfo* pnvsi)
783 {
784 	bool sequenceUpdate = m_nvsi.nMaxWidth != 0 && m_nvsi.nMaxHeight != 0;
785 
786 	const deUint32 maxDpbSlots =  (pnvsi->eCodec == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) ? VkParserPerFrameDecodeParameters::MAX_DPB_REF_AND_SETUP_SLOTS : VkParserPerFrameDecodeParameters::MAX_DPB_REF_SLOTS;
787 	deUint32 configDpbSlots = (pnvsi->nMinNumDpbSlots > 0) ? pnvsi->nMinNumDpbSlots : maxDpbSlots;
788 	configDpbSlots = std::min<deUint32>(configDpbSlots, maxDpbSlots);
789 
790 	bool sequenceReconfigureFormat = false;
791 	bool sequenceReconfigureCodedExtent = false;
792 	if (sequenceUpdate) {
793 		if ((pnvsi->eCodec != m_nvsi.eCodec) ||
794 			(pnvsi->nChromaFormat != m_nvsi.nChromaFormat) || (pnvsi->uBitDepthLumaMinus8 != m_nvsi.uBitDepthLumaMinus8) ||
795 			(pnvsi->uBitDepthChromaMinus8 != m_nvsi.uBitDepthChromaMinus8) ||
796 			(pnvsi->bProgSeq != m_nvsi.bProgSeq)) {
797 			sequenceReconfigureFormat = true;
798 		}
799 
800 		if ((pnvsi->nCodedWidth != m_nvsi.nCodedWidth) || (pnvsi->nCodedHeight != m_nvsi.nCodedHeight)) {
801 			sequenceReconfigureCodedExtent = true;
802 		}
803 
804 	}
805 
806 	m_nvsi = *pnvsi;
807 	m_nvsi.nMaxWidth = pnvsi->nCodedWidth;
808 	m_nvsi.nMaxHeight = pnvsi->nCodedHeight;
809 
810 	m_maxNumDecodeSurfaces = pnvsi->nMinNumDecodeSurfaces;
811 
812 		VkParserDetectedVideoFormat detectedFormat;
813 		deUint8 raw_seqhdr_data[1024]; /* Output the sequence header data, currently
814                                       not used */
815 
816 		memset(&detectedFormat, 0, sizeof(detectedFormat));
817 
818 		detectedFormat.sequenceUpdate = sequenceUpdate;
819 		detectedFormat.sequenceReconfigureFormat = sequenceReconfigureFormat;
820 		detectedFormat.sequenceReconfigureCodedExtent = sequenceReconfigureCodedExtent;
821 
822 		detectedFormat.codec = pnvsi->eCodec;
823 		detectedFormat.frame_rate.numerator = NV_FRAME_RATE_NUM(pnvsi->frameRate);
824 		detectedFormat.frame_rate.denominator = NV_FRAME_RATE_DEN(pnvsi->frameRate);
825 		detectedFormat.progressive_sequence = pnvsi->bProgSeq;
826 		detectedFormat.coded_width = pnvsi->nCodedWidth;
827 		detectedFormat.coded_height = pnvsi->nCodedHeight;
828 		detectedFormat.display_area.right = pnvsi->nDisplayWidth;
829 		detectedFormat.display_area.bottom = pnvsi->nDisplayHeight;
830 
831 		if ((StdChromaFormatIdc)pnvsi->nChromaFormat == chroma_format_idc_420) {
832 			detectedFormat.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR;
833 		} else if ((StdChromaFormatIdc)pnvsi->nChromaFormat == chroma_format_idc_422) {
834 			detectedFormat.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR;
835 		} else if ((StdChromaFormatIdc)pnvsi->nChromaFormat == chroma_format_idc_444) {
836 			detectedFormat.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR;
837 		} else {
838 			DE_ASSERT(!"Invalid chroma sub-sampling format");
839 		}
840 
841 		switch (pnvsi->uBitDepthLumaMinus8) {
842 			case 0:
843 				detectedFormat.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
844 				break;
845 			case 2:
846 				detectedFormat.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
847 				break;
848 			case 4:
849 				detectedFormat.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
850 				break;
851 			default:
852 				DE_ASSERT(false);
853 		}
854 
855 		switch (pnvsi->uBitDepthChromaMinus8) {
856 			case 0:
857 				detectedFormat.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
858 				break;
859 			case 2:
860 				detectedFormat.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
861 				break;
862 			case 4:
863 				detectedFormat.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
864 				break;
865 			default:
866 				DE_ASSERT(false);
867 		}
868 
869 		detectedFormat.bit_depth_luma_minus8 = pnvsi->uBitDepthLumaMinus8;
870 		detectedFormat.bit_depth_chroma_minus8 = pnvsi->uBitDepthChromaMinus8;
871 		detectedFormat.bitrate = pnvsi->lBitrate;
872 		detectedFormat.display_aspect_ratio.x = pnvsi->lDARWidth;
873 		detectedFormat.display_aspect_ratio.y = pnvsi->lDARHeight;
874 		detectedFormat.video_signal_description.video_format = pnvsi->lVideoFormat;
875 		detectedFormat.video_signal_description.video_full_range_flag = pnvsi->uVideoFullRange;
876 		detectedFormat.video_signal_description.color_primaries = pnvsi->lColorPrimaries;
877 		detectedFormat.video_signal_description.transfer_characteristics = pnvsi->lTransferCharacteristics;
878 		detectedFormat.video_signal_description.matrix_coefficients = pnvsi->lMatrixCoefficients;
879 		detectedFormat.seqhdr_data_length = (deUint32)std::min((size_t)pnvsi->cbSequenceHeader, sizeof(raw_seqhdr_data));
880 		detectedFormat.minNumDecodeSurfaces = pnvsi->nMinNumDecodeSurfaces;
881 		detectedFormat.maxNumDpbSlots = configDpbSlots;
882 		detectedFormat.codecProfile = pnvsi->codecProfile;
883 
884 		if (detectedFormat.seqhdr_data_length > 0) {
885 			memcpy(raw_seqhdr_data, pnvsi->SequenceHeaderData,
886 				   detectedFormat.seqhdr_data_length);
887 		}
888 		int32_t maxDecodeRTs = StartVideoSequence(&detectedFormat);
889 		// nDecodeRTs <= 0 means SequenceCallback failed
890 		// nDecodeRTs  = 1 means SequenceCallback succeeded
891 		// nDecodeRTs  > 1 means we need to overwrite the MaxNumDecodeSurfaces
892 		if (maxDecodeRTs <= 0) {
893 			return 0;
894 		}
895 		// MaxNumDecodeSurface may not be correctly calculated by the client while
896 		// parser creation so overwrite it with NumDecodeSurface. (only if nDecodeRT
897 		// > 1)
898 		if (maxDecodeRTs > 1) {
899 			m_maxNumDecodeSurfaces = maxDecodeRTs;
900 		}
901 
902 	// Always deinit the DPB between sequences. The optimization path does not work for resolution change cases.
903 	m_maxNumDpbSlots = m_dpb.Init(configDpbSlots, false /* reconfigure the DPB size if true */);
904 	// Ensure the picture map is empited, so that DPB slot management doesn't get confused in-between sequences.
905 	m_pictureToDpbSlotMap.fill(-1);
906 
907 	return m_maxNumDecodeSurfaces;
908 }
909 
AllocPictureBuffer(VkPicIf ** ppNvidiaVulkanPicture)910 bool VideoBaseDecoder::AllocPictureBuffer (VkPicIf** ppNvidiaVulkanPicture)
911 {
912 	DEBUGLOG(std::cout << "VideoBaseDecoder::AllocPictureBuffer" << std::endl);
913 	bool result = false;
914 
915 	*ppNvidiaVulkanPicture = m_videoFrameBuffer->ReservePictureBuffer();
916 
917 	if (*ppNvidiaVulkanPicture)
918 	{
919 		result = true;
920 
921 		DEBUGLOG(std::cout << "\tVideoBaseDecoder::AllocPictureBuffer " << (void*)*ppNvidiaVulkanPicture << std::endl);
922 	}
923 
924 	if (!result)
925 	{
926 		*ppNvidiaVulkanPicture = (VkPicIf*)nullptr;
927 	}
928 
929 	return result;
930 }
931 
DecodePicture(VkParserPictureData * pd)932 bool VideoBaseDecoder::DecodePicture (VkParserPictureData* pd)
933 {
934 	DEBUGLOG(std::cout << "VideoBaseDecoder::DecodePicture" << std::endl);
935 	bool							result				= false;
936 
937 	if (!pd->pCurrPic)
938 	{
939 		return result;
940 	}
941 
942 	vkPicBuffBase*	pVkPicBuff	= GetPic(pd->pCurrPic);
943 	const int32_t				picIdx		= pVkPicBuff ? pVkPicBuff->m_picIdx : -1;
944 	if (videoLoggingEnabled())
945 		std::cout
946             << "\t ==> VulkanVideoParser::DecodePicture " << picIdx << std::endl
947             << "\t\t progressive: " << (bool)pd->progressive_frame
948             << // Frame is progressive
949             "\t\t field: " << (bool)pd->field_pic_flag << std::endl
950             << // 0 = frame picture, 1 = field picture
951             "\t\t\t bottom_field: " << (bool)pd->bottom_field_flag
952             << // 0 = top field, 1 = bottom field (ignored if field_pic_flag=0)
953             "\t\t\t second_field: " << (bool)pd->second_field
954             << // Second field of a complementary field pair
955             "\t\t\t top_field: " << (bool)pd->top_field_first << std::endl
956             << // Frame pictures only
957             "\t\t repeat_first: " << pd->repeat_first_field
958             << // For 3:2 pulldown (number of additional fields, 2 = frame
959             // doubling, 4 = frame tripling)
960             "\t\t ref_pic: " << (bool)pd->ref_pic_flag
961             << std::endl; // Frame is a reference frame
962 
963 	DE_ASSERT(picIdx < MAX_FRM_CNT);
964 
965 	VkParserDecodePictureInfo	decodePictureInfo	= VkParserDecodePictureInfo();
966 	decodePictureInfo.pictureIndex				= picIdx;
967 	decodePictureInfo.flags.progressiveFrame	= pd->progressive_frame;
968 	decodePictureInfo.flags.fieldPic			= pd->field_pic_flag;			// 0 = frame picture, 1 = field picture
969 	decodePictureInfo.flags.repeatFirstField	= pd->repeat_first_field;	// For 3:2 pulldown (number of additional fields, 2 = frame doubling, 4 = frame tripling)
970 	decodePictureInfo.flags.refPic				= pd->ref_pic_flag;				// Frame is a reference frame
971 
972 	// Mark the first field as unpaired Detect unpaired fields
973 	if (pd->field_pic_flag)
974 	{
975 		decodePictureInfo.flags.bottomField		= pd->bottom_field_flag;	// 0 = top field, 1 = bottom field (ignored if field_pic_flag=0)
976 		decodePictureInfo.flags.secondField		= pd->second_field;			// Second field of a complementary field pair
977 		decodePictureInfo.flags.topFieldFirst	= pd->top_field_first;		// Frame pictures only
978 
979 		if (!pd->second_field)
980 		{
981 			decodePictureInfo.flags.unpairedField = true; // Incomplete (half) frame.
982 		}
983 		else
984 		{
985 			if (decodePictureInfo.flags.unpairedField)
986 			{
987 				decodePictureInfo.flags.syncToFirstField = true;
988 				decodePictureInfo.flags.unpairedField = false;
989 			}
990 		}
991 	}
992 
993 	decodePictureInfo.frameSyncinfo.unpairedField		= decodePictureInfo.flags.unpairedField;
994 	decodePictureInfo.frameSyncinfo.syncToFirstField	= decodePictureInfo.flags.syncToFirstField;
995 
996 	return DecodePicture(pd, pVkPicBuff, &decodePictureInfo);
997 }
998 
999 
DecodePicture(VkParserPictureData * pd,vkPicBuffBase *,VkParserDecodePictureInfo * pDecodePictureInfo)1000 bool VideoBaseDecoder::DecodePicture (VkParserPictureData* pd,
1001 									  vkPicBuffBase* /*pVkPicBuff*/,
1002 									  VkParserDecodePictureInfo* pDecodePictureInfo)
1003 {
1004 	DEBUGLOG(std::cout << "\tDecodePicture sps_sid:" << (deUint32)pNvidiaVulkanParserPictureData->CodecSpecific.h264.pStdSps->seq_parameter_set_id << " pps_sid:" << (deUint32)pNvidiaVulkanParserPictureData->CodecSpecific.h264.pStdPps->seq_parameter_set_id << " pps_pid:" << (deUint32)pNvidiaVulkanParserPictureData->CodecSpecific.h264.pStdPps->pic_parameter_set_id << std::endl);
1005 
1006 	if (!pd->pCurrPic)
1007 	{
1008 		return false;
1009 	}
1010 	const deUint32 PicIdx = GetPicIdx(pd->pCurrPic);
1011 	TCU_CHECK (PicIdx < MAX_FRM_CNT);
1012 
1013 	m_cachedDecodeParams.emplace_back(new CachedDecodeParameters);
1014 	auto& cachedParameters = m_cachedDecodeParams.back();
1015 	bool bRet = false;
1016 
1017 	if (m_resetDecoder)
1018 	{
1019 		cachedParameters->performCodecReset = true;
1020 		m_resetDecoder = false;
1021 	}
1022 	else
1023 	{
1024 		cachedParameters->performCodecReset = false;
1025 	}
1026 
1027 	// Copy the picture data over, taking care to memcpy the heap resources that might get freed on the parser side (we have no guarantees about those pointers)
1028 	cachedParameters->pd = *pd;
1029 	if (pd->sideDataLen > 0)
1030 	{
1031 		cachedParameters->pd.pSideData = new deUint8[pd->sideDataLen];
1032 		deMemcpy(cachedParameters->pd.pSideData, pd->pSideData, pd->sideDataLen);
1033 	}
1034 	// And again for the decoded picture information, these are all POD types for now.
1035 	cachedParameters->decodedPictureInfo = *pDecodePictureInfo;
1036 	pDecodePictureInfo = &cachedParameters->decodedPictureInfo;
1037 
1038 	// Now build up the frame's decode parameters and store it in the cache
1039 	cachedParameters->pictureParams = VkParserPerFrameDecodeParameters();
1040 	VkParserPerFrameDecodeParameters* pCurrFrameDecParams = &cachedParameters->pictureParams;
1041 	pCurrFrameDecParams->currPicIdx = PicIdx;
1042 	pCurrFrameDecParams->numSlices = pd->numSlices;
1043 	pCurrFrameDecParams->firstSliceIndex = pd->firstSliceIndex;
1044 	pCurrFrameDecParams->bitstreamDataOffset = pd->bitstreamDataOffset;
1045 	pCurrFrameDecParams->bitstreamDataLen = pd->bitstreamDataLen;
1046 	pCurrFrameDecParams->bitstreamData = pd->bitstreamData;
1047 
1048 	auto& referenceSlots = cachedParameters->referenceSlots;
1049 	auto& setupReferenceSlot = cachedParameters->setupReferenceSlot;
1050 	setupReferenceSlot.sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR;
1051 	setupReferenceSlot.pPictureResource = nullptr;
1052 	setupReferenceSlot.slotIndex = -1;
1053 
1054 	pCurrFrameDecParams->decodeFrameInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR;
1055 	pCurrFrameDecParams->decodeFrameInfo.dstPictureResource.sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR;
1056 	pCurrFrameDecParams->dpbSetupPictureResource.sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR;
1057 
1058 	if (m_profile.GetCodecType() == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR)
1059 	{
1060 		const VkParserH264PictureData* const pin = &pd->CodecSpecific.h264;
1061 		cachedParameters->h264PicParams = nvVideoH264PicParameters();
1062 		VkVideoDecodeH264PictureInfoKHR* h264PictureInfo = &cachedParameters->h264PicParams.pictureInfo;
1063 		nvVideoDecodeH264DpbSlotInfo* h264DpbReferenceList = cachedParameters->h264PicParams.dpbRefList;
1064 		StdVideoDecodeH264PictureInfo* h264StandardPictureInfo = &cachedParameters->h264PicParams.stdPictureInfo;
1065 
1066 		pCurrFrameDecParams->pStdPps = pin->pStdPps;
1067 		pCurrFrameDecParams->pStdSps = pin->pStdSps;
1068 		pCurrFrameDecParams->pStdVps = nullptr;
1069 
1070 		cachedParameters->decodedPictureInfo.videoFrameType = 0; // pd->CodecSpecific.h264.slice_type;
1071 		// FIXME: If mvcext is enabled.
1072 		cachedParameters->decodedPictureInfo.viewId = pd->CodecSpecific.h264.mvcext.view_id;
1073 
1074 		h264PictureInfo->pStdPictureInfo = &cachedParameters->h264PicParams.stdPictureInfo;
1075 		h264PictureInfo->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_KHR;
1076 		h264PictureInfo->pNext = nullptr;
1077 		pCurrFrameDecParams->decodeFrameInfo.pNext = h264PictureInfo;
1078 
1079 		h264StandardPictureInfo->pic_parameter_set_id = pin->pic_parameter_set_id; // PPS ID
1080 		h264StandardPictureInfo->seq_parameter_set_id = pin->seq_parameter_set_id; // SPS ID;
1081 		h264StandardPictureInfo->frame_num = (deUint16)pin->frame_num;
1082 		h264PictureInfo->sliceCount = pd->numSlices;
1083 
1084 		deUint32 maxSliceCount = 0;
1085 		DE_ASSERT(pd->firstSliceIndex == 0); // No slice and MV modes are supported yet
1086 		h264PictureInfo->pSliceOffsets = pd->bitstreamData->GetStreamMarkersPtr(pd->firstSliceIndex, maxSliceCount);
1087 		DE_ASSERT(maxSliceCount == pd->numSlices);
1088 
1089 		StdVideoDecodeH264PictureInfoFlags currPicFlags = StdVideoDecodeH264PictureInfoFlags();
1090 		currPicFlags.is_intra = (pd->intra_pic_flag != 0);
1091 		// 0 = frame picture, 1 = field picture
1092 		if (pd->field_pic_flag) {
1093 			// 0 = top field, 1 = bottom field (ignored if field_pic_flag = 0)
1094 			currPicFlags.field_pic_flag = true;
1095 			if (pd->bottom_field_flag) {
1096 				currPicFlags.bottom_field_flag = true;
1097 			}
1098 		}
1099 		// Second field of a complementary field pair
1100 		if (pd->second_field) {
1101 			currPicFlags.complementary_field_pair = true;
1102 		}
1103 		// Frame is a reference frame
1104 		if (pd->ref_pic_flag) {
1105 			currPicFlags.is_reference = true;
1106 		}
1107 		h264StandardPictureInfo->flags = currPicFlags;
1108 		if (!pd->field_pic_flag) {
1109 			h264StandardPictureInfo->PicOrderCnt[0] = pin->CurrFieldOrderCnt[0];
1110 			h264StandardPictureInfo->PicOrderCnt[1] = pin->CurrFieldOrderCnt[1];
1111 		} else {
1112 			h264StandardPictureInfo->PicOrderCnt[pd->bottom_field_flag] = pin->CurrFieldOrderCnt[pd->bottom_field_flag];
1113 		}
1114 
1115 		const deUint32 maxDpbInputSlots = sizeof(pin->dpb) / sizeof(pin->dpb[0]);
1116 		pCurrFrameDecParams->numGopReferenceSlots = FillDpbH264State(
1117 				pd, pin->dpb, maxDpbInputSlots, h264DpbReferenceList,
1118 				VkParserPerFrameDecodeParameters::MAX_DPB_REF_SLOTS, // 16 reference pictures
1119 				referenceSlots, pCurrFrameDecParams->pGopReferenceImagesIndexes,
1120 				h264StandardPictureInfo->flags, &setupReferenceSlot.slotIndex);
1121 
1122 		DE_ASSERT(!pd->ref_pic_flag || (setupReferenceSlot.slotIndex >= 0));
1123 
1124 		// TODO: Dummy struct to silence validation. The root problem is that the dpb map doesn't take account of the setup slot,
1125 		// for some reason... So we can't use the existing logic to setup the picture flags and frame number from the dpbEntry
1126 		// class.
1127 		cachedParameters->h264SlotInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR;
1128 		cachedParameters->h264SlotInfo.pNext = nullptr;
1129 		cachedParameters->h264SlotInfo.pStdReferenceInfo = &cachedParameters->h264RefInfo;
1130 
1131 		if (setupReferenceSlot.slotIndex >= 0) {
1132 			setupReferenceSlot.pPictureResource = &pCurrFrameDecParams->dpbSetupPictureResource;
1133 			setupReferenceSlot.pNext = &cachedParameters->h264SlotInfo;
1134 			pCurrFrameDecParams->decodeFrameInfo.pSetupReferenceSlot = &setupReferenceSlot;
1135 		}
1136 		if (pCurrFrameDecParams->numGopReferenceSlots) {
1137 			DE_ASSERT(pCurrFrameDecParams->numGopReferenceSlots <= (int32_t)VkParserPerFrameDecodeParameters::MAX_DPB_REF_SLOTS);
1138 			for (deUint32 dpbEntryIdx = 0; dpbEntryIdx < (deUint32)pCurrFrameDecParams->numGopReferenceSlots;
1139 				 dpbEntryIdx++) {
1140 				pCurrFrameDecParams->pictureResources[dpbEntryIdx].sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR;
1141 				referenceSlots[dpbEntryIdx].pPictureResource = &pCurrFrameDecParams->pictureResources[dpbEntryIdx];
1142 				DE_ASSERT(h264DpbReferenceList[dpbEntryIdx].IsReference());
1143 			}
1144 
1145 			pCurrFrameDecParams->decodeFrameInfo.pReferenceSlots = referenceSlots;
1146 			pCurrFrameDecParams->decodeFrameInfo.referenceSlotCount = pCurrFrameDecParams->numGopReferenceSlots;
1147 		} else {
1148 			pCurrFrameDecParams->decodeFrameInfo.pReferenceSlots = NULL;
1149 			pCurrFrameDecParams->decodeFrameInfo.referenceSlotCount = 0;
1150 		}
1151 	}
1152 	else if (m_profile.GetCodecType() == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR)
1153 	{
1154 		const VkParserHevcPictureData* const pin = &pd->CodecSpecific.hevc;
1155 		cachedParameters->h265PicParams = nvVideoH265PicParameters();
1156 		VkVideoDecodeH265PictureInfoKHR* pPictureInfo = &cachedParameters->h265PicParams.pictureInfo;
1157 		StdVideoDecodeH265PictureInfo* pStdPictureInfo = &cachedParameters->h265PicParams.stdPictureInfo;
1158 		nvVideoDecodeH265DpbSlotInfo* pDpbRefList = cachedParameters->h265PicParams.dpbRefList;
1159 
1160 		pCurrFrameDecParams->pStdPps = pin->pStdPps;
1161 		pCurrFrameDecParams->pStdSps = pin->pStdSps;
1162 		pCurrFrameDecParams->pStdVps = pin->pStdVps;
1163 		if (videoLoggingEnabled()) {
1164 			std::cout << "\n\tCurrent h.265 Picture VPS update : "
1165 					  << pin->pStdVps->GetUpdateSequenceCount() << std::endl;
1166 			std::cout << "\n\tCurrent h.265 Picture SPS update : "
1167 					  << pin->pStdSps->GetUpdateSequenceCount() << std::endl;
1168 			std::cout << "\tCurrent h.265 Picture PPS update : "
1169 					  << pin->pStdPps->GetUpdateSequenceCount() << std::endl;
1170 		}
1171 
1172 		pPictureInfo->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_KHR;
1173 		pPictureInfo->pNext = nullptr;
1174 
1175 		pPictureInfo->pStdPictureInfo = &cachedParameters->h265PicParams.stdPictureInfo;
1176 		pCurrFrameDecParams->decodeFrameInfo.pNext = &cachedParameters->h265PicParams.pictureInfo;
1177 
1178 		pDecodePictureInfo->videoFrameType = 0; // pd->CodecSpecific.hevc.SliceType;
1179 		if (pd->CodecSpecific.hevc.mv_hevc_enable) {
1180 			pDecodePictureInfo->viewId = pd->CodecSpecific.hevc.nuh_layer_id;
1181 		} else {
1182 			pDecodePictureInfo->viewId = 0;
1183 		}
1184 
1185 		pPictureInfo->sliceSegmentCount = pd->numSlices;
1186 		deUint32 maxSliceCount = 0;
1187 		DE_ASSERT(pd->firstSliceIndex == 0); // No slice and MV modes are supported yet
1188 		pPictureInfo->pSliceSegmentOffsets = pd->bitstreamData->GetStreamMarkersPtr(pd->firstSliceIndex, maxSliceCount);
1189 		DE_ASSERT(maxSliceCount == pd->numSlices);
1190 
1191 		pStdPictureInfo->pps_pic_parameter_set_id   = pin->pic_parameter_set_id;       // PPS ID
1192 		pStdPictureInfo->pps_seq_parameter_set_id   = pin->seq_parameter_set_id;       // SPS ID
1193 		pStdPictureInfo->sps_video_parameter_set_id = pin->vps_video_parameter_set_id; // VPS ID
1194 
1195 		// hevc->irapPicFlag = m_slh.nal_unit_type >= NUT_BLA_W_LP &&
1196 		// m_slh.nal_unit_type <= NUT_CRA_NUT;
1197 		pStdPictureInfo->flags.IrapPicFlag = pin->IrapPicFlag; // Intra Random Access Point for current picture.
1198 		// hevc->idrPicFlag = m_slh.nal_unit_type == NUT_IDR_W_RADL ||
1199 		// m_slh.nal_unit_type == NUT_IDR_N_LP;
1200 		pStdPictureInfo->flags.IdrPicFlag = pin->IdrPicFlag; // Instantaneous Decoding Refresh for current picture.
1201 
1202 		// NumBitsForShortTermRPSInSlice = s->sh.short_term_rps ?
1203 		// s->sh.short_term_ref_pic_set_size : 0
1204 		pStdPictureInfo->NumBitsForSTRefPicSetInSlice = pin->NumBitsForShortTermRPSInSlice;
1205 
1206 		// NumDeltaPocsOfRefRpsIdx = s->sh.short_term_rps ?
1207 		// s->sh.short_term_rps->rps_idx_num_delta_pocs : 0
1208 		pStdPictureInfo->NumDeltaPocsOfRefRpsIdx = pin->NumDeltaPocsOfRefRpsIdx;
1209 		pStdPictureInfo->PicOrderCntVal = pin->CurrPicOrderCntVal;
1210 
1211 		if (videoLoggingEnabled())
1212 			std::cout << "\tnumPocStCurrBefore: " << (int32_t)pin->NumPocStCurrBefore
1213 					  << " numPocStCurrAfter: " << (int32_t)pin->NumPocStCurrAfter
1214 					  << " numPocLtCurr: " << (int32_t)pin->NumPocLtCurr << std::endl;
1215 
1216 		pCurrFrameDecParams->numGopReferenceSlots = FillDpbH265State(pd, pin, pDpbRefList, pStdPictureInfo,
1217 																	 VkParserPerFrameDecodeParameters::MAX_DPB_REF_SLOTS, // max 16 reference pictures
1218 																	 referenceSlots, pCurrFrameDecParams->pGopReferenceImagesIndexes,
1219 																	 &setupReferenceSlot.slotIndex);
1220 
1221 		DE_ASSERT(!pd->ref_pic_flag || (setupReferenceSlot.slotIndex >= 0));
1222 		// TODO: Dummy struct to silence validation. The root problem is that the dpb map doesn't take account of the setup slot,
1223 		// for some reason... So we can't use the existing logic to setup the picture flags and frame number from the dpbEntry
1224 		// class.
1225 		cachedParameters->h265SlotInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_KHR;
1226 		cachedParameters->h265SlotInfo.pNext = nullptr;
1227 		cachedParameters->h265SlotInfo.pStdReferenceInfo = &cachedParameters->h265RefInfo;
1228 
1229 		if (setupReferenceSlot.slotIndex >= 0) {
1230 			setupReferenceSlot.pPictureResource = &pCurrFrameDecParams->dpbSetupPictureResource;
1231 			setupReferenceSlot.pNext = &cachedParameters->h265SlotInfo;
1232 			pCurrFrameDecParams->decodeFrameInfo.pSetupReferenceSlot = &setupReferenceSlot;
1233 		}
1234 		if (pCurrFrameDecParams->numGopReferenceSlots) {
1235 			DE_ASSERT(pCurrFrameDecParams->numGopReferenceSlots <= (int32_t)VkParserPerFrameDecodeParameters::MAX_DPB_REF_SLOTS);
1236 			for (deUint32 dpbEntryIdx = 0; dpbEntryIdx < (deUint32)pCurrFrameDecParams->numGopReferenceSlots;
1237 				 dpbEntryIdx++) {
1238 				pCurrFrameDecParams->pictureResources[dpbEntryIdx].sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR;
1239 				referenceSlots[dpbEntryIdx].pPictureResource = &pCurrFrameDecParams->pictureResources[dpbEntryIdx];
1240 				DE_ASSERT(pDpbRefList[dpbEntryIdx].IsReference());
1241 			}
1242 
1243 			pCurrFrameDecParams->decodeFrameInfo.pReferenceSlots = referenceSlots;
1244 			pCurrFrameDecParams->decodeFrameInfo.referenceSlotCount = pCurrFrameDecParams->numGopReferenceSlots;
1245 		} else {
1246 			pCurrFrameDecParams->decodeFrameInfo.pReferenceSlots = nullptr;
1247 			pCurrFrameDecParams->decodeFrameInfo.referenceSlotCount = 0;
1248 		}
1249 
1250 		if (videoLoggingEnabled()) {
1251 			for (int32_t i = 0; i < HEVC_MAX_DPB_SLOTS; i++) {
1252 				std::cout << "\tdpbIndex: " << i;
1253 				if (pDpbRefList[i]) {
1254 					std::cout << " REFERENCE FRAME";
1255 
1256 					std::cout << " picOrderCntValList: "
1257 							  << (int32_t)pDpbRefList[i]
1258 									  .dpbSlotInfo.pStdReferenceInfo->PicOrderCntVal;
1259 
1260 					std::cout << "\t\t Flags: ";
1261 					if (pDpbRefList[i]
1262 							.dpbSlotInfo.pStdReferenceInfo->flags.used_for_long_term_reference) {
1263 						std::cout << "IS LONG TERM ";
1264 					}
1265 
1266 				} else {
1267 					std::cout << " NOT A REFERENCE ";
1268 				}
1269 				std::cout << std::endl;
1270 			}
1271 		}
1272 	}
1273 
1274 	pDecodePictureInfo->displayWidth	= m_nvsi.nDisplayWidth;
1275 	pDecodePictureInfo->displayHeight	= m_nvsi.nDisplayHeight;
1276 
1277 	bRet = DecodePictureWithParameters(cachedParameters) >= 0;
1278 
1279 	DE_ASSERT(bRet);
1280 
1281 	m_nCurrentPictureID++;
1282 
1283 	return bRet;
1284 }
1285 
DecodePictureWithParameters(MovePtr<CachedDecodeParameters> & cachedParameters)1286 int32_t VideoBaseDecoder::DecodePictureWithParameters(MovePtr<CachedDecodeParameters>& cachedParameters)
1287 {
1288 	TCU_CHECK_MSG(m_videoSession, "Video session has not been initialized!");
1289 
1290 	auto *pPicParams = &cachedParameters->pictureParams;
1291 
1292 	int32_t currPicIdx = pPicParams->currPicIdx;
1293 	DE_ASSERT((deUint32) currPicIdx < m_numDecodeSurfaces);
1294 
1295 	cachedParameters->picNumInDecodeOrder = m_decodePicCount++;
1296 	m_videoFrameBuffer->SetPicNumInDecodeOrder(currPicIdx, cachedParameters->picNumInDecodeOrder);
1297 
1298 	DE_ASSERT(pPicParams->bitstreamData->GetMaxSize() >= pPicParams->bitstreamDataLen);
1299 	pPicParams->decodeFrameInfo.srcBuffer = pPicParams->bitstreamData->GetBuffer();
1300 	DE_ASSERT(pPicParams->bitstreamDataOffset == 0);
1301 	DE_ASSERT(pPicParams->firstSliceIndex == 0);
1302 	pPicParams->decodeFrameInfo.srcBufferOffset = pPicParams->bitstreamDataOffset;
1303 	pPicParams->decodeFrameInfo.srcBufferRange = deAlign64(pPicParams->bitstreamDataLen, m_videoCaps.minBitstreamBufferSizeAlignment);
1304 
1305 	int32_t retPicIdx = GetCurrentFrameData((deUint32) currPicIdx, cachedParameters->frameDataSlot);
1306 	DE_ASSERT(retPicIdx == currPicIdx);
1307 
1308 	if (retPicIdx != currPicIdx)
1309 	{
1310 		fprintf(stderr, "\nERROR: DecodePictureWithParameters() retPicIdx(%d) != currPicIdx(%d)\n", retPicIdx, currPicIdx);
1311 	}
1312 
1313 	auto &decodeBeginInfo = cachedParameters->decodeBeginInfo;
1314 	decodeBeginInfo.sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR;
1315 	// CmdResetQueryPool are NOT Supported yet.
1316 	decodeBeginInfo.pNext = pPicParams->beginCodingInfoPictureParametersExt;
1317 	decodeBeginInfo.videoSession = m_videoSession->GetVideoSession();
1318 
1319 	cachedParameters->currentPictureParameterObject = m_currentPictureParameters;
1320 
1321 	DE_ASSERT(!!pPicParams->decodeFrameInfo.srcBuffer);
1322 	cachedParameters->bitstreamBufferMemoryBarrier = {
1323 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR,
1324 			nullptr,
1325 			VK_PIPELINE_STAGE_2_NONE_KHR,
1326 			0, // VK_ACCESS_2_HOST_WRITE_BIT_KHR,
1327 			VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
1328 			VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR,
1329 			(deUint32) m_deviceContext->decodeQueueFamilyIdx(),
1330 			(deUint32) m_deviceContext->decodeQueueFamilyIdx(),
1331 			pPicParams->decodeFrameInfo.srcBuffer,
1332 			pPicParams->decodeFrameInfo.srcBufferOffset,
1333 			pPicParams->decodeFrameInfo.srcBufferRange
1334 	};
1335 
1336 	deUint32 baseArrayLayer = (m_useImageArray || m_useImageViewArray) ? pPicParams->currPicIdx : 0;
1337 	const VkImageMemoryBarrier2KHR dpbBarrierTemplate = {
1338 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR, // VkStructureType sType
1339 			nullptr, // const void*     pNext
1340 			VK_PIPELINE_STAGE_2_NONE_KHR, // VkPipelineStageFlags2KHR srcStageMask
1341 			0, // VkAccessFlags2KHR        srcAccessMask
1342 			VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask;
1343 			VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR, // VkAccessFlags   dstAccessMask
1344 			VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout   oldLayout
1345 			VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, // VkImageLayout   newLayout
1346 			(deUint32) m_deviceContext->decodeQueueFamilyIdx(), // deUint32        srcQueueFamilyIndex
1347 			(deUint32) m_deviceContext->decodeQueueFamilyIdx(), // deUint32   dstQueueFamilyIndex
1348 			VK_NULL_HANDLE, // VkImage         image;
1349 			{
1350 					// VkImageSubresourceRange   subresourceRange
1351 					VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1352 					0, // deUint32           baseMipLevel
1353 					1, // deUint32           levelCount
1354 					baseArrayLayer, // deUint32           baseArrayLayer
1355 					1, // deUint32           layerCount;
1356 			},
1357 	};
1358 
1359 	cachedParameters->currentDpbPictureResourceInfo = VulkanVideoFrameBuffer::PictureResourceInfo();
1360 	cachedParameters->currentOutputPictureResourceInfo = VulkanVideoFrameBuffer::PictureResourceInfo();
1361 	deMemset(&cachedParameters->currentOutputPictureResource, 0, sizeof(VkVideoPictureResourceInfoKHR));
1362 	cachedParameters->currentOutputPictureResource.sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR;
1363 
1364 	auto *pOutputPictureResource = cachedParameters->pOutputPictureResource;
1365 	auto *pOutputPictureResourceInfo = cachedParameters->pOutputPictureResourceInfo;
1366 	if (!dpbAndOutputCoincide())
1367 	{
1368 		// Output Distinct will use the decodeFrameInfo.dstPictureResource directly.
1369 		pOutputPictureResource = &pPicParams->decodeFrameInfo.dstPictureResource;
1370 	}
1371 	else if (true) // TODO: Tidying
1372 	{
1373 		// Output Coincide needs the output only if we are processing linear images that we need to copy to below.
1374 		pOutputPictureResource = &cachedParameters->currentOutputPictureResource;
1375 	}
1376 
1377 	if (pOutputPictureResource)
1378 	{
1379 		// if the pOutputPictureResource is set then we also need the pOutputPictureResourceInfo.
1380 		pOutputPictureResourceInfo = &cachedParameters->currentOutputPictureResourceInfo;
1381 	}
1382 
1383 	if (pPicParams->currPicIdx !=
1384 		m_videoFrameBuffer->GetCurrentImageResourceByIndex(pPicParams->currPicIdx,
1385 														   &pPicParams->dpbSetupPictureResource,
1386 														   &cachedParameters->currentDpbPictureResourceInfo,
1387 														   VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
1388 														   pOutputPictureResource,
1389 														   pOutputPictureResourceInfo,
1390 														   VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR))
1391 	{
1392 		DE_ASSERT(!"GetImageResourcesByIndex has failed");
1393 	}
1394 
1395 	if (dpbAndOutputCoincide())
1396 	{
1397 		// For the Output Coincide, the DPB and destination output resources are the same.
1398 		pPicParams->decodeFrameInfo.dstPictureResource = pPicParams->dpbSetupPictureResource;
1399 
1400 		// Also, when we are copying the output we need to know which layer is used for the current frame.
1401 		// This is if a multi-layered image is used for the DPB and the output (since they coincide).
1402 		cachedParameters->decodedPictureInfo.imageLayerIndex = pPicParams->dpbSetupPictureResource.baseArrayLayer;
1403 	}
1404 	else if (pOutputPictureResourceInfo)
1405 	{
1406 		// For Output Distinct transition the image to DECODE_DST
1407 		if (pOutputPictureResourceInfo->currentImageLayout == VK_IMAGE_LAYOUT_UNDEFINED)
1408 		{
1409 			VkImageMemoryBarrier2KHR barrier = dpbBarrierTemplate;
1410 			barrier.oldLayout = pOutputPictureResourceInfo->currentImageLayout;
1411 			barrier.newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR;
1412 			barrier.image = pOutputPictureResourceInfo->image;
1413 			barrier.dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR;
1414 			cachedParameters->imageBarriers.push_back(barrier);
1415 			DE_ASSERT(!!cachedParameters->imageBarriers.back().image);
1416 		}
1417 	}
1418 
1419 	if (cachedParameters->currentDpbPictureResourceInfo.currentImageLayout == VK_IMAGE_LAYOUT_UNDEFINED)
1420 	{
1421 		VkImageMemoryBarrier2KHR barrier = dpbBarrierTemplate;
1422 		barrier.oldLayout = cachedParameters->currentDpbPictureResourceInfo.currentImageLayout;
1423 		barrier.newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
1424 		barrier.image = cachedParameters->currentDpbPictureResourceInfo.image;
1425 		barrier.dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR;
1426 		cachedParameters->imageBarriers.push_back(barrier);
1427 		DE_ASSERT(!!cachedParameters->imageBarriers.back().image);
1428 	}
1429 
1430 	// Transition all the DPB images to DECODE_DPB layout, if necessary.
1431 	deMemset(cachedParameters->pictureResourcesInfo, 0, DE_LENGTH_OF_ARRAY(cachedParameters->pictureResourcesInfo) * sizeof(cachedParameters->pictureResourcesInfo[0]));
1432 	const int8_t *pGopReferenceImagesIndexes = pPicParams->pGopReferenceImagesIndexes;
1433 	if (pPicParams->numGopReferenceSlots)
1434 	{
1435 		if (pPicParams->numGopReferenceSlots != m_videoFrameBuffer->GetDpbImageResourcesByIndex(
1436 				pPicParams->numGopReferenceSlots,
1437 				pGopReferenceImagesIndexes,
1438 				pPicParams->pictureResources,
1439 				cachedParameters->pictureResourcesInfo,
1440 				VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR))
1441 		{
1442 			DE_ASSERT(!"GetImageResourcesByIndex has failed");
1443 		}
1444 		for (int32_t resId = 0; resId < pPicParams->numGopReferenceSlots; resId++)
1445 		{
1446 			// slotLayer requires NVIDIA specific extension VK_KHR_video_layers, not enabled, just yet.
1447 			// pGopReferenceSlots[resId].slotLayerIndex = 0;
1448 			// pictureResourcesInfo[resId].image can be a nullptr handle if the picture is not-existent.
1449 			if (!!cachedParameters->pictureResourcesInfo[resId].image &&
1450 				(cachedParameters->pictureResourcesInfo[resId].currentImageLayout != VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR) &&
1451 				(cachedParameters->pictureResourcesInfo[resId].currentImageLayout != VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR))
1452 			{
1453 				VkImageMemoryBarrier2KHR barrier = dpbBarrierTemplate;
1454 				barrier.oldLayout = cachedParameters->currentDpbPictureResourceInfo.currentImageLayout;
1455 				barrier.newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
1456 				barrier.image = cachedParameters->pictureResourcesInfo[resId].image;
1457 				barrier.dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR;
1458 				cachedParameters->imageBarriers.push_back(barrier);
1459 				DE_ASSERT(!!cachedParameters->imageBarriers.back().image);
1460 			}
1461 		}
1462 	}
1463 
1464 	decodeBeginInfo.referenceSlotCount = pPicParams->decodeFrameInfo.referenceSlotCount;
1465 	decodeBeginInfo.pReferenceSlots = pPicParams->decodeFrameInfo.pReferenceSlots;
1466 
1467 	// Ensure the resource for the resources associated with the
1468 	// reference slot (if it exists) are in the bound picture
1469 	// resources set.  See VUID-vkCmdDecodeVideoKHR-pDecodeInfo-07149.
1470 	if (pPicParams->decodeFrameInfo.pSetupReferenceSlot != nullptr)
1471 	{
1472 		cachedParameters->fullReferenceSlots.clear();
1473 		for (deUint32 i = 0; i < decodeBeginInfo.referenceSlotCount; i++)
1474 			cachedParameters->fullReferenceSlots.push_back(decodeBeginInfo.pReferenceSlots[i]);
1475 		VkVideoReferenceSlotInfoKHR setupActivationSlot = {};
1476 		setupActivationSlot.sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR;
1477 		setupActivationSlot.slotIndex = -1;
1478 		setupActivationSlot.pPictureResource = &pPicParams->dpbSetupPictureResource; //dpbAndOutputCoincide() ? &pPicParams->decodeFrameInfo.dstPictureResource : &pPicParams->pictureResources[pPicParams->numGopReferenceSlots];
1479 		cachedParameters->fullReferenceSlots.push_back(setupActivationSlot);
1480 		decodeBeginInfo.referenceSlotCount++;
1481 		decodeBeginInfo.pReferenceSlots = cachedParameters->fullReferenceSlots.data();
1482 	}
1483 
1484 	if (cachedParameters->decodedPictureInfo.flags.unpairedField)
1485 	{
1486 		// DE_ASSERT(pFrameSyncinfo->frameCompleteSemaphore == VK_NULL_HANDLE);
1487 		cachedParameters->decodedPictureInfo.flags.syncFirstReady = true;
1488 	}
1489 	// FIXME: the below sequence for interlaced synchronization.
1490 	cachedParameters->decodedPictureInfo.flags.syncToFirstField = false;
1491 
1492 	cachedParameters->frameSynchronizationInfo = VulkanVideoFrameBuffer::FrameSynchronizationInfo();
1493 	cachedParameters->frameSynchronizationInfo.hasFrameCompleteSignalFence = true;
1494 	cachedParameters->frameSynchronizationInfo.hasFrameCompleteSignalSemaphore = true;
1495 
1496 
1497 	VulkanVideoFrameBuffer::ReferencedObjectsInfo referencedObjectsInfo(pPicParams->bitstreamData,
1498 																		pPicParams->pStdPps,
1499 																		pPicParams->pStdSps,
1500 																		pPicParams->pStdVps);
1501 	int picIdx = m_videoFrameBuffer->QueuePictureForDecode(currPicIdx, &cachedParameters->decodedPictureInfo, &referencedObjectsInfo,
1502 														   &cachedParameters->frameSynchronizationInfo);
1503 	DE_ASSERT(picIdx == currPicIdx);
1504 	DE_UNREF(picIdx);
1505 
1506 	if (m_outOfOrderDecoding)
1507 		return currPicIdx;
1508 
1509 	WaitForFrameFences(cachedParameters);
1510 	ApplyPictureParameters(cachedParameters);
1511 	RecordCommandBuffer(cachedParameters);
1512 	SubmitQueue(cachedParameters);
1513 	if (m_queryResultWithStatus)
1514 	{
1515 		QueryDecodeResults(cachedParameters);
1516 	}
1517 
1518 	return currPicIdx;
1519 }
1520 
ApplyPictureParameters(de::MovePtr<CachedDecodeParameters> & cachedParameters)1521 void VideoBaseDecoder::ApplyPictureParameters(de::MovePtr<CachedDecodeParameters> &cachedParameters)
1522 {
1523 	auto* pPicParams = &cachedParameters->pictureParams;
1524 	VkSharedBaseObj<VkVideoRefCountBase> currentVkPictureParameters;
1525 	bool valid = pPicParams->pStdPps->GetClientObject(currentVkPictureParameters);
1526 	DE_ASSERT(currentVkPictureParameters && valid);
1527 	VkParserVideoPictureParameters *pOwnerPictureParameters =
1528 			VkParserVideoPictureParameters::VideoPictureParametersFromBase(currentVkPictureParameters);
1529 	DE_ASSERT(pOwnerPictureParameters);
1530 	int32_t ret = pOwnerPictureParameters->FlushPictureParametersQueue(m_videoSession);
1531 	DE_ASSERT(ret >= 0);
1532 	DE_UNREF(ret);
1533 	bool isSps = false;
1534 	int32_t spsId = pPicParams->pStdPps->GetSpsId(isSps);
1535 	DE_ASSERT(!isSps);
1536 	DE_ASSERT(spsId >= 0);
1537 	DE_ASSERT(pOwnerPictureParameters->HasSpsId(spsId));
1538 	bool isPps = false;
1539 	int32_t ppsId = pPicParams->pStdPps->GetPpsId(isPps);
1540 	DE_ASSERT(isPps);
1541 	DE_ASSERT(ppsId >= 0);
1542 	DE_ASSERT(pOwnerPictureParameters->HasPpsId(ppsId));
1543 	DE_UNREF(valid);
1544 
1545 	cachedParameters->decodeBeginInfo.videoSessionParameters = *pOwnerPictureParameters;
1546 
1547 	if (videoLoggingEnabled())
1548 	{
1549 		std::cout << "ApplyPictureParameters object " << cachedParameters->decodeBeginInfo.videoSessionParameters << " with ID: (" << pOwnerPictureParameters->GetId() << ")"
1550 				  << " for SPS: " << spsId << ", PPS: " << ppsId << std::endl;
1551 	}
1552 }
1553 
WaitForFrameFences(de::MovePtr<CachedDecodeParameters> & cachedParameters)1554 void VideoBaseDecoder::WaitForFrameFences(de::MovePtr<CachedDecodeParameters> &cachedParameters)
1555 {
1556 	// Check here that the frame for this entry (for this command buffer) has already completed decoding.
1557 	// Otherwise we may step over a hot command buffer by starting a new recording.
1558 	// This fence wait should be NOP in 99.9% of the cases, because the decode queue is deep enough to
1559 	// ensure the frame has already been completed.
1560 	VK_CHECK(m_deviceContext->getDeviceDriver().waitForFences(m_deviceContext->device, 1, &cachedParameters->frameSynchronizationInfo.frameCompleteFence, true, TIMEOUT_100ms));
1561 	VkResult result = m_deviceContext->getDeviceDriver().getFenceStatus(m_deviceContext->device, cachedParameters->frameSynchronizationInfo.frameCompleteFence);
1562 	TCU_CHECK_MSG(result == VK_SUCCESS || result == VK_NOT_READY, "Bad fence status");
1563 }
1564 
RecordCommandBuffer(de::MovePtr<CachedDecodeParameters> & cachedParameters)1565 void VideoBaseDecoder::RecordCommandBuffer(de::MovePtr<CachedDecodeParameters> &cachedParameters)
1566 {
1567 	auto &vk = m_deviceContext->getDeviceDriver();
1568 
1569 	VkCommandBuffer commandBuffer = cachedParameters->frameDataSlot.commandBuffer;
1570 
1571 	VkCommandBufferBeginInfo beginInfo{};
1572 	beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1573 	beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1574 	beginInfo.pInheritanceInfo = nullptr;
1575 
1576 	vk.beginCommandBuffer(commandBuffer, &beginInfo);
1577 
1578 	if (m_queryResultWithStatus)
1579 	{
1580 		vk.cmdResetQueryPool(commandBuffer, cachedParameters->frameSynchronizationInfo.queryPool, cachedParameters->frameSynchronizationInfo.startQueryId,
1581 							 cachedParameters->frameSynchronizationInfo.numQueries);
1582 	}
1583 
1584 	vk.cmdBeginVideoCodingKHR(commandBuffer, &cachedParameters->decodeBeginInfo);
1585 
1586 	if (cachedParameters->performCodecReset)
1587 	{
1588 		VkVideoCodingControlInfoKHR codingControlInfo = {VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
1589 														 nullptr,
1590 														 VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR};
1591 		vk.cmdControlVideoCodingKHR(commandBuffer, &codingControlInfo);
1592 	}
1593 
1594 	const VkDependencyInfoKHR dependencyInfo = {
1595 			VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,
1596 			nullptr,
1597 			VK_DEPENDENCY_BY_REGION_BIT,
1598 			0,
1599 			nullptr,
1600 			1,
1601 			&cachedParameters->bitstreamBufferMemoryBarrier,
1602 			static_cast<deUint32>(cachedParameters->imageBarriers.size()),
1603 			cachedParameters->imageBarriers.data(),
1604 	};
1605 	vk.cmdPipelineBarrier2(commandBuffer, &dependencyInfo);
1606 
1607 	if (m_queryResultWithStatus)
1608 	{
1609 		vk.cmdBeginQuery(commandBuffer, cachedParameters->frameSynchronizationInfo.queryPool, cachedParameters->frameSynchronizationInfo.startQueryId, VkQueryControlFlags());
1610 	}
1611 
1612 	vk.cmdDecodeVideoKHR(commandBuffer, &cachedParameters->pictureParams.decodeFrameInfo);
1613 
1614 	if (m_queryResultWithStatus)
1615 	{
1616 		vk.cmdEndQuery(commandBuffer, cachedParameters->frameSynchronizationInfo.queryPool, cachedParameters->frameSynchronizationInfo.startQueryId);
1617 	}
1618 
1619 	VkVideoEndCodingInfoKHR decodeEndInfo{};
1620 	decodeEndInfo.sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR;
1621 	vk.cmdEndVideoCodingKHR(commandBuffer, &decodeEndInfo);
1622 
1623 	m_deviceContext->getDeviceDriver().endCommandBuffer(commandBuffer);
1624 }
1625 
SubmitQueue(de::MovePtr<CachedDecodeParameters> & cachedParameters)1626 void VideoBaseDecoder::SubmitQueue(de::MovePtr<CachedDecodeParameters> &cachedParameters)
1627 {
1628 	auto&			vk								 = m_deviceContext->getDeviceDriver();
1629 	auto			device							 = m_deviceContext->device;
1630 	VkCommandBuffer commandBuffer					 = cachedParameters->frameDataSlot.commandBuffer;
1631 	VkSubmitInfo	submitInfo{};
1632 	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1633 	submitInfo.waitSemaphoreCount					 = (cachedParameters->frameSynchronizationInfo.frameConsumerDoneSemaphore == VK_NULL_HANDLE) ? 0 : 1;
1634 	submitInfo.pWaitSemaphores						 = &cachedParameters->frameSynchronizationInfo.frameConsumerDoneSemaphore;
1635 	VkPipelineStageFlags videoDecodeSubmitWaitStages = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR;
1636 	submitInfo.pWaitDstStageMask					 = &videoDecodeSubmitWaitStages;
1637 	submitInfo.commandBufferCount					 = 1;
1638 	submitInfo.pCommandBuffers						 = &commandBuffer;
1639 	submitInfo.signalSemaphoreCount					 = 1;
1640 	submitInfo.pSignalSemaphores					 = &cachedParameters->frameSynchronizationInfo.frameCompleteSemaphore;
1641 
1642 	if ((cachedParameters->frameSynchronizationInfo.frameConsumerDoneSemaphore == VK_NULL_HANDLE) &&
1643 		(cachedParameters->frameSynchronizationInfo.frameConsumerDoneFence != VK_NULL_HANDLE))
1644 	{
1645 		VK_CHECK(vk.waitForFences(device, 1, &cachedParameters->frameSynchronizationInfo.frameConsumerDoneFence, true, TIMEOUT_100ms));
1646 		VkResult result = vk.getFenceStatus(device, cachedParameters->frameSynchronizationInfo.frameCompleteFence);
1647 		TCU_CHECK_MSG(result == VK_SUCCESS || result == VK_NOT_READY, "Bad fence status");
1648 	}
1649 
1650 	VK_CHECK(vk.resetFences(device, 1, &cachedParameters->frameSynchronizationInfo.frameCompleteFence));
1651 	VkResult result = vk.getFenceStatus(device, cachedParameters->frameSynchronizationInfo.frameCompleteFence);
1652 	TCU_CHECK_MSG(result == VK_SUCCESS || result == VK_NOT_READY, "Bad fence status");
1653 
1654 	VK_CHECK(vk.queueSubmit(m_deviceContext->decodeQueue, 1, &submitInfo, cachedParameters->frameSynchronizationInfo.frameCompleteFence));
1655 
1656 	if (videoLoggingEnabled())
1657 	{
1658 		std::cout << "\t +++++++++++++++++++++++++++< " << cachedParameters->pictureParams.currPicIdx << " >++++++++++++++++++++++++++++++" << std::endl;
1659 		std::cout << std::dec << "\t => Decode Submitted for CurrPicIdx: " << cachedParameters->pictureParams.currPicIdx << std::endl
1660 				  << "\t\tm_nPicNumInDecodeOrder: " << cachedParameters->picNumInDecodeOrder << "\t\tframeCompleteFence " << cachedParameters->frameSynchronizationInfo.frameCompleteFence
1661 				  << "\t\tframeCompleteSemaphore " << cachedParameters->frameSynchronizationInfo.frameCompleteSemaphore << "\t\tdstImageView "
1662 				  << cachedParameters->pictureParams.decodeFrameInfo.dstPictureResource.imageViewBinding << std::endl;
1663 	}
1664 
1665 	const bool checkDecodeIdleSync = false; // For fence/sync/idle debugging
1666 	if (checkDecodeIdleSync)
1667 	{ // For fence/sync debugging
1668 		if (cachedParameters->frameSynchronizationInfo.frameCompleteFence == VK_NULL_HANDLE)
1669 		{
1670 			VK_CHECK(vk.queueWaitIdle(m_deviceContext->decodeQueue));
1671 		}
1672 		else
1673 		{
1674 			if (cachedParameters->frameSynchronizationInfo.frameCompleteSemaphore == VK_NULL_HANDLE)
1675 			{
1676 				VK_CHECK(vk.waitForFences(device, 1, &cachedParameters->frameSynchronizationInfo.frameCompleteFence, true, TIMEOUT_100ms));
1677 				result = vk.getFenceStatus(device, cachedParameters->frameSynchronizationInfo.frameCompleteFence);
1678 				TCU_CHECK_MSG(result == VK_SUCCESS || result == VK_NOT_READY, "Bad fence status");
1679 			}
1680 		}
1681 	}
1682 }
1683 
QueryDecodeResults(de::MovePtr<CachedDecodeParameters> & cachedParameters)1684 void VideoBaseDecoder::QueryDecodeResults(de::MovePtr<CachedDecodeParameters> &cachedParameters)
1685 {
1686 	auto& vk						   = m_deviceContext->getDeviceDriver();
1687 	auto  device					   = m_deviceContext->device;
1688 
1689 	VkQueryResultStatusKHR decodeStatus;
1690 	VkResult result = vk.getQueryPoolResults(device,
1691 											 cachedParameters->frameSynchronizationInfo.queryPool,
1692 											 cachedParameters->frameSynchronizationInfo.startQueryId,
1693 											 1,
1694 											 sizeof(decodeStatus),
1695 											 &decodeStatus,
1696 											 sizeof(decodeStatus),
1697 											 VK_QUERY_RESULT_WITH_STATUS_BIT_KHR | VK_QUERY_RESULT_WAIT_BIT);
1698 	if (videoLoggingEnabled())
1699 	{
1700 		std::cout << "\t +++++++++++++++++++++++++++< " << cachedParameters->pictureParams.currPicIdx << " >++++++++++++++++++++++++++++++" << std::endl;
1701 		std::cout << "\t => Decode Status for CurrPicIdx: " << cachedParameters->pictureParams.currPicIdx << std::endl
1702 				  << "\t\tdecodeStatus: " << decodeStatus << std::endl;
1703 	}
1704 
1705 	TCU_CHECK_AND_THROW(TestError, result == VK_SUCCESS || result == VK_ERROR_DEVICE_LOST, "Driver has returned an invalid query result");
1706 	TCU_CHECK_AND_THROW(TestError, decodeStatus != VK_QUERY_RESULT_STATUS_ERROR_KHR, "Decode query returned an unexpected error");
1707 }
1708 
decodeFramesOutOfOrder()1709 void VideoBaseDecoder::decodeFramesOutOfOrder()
1710 {
1711 	std::vector<int> ordering(m_cachedDecodeParams.size());
1712 	std::iota(ordering.begin(), ordering.end(), 0);
1713 	if (ordering.size() == 2)
1714 		std::swap(ordering[0], ordering[1]);
1715 	else // TODO: test seeding
1716 		std::shuffle(ordering.begin(), ordering.end(), std::mt19937{std::random_device{}()});
1717 
1718 	DE_ASSERT(m_cachedDecodeParams.size() > 1);
1719 
1720 	// Record out of order
1721 	for (int recordOrderIdx : ordering)
1722 	{
1723 		auto &cachedParams = m_cachedDecodeParams[recordOrderIdx];
1724 		WaitForFrameFences(cachedParams);
1725 		ApplyPictureParameters(cachedParams);
1726 		RecordCommandBuffer(cachedParams);
1727 	}
1728 
1729 	// Submit in order
1730 	for (int i = 0; i < m_cachedDecodeParams.size(); i++)
1731 	{
1732 		auto& cachedParams = m_cachedDecodeParams[i];
1733 		SubmitQueue(cachedParams);
1734 		if (m_queryResultWithStatus)
1735 		{
1736 			QueryDecodeResults(cachedParams);
1737 		}
1738 	}
1739 }
1740 
UpdatePictureParameters(VkSharedBaseObj<StdVideoPictureParametersSet> & pictureParametersObject,VkSharedBaseObj<VkVideoRefCountBase> & client)1741 bool VideoBaseDecoder::UpdatePictureParameters(VkSharedBaseObj<StdVideoPictureParametersSet>& pictureParametersObject, /* in */
1742 											   VkSharedBaseObj<VkVideoRefCountBase>&		  client)
1743 {
1744 	triggerPictureParameterSequenceCount();
1745 
1746 	VkResult result = VkParserVideoPictureParameters::AddPictureParameters(*m_deviceContext,
1747 																		   m_videoSession,
1748 																		   pictureParametersObject,
1749 																		   m_currentPictureParameters);
1750 	client			= m_currentPictureParameters;
1751 	return (result == VK_SUCCESS);
1752 }
1753 
DisplayPicture(VkPicIf * pNvidiaVulkanPicture,int64_t)1754 bool VideoBaseDecoder::DisplayPicture (VkPicIf*	pNvidiaVulkanPicture,
1755 									   int64_t					/*llPTS*/)
1756 {
1757 	vkPicBuffBase* pVkPicBuff = GetPic(pNvidiaVulkanPicture);
1758 
1759 	DE_ASSERT(pVkPicBuff != DE_NULL);
1760 	int32_t picIdx = pVkPicBuff ? pVkPicBuff->m_picIdx : -1;
1761 	DE_ASSERT(picIdx != -1);
1762 	DE_ASSERT(m_videoFrameBuffer != nullptr);
1763 
1764 	if (videoLoggingEnabled())
1765 	{
1766 		std::cout << "\t ======================< " << picIdx << " >============================" << std::endl;
1767 		std::cout << "\t ==> VulkanVideoParser::DisplayPicture " << picIdx << std::endl;
1768 	}
1769 
1770 	VulkanVideoDisplayPictureInfo dispInfo = VulkanVideoDisplayPictureInfo();
1771 
1772 	dispInfo.timestamp					   = 0; // NOTE: we ignore PTS in the CTS
1773 
1774 	const int32_t retVal				   = m_videoFrameBuffer->QueueDecodedPictureForDisplay((int8_t)picIdx, &dispInfo);
1775 	DE_ASSERT(picIdx == retVal);
1776 	DE_UNREF(retVal);
1777 
1778 	return true;
1779 }
1780 
ReleaseDisplayedFrame(DecodedFrame * pDisplayedFrame)1781 int32_t VideoBaseDecoder::ReleaseDisplayedFrame(DecodedFrame* pDisplayedFrame)
1782 {
1783 	if (pDisplayedFrame->pictureIndex == -1)
1784 		return -1;
1785 
1786 	DecodedFrameRelease	 decodedFramesRelease		 = {pDisplayedFrame->pictureIndex, 0, 0, 0, 0, 0};
1787 	DecodedFrameRelease* decodedFramesReleasePtr	 = &decodedFramesRelease;
1788 	pDisplayedFrame->pictureIndex					 = -1;
1789 	decodedFramesRelease.decodeOrder				 = pDisplayedFrame->decodeOrder;
1790 	decodedFramesRelease.displayOrder				 = pDisplayedFrame->displayOrder;
1791 	decodedFramesRelease.hasConsummerSignalFence	 = pDisplayedFrame->hasConsummerSignalFence;
1792 	decodedFramesRelease.hasConsummerSignalSemaphore = pDisplayedFrame->hasConsummerSignalSemaphore;
1793 	decodedFramesRelease.timestamp					 = 0;
1794 
1795 	return m_videoFrameBuffer->ReleaseDisplayedPicture(&decodedFramesReleasePtr, 1);
1796 }
1797 
GetBitstreamBuffer(VkDeviceSize size,VkDeviceSize minBitstreamBufferOffsetAlignment,VkDeviceSize minBitstreamBufferSizeAlignment,const deUint8 * pInitializeBufferMemory,VkDeviceSize initializeBufferMemorySize,VkSharedBaseObj<VulkanBitstreamBuffer> & bitstreamBuffer)1798 VkDeviceSize VideoBaseDecoder::GetBitstreamBuffer(VkDeviceSize size, VkDeviceSize minBitstreamBufferOffsetAlignment, VkDeviceSize minBitstreamBufferSizeAlignment, const deUint8* pInitializeBufferMemory, VkDeviceSize initializeBufferMemorySize, VkSharedBaseObj<VulkanBitstreamBuffer>& bitstreamBuffer)
1799 {
1800 	DE_ASSERT(initializeBufferMemorySize <= size);
1801 	VkDeviceSize							newSize = size;
1802 	VkSharedBaseObj<BitstreamBufferImpl>	newBitstreamBuffer;
1803 
1804 	VK_CHECK(BitstreamBufferImpl::Create(m_deviceContext,
1805 										 m_deviceContext->decodeQueueFamilyIdx(),
1806 										 newSize,
1807 										 minBitstreamBufferOffsetAlignment,
1808 										 minBitstreamBufferSizeAlignment,
1809 										 newBitstreamBuffer,
1810 										 m_profile.GetProfileListInfo()));
1811 	if (videoLoggingEnabled())
1812 	{
1813 		std::cout << "\tAllocated bitstream buffer with size " << newSize << " B, " << newSize / 1024 << " KB, " << newSize / 1024 / 1024 << " MB" << std::endl;
1814 	}
1815 
1816 	DE_ASSERT(newBitstreamBuffer);
1817 	newSize = newBitstreamBuffer->GetMaxSize();
1818 	DE_ASSERT(initializeBufferMemorySize <= newSize);
1819 
1820 	size_t bytesToCopy = std::min(initializeBufferMemorySize, newSize);
1821 	size_t bytesCopied = newBitstreamBuffer->CopyDataFromBuffer((const deUint8*)pInitializeBufferMemory, 0, 0, bytesToCopy);
1822 	DE_ASSERT(bytesToCopy == bytesCopied);
1823 	DE_UNREF(bytesCopied);
1824 
1825 	newBitstreamBuffer->MemsetData(0x0, bytesToCopy, newSize - bytesToCopy);
1826 
1827 	if (videoLoggingEnabled())
1828 	{
1829 		std::cout << "\t\tFrom bitstream buffer pool with size " << newSize << " B, " << newSize / 1024 << " KB, " << newSize / 1024 / 1024 << " MB" << std::endl;
1830 
1831 		std::cout << "\t\t\t FreeNodes " << m_decodeFramesData.GetBitstreamBuffersQueue().GetFreeNodesNumber();
1832 		std::cout << " of MaxNodes " << m_decodeFramesData.GetBitstreamBuffersQueue().GetMaxNodes();
1833 		std::cout << ", AvailableNodes " << m_decodeFramesData.GetBitstreamBuffersQueue().GetAvailableNodesNumber();
1834 		std::cout << std::endl;
1835 	}
1836 
1837 	bitstreamBuffer = newBitstreamBuffer;
1838 	if (videoLoggingEnabled() && newSize > m_maxStreamBufferSize)
1839 	{
1840 		std::cout << "\tAllocated bitstream buffer with size " << newSize << " B, " << newSize / 1024 << " KB, " << newSize / 1024 / 1024 << " MB" << std::endl;
1841 		m_maxStreamBufferSize = newSize;
1842 	}
1843 	return bitstreamBuffer->GetMaxSize();
1844 }
1845 
UnhandledNALU(const deUint8 * pbData,size_t cbData)1846 void VideoBaseDecoder::UnhandledNALU (const deUint8*	pbData,
1847 									  size_t			cbData)
1848 {
1849 	const vector<deUint8> data (pbData, pbData + cbData);
1850 	ostringstream css;
1851 
1852 	css << "UnhandledNALU=";
1853 
1854 	for (const auto& i: data)
1855 		css << std::hex << std::setw(2) << std::setfill('0') << (deUint32)i << ' ';
1856 
1857 	TCU_THROW(InternalError, css.str());
1858 }
1859 
FillDpbH264State(const VkParserPictureData * pd,const VkParserH264DpbEntry * dpbIn,deUint32 maxDpbInSlotsInUse,nvVideoDecodeH264DpbSlotInfo * pDpbRefList,deUint32,VkVideoReferenceSlotInfoKHR * pReferenceSlots,int8_t * pGopReferenceImagesIndexes,StdVideoDecodeH264PictureInfoFlags currPicFlags,int32_t * pCurrAllocatedSlotIndex)1860 deUint32 VideoBaseDecoder::FillDpbH264State (const VkParserPictureData *	pd,
1861 											 const VkParserH264DpbEntry*	dpbIn,
1862 											 deUint32								maxDpbInSlotsInUse,
1863 											 nvVideoDecodeH264DpbSlotInfo*		pDpbRefList,
1864 											 deUint32			/*maxRefPictures*/,
1865 											 VkVideoReferenceSlotInfoKHR*			pReferenceSlots,
1866 											 int8_t*								pGopReferenceImagesIndexes,
1867 											 StdVideoDecodeH264PictureInfoFlags		currPicFlags,
1868 											 int32_t*								pCurrAllocatedSlotIndex)
1869 {
1870 	// #### Update m_dpb based on dpb parameters ####
1871 	// Create unordered DPB and generate a bitmask of all render targets present
1872 	// in DPB
1873 	deUint32 num_ref_frames = pd->CodecSpecific.h264.pStdSps->GetStdH264Sps()->max_num_ref_frames;
1874 	DE_ASSERT(num_ref_frames <= HEVC_MAX_DPB_SLOTS);
1875 	DE_ASSERT(num_ref_frames <= m_maxNumDpbSlots);
1876 	dpbH264Entry refOnlyDpbIn[AVC_MAX_DPB_SLOTS]; // max number of Dpb
1877 	// surfaces
1878 	memset(&refOnlyDpbIn, 0, m_maxNumDpbSlots * sizeof(refOnlyDpbIn[0]));
1879 	deUint32 refDpbUsedAndValidMask = 0;
1880 	deUint32 numUsedRef = 0;
1881 	for (int32_t inIdx = 0; (deUint32)inIdx < maxDpbInSlotsInUse; inIdx++) {
1882 		// used_for_reference: 0 = unused, 1 = top_field, 2 = bottom_field, 3 =
1883 		// both_fields
1884 		const deUint32 used_for_reference = dpbIn[inIdx].used_for_reference & fieldIsReferenceMask;
1885 		if (used_for_reference) {
1886 			int8_t picIdx = (!dpbIn[inIdx].not_existing && dpbIn[inIdx].pPicBuf)
1887 							? GetPicIdx(dpbIn[inIdx].pPicBuf)
1888 							: -1;
1889 			const bool isFieldRef = (picIdx >= 0) ? GetFieldPicFlag(picIdx)
1890 												  : (used_for_reference && (used_for_reference != fieldIsReferenceMask));
1891 			const int16_t fieldOrderCntList[2] = {
1892 					(int16_t)dpbIn[inIdx].FieldOrderCnt[0],
1893 					(int16_t)dpbIn[inIdx].FieldOrderCnt[1]
1894 			};
1895 			refOnlyDpbIn[numUsedRef].setReferenceAndTopBottomField(
1896 					!!used_for_reference,
1897 					(picIdx < 0), /* not_existing is frame inferred by the decoding
1898                            process for gaps in frame_num */
1899 					!!dpbIn[inIdx].is_long_term, isFieldRef,
1900 					!!(used_for_reference & topFieldMask),
1901 					!!(used_for_reference & bottomFieldMask), dpbIn[inIdx].FrameIdx,
1902 					fieldOrderCntList, GetPic(dpbIn[inIdx].pPicBuf));
1903 			if (picIdx >= 0) {
1904 				refDpbUsedAndValidMask |= (1 << picIdx);
1905 			}
1906 			numUsedRef++;
1907 		}
1908 		// Invalidate all slots.
1909 		pReferenceSlots[inIdx].slotIndex = -1;
1910 		pGopReferenceImagesIndexes[inIdx] = -1;
1911 	}
1912 
1913 	DE_ASSERT(numUsedRef <= HEVC_MAX_DPB_SLOTS);
1914 	DE_ASSERT(numUsedRef <= m_maxNumDpbSlots);
1915 	DE_ASSERT(numUsedRef <= num_ref_frames);
1916 
1917 	if (videoLoggingEnabled()) {
1918 		std::cout << " =>>> ********************* picIdx: "
1919 				  << (int32_t)GetPicIdx(pd->pCurrPic)
1920 				  << " *************************" << std::endl;
1921 		std::cout << "\tRef frames data in for picIdx: "
1922 				  << (int32_t)GetPicIdx(pd->pCurrPic) << std::endl
1923 				  << "\tSlot Index:\t\t";
1924 		if (numUsedRef == 0)
1925 			std::cout << "(none)" << std::endl;
1926 		else
1927 		{
1928 			for (deUint32 slot = 0; slot < numUsedRef; slot++)
1929 			{
1930 				if (!refOnlyDpbIn[slot].is_non_existing)
1931 				{
1932 					std::cout << slot << ",\t";
1933 				}
1934 				else
1935 				{
1936 					std::cout << 'X' << ",\t";
1937 				}
1938 			}
1939 			std::cout << std::endl;
1940 		}
1941 		std::cout << "\tPict Index:\t\t";
1942 		if (numUsedRef == 0)
1943 			std::cout << "(none)" << std::endl;
1944 		else
1945 		{
1946 			for (deUint32 slot = 0; slot < numUsedRef; slot++)
1947 			{
1948 				if (!refOnlyDpbIn[slot].is_non_existing)
1949 				{
1950 					std::cout << refOnlyDpbIn[slot].m_picBuff->m_picIdx << ",\t";
1951 				}
1952 				else
1953 				{
1954 					std::cout << 'X' << ",\t";
1955 				}
1956 			}
1957 		}
1958 		std::cout << "\n\tTotal Ref frames for picIdx: "
1959 				  << (int32_t)GetPicIdx(pd->pCurrPic) << " : " << numUsedRef
1960 				  << " out of " << num_ref_frames << " MAX(" << m_maxNumDpbSlots
1961 				  << ")" << std::endl
1962 				  << std::endl;
1963 
1964 		std::cout << std::flush;
1965 	}
1966 
1967 	// Map all frames not present in DPB as non-reference, and generate a mask of
1968 	// all used DPB entries
1969 	/* deUint32 destUsedDpbMask = */ ResetPicDpbSlots(refDpbUsedAndValidMask);
1970 
1971 	// Now, map DPB render target indices to internal frame buffer index,
1972 	// assign each reference a unique DPB entry, and create the ordered DPB
1973 	// This is an undocumented MV restriction: the position in the DPB is stored
1974 	// along with the co-located data, so once a reference frame is assigned a DPB
1975 	// entry, it can no longer change.
1976 
1977 	// Find or allocate slots for existing dpb items.
1978 	// Take into account the reference picture now.
1979 	int8_t currPicIdx = GetPicIdx(pd->pCurrPic);
1980 	DE_ASSERT(currPicIdx >= 0);
1981 	int8_t bestNonExistingPicIdx = currPicIdx;
1982 	if (refDpbUsedAndValidMask) {
1983 		int32_t minFrameNumDiff = 0x10000;
1984 		for (int32_t dpbIdx = 0; (deUint32)dpbIdx < numUsedRef; dpbIdx++) {
1985 			if (!refOnlyDpbIn[dpbIdx].is_non_existing) {
1986 				vkPicBuffBase* picBuff = refOnlyDpbIn[dpbIdx].m_picBuff;
1987 				int8_t picIdx = GetPicIdx(picBuff); // should always be valid at this point
1988 				DE_ASSERT(picIdx >= 0);
1989 				// We have up to 17 internal frame buffers, but only MAX_DPB_SIZE dpb
1990 				// entries, so we need to re-map the index from the [0..MAX_DPB_SIZE]
1991 				// range to [0..15]
1992 				int8_t dpbSlot = GetPicDpbSlot(picIdx);
1993 				if (dpbSlot < 0) {
1994 					dpbSlot = m_dpb.AllocateSlot();
1995 					DE_ASSERT((dpbSlot >= 0) && ((deUint32)dpbSlot < m_maxNumDpbSlots));
1996 					SetPicDpbSlot(picIdx, dpbSlot);
1997 					m_dpb[dpbSlot].setPictureResource(picBuff, m_nCurrentPictureID);
1998 				}
1999 				m_dpb[dpbSlot].MarkInUse(m_nCurrentPictureID);
2000 				DE_ASSERT(dpbSlot >= 0);
2001 
2002 				if (dpbSlot >= 0) {
2003 					refOnlyDpbIn[dpbIdx].dpbSlot = dpbSlot;
2004 				} else {
2005 					// This should never happen
2006 					printf("DPB mapping logic broken!\n");
2007 					DE_ASSERT(0);
2008 				}
2009 
2010 				int32_t frameNumDiff = ((int32_t)pd->CodecSpecific.h264.frame_num - refOnlyDpbIn[dpbIdx].FrameIdx);
2011 				if (frameNumDiff <= 0) {
2012 					frameNumDiff = 0xffff;
2013 				}
2014 				if (frameNumDiff < minFrameNumDiff) {
2015 					bestNonExistingPicIdx = picIdx;
2016 					minFrameNumDiff = frameNumDiff;
2017 				} else if (bestNonExistingPicIdx == currPicIdx) {
2018 					bestNonExistingPicIdx = picIdx;
2019 				}
2020 			}
2021 		}
2022 	}
2023 	// In Vulkan, we always allocate a Dbp slot for the current picture,
2024 	// regardless if it is going to become a reference or not. Non-reference slots
2025 	// get freed right after usage. if (pd->ref_pic_flag) {
2026 	int8_t currPicDpbSlot = AllocateDpbSlotForCurrentH264(GetPic(pd->pCurrPic),
2027 														  currPicFlags, pd->current_dpb_id);
2028 	DE_ASSERT(currPicDpbSlot >= 0);
2029 	*pCurrAllocatedSlotIndex = currPicDpbSlot;
2030 
2031 	if (refDpbUsedAndValidMask) {
2032 		// Find or allocate slots for non existing dpb items and populate the slots.
2033 		deUint32 dpbInUseMask = m_dpb.getSlotInUseMask();
2034 		int8_t firstNonExistingDpbSlot = 0;
2035 		for (deUint32 dpbIdx = 0; dpbIdx < numUsedRef; dpbIdx++) {
2036 			int8_t dpbSlot = -1;
2037 			int8_t picIdx = -1;
2038 			if (refOnlyDpbIn[dpbIdx].is_non_existing) {
2039 				DE_ASSERT(refOnlyDpbIn[dpbIdx].m_picBuff == NULL);
2040 				while (((deUint32)firstNonExistingDpbSlot < m_maxNumDpbSlots) && (dpbSlot == -1)) {
2041 					if (!(dpbInUseMask & (1 << firstNonExistingDpbSlot))) {
2042 						dpbSlot = firstNonExistingDpbSlot;
2043 					}
2044 					firstNonExistingDpbSlot++;
2045 				}
2046 				DE_ASSERT((dpbSlot >= 0) && ((deUint32)dpbSlot < m_maxNumDpbSlots));
2047 				picIdx = bestNonExistingPicIdx;
2048 				// Find the closest valid refpic already in the DPB
2049 				deUint32 minDiffPOC = 0x7fff;
2050 				for (deUint32 j = 0; j < numUsedRef; j++) {
2051 					if (!refOnlyDpbIn[j].is_non_existing && (refOnlyDpbIn[j].used_for_reference & refOnlyDpbIn[dpbIdx].used_for_reference) == refOnlyDpbIn[dpbIdx].used_for_reference) {
2052 						deUint32 diffPOC = abs((int32_t)(refOnlyDpbIn[j].FieldOrderCnt[0] - refOnlyDpbIn[dpbIdx].FieldOrderCnt[0]));
2053 						if (diffPOC <= minDiffPOC) {
2054 							minDiffPOC = diffPOC;
2055 							picIdx = GetPicIdx(refOnlyDpbIn[j].m_picBuff);
2056 						}
2057 					}
2058 				}
2059 			} else {
2060 				DE_ASSERT(refOnlyDpbIn[dpbIdx].m_picBuff != NULL);
2061 				dpbSlot = refOnlyDpbIn[dpbIdx].dpbSlot;
2062 				picIdx = GetPicIdx(refOnlyDpbIn[dpbIdx].m_picBuff);
2063 			}
2064 			DE_ASSERT((dpbSlot >= 0) && ((deUint32)dpbSlot < m_maxNumDpbSlots));
2065 			refOnlyDpbIn[dpbIdx].setH264PictureData(pDpbRefList, pReferenceSlots,
2066 													dpbIdx, dpbSlot, pd->progressive_frame);
2067 			pGopReferenceImagesIndexes[dpbIdx] = picIdx;
2068 		}
2069 	}
2070 
2071 	if (videoLoggingEnabled()) {
2072 		deUint32 slotInUseMask = m_dpb.getSlotInUseMask();
2073 		deUint32 slotsInUseCount = 0;
2074 		std::cout << "\tAllocated DPB slot " << (int32_t)currPicDpbSlot << " for "
2075 				  << (pd->ref_pic_flag ? "REFERENCE" : "NON-REFERENCE")
2076 				  << " picIdx: " << (int32_t)currPicIdx << std::endl;
2077 		std::cout << "\tDPB frames map for picIdx: " << (int32_t)currPicIdx
2078 				  << std::endl
2079 				  << "\tSlot Index:\t\t";
2080 		for (deUint32 slot = 0; slot < m_dpb.getMaxSize(); slot++) {
2081 			if (slotInUseMask & (1 << slot)) {
2082 				std::cout << slot << ",\t";
2083 				slotsInUseCount++;
2084 			} else {
2085 				std::cout << 'X' << ",\t";
2086 			}
2087 		}
2088 		std::cout << std::endl
2089 				  << "\tPict Index:\t\t";
2090 		for (deUint32 slot = 0; slot < m_dpb.getMaxSize(); slot++) {
2091 			if (slotInUseMask & (1 << slot)) {
2092 				if (m_dpb[slot].getPictureResource()) {
2093 					std::cout << m_dpb[slot].getPictureResource()->m_picIdx << ",\t";
2094 				} else {
2095 					std::cout << "non existent"
2096 							  << ",\t";
2097 				}
2098 			} else {
2099 				std::cout << 'X' << ",\t";
2100 			}
2101 		}
2102 		std::cout << "\n\tTotal slots in use for picIdx: " << (int32_t)currPicIdx
2103 				  << " : " << slotsInUseCount << " out of " << m_dpb.getMaxSize()
2104 				  << std::endl;
2105 		std::cout << " <<<= ********************* picIdx: "
2106 				  << (int32_t)GetPicIdx(pd->pCurrPic)
2107 				  << " *************************" << std::endl
2108 				  << std::endl;
2109 		std::cout << std::flush;
2110 	}
2111 	return refDpbUsedAndValidMask ? numUsedRef : 0;}
2112 
FillDpbH265State(const VkParserPictureData * pd,const VkParserHevcPictureData * pin,nvVideoDecodeH265DpbSlotInfo * pDpbSlotInfo,StdVideoDecodeH265PictureInfo * pStdPictureInfo,deUint32,VkVideoReferenceSlotInfoKHR * pReferenceSlots,int8_t * pGopReferenceImagesIndexes,int32_t * pCurrAllocatedSlotIndex)2113 deUint32 VideoBaseDecoder::FillDpbH265State (const VkParserPictureData* pd,
2114 											 const VkParserHevcPictureData* pin,
2115 											 nvVideoDecodeH265DpbSlotInfo* pDpbSlotInfo,
2116 											 StdVideoDecodeH265PictureInfo* pStdPictureInfo,
2117 											 deUint32 /*maxRefPictures*/,
2118 											 VkVideoReferenceSlotInfoKHR* pReferenceSlots,
2119 											 int8_t* pGopReferenceImagesIndexes,
2120 											 int32_t* pCurrAllocatedSlotIndex)
2121 {
2122 	// #### Update m_dpb based on dpb parameters ####
2123 	// Create unordered DPB and generate a bitmask of all render targets present
2124 	// in DPB
2125 	dpbH264Entry refOnlyDpbIn[HEVC_MAX_DPB_SLOTS];
2126 	DE_ASSERT(m_maxNumDpbSlots <= HEVC_MAX_DPB_SLOTS);
2127 	memset(&refOnlyDpbIn, 0, m_maxNumDpbSlots * sizeof(refOnlyDpbIn[0]));
2128 	deUint32 refDpbUsedAndValidMask = 0;
2129 	deUint32 numUsedRef = 0;
2130 	if (videoLoggingEnabled())
2131 		std::cout << "Ref frames data: " << std::endl;
2132 	for (int32_t inIdx = 0; inIdx < HEVC_MAX_DPB_SLOTS; inIdx++) {
2133 		// used_for_reference: 0 = unused, 1 = top_field, 2 = bottom_field, 3 =
2134 		// both_fields
2135 		int8_t picIdx = GetPicIdx(pin->RefPics[inIdx]);
2136 		if (picIdx >= 0) {
2137 			DE_ASSERT(numUsedRef < HEVC_MAX_DPB_SLOTS);
2138 			refOnlyDpbIn[numUsedRef].setReference((pin->IsLongTerm[inIdx] == 1),
2139 												  pin->PicOrderCntVal[inIdx],
2140 												  GetPic(pin->RefPics[inIdx]));
2141 			if (picIdx >= 0) {
2142 				refDpbUsedAndValidMask |= (1 << picIdx);
2143 			}
2144 			refOnlyDpbIn[numUsedRef].originalDpbIndex = inIdx;
2145 			numUsedRef++;
2146 		}
2147 		// Invalidate all slots.
2148 		pReferenceSlots[inIdx].slotIndex = -1;
2149 		pGopReferenceImagesIndexes[inIdx] = -1;
2150 	}
2151 
2152 	if (videoLoggingEnabled())
2153 		std::cout << "Total Ref frames: " << numUsedRef << std::endl;
2154 
2155 	DE_ASSERT(numUsedRef <= m_maxNumDpbSlots);
2156 	DE_ASSERT(numUsedRef <= HEVC_MAX_DPB_SLOTS);
2157 
2158 	// Take into account the reference picture now.
2159 	int8_t currPicIdx = GetPicIdx(pd->pCurrPic);
2160 	DE_ASSERT(currPicIdx >= 0);
2161 	if (currPicIdx >= 0) {
2162 		refDpbUsedAndValidMask |= (1 << currPicIdx);
2163 	}
2164 
2165 	// Map all frames not present in DPB as non-reference, and generate a mask of
2166 	// all used DPB entries
2167 	/* deUint32 destUsedDpbMask = */ ResetPicDpbSlots(refDpbUsedAndValidMask);
2168 
2169 	// Now, map DPB render target indices to internal frame buffer index,
2170 	// assign each reference a unique DPB entry, and create the ordered DPB
2171 	// This is an undocumented MV restriction: the position in the DPB is stored
2172 	// along with the co-located data, so once a reference frame is assigned a DPB
2173 	// entry, it can no longer change.
2174 
2175 	int8_t frmListToDpb[HEVC_MAX_DPB_SLOTS];
2176 	// TODO change to -1 for invalid indexes.
2177 	memset(&frmListToDpb, 0, sizeof(frmListToDpb));
2178 	// Find or allocate slots for existing dpb items.
2179 	for (int32_t dpbIdx = 0; (deUint32)dpbIdx < numUsedRef; dpbIdx++) {
2180 		if (!refOnlyDpbIn[dpbIdx].is_non_existing) {
2181 			vkPicBuffBase* picBuff = refOnlyDpbIn[dpbIdx].m_picBuff;
2182 			int32_t picIdx = GetPicIdx(picBuff); // should always be valid at this point
2183 			DE_ASSERT(picIdx >= 0);
2184 			// We have up to 17 internal frame buffers, but only HEVC_MAX_DPB_SLOTS
2185 			// dpb entries, so we need to re-map the index from the
2186 			// [0..HEVC_MAX_DPB_SLOTS] range to [0..15]
2187 			int8_t dpbSlot = GetPicDpbSlot(picIdx);
2188 			if (dpbSlot < 0) {
2189 				dpbSlot = m_dpb.AllocateSlot();
2190 				DE_ASSERT(dpbSlot >= 0);
2191 				SetPicDpbSlot(picIdx, dpbSlot);
2192 				m_dpb[dpbSlot].setPictureResource(picBuff, m_nCurrentPictureID);
2193 			}
2194 			m_dpb[dpbSlot].MarkInUse(m_nCurrentPictureID);
2195 			DE_ASSERT(dpbSlot >= 0);
2196 
2197 			if (dpbSlot >= 0) {
2198 				refOnlyDpbIn[dpbIdx].dpbSlot = dpbSlot;
2199 				deUint32 originalDpbIndex = refOnlyDpbIn[dpbIdx].originalDpbIndex;
2200 				DE_ASSERT(originalDpbIndex < HEVC_MAX_DPB_SLOTS);
2201 				frmListToDpb[originalDpbIndex] = dpbSlot;
2202 			} else {
2203 				// This should never happen
2204 				printf("DPB mapping logic broken!\n");
2205 				DE_ASSERT(0);
2206 			}
2207 		}
2208 	}
2209 
2210 	// Find or allocate slots for non existing dpb items and populate the slots.
2211 	deUint32 dpbInUseMask = m_dpb.getSlotInUseMask();
2212 	int8_t firstNonExistingDpbSlot = 0;
2213 	for (deUint32 dpbIdx = 0; dpbIdx < numUsedRef; dpbIdx++) {
2214 		int8_t dpbSlot = -1;
2215 		if (refOnlyDpbIn[dpbIdx].is_non_existing) {
2216 			// There shouldn't be  not_existing in h.265
2217 			DE_ASSERT(0);
2218 			DE_ASSERT(refOnlyDpbIn[dpbIdx].m_picBuff == NULL);
2219 			while (((deUint32)firstNonExistingDpbSlot < m_maxNumDpbSlots) && (dpbSlot == -1)) {
2220 				if (!(dpbInUseMask & (1 << firstNonExistingDpbSlot))) {
2221 					dpbSlot = firstNonExistingDpbSlot;
2222 				}
2223 				firstNonExistingDpbSlot++;
2224 			}
2225 			DE_ASSERT((dpbSlot >= 0) && ((deUint32)dpbSlot < m_maxNumDpbSlots));
2226 		} else {
2227 			DE_ASSERT(refOnlyDpbIn[dpbIdx].m_picBuff != NULL);
2228 			dpbSlot = refOnlyDpbIn[dpbIdx].dpbSlot;
2229 		}
2230 		DE_ASSERT((dpbSlot >= 0) && (dpbSlot < HEVC_MAX_DPB_SLOTS));
2231 		refOnlyDpbIn[dpbIdx].setH265PictureData(pDpbSlotInfo, pReferenceSlots,
2232 												dpbIdx, dpbSlot);
2233 		pGopReferenceImagesIndexes[dpbIdx] = GetPicIdx(refOnlyDpbIn[dpbIdx].m_picBuff);
2234 	}
2235 
2236 	if (videoLoggingEnabled()) {
2237 		std::cout << "frmListToDpb:" << std::endl;
2238 		for (int8_t dpbResIdx = 0; dpbResIdx < HEVC_MAX_DPB_SLOTS; dpbResIdx++) {
2239 			std::cout << "\tfrmListToDpb[" << (int32_t)dpbResIdx << "] is "
2240 					  << (int32_t)frmListToDpb[dpbResIdx] << std::endl;
2241 		}
2242 	}
2243 
2244 	int32_t numPocStCurrBefore = 0;
2245 	const size_t maxNumPocStCurrBefore = sizeof(pStdPictureInfo->RefPicSetStCurrBefore) / sizeof(pStdPictureInfo->RefPicSetStCurrBefore[0]);
2246 	DE_ASSERT((size_t)pin->NumPocStCurrBefore <= maxNumPocStCurrBefore);
2247 	if ((size_t)pin->NumPocStCurrBefore > maxNumPocStCurrBefore) {
2248 		tcu::print("\nERROR: FillDpbH265State() pin->NumPocStCurrBefore(%d) must be smaller than maxNumPocStCurrBefore(%zd)\n", pin->NumPocStCurrBefore, maxNumPocStCurrBefore);
2249 	}
2250 	for (int32_t i = 0; i < pin->NumPocStCurrBefore; i++) {
2251 		deUint8 idx = (deUint8)pin->RefPicSetStCurrBefore[i];
2252 		if (idx < HEVC_MAX_DPB_SLOTS) {
2253 			if (videoLoggingEnabled())
2254 				std::cout << "\trefPicSetStCurrBefore[" << i << "] is " << (int32_t)idx
2255 						  << " -> " << (int32_t)frmListToDpb[idx] << std::endl;
2256 			pStdPictureInfo->RefPicSetStCurrBefore[numPocStCurrBefore++] = frmListToDpb[idx] & 0xf;
2257 		}
2258 	}
2259 	while (numPocStCurrBefore < 8) {
2260 		pStdPictureInfo->RefPicSetStCurrBefore[numPocStCurrBefore++] = 0xff;
2261 	}
2262 
2263 	int32_t numPocStCurrAfter = 0;
2264 	const size_t maxNumPocStCurrAfter = sizeof(pStdPictureInfo->RefPicSetStCurrAfter) / sizeof(pStdPictureInfo->RefPicSetStCurrAfter[0]);
2265 	DE_ASSERT((size_t)pin->NumPocStCurrAfter <= maxNumPocStCurrAfter);
2266 	if ((size_t)pin->NumPocStCurrAfter > maxNumPocStCurrAfter) {
2267 		fprintf(stderr, "\nERROR: FillDpbH265State() pin->NumPocStCurrAfter(%d) must be smaller than maxNumPocStCurrAfter(%zd)\n", pin->NumPocStCurrAfter, maxNumPocStCurrAfter);
2268 	}
2269 	for (int32_t i = 0; i < pin->NumPocStCurrAfter; i++) {
2270 		deUint8 idx = (deUint8)pin->RefPicSetStCurrAfter[i];
2271 		if (idx < HEVC_MAX_DPB_SLOTS) {
2272 			if (videoLoggingEnabled())
2273 				std::cout << "\trefPicSetStCurrAfter[" << i << "] is " << (int32_t)idx
2274 						  << " -> " << (int32_t)frmListToDpb[idx] << std::endl;
2275 			pStdPictureInfo->RefPicSetStCurrAfter[numPocStCurrAfter++] = frmListToDpb[idx] & 0xf;
2276 		}
2277 	}
2278 	while (numPocStCurrAfter < 8) {
2279 		pStdPictureInfo->RefPicSetStCurrAfter[numPocStCurrAfter++] = 0xff;
2280 	}
2281 
2282 	int32_t numPocLtCurr = 0;
2283 	const size_t maxNumPocLtCurr = sizeof(pStdPictureInfo->RefPicSetLtCurr) / sizeof(pStdPictureInfo->RefPicSetLtCurr[0]);
2284 	DE_ASSERT((size_t)pin->NumPocLtCurr <= maxNumPocLtCurr);
2285 	if ((size_t)pin->NumPocLtCurr > maxNumPocLtCurr) {
2286 		fprintf(stderr, "\nERROR: FillDpbH265State() pin->NumPocLtCurr(%d) must be smaller than maxNumPocLtCurr(%zd)\n", pin->NumPocLtCurr, maxNumPocLtCurr);
2287 	}
2288 	for (int32_t i = 0; i < pin->NumPocLtCurr; i++) {
2289 		deUint8 idx = (deUint8)pin->RefPicSetLtCurr[i];
2290 		if (idx < HEVC_MAX_DPB_SLOTS) {
2291 			if (videoLoggingEnabled())
2292 				std::cout << "\trefPicSetLtCurr[" << i << "] is " << (int32_t)idx
2293 						  << " -> " << (int32_t)frmListToDpb[idx] << std::endl;
2294 			pStdPictureInfo->RefPicSetLtCurr[numPocLtCurr++] = frmListToDpb[idx] & 0xf;
2295 		}
2296 	}
2297 	while (numPocLtCurr < 8) {
2298 		pStdPictureInfo->RefPicSetLtCurr[numPocLtCurr++] = 0xff;
2299 	}
2300 
2301 	for (int32_t i = 0; i < 8; i++) {
2302 		if (videoLoggingEnabled())
2303 			std::cout << "\tlist indx " << i << ": "
2304 					  << " refPicSetStCurrBefore: "
2305 					  << (int32_t)pStdPictureInfo->RefPicSetStCurrBefore[i]
2306 					  << " refPicSetStCurrAfter: "
2307 					  << (int32_t)pStdPictureInfo->RefPicSetStCurrAfter[i]
2308 					  << " refPicSetLtCurr: "
2309 					  << (int32_t)pStdPictureInfo->RefPicSetLtCurr[i] << std::endl;
2310 	}
2311 
2312 	int8_t dpbSlot = AllocateDpbSlotForCurrentH265(GetPic(pd->pCurrPic),
2313 												   true /* isReference */, pd->current_dpb_id);
2314 	*pCurrAllocatedSlotIndex = dpbSlot;
2315 	DE_ASSERT(!(dpbSlot < 0));
2316 	if (dpbSlot >= 0) {
2317 		DE_ASSERT(pd->ref_pic_flag);
2318 	}
2319 
2320 	return numUsedRef;
2321 }
2322 
AllocateDpbSlotForCurrentH264(vkPicBuffBase * pPic,StdVideoDecodeH264PictureInfoFlags currPicFlags,int8_t)2323 int8_t VideoBaseDecoder::AllocateDpbSlotForCurrentH264 (vkPicBuffBase* pPic, StdVideoDecodeH264PictureInfoFlags currPicFlags,
2324 														int8_t /*presetDpbSlot*/)
2325 {
2326 	// Now, map the current render target
2327 	int8_t dpbSlot = -1;
2328 	int8_t currPicIdx = GetPicIdx(pPic);
2329 	DE_ASSERT(currPicIdx >= 0);
2330 	SetFieldPicFlag(currPicIdx, currPicFlags.field_pic_flag);
2331 	// In Vulkan we always allocate reference slot for the current picture.
2332 	if (true /* currPicFlags.is_reference */) {
2333 		dpbSlot = GetPicDpbSlot(currPicIdx);
2334 		if (dpbSlot < 0) {
2335 			dpbSlot = m_dpb.AllocateSlot();
2336 			DE_ASSERT(dpbSlot >= 0);
2337 			SetPicDpbSlot(currPicIdx, dpbSlot);
2338 			m_dpb[dpbSlot].setPictureResource(pPic, m_nCurrentPictureID);
2339 		}
2340 		DE_ASSERT(dpbSlot >= 0);
2341 	}
2342 	return dpbSlot;
2343 }
2344 
AllocateDpbSlotForCurrentH265(vkPicBuffBase * pPic,bool isReference,int8_t)2345 int8_t VideoBaseDecoder::AllocateDpbSlotForCurrentH265 (vkPicBuffBase* pPic,
2346 														bool isReference, int8_t /*presetDpbSlot*/)
2347 {
2348 	// Now, map the current render target
2349 	int8_t dpbSlot = -1;
2350 	int8_t currPicIdx = GetPicIdx(pPic);
2351 	DE_ASSERT(currPicIdx >= 0);
2352 	DE_ASSERT(isReference);
2353 	if (isReference) {
2354 		dpbSlot = GetPicDpbSlot(currPicIdx);
2355 		if (dpbSlot < 0) {
2356 			dpbSlot = m_dpb.AllocateSlot();
2357 			DE_ASSERT(dpbSlot >= 0);
2358 			SetPicDpbSlot(currPicIdx, dpbSlot);
2359 			m_dpb[dpbSlot].setPictureResource(pPic, m_nCurrentPictureID);
2360 		}
2361 		DE_ASSERT(dpbSlot >= 0);
2362 	}
2363 	return dpbSlot;
2364 }
2365 
getRecommendedFormat(const vector<VkFormat> & formats,VkFormat recommendedFormat)2366 VkFormat getRecommendedFormat (const vector<VkFormat>& formats, VkFormat recommendedFormat)
2367 {
2368 	if (formats.empty())
2369 		return VK_FORMAT_UNDEFINED;
2370 	else if (recommendedFormat != VK_FORMAT_UNDEFINED && std::find(formats.begin(), formats.end(), recommendedFormat) != formats.end())
2371 		return recommendedFormat;
2372 	else
2373 		return formats[0];
2374 }
2375 
Create(DeviceContext & vkDevCtx,deUint32 videoQueueFamily,VkVideoCoreProfile * pVideoProfile,VkFormat pictureFormat,const VkExtent2D & maxCodedExtent,VkFormat referencePicturesFormat,deUint32 maxDpbSlots,deUint32 maxActiveReferencePictures,VkSharedBaseObj<VulkanVideoSession> & videoSession)2376 VkResult VulkanVideoSession::Create(DeviceContext& vkDevCtx,
2377 								   deUint32            videoQueueFamily,
2378 								   VkVideoCoreProfile* pVideoProfile,
2379 								   VkFormat            pictureFormat,
2380 								   const VkExtent2D&   maxCodedExtent,
2381 								   VkFormat            referencePicturesFormat,
2382 								   deUint32            maxDpbSlots,
2383 								   deUint32            maxActiveReferencePictures,
2384 								   VkSharedBaseObj<VulkanVideoSession>& videoSession)
2385 {
2386 	auto& vk = vkDevCtx.getDeviceDriver();
2387 	auto device = vkDevCtx.device;
2388 
2389 	VulkanVideoSession* pNewVideoSession = new VulkanVideoSession(vkDevCtx, pVideoProfile);
2390 
2391 	static const VkExtensionProperties h264DecodeStdExtensionVersion = { VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION };
2392 	static const VkExtensionProperties h265DecodeStdExtensionVersion = { VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION };
2393 	static const VkExtensionProperties h264EncodeStdExtensionVersion = { VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME, VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION };
2394 	static const VkExtensionProperties h265EncodeStdExtensionVersion = { VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME, VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION };
2395 
2396 	VkVideoSessionCreateInfoKHR& createInfo = pNewVideoSession->m_createInfo;
2397 	createInfo.flags = 0;
2398 	createInfo.pVideoProfile = pVideoProfile->GetProfile();
2399 	createInfo.queueFamilyIndex = videoQueueFamily;
2400 	createInfo.pictureFormat = pictureFormat;
2401 	createInfo.maxCodedExtent = maxCodedExtent;
2402 	createInfo.maxDpbSlots = maxDpbSlots;
2403 	createInfo.maxActiveReferencePictures = maxActiveReferencePictures;
2404 	createInfo.referencePictureFormat = referencePicturesFormat;
2405 
2406 	switch ((int32_t)pVideoProfile->GetCodecType()) {
2407 		case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
2408 			createInfo.pStdHeaderVersion = &h264DecodeStdExtensionVersion;
2409 			break;
2410 		case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
2411 			createInfo.pStdHeaderVersion = &h265DecodeStdExtensionVersion;
2412 			break;
2413 		case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT:
2414 			createInfo.pStdHeaderVersion = &h264EncodeStdExtensionVersion;
2415 			break;
2416 		case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT:
2417 			createInfo.pStdHeaderVersion = &h265EncodeStdExtensionVersion;
2418 			break;
2419 		default:
2420 			DE_ASSERT(0);
2421 	}
2422 	VkResult result = vk.createVideoSessionKHR(device, &createInfo, NULL, &pNewVideoSession->m_videoSession);
2423 	if (result != VK_SUCCESS) {
2424 		return result;
2425 	}
2426 
2427 	deUint32 videoSessionMemoryRequirementsCount = 0;
2428 	VkVideoSessionMemoryRequirementsKHR decodeSessionMemoryRequirements[MAX_BOUND_MEMORY];
2429 	// Get the count first
2430 	result = vk.getVideoSessionMemoryRequirementsKHR(device, pNewVideoSession->m_videoSession,
2431 															&videoSessionMemoryRequirementsCount, NULL);
2432 	DE_ASSERT(result == VK_SUCCESS);
2433 	DE_ASSERT(videoSessionMemoryRequirementsCount <= MAX_BOUND_MEMORY);
2434 
2435 	memset(decodeSessionMemoryRequirements, 0x00, sizeof(decodeSessionMemoryRequirements));
2436 	for (deUint32 i = 0; i < videoSessionMemoryRequirementsCount; i++) {
2437 		decodeSessionMemoryRequirements[i].sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR;
2438 	}
2439 
2440 	result = vk.getVideoSessionMemoryRequirementsKHR(device, pNewVideoSession->m_videoSession,
2441 															&videoSessionMemoryRequirementsCount,
2442 															decodeSessionMemoryRequirements);
2443 	if (result != VK_SUCCESS) {
2444 		return result;
2445 	}
2446 
2447 	deUint32 decodeSessionBindMemoryCount = videoSessionMemoryRequirementsCount;
2448 	VkBindVideoSessionMemoryInfoKHR decodeSessionBindMemory[MAX_BOUND_MEMORY];
2449 
2450 	for (deUint32 memIdx = 0; memIdx < decodeSessionBindMemoryCount; memIdx++) {
2451 
2452 		deUint32 memoryTypeIndex = 0;
2453 		deUint32 memoryTypeBits = decodeSessionMemoryRequirements[memIdx].memoryRequirements.memoryTypeBits;
2454 		if (memoryTypeBits == 0) {
2455 			return VK_ERROR_INITIALIZATION_FAILED;
2456 		}
2457 
2458 		// Find an available memory type that satisfies the requested properties.
2459 		for (; !(memoryTypeBits & 1); memoryTypeIndex++  ) {
2460 			memoryTypeBits >>= 1;
2461 		}
2462 
2463 		VkMemoryAllocateInfo memInfo = {
2464 				VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,                          // sType
2465 				NULL,                                                            // pNext
2466 				decodeSessionMemoryRequirements[memIdx].memoryRequirements.size, // allocationSize
2467 				memoryTypeIndex,                                                 // memoryTypeIndex
2468 		};
2469 
2470 		result = vk.allocateMemory(device, &memInfo, 0,
2471 										  &pNewVideoSession->m_memoryBound[memIdx]);
2472 		if (result != VK_SUCCESS) {
2473 			return result;
2474 		}
2475 
2476 		DE_ASSERT(result == VK_SUCCESS);
2477 		decodeSessionBindMemory[memIdx].pNext = NULL;
2478 		decodeSessionBindMemory[memIdx].sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR;
2479 		decodeSessionBindMemory[memIdx].memory = pNewVideoSession->m_memoryBound[memIdx];
2480 
2481 		decodeSessionBindMemory[memIdx].memoryBindIndex = decodeSessionMemoryRequirements[memIdx].memoryBindIndex;
2482 		decodeSessionBindMemory[memIdx].memoryOffset = 0;
2483 		decodeSessionBindMemory[memIdx].memorySize = decodeSessionMemoryRequirements[memIdx].memoryRequirements.size;
2484 	}
2485 
2486 	result = vk.bindVideoSessionMemoryKHR(device, pNewVideoSession->m_videoSession, decodeSessionBindMemoryCount,
2487 												 decodeSessionBindMemory);
2488 	DE_ASSERT(result == VK_SUCCESS);
2489 
2490 	videoSession = pNewVideoSession;
2491 
2492 	// Make sure we do not use dangling (on the stack) pointers
2493 	createInfo.pNext = nullptr;
2494 
2495 	return result;
2496 }
2497 
2498 
2499 
2500 
2501 
2502 
Create(DeviceContext & vkDevCtx,const VkImageCreateInfo * pImageCreateInfo,VkSharedBaseObj<VkImageResource> & imageResource)2503 VkResult VkImageResource::Create(DeviceContext&					   vkDevCtx,
2504 								 const VkImageCreateInfo*		   pImageCreateInfo,
2505 								 VkSharedBaseObj<VkImageResource>& imageResource)
2506 {
2507 	imageResource = new VkImageResource(vkDevCtx,
2508 										pImageCreateInfo);
2509 
2510 	return VK_SUCCESS;
2511 }
2512 
Create(DeviceContext & vkDevCtx,VkSharedBaseObj<VkImageResource> & imageResource,VkImageSubresourceRange & imageSubresourceRange,VkSharedBaseObj<VkImageResourceView> & imageResourceView)2513 VkResult VkImageResourceView::Create(DeviceContext& vkDevCtx,
2514 									 VkSharedBaseObj<VkImageResource>& imageResource,
2515 									 VkImageSubresourceRange &imageSubresourceRange,
2516 									 VkSharedBaseObj<VkImageResourceView>& imageResourceView)
2517 {
2518 	auto& vk = vkDevCtx.getDeviceDriver();
2519 	VkDevice device = vkDevCtx.device;
2520 	VkImageView  imageView;
2521 	VkImageViewCreateInfo viewInfo = VkImageViewCreateInfo();
2522 	viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
2523 	viewInfo.pNext = nullptr;
2524 	viewInfo.image = imageResource->GetImage();
2525 	viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
2526 	viewInfo.format = imageResource->GetImageCreateInfo().format;
2527 	viewInfo.components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
2528 							VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
2529 	viewInfo.subresourceRange = imageSubresourceRange;
2530 	viewInfo.flags = 0;
2531 	VkResult result = vk.createImageView(device, &viewInfo, nullptr, &imageView);
2532 	if (result != VK_SUCCESS) {
2533 		return result;
2534 	}
2535 
2536 	imageResourceView = new VkImageResourceView(vkDevCtx, imageResource,
2537 												imageView, imageSubresourceRange);
2538 
2539 	return result;
2540 }
2541 
~VkImageResourceView()2542 VkImageResourceView::~VkImageResourceView()
2543 {
2544 	auto& vk = m_vkDevCtx.getDeviceDriver();
2545 	auto device = m_vkDevCtx.device;
2546 
2547 	if (m_imageView != VK_NULL_HANDLE) {
2548 		vk.destroyImageView(device, m_imageView, nullptr);
2549 		m_imageView = VK_NULL_HANDLE;
2550 	}
2551 
2552 	m_imageResource = nullptr;
2553 }
2554 
2555 
2556 const char* VkParserVideoPictureParameters::m_refClassId = "VkParserVideoPictureParameters";
2557 int32_t VkParserVideoPictureParameters::m_currentId = 0;
2558 
PopulateH264UpdateFields(const StdVideoPictureParametersSet * pStdPictureParametersSet,VkVideoDecodeH264SessionParametersAddInfoKHR & h264SessionParametersAddInfo)2559 int32_t VkParserVideoPictureParameters::PopulateH264UpdateFields(const StdVideoPictureParametersSet* pStdPictureParametersSet,
2560 																 VkVideoDecodeH264SessionParametersAddInfoKHR& h264SessionParametersAddInfo)
2561 {
2562 	int32_t currentId = -1;
2563 	if (pStdPictureParametersSet == nullptr) {
2564 		return currentId;
2565 	}
2566 
2567 	DE_ASSERT( (pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H264_SPS) ||
2568 			(pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H264_PPS));
2569 
2570 	DE_ASSERT(h264SessionParametersAddInfo.sType == VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR);
2571 
2572 	if (pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H264_SPS) {
2573 		h264SessionParametersAddInfo.stdSPSCount = 1;
2574 		h264SessionParametersAddInfo.pStdSPSs = pStdPictureParametersSet->GetStdH264Sps();
2575 		bool isSps = false;
2576 		currentId = pStdPictureParametersSet->GetSpsId(isSps);
2577 		DE_ASSERT(isSps);
2578 	} else if (pStdPictureParametersSet->GetStdType() ==  StdVideoPictureParametersSet::TYPE_H264_PPS ) {
2579 		h264SessionParametersAddInfo.stdPPSCount = 1;
2580 		h264SessionParametersAddInfo.pStdPPSs = pStdPictureParametersSet->GetStdH264Pps();
2581 		bool isPps = false;
2582 		currentId = pStdPictureParametersSet->GetPpsId(isPps);
2583 		DE_ASSERT(isPps);
2584 	} else {
2585 		DE_ASSERT(!"Incorrect h.264 type");
2586 	}
2587 
2588 	return currentId;
2589 }
2590 
PopulateH265UpdateFields(const StdVideoPictureParametersSet * pStdPictureParametersSet,VkVideoDecodeH265SessionParametersAddInfoKHR & h265SessionParametersAddInfo)2591 int32_t VkParserVideoPictureParameters::PopulateH265UpdateFields(const StdVideoPictureParametersSet* pStdPictureParametersSet,
2592 																 VkVideoDecodeH265SessionParametersAddInfoKHR& h265SessionParametersAddInfo)
2593 {
2594 	int32_t currentId = -1;
2595 	if (pStdPictureParametersSet == nullptr) {
2596 		return currentId;
2597 	}
2598 
2599 	DE_ASSERT( (pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H265_VPS) ||
2600 			(pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H265_SPS) ||
2601 			(pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H265_PPS));
2602 
2603 	DE_ASSERT(h265SessionParametersAddInfo.sType == VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR);
2604 
2605 	if (pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H265_VPS) {
2606 		h265SessionParametersAddInfo.stdVPSCount = 1;
2607 		h265SessionParametersAddInfo.pStdVPSs = pStdPictureParametersSet->GetStdH265Vps();
2608 		bool isVps = false;
2609 		currentId = pStdPictureParametersSet->GetVpsId(isVps);
2610 		DE_ASSERT(isVps);
2611 	} else if (pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H265_SPS) {
2612 		h265SessionParametersAddInfo.stdSPSCount = 1;
2613 		h265SessionParametersAddInfo.pStdSPSs = pStdPictureParametersSet->GetStdH265Sps();
2614 		bool isSps = false;
2615 		currentId = pStdPictureParametersSet->GetSpsId(isSps);
2616 		DE_ASSERT(isSps);
2617 	} else if (pStdPictureParametersSet->GetStdType() == StdVideoPictureParametersSet::TYPE_H265_PPS) {
2618 		h265SessionParametersAddInfo.stdPPSCount = 1;
2619 		h265SessionParametersAddInfo.pStdPPSs = pStdPictureParametersSet->GetStdH265Pps();
2620 		bool isPps = false;
2621 		currentId = pStdPictureParametersSet->GetPpsId(isPps);
2622 		DE_ASSERT(isPps);
2623 	} else {
2624 		DE_ASSERT(!"Incorrect h.265 type");
2625 	}
2626 
2627 	return currentId;
2628 }
2629 
2630 VkResult
Create(DeviceContext & deviceContext,VkSharedBaseObj<VkParserVideoPictureParameters> & templatePictureParameters,VkSharedBaseObj<VkParserVideoPictureParameters> & videoPictureParameters)2631 VkParserVideoPictureParameters::Create(DeviceContext& deviceContext,
2632 									   VkSharedBaseObj<VkParserVideoPictureParameters>& templatePictureParameters,
2633 									   VkSharedBaseObj<VkParserVideoPictureParameters>& videoPictureParameters)
2634 {
2635 	VkSharedBaseObj<VkParserVideoPictureParameters> newVideoPictureParameters(
2636 			new VkParserVideoPictureParameters(deviceContext, templatePictureParameters));
2637 	if (!newVideoPictureParameters) {
2638 		return VK_ERROR_OUT_OF_HOST_MEMORY;
2639 	}
2640 
2641 	videoPictureParameters = newVideoPictureParameters;
2642 	return VK_SUCCESS;
2643 }
2644 
CreateParametersObject(VkSharedBaseObj<VulkanVideoSession> & videoSession,const StdVideoPictureParametersSet * pStdVideoPictureParametersSet,VkParserVideoPictureParameters * pTemplatePictureParameters)2645 VkResult VkParserVideoPictureParameters::CreateParametersObject(VkSharedBaseObj<VulkanVideoSession>& videoSession,
2646 																const StdVideoPictureParametersSet* pStdVideoPictureParametersSet,
2647 																VkParserVideoPictureParameters* pTemplatePictureParameters)
2648 {
2649 	int32_t currentId = -1;
2650 
2651 	VkVideoSessionParametersCreateInfoKHR createInfo{};
2652 	createInfo.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR;
2653 
2654 	VkVideoDecodeH264SessionParametersCreateInfoKHR h264SessionParametersCreateInfo{};
2655 	h264SessionParametersCreateInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR;
2656 	VkVideoDecodeH264SessionParametersAddInfoKHR h264SessionParametersAddInfo{};
2657 	h264SessionParametersAddInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR;
2658 
2659 	VkVideoDecodeH265SessionParametersCreateInfoKHR h265SessionParametersCreateInfo{};
2660 	h265SessionParametersCreateInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR;
2661 	VkVideoDecodeH265SessionParametersAddInfoKHR h265SessionParametersAddInfo{};
2662 	h265SessionParametersAddInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR;
2663 
2664 	StdVideoPictureParametersSet::StdType updateType = pStdVideoPictureParametersSet->GetStdType();
2665 	switch (updateType)
2666 	{
2667 		case StdVideoPictureParametersSet::TYPE_H264_SPS:
2668 		case StdVideoPictureParametersSet::TYPE_H264_PPS:
2669 		{
2670 			createInfo.pNext =  &h264SessionParametersCreateInfo;
2671 			h264SessionParametersCreateInfo.maxStdSPSCount = MAX_SPS_IDS;
2672 			h264SessionParametersCreateInfo.maxStdPPSCount = MAX_PPS_IDS;
2673 			h264SessionParametersCreateInfo.pParametersAddInfo = &h264SessionParametersAddInfo;
2674 
2675 			currentId = PopulateH264UpdateFields(pStdVideoPictureParametersSet, h264SessionParametersAddInfo);
2676 
2677 		}
2678 			break;
2679 		case StdVideoPictureParametersSet::TYPE_H265_VPS:
2680 		case StdVideoPictureParametersSet::TYPE_H265_SPS:
2681 		case StdVideoPictureParametersSet::TYPE_H265_PPS:
2682 		{
2683 			createInfo.pNext =  &h265SessionParametersCreateInfo;
2684 			h265SessionParametersCreateInfo.maxStdVPSCount = MAX_VPS_IDS;
2685 			h265SessionParametersCreateInfo.maxStdSPSCount = MAX_SPS_IDS;
2686 			h265SessionParametersCreateInfo.maxStdPPSCount = MAX_PPS_IDS;
2687 			h265SessionParametersCreateInfo.pParametersAddInfo = &h265SessionParametersAddInfo;
2688 
2689 			currentId = PopulateH265UpdateFields(pStdVideoPictureParametersSet, h265SessionParametersAddInfo);
2690 		}
2691 			break;
2692 		default:
2693 			DE_ASSERT(!"Invalid Parser format");
2694 			return VK_ERROR_INITIALIZATION_FAILED;
2695 	}
2696 
2697 	createInfo.videoSessionParametersTemplate = pTemplatePictureParameters ? VkVideoSessionParametersKHR(*pTemplatePictureParameters) : VK_NULL_HANDLE;
2698 	createInfo.videoSession = videoSession->GetVideoSession();
2699 	VkResult result = m_deviceContext.getDeviceDriver().createVideoSessionParametersKHR(m_deviceContext.device,
2700 																&createInfo,
2701 																nullptr,
2702 																&m_sessionParameters);
2703 
2704 	if (result != VK_SUCCESS) {
2705 
2706 		DE_ASSERT(!"Could not create Session Parameters Object");
2707 		return result;
2708 
2709 	} else {
2710 
2711 		m_videoSession = videoSession;
2712 
2713 		if (pTemplatePictureParameters) {
2714 			m_vpsIdsUsed = pTemplatePictureParameters->m_vpsIdsUsed;
2715 			m_spsIdsUsed = pTemplatePictureParameters->m_spsIdsUsed;
2716 			m_ppsIdsUsed = pTemplatePictureParameters->m_ppsIdsUsed;
2717 		}
2718 
2719 		assert (currentId >= 0);
2720 		switch (pStdVideoPictureParametersSet->GetParameterType()) {
2721 			case StdVideoPictureParametersSet::PPS_TYPE:
2722 				m_ppsIdsUsed.set(currentId, true);
2723 				break;
2724 
2725 			case StdVideoPictureParametersSet::SPS_TYPE:
2726 				m_spsIdsUsed.set(currentId, true);
2727 				break;
2728 
2729 			case StdVideoPictureParametersSet::VPS_TYPE:
2730 				m_vpsIdsUsed.set(currentId, true);
2731 				break;
2732 			default:
2733 				DE_ASSERT(!"Invalid StdVideoPictureParametersSet Parameter Type!");
2734 		}
2735 		m_Id = ++m_currentId;
2736 	}
2737 
2738 	return result;
2739 }
2740 
UpdateParametersObject(StdVideoPictureParametersSet * pStdVideoPictureParametersSet)2741 VkResult VkParserVideoPictureParameters::UpdateParametersObject(StdVideoPictureParametersSet* pStdVideoPictureParametersSet)
2742 {
2743 	if (pStdVideoPictureParametersSet == nullptr) {
2744 		return VK_SUCCESS;
2745 	}
2746 
2747 	int32_t currentId = -1;
2748 	VkVideoSessionParametersUpdateInfoKHR updateInfo{};
2749 	updateInfo.sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR;
2750 	VkVideoDecodeH264SessionParametersAddInfoKHR h264SessionParametersAddInfo{};
2751 	h264SessionParametersAddInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_KHR;
2752 	VkVideoDecodeH265SessionParametersAddInfoKHR h265SessionParametersAddInfo{};
2753 	h265SessionParametersAddInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_KHR;
2754 
2755 	StdVideoPictureParametersSet::StdType updateType = pStdVideoPictureParametersSet->GetStdType();
2756 	switch (updateType)
2757 	{
2758 		case StdVideoPictureParametersSet::TYPE_H264_SPS:
2759 		case StdVideoPictureParametersSet::TYPE_H264_PPS:
2760 		{
2761 			updateInfo.pNext = &h264SessionParametersAddInfo;
2762 			currentId = PopulateH264UpdateFields(pStdVideoPictureParametersSet, h264SessionParametersAddInfo);
2763 		}
2764 			break;
2765 		case StdVideoPictureParametersSet::TYPE_H265_VPS:
2766 		case StdVideoPictureParametersSet::TYPE_H265_SPS:
2767 		case StdVideoPictureParametersSet::TYPE_H265_PPS:
2768 		{
2769 			updateInfo.pNext = &h265SessionParametersAddInfo;
2770 			currentId = PopulateH265UpdateFields(pStdVideoPictureParametersSet, h265SessionParametersAddInfo);
2771 		}
2772 			break;
2773 		default:
2774 			DE_ASSERT(!"Invalid Parser format");
2775 			return VK_ERROR_INITIALIZATION_FAILED;
2776 	}
2777 
2778 	updateInfo.updateSequenceCount = ++m_updateCount;
2779 	VK_CHECK(m_deviceContext.getDeviceDriver().updateVideoSessionParametersKHR(m_deviceContext.device,
2780 																			   m_sessionParameters,
2781 																			   &updateInfo));
2782 
2783 
2784 	DE_ASSERT(currentId >= 0);
2785 	switch (pStdVideoPictureParametersSet->GetParameterType()) {
2786 		case StdVideoPictureParametersSet::PPS_TYPE:
2787 			m_ppsIdsUsed.set(currentId, true);
2788 			break;
2789 
2790 		case StdVideoPictureParametersSet::SPS_TYPE:
2791 			m_spsIdsUsed.set(currentId, true);
2792 			break;
2793 
2794 		case StdVideoPictureParametersSet::VPS_TYPE:
2795 			m_vpsIdsUsed.set(currentId, true);
2796 			break;
2797 		default:
2798 			DE_ASSERT(!"Invalid StdVideoPictureParametersSet Parameter Type!");
2799 	}
2800 
2801 	return VK_SUCCESS;
2802 }
2803 
~VkParserVideoPictureParameters()2804 VkParserVideoPictureParameters::~VkParserVideoPictureParameters()
2805 {
2806 	if (!!m_sessionParameters) {
2807 		m_deviceContext.getDeviceDriver().destroyVideoSessionParametersKHR(m_deviceContext.device, m_sessionParameters, nullptr);
2808 		m_sessionParameters = VK_NULL_HANDLE;
2809 	}
2810 	m_videoSession = nullptr;
2811 }
2812 
UpdatePictureParametersHierarchy(VkSharedBaseObj<StdVideoPictureParametersSet> & pictureParametersObject)2813 bool VkParserVideoPictureParameters::UpdatePictureParametersHierarchy(
2814 		VkSharedBaseObj<StdVideoPictureParametersSet>& pictureParametersObject)
2815 {
2816 	int32_t nodeId = -1;
2817 	bool isNodeId = false;
2818 	StdVideoPictureParametersSet::ParameterType nodeParent = StdVideoPictureParametersSet::INVALID_TYPE;
2819 	StdVideoPictureParametersSet::ParameterType nodeChild = StdVideoPictureParametersSet::INVALID_TYPE;
2820 	switch (pictureParametersObject->GetParameterType()) {
2821 		case StdVideoPictureParametersSet::PPS_TYPE:
2822 			nodeParent = StdVideoPictureParametersSet::SPS_TYPE;
2823 			nodeId = pictureParametersObject->GetPpsId(isNodeId);
2824 			if (!((deUint32)nodeId < VkParserVideoPictureParameters::MAX_PPS_IDS)) {
2825 				DE_ASSERT(!"PPS ID is out of bounds");
2826 				return false;
2827 			}
2828 			DE_ASSERT(isNodeId);
2829 			if (m_lastPictParamsQueue[nodeParent]) {
2830 				bool isParentId = false;
2831 				const int32_t spsParentId = pictureParametersObject->GetSpsId(isParentId);
2832 				DE_ASSERT(!isParentId);
2833 				if (spsParentId == m_lastPictParamsQueue[nodeParent]->GetSpsId(isParentId)) {
2834 					DE_ASSERT(isParentId);
2835 					pictureParametersObject->m_parent = m_lastPictParamsQueue[nodeParent];
2836 				}
2837 			}
2838 			break;
2839 		case StdVideoPictureParametersSet::SPS_TYPE:
2840 			nodeParent = StdVideoPictureParametersSet::VPS_TYPE;
2841 			nodeChild = StdVideoPictureParametersSet::PPS_TYPE;
2842 			nodeId = pictureParametersObject->GetSpsId(isNodeId);
2843 			if (!((deUint32)nodeId < VkParserVideoPictureParameters::MAX_SPS_IDS)) {
2844 				DE_ASSERT(!"SPS ID is out of bounds");
2845 				return false;
2846 			}
2847 			DE_ASSERT(isNodeId);
2848 			if (m_lastPictParamsQueue[nodeChild]) {
2849 				const int32_t spsChildId = m_lastPictParamsQueue[nodeChild]->GetSpsId(isNodeId);
2850 				DE_ASSERT(!isNodeId);
2851 				if (spsChildId == nodeId) {
2852 					m_lastPictParamsQueue[nodeChild]->m_parent = pictureParametersObject;
2853 				}
2854 			}
2855 			if (m_lastPictParamsQueue[nodeParent]) {
2856 				const int32_t vpsParentId = pictureParametersObject->GetVpsId(isNodeId);
2857 				DE_ASSERT(!isNodeId);
2858 				if (vpsParentId == m_lastPictParamsQueue[nodeParent]->GetVpsId(isNodeId)) {
2859 					pictureParametersObject->m_parent = m_lastPictParamsQueue[nodeParent];
2860 					DE_ASSERT(isNodeId);
2861 				}
2862 			}
2863 			break;
2864 		case StdVideoPictureParametersSet::VPS_TYPE:
2865 			nodeChild = StdVideoPictureParametersSet::SPS_TYPE;
2866 			nodeId = pictureParametersObject->GetVpsId(isNodeId);
2867 			if (!((deUint32)nodeId < VkParserVideoPictureParameters::MAX_VPS_IDS)) {
2868 				DE_ASSERT(!"VPS ID is out of bounds");
2869 				return false;
2870 			}
2871 			DE_ASSERT(isNodeId);
2872 			if (m_lastPictParamsQueue[nodeChild]) {
2873 				const int32_t vpsParentId = m_lastPictParamsQueue[nodeChild]->GetVpsId(isNodeId);
2874 				DE_ASSERT(!isNodeId);
2875 				if (vpsParentId == nodeId) {
2876 					m_lastPictParamsQueue[nodeChild]->m_parent = pictureParametersObject;
2877 				}
2878 			}
2879 			break;
2880 		default:
2881 			DE_ASSERT("!Invalid STD type");
2882 			return false;
2883 	}
2884 	m_lastPictParamsQueue[pictureParametersObject->GetParameterType()] = pictureParametersObject;
2885 
2886 	return true;
2887 }
2888 
AddPictureParametersToQueue(VkSharedBaseObj<StdVideoPictureParametersSet> & pictureParametersSet)2889 VkResult VkParserVideoPictureParameters::AddPictureParametersToQueue(VkSharedBaseObj<StdVideoPictureParametersSet>& pictureParametersSet)
2890 {
2891 	m_pictureParametersQueue.push(pictureParametersSet);
2892 	return VK_SUCCESS;
2893 }
2894 
HandleNewPictureParametersSet(VkSharedBaseObj<VulkanVideoSession> & videoSession,StdVideoPictureParametersSet * pStdVideoPictureParametersSet)2895 VkResult VkParserVideoPictureParameters::HandleNewPictureParametersSet(VkSharedBaseObj<VulkanVideoSession>& videoSession,
2896 																	   StdVideoPictureParametersSet* pStdVideoPictureParametersSet)
2897 {
2898 	VkResult result;
2899 	if (m_sessionParameters == VK_NULL_HANDLE) {
2900 		DE_ASSERT(videoSession != VK_NULL_HANDLE);
2901 		DE_ASSERT(m_videoSession == VK_NULL_HANDLE);
2902 		if (m_templatePictureParameters) {
2903 			m_templatePictureParameters->FlushPictureParametersQueue(videoSession);
2904 		}
2905 		result = CreateParametersObject(videoSession, pStdVideoPictureParametersSet,
2906 										m_templatePictureParameters);
2907 		DE_ASSERT(result == VK_SUCCESS);
2908 		m_templatePictureParameters = nullptr; // the template object is not needed anymore
2909 		m_videoSession = videoSession;
2910 
2911 	} else {
2912 		DE_ASSERT(m_videoSession != VK_NULL_HANDLE);
2913 		DE_ASSERT(m_sessionParameters != VK_NULL_HANDLE);
2914 		result = UpdateParametersObject(pStdVideoPictureParametersSet);
2915 		DE_ASSERT(result == VK_SUCCESS);
2916 	}
2917 
2918 	return result;
2919 }
2920 
2921 
FlushPictureParametersQueue(VkSharedBaseObj<VulkanVideoSession> & videoSession)2922 int32_t VkParserVideoPictureParameters::FlushPictureParametersQueue(VkSharedBaseObj<VulkanVideoSession>& videoSession)
2923 {
2924 	if (!videoSession) {
2925 		return -1;
2926 	}
2927 	deUint32 numQueueItems = 0;
2928 	while (!m_pictureParametersQueue.empty()) {
2929 		VkSharedBaseObj<StdVideoPictureParametersSet>& stdVideoPictureParametersSet = m_pictureParametersQueue.front();
2930 
2931 		VkResult result =  HandleNewPictureParametersSet(videoSession, stdVideoPictureParametersSet);
2932 		if (result != VK_SUCCESS) {
2933 			return -1;
2934 		}
2935 
2936 		m_pictureParametersQueue.pop();
2937 		numQueueItems++;
2938 	}
2939 
2940 	return numQueueItems;
2941 }
2942 
CheckStdObjectBeforeUpdate(VkSharedBaseObj<StdVideoPictureParametersSet> & stdPictureParametersSet,VkSharedBaseObj<VkParserVideoPictureParameters> & currentVideoPictureParameters)2943 bool VkParserVideoPictureParameters::CheckStdObjectBeforeUpdate(VkSharedBaseObj<StdVideoPictureParametersSet>& stdPictureParametersSet,
2944 																VkSharedBaseObj<VkParserVideoPictureParameters>& currentVideoPictureParameters)
2945 {
2946 	if (!stdPictureParametersSet) {
2947 		return false;
2948 	}
2949 
2950 	bool stdObjectUpdate = (stdPictureParametersSet->GetUpdateSequenceCount() > 0);
2951 
2952 	if (!currentVideoPictureParameters || stdObjectUpdate) {
2953 
2954 		// Create new Vulkan Picture Parameters object
2955 		return true;
2956 
2957 	} else { // existing VkParserVideoPictureParameters object
2958 		DE_ASSERT(currentVideoPictureParameters);
2959 		// Update with the existing Vulkan Picture Parameters object
2960 	}
2961 
2962 	VkSharedBaseObj<VkVideoRefCountBase> clientObject;
2963 	stdPictureParametersSet->GetClientObject(clientObject);
2964 	DE_ASSERT(!clientObject);
2965 
2966 	return false;
2967 }
2968 
2969 VkResult
AddPictureParameters(DeviceContext & deviceContext,VkSharedBaseObj<VulkanVideoSession> &,VkSharedBaseObj<StdVideoPictureParametersSet> & stdPictureParametersSet,VkSharedBaseObj<VkParserVideoPictureParameters> & currentVideoPictureParameters)2970 VkParserVideoPictureParameters::AddPictureParameters(DeviceContext& deviceContext,
2971 													 VkSharedBaseObj<VulkanVideoSession>& /*videoSession*/,
2972 													 VkSharedBaseObj<StdVideoPictureParametersSet>& stdPictureParametersSet,
2973 													 VkSharedBaseObj<VkParserVideoPictureParameters>& currentVideoPictureParameters)
2974 {
2975 	if (!stdPictureParametersSet) {
2976 		return VK_ERROR_INITIALIZATION_FAILED;
2977 	}
2978 
2979 	VkResult result;
2980 	if (CheckStdObjectBeforeUpdate(stdPictureParametersSet, currentVideoPictureParameters)) {
2981 		result = VkParserVideoPictureParameters::Create(deviceContext,
2982 														currentVideoPictureParameters,
2983 														currentVideoPictureParameters);
2984 	}
2985 
2986 	result = currentVideoPictureParameters->AddPictureParametersToQueue(stdPictureParametersSet);
2987 
2988 	return result;
2989 }
2990 
2991 
AddRef()2992 int32_t VkParserVideoPictureParameters::AddRef()
2993 {
2994 	return ++m_refCount;
2995 }
2996 
Release()2997 int32_t VkParserVideoPictureParameters::Release()
2998 {
2999 	deUint32 ret;
3000 	ret = --m_refCount;
3001 	// Destroy the device if refcount reaches zero
3002 	if (ret == 0) {
3003 		delete this;
3004 	}
3005 	return ret;
3006 }
3007 
3008 }	// video
3009 }	// vkt
3010