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