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 &¶ms)
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> ¤tVideoPictureParameters)
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 ¤tVideoPictureParameters /* 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