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