1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci* Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci* ------------------------
4e5c31af7Sopenharmony_ci*
5e5c31af7Sopenharmony_ci* Copyright (c) 2023 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci*
7e5c31af7Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci* you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci* You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci*
11e5c31af7Sopenharmony_ci*	  http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci*
13e5c31af7Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci* See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci* limitations under the License.
18e5c31af7Sopenharmony_ci*
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci* \file
21e5c31af7Sopenharmony_ci* \brief Video framebuffer
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci/*
24e5c31af7Sopenharmony_ci* Copyright 2020 NVIDIA Corporation.
25e5c31af7Sopenharmony_ci*
26e5c31af7Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License");
27e5c31af7Sopenharmony_ci* you may not use this file except in compliance with the License.
28e5c31af7Sopenharmony_ci* You may obtain a copy of the License at
29e5c31af7Sopenharmony_ci*
30e5c31af7Sopenharmony_ci*    http://www.apache.org/licenses/LICENSE-2.0
31e5c31af7Sopenharmony_ci*
32e5c31af7Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software
33e5c31af7Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS,
34e5c31af7Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35e5c31af7Sopenharmony_ci* See the License for the specific language governing permissions and
36e5c31af7Sopenharmony_ci* limitations under the License.
37e5c31af7Sopenharmony_ci */
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ci#include "vktVideoFrameBuffer.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include <queue>
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_cinamespace vkt
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_cinamespace video
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_cistatic VkSharedBaseObj<VkImageResourceView> emptyImageView;
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ciclass NvPerFrameDecodeResources : public vkPicBuffBase {
50e5c31af7Sopenharmony_cipublic:
51e5c31af7Sopenharmony_ci	NvPerFrameDecodeResources()
52e5c31af7Sopenharmony_ci		: m_picDispInfo()
53e5c31af7Sopenharmony_ci		, m_frameCompleteFence(VK_NULL_HANDLE)
54e5c31af7Sopenharmony_ci		, m_frameCompleteSemaphore(VK_NULL_HANDLE)
55e5c31af7Sopenharmony_ci		, m_frameConsumerDoneFence(VK_NULL_HANDLE)
56e5c31af7Sopenharmony_ci		, m_frameConsumerDoneSemaphore(VK_NULL_HANDLE)
57e5c31af7Sopenharmony_ci		, m_hasFrameCompleteSignalFence(false)
58e5c31af7Sopenharmony_ci		, m_hasFrameCompleteSignalSemaphore(false)
59e5c31af7Sopenharmony_ci		, m_hasConsummerSignalFence(false)
60e5c31af7Sopenharmony_ci		, m_hasConsummerSignalSemaphore(false)
61e5c31af7Sopenharmony_ci		, m_recreateImage(false)
62e5c31af7Sopenharmony_ci		, m_currentDpbImageLayerLayout(VK_IMAGE_LAYOUT_UNDEFINED)
63e5c31af7Sopenharmony_ci		, m_currentOutputImageLayout(VK_IMAGE_LAYOUT_UNDEFINED)
64e5c31af7Sopenharmony_ci		, m_vkDevCtx(nullptr)
65e5c31af7Sopenharmony_ci		, m_frameDpbImageView(VK_NULL_HANDLE)
66e5c31af7Sopenharmony_ci		, m_outImageView(VK_NULL_HANDLE)
67e5c31af7Sopenharmony_ci	{
68e5c31af7Sopenharmony_ci	}
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci	VkResult CreateImage( DeviceContext& vkDevCtx,
71e5c31af7Sopenharmony_ci						 const VkImageCreateInfo* pDpbImageCreateInfo,
72e5c31af7Sopenharmony_ci						 const VkImageCreateInfo* pOutImageCreateInfo,
73e5c31af7Sopenharmony_ci						 deUint32 imageIndex,
74e5c31af7Sopenharmony_ci						 VkSharedBaseObj<VkImageResource>&  imageArrayParent,
75e5c31af7Sopenharmony_ci						 VkSharedBaseObj<VkImageResourceView>& imageViewArrayParent,
76e5c31af7Sopenharmony_ci						 bool useSeparateOutputImage = false,
77e5c31af7Sopenharmony_ci						 bool useLinearOutput = false);
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci	VkResult init(DeviceContext& vkDevCtx);
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci	void Deinit();
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	NvPerFrameDecodeResources (const NvPerFrameDecodeResources &srcObj) = delete;
84e5c31af7Sopenharmony_ci	NvPerFrameDecodeResources (NvPerFrameDecodeResources &&srcObj) = delete;
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci	~NvPerFrameDecodeResources() override
87e5c31af7Sopenharmony_ci	{
88e5c31af7Sopenharmony_ci		Deinit();
89e5c31af7Sopenharmony_ci	}
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkImageResourceView>& GetFrameImageView() {
92e5c31af7Sopenharmony_ci		if (ImageExist()) {
93e5c31af7Sopenharmony_ci			return m_frameDpbImageView;
94e5c31af7Sopenharmony_ci		} else {
95e5c31af7Sopenharmony_ci			return emptyImageView;
96e5c31af7Sopenharmony_ci		}
97e5c31af7Sopenharmony_ci	}
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkImageResourceView>& GetDisplayImageView() {
100e5c31af7Sopenharmony_ci		if (ImageExist()) {
101e5c31af7Sopenharmony_ci			return m_outImageView;
102e5c31af7Sopenharmony_ci		} else {
103e5c31af7Sopenharmony_ci			return emptyImageView;
104e5c31af7Sopenharmony_ci		}
105e5c31af7Sopenharmony_ci	}
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	bool ImageExist() {
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci		return (!!m_frameDpbImageView && (m_frameDpbImageView->GetImageView() != VK_NULL_HANDLE));
110e5c31af7Sopenharmony_ci	}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ci	bool GetImageSetNewLayout(VkImageLayout newDpbImageLayout,
113e5c31af7Sopenharmony_ci							  VkVideoPictureResourceInfoKHR* pDpbPictureResource,
114e5c31af7Sopenharmony_ci							  VulkanVideoFrameBuffer::PictureResourceInfo* pDpbPictureResourceInfo,
115e5c31af7Sopenharmony_ci							  VkImageLayout newOutputImageLayout = VK_IMAGE_LAYOUT_MAX_ENUM,
116e5c31af7Sopenharmony_ci							  VkVideoPictureResourceInfoKHR* pOutputPictureResource = nullptr,
117e5c31af7Sopenharmony_ci							  VulkanVideoFrameBuffer::PictureResourceInfo* pOutputPictureResourceInfo = nullptr) {
118e5c31af7Sopenharmony_ci
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci		if (m_recreateImage || !ImageExist()) {
121e5c31af7Sopenharmony_ci			return false;
122e5c31af7Sopenharmony_ci		}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci		if (pDpbPictureResourceInfo) {
125e5c31af7Sopenharmony_ci			pDpbPictureResourceInfo->image = m_frameDpbImageView->GetImageResource()->GetImage();
126e5c31af7Sopenharmony_ci			pDpbPictureResourceInfo->imageFormat = m_frameDpbImageView->GetImageResource()->GetImageCreateInfo().format;
127e5c31af7Sopenharmony_ci			pDpbPictureResourceInfo->currentImageLayout = m_currentDpbImageLayerLayout;
128e5c31af7Sopenharmony_ci		}
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ci		if (VK_IMAGE_LAYOUT_MAX_ENUM != newDpbImageLayout) {
131e5c31af7Sopenharmony_ci			m_currentDpbImageLayerLayout = newDpbImageLayout;
132e5c31af7Sopenharmony_ci		}
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci		if (pDpbPictureResource) {
135e5c31af7Sopenharmony_ci			pDpbPictureResource->imageViewBinding = m_frameDpbImageView->GetImageView();
136e5c31af7Sopenharmony_ci		}
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ci		if (pOutputPictureResourceInfo) {
139e5c31af7Sopenharmony_ci			pOutputPictureResourceInfo->image = m_outImageView->GetImageResource()->GetImage();
140e5c31af7Sopenharmony_ci			pOutputPictureResourceInfo->imageFormat = m_outImageView->GetImageResource()->GetImageCreateInfo().format;
141e5c31af7Sopenharmony_ci			pOutputPictureResourceInfo->currentImageLayout = m_currentOutputImageLayout;
142e5c31af7Sopenharmony_ci		}
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ci		if (VK_IMAGE_LAYOUT_MAX_ENUM != newOutputImageLayout) {
145e5c31af7Sopenharmony_ci			m_currentOutputImageLayout = newOutputImageLayout;
146e5c31af7Sopenharmony_ci		}
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci		if (pOutputPictureResource) {
149e5c31af7Sopenharmony_ci			pOutputPictureResource->imageViewBinding = m_outImageView->GetImageView();
150e5c31af7Sopenharmony_ci		}
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci		return true;
153e5c31af7Sopenharmony_ci	}
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci	VkParserDecodePictureInfo m_picDispInfo;
156e5c31af7Sopenharmony_ci	VkFence m_frameCompleteFence;
157e5c31af7Sopenharmony_ci	VkSemaphore m_frameCompleteSemaphore;
158e5c31af7Sopenharmony_ci	VkFence m_frameConsumerDoneFence;
159e5c31af7Sopenharmony_ci	VkSemaphore m_frameConsumerDoneSemaphore;
160e5c31af7Sopenharmony_ci	deUint32 m_hasFrameCompleteSignalFence : 1;
161e5c31af7Sopenharmony_ci	deUint32 m_hasFrameCompleteSignalSemaphore : 1;
162e5c31af7Sopenharmony_ci	deUint32 m_hasConsummerSignalFence : 1;
163e5c31af7Sopenharmony_ci	deUint32 m_hasConsummerSignalSemaphore : 1;
164e5c31af7Sopenharmony_ci	deUint32 m_recreateImage : 1;
165e5c31af7Sopenharmony_ci	// VPS
166e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkVideoRefCountBase>  stdVps;
167e5c31af7Sopenharmony_ci	// SPS
168e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkVideoRefCountBase>  stdSps;
169e5c31af7Sopenharmony_ci	// PPS
170e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkVideoRefCountBase>  stdPps;
171e5c31af7Sopenharmony_ci	// The bitstream Buffer
172e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkVideoRefCountBase>  bitstreamData;
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ciprivate:
175e5c31af7Sopenharmony_ci	VkImageLayout                        m_currentDpbImageLayerLayout;
176e5c31af7Sopenharmony_ci	VkImageLayout                        m_currentOutputImageLayout;
177e5c31af7Sopenharmony_ci	DeviceContext*						 m_vkDevCtx;
178e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkImageResourceView> m_frameDpbImageView;
179e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkImageResourceView> m_outImageView;
180e5c31af7Sopenharmony_ci};
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ciclass NvPerFrameDecodeImageSet {
183e5c31af7Sopenharmony_cipublic:
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	static constexpr size_t maxImages = 32;
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci	NvPerFrameDecodeImageSet()
188e5c31af7Sopenharmony_ci		: m_queueFamilyIndex((deUint32)-1)
189e5c31af7Sopenharmony_ci		, m_dpbImageCreateInfo()
190e5c31af7Sopenharmony_ci		, m_outImageCreateInfo()
191e5c31af7Sopenharmony_ci		, m_numImages(0)
192e5c31af7Sopenharmony_ci		, m_usesImageArray(false)
193e5c31af7Sopenharmony_ci		, m_usesImageViewArray(false)
194e5c31af7Sopenharmony_ci		, m_usesSeparateOutputImage(false)
195e5c31af7Sopenharmony_ci		, m_usesLinearOutput(false)
196e5c31af7Sopenharmony_ci		, m_perFrameDecodeResources(maxImages)
197e5c31af7Sopenharmony_ci		, m_imageArray()
198e5c31af7Sopenharmony_ci		, m_imageViewArray()
199e5c31af7Sopenharmony_ci	{
200e5c31af7Sopenharmony_ci	}
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ci	int32_t init(DeviceContext& vkDevCtx,
203e5c31af7Sopenharmony_ci				 const VkVideoProfileInfoKHR* pDecodeProfile,
204e5c31af7Sopenharmony_ci				 deUint32              numImages,
205e5c31af7Sopenharmony_ci				 VkFormat              dpbImageFormat,
206e5c31af7Sopenharmony_ci				 VkFormat              outImageFormat,
207e5c31af7Sopenharmony_ci				 const VkExtent2D&     maxImageExtent,
208e5c31af7Sopenharmony_ci				 VkImageUsageFlags     dpbImageUsage,
209e5c31af7Sopenharmony_ci				 VkImageUsageFlags     outImageUsage,
210e5c31af7Sopenharmony_ci				 deUint32              queueFamilyIndex,
211e5c31af7Sopenharmony_ci				 bool useImageArray = false,
212e5c31af7Sopenharmony_ci				 bool useImageViewArray = false,
213e5c31af7Sopenharmony_ci				 bool useSeparateOutputImages = false,
214e5c31af7Sopenharmony_ci				 bool useLinearOutput = false);
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ci	~NvPerFrameDecodeImageSet()
217e5c31af7Sopenharmony_ci	{
218e5c31af7Sopenharmony_ci		m_numImages = 0;
219e5c31af7Sopenharmony_ci	}
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci	NvPerFrameDecodeResources& operator[](unsigned int index)
222e5c31af7Sopenharmony_ci	{
223e5c31af7Sopenharmony_ci		DE_ASSERT(index < m_perFrameDecodeResources.size());
224e5c31af7Sopenharmony_ci		return m_perFrameDecodeResources[index];
225e5c31af7Sopenharmony_ci	}
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci	size_t size() const
228e5c31af7Sopenharmony_ci	{
229e5c31af7Sopenharmony_ci		return m_numImages;
230e5c31af7Sopenharmony_ci	}
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci	VkResult GetImageSetNewLayout(DeviceContext& vkDevCtx,
233e5c31af7Sopenharmony_ci								  deUint32 imageIndex,
234e5c31af7Sopenharmony_ci								  VkImageLayout newDpbImageLayout,
235e5c31af7Sopenharmony_ci								  VkVideoPictureResourceInfoKHR* pDpbPictureResource = nullptr,
236e5c31af7Sopenharmony_ci								  VulkanVideoFrameBuffer::PictureResourceInfo* pDpbPictureResourceInfo = nullptr,
237e5c31af7Sopenharmony_ci								  VkImageLayout newOutputImageLayout = VK_IMAGE_LAYOUT_MAX_ENUM,
238e5c31af7Sopenharmony_ci								  VkVideoPictureResourceInfoKHR* pOutputPictureResource = nullptr,
239e5c31af7Sopenharmony_ci								  VulkanVideoFrameBuffer::PictureResourceInfo* pOutputPictureResourceInfo = nullptr) {
240e5c31af7Sopenharmony_ci
241e5c31af7Sopenharmony_ci		VkResult result = VK_SUCCESS;
242e5c31af7Sopenharmony_ci		if (pDpbPictureResource) {
243e5c31af7Sopenharmony_ci			if (m_imageViewArray) {
244e5c31af7Sopenharmony_ci				// We have an image view that has the same number of layers as the image.
245e5c31af7Sopenharmony_ci				// In that scenario, while specifying the resource, the API must specifically choose the image layer.
246e5c31af7Sopenharmony_ci				pDpbPictureResource->baseArrayLayer = imageIndex;
247e5c31af7Sopenharmony_ci			} else {
248e5c31af7Sopenharmony_ci				// Let the image view sub-resource specify the image layer.
249e5c31af7Sopenharmony_ci				pDpbPictureResource->baseArrayLayer = 0;
250e5c31af7Sopenharmony_ci			}
251e5c31af7Sopenharmony_ci		}
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci		if(pOutputPictureResource) {
254e5c31af7Sopenharmony_ci			// Output pictures currently are only allocated as discrete
255e5c31af7Sopenharmony_ci			// Let the image view sub-resource specify the image layer.
256e5c31af7Sopenharmony_ci			pOutputPictureResource->baseArrayLayer = 0;
257e5c31af7Sopenharmony_ci		}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci		bool validImage = m_perFrameDecodeResources[imageIndex].GetImageSetNewLayout(
260e5c31af7Sopenharmony_ci			newDpbImageLayout,
261e5c31af7Sopenharmony_ci			pDpbPictureResource,
262e5c31af7Sopenharmony_ci			pDpbPictureResourceInfo,
263e5c31af7Sopenharmony_ci			newOutputImageLayout,
264e5c31af7Sopenharmony_ci			pOutputPictureResource,
265e5c31af7Sopenharmony_ci			pOutputPictureResourceInfo);
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ci		if (!validImage) {
268e5c31af7Sopenharmony_ci			result = m_perFrameDecodeResources[imageIndex].CreateImage(
269e5c31af7Sopenharmony_ci				vkDevCtx,
270e5c31af7Sopenharmony_ci				&m_dpbImageCreateInfo,
271e5c31af7Sopenharmony_ci				&m_outImageCreateInfo,
272e5c31af7Sopenharmony_ci				imageIndex,
273e5c31af7Sopenharmony_ci				m_imageArray,
274e5c31af7Sopenharmony_ci				m_imageViewArray,
275e5c31af7Sopenharmony_ci				m_usesSeparateOutputImage,
276e5c31af7Sopenharmony_ci				m_usesLinearOutput);
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci			if (result == VK_SUCCESS) {
279e5c31af7Sopenharmony_ci				validImage = m_perFrameDecodeResources[imageIndex].GetImageSetNewLayout(
280e5c31af7Sopenharmony_ci					newDpbImageLayout,
281e5c31af7Sopenharmony_ci					pDpbPictureResource,
282e5c31af7Sopenharmony_ci					pDpbPictureResourceInfo,
283e5c31af7Sopenharmony_ci					newOutputImageLayout,
284e5c31af7Sopenharmony_ci					pOutputPictureResource,
285e5c31af7Sopenharmony_ci					pOutputPictureResourceInfo);
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_ci				DE_ASSERT(validImage);
288e5c31af7Sopenharmony_ci			}
289e5c31af7Sopenharmony_ci		}
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci		return result;
292e5c31af7Sopenharmony_ci	}
293e5c31af7Sopenharmony_ci
294e5c31af7Sopenharmony_ciprivate:
295e5c31af7Sopenharmony_ci	deUint32							   m_queueFamilyIndex;
296e5c31af7Sopenharmony_ci	VkVideoCoreProfile					   m_videoProfile;
297e5c31af7Sopenharmony_ci	VkImageCreateInfo					   m_dpbImageCreateInfo;
298e5c31af7Sopenharmony_ci	VkImageCreateInfo					   m_outImageCreateInfo;
299e5c31af7Sopenharmony_ci	deUint32							   m_numImages;
300e5c31af7Sopenharmony_ci	// TODO: This code copied from the NVIDIA sample app has never been tested. Need to make sure the IHVs have a Radeon 5000 series GPU that uses this feature.
301e5c31af7Sopenharmony_ci	deUint32							   m_usesImageArray : 1;
302e5c31af7Sopenharmony_ci	deUint32							   m_usesImageViewArray : 1;
303e5c31af7Sopenharmony_ci	deUint32							   m_usesSeparateOutputImage : 1;
304e5c31af7Sopenharmony_ci	deUint32							   m_usesLinearOutput : 1;
305e5c31af7Sopenharmony_ci	std::vector<NvPerFrameDecodeResources> m_perFrameDecodeResources;
306e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkImageResource>	   m_imageArray; // must be valid if m_usesImageArray is true
307e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkImageResourceView>   m_imageViewArray; // must be valid if m_usesImageViewArray is true
308e5c31af7Sopenharmony_ci};
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ciclass VkVideoFrameBuffer : public VulkanVideoFrameBuffer {
311e5c31af7Sopenharmony_cipublic:
312e5c31af7Sopenharmony_ci	static constexpr size_t maxFramebufferImages = 32;
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_ci	VkVideoFrameBuffer(DeviceContext& vkDevCtx, bool supportsQueries)
315e5c31af7Sopenharmony_ci		: m_vkDevCtx(vkDevCtx),
316e5c31af7Sopenharmony_ci		m_refCount(0),
317e5c31af7Sopenharmony_ci		m_displayQueueMutex(),
318e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet(),
319e5c31af7Sopenharmony_ci		m_displayFrames(),
320e5c31af7Sopenharmony_ci		m_supportsQueries(supportsQueries),
321e5c31af7Sopenharmony_ci		m_queryPool(VK_NULL_HANDLE),
322e5c31af7Sopenharmony_ci		m_ownedByDisplayMask(0),
323e5c31af7Sopenharmony_ci		m_frameNumInDecodeOrder(0),
324e5c31af7Sopenharmony_ci		m_frameNumInDisplayOrder(0),
325e5c31af7Sopenharmony_ci		m_codedExtent{0, 0},
326e5c31af7Sopenharmony_ci		m_numberParameterUpdates(0)
327e5c31af7Sopenharmony_ci	{ }
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci	int32_t AddRef() override;
330e5c31af7Sopenharmony_ci	int32_t Release() override;
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	VkResult CreateVideoQueries(deUint32 numSlots, DeviceContext& vkDevCtx,
333e5c31af7Sopenharmony_ci									   const VkVideoProfileInfoKHR* pDecodeProfile) {
334e5c31af7Sopenharmony_ci		DE_ASSERT(numSlots <= maxFramebufferImages);
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci		auto& vk = vkDevCtx.context->getDeviceInterface();
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ci		if (m_queryPool == VK_NULL_HANDLE) {
339e5c31af7Sopenharmony_ci			// It would be difficult to resize a query pool, so allocate the maximum possible slot.
340e5c31af7Sopenharmony_ci			numSlots = maxFramebufferImages;
341e5c31af7Sopenharmony_ci			VkQueryPoolCreateInfo queryPoolCreateInfo{};
342e5c31af7Sopenharmony_ci			queryPoolCreateInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
343e5c31af7Sopenharmony_ci			queryPoolCreateInfo.pNext = pDecodeProfile;
344e5c31af7Sopenharmony_ci			queryPoolCreateInfo.queryType = VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR;
345e5c31af7Sopenharmony_ci			queryPoolCreateInfo.queryCount = numSlots;  // m_numDecodeSurfaces frames worth
346e5c31af7Sopenharmony_ci
347e5c31af7Sopenharmony_ci			return vk.createQueryPool(vkDevCtx.device, &queryPoolCreateInfo, nullptr, &m_queryPool);
348e5c31af7Sopenharmony_ci		}
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci		return VK_SUCCESS;
351e5c31af7Sopenharmony_ci	}
352e5c31af7Sopenharmony_ci
353e5c31af7Sopenharmony_ci	void DestroyVideoQueries() {
354e5c31af7Sopenharmony_ci		if (m_queryPool != VK_NULL_HANDLE) {
355e5c31af7Sopenharmony_ci			m_vkDevCtx.getDeviceDriver().destroyQueryPool(m_vkDevCtx.device, m_queryPool, nullptr);
356e5c31af7Sopenharmony_ci			m_queryPool = VK_NULL_HANDLE;
357e5c31af7Sopenharmony_ci		}
358e5c31af7Sopenharmony_ci	}
359e5c31af7Sopenharmony_ci
360e5c31af7Sopenharmony_ci	deUint32 FlushDisplayQueue() {
361e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci		deUint32 flushedImages = 0;
364e5c31af7Sopenharmony_ci		while (!m_displayFrames.empty()) {
365e5c31af7Sopenharmony_ci			deUint8 pictureIndex = m_displayFrames.front();
366e5c31af7Sopenharmony_ci			DE_ASSERT(pictureIndex < m_perFrameDecodeImageSet.size());
367e5c31af7Sopenharmony_ci			m_displayFrames.pop();
368e5c31af7Sopenharmony_ci			if (m_perFrameDecodeImageSet[(deUint32)pictureIndex].IsAvailable()) {
369e5c31af7Sopenharmony_ci				// The frame is not released yet - force release it.
370e5c31af7Sopenharmony_ci				m_perFrameDecodeImageSet[(deUint32)pictureIndex].Release();
371e5c31af7Sopenharmony_ci			}
372e5c31af7Sopenharmony_ci			flushedImages++;
373e5c31af7Sopenharmony_ci		}
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci		return flushedImages;
376e5c31af7Sopenharmony_ci	}
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci	int32_t InitImagePool(const VkVideoProfileInfoKHR* pDecodeProfile, deUint32 numImages, VkFormat dpbImageFormat,
379e5c31af7Sopenharmony_ci								  VkFormat outImageFormat, const VkExtent2D& codedExtent, const VkExtent2D& maxImageExtent,
380e5c31af7Sopenharmony_ci								  VkImageUsageFlags dpbImageUsage, VkImageUsageFlags outImageUsage, deUint32 queueFamilyIndex,
381e5c31af7Sopenharmony_ci								  bool useImageArray, bool useImageViewArray,
382e5c31af7Sopenharmony_ci								  bool useSeparateOutputImage, bool useLinearOutput) override;
383e5c31af7Sopenharmony_ci
384e5c31af7Sopenharmony_ci	void Deinitialize() {
385e5c31af7Sopenharmony_ci		FlushDisplayQueue();
386e5c31af7Sopenharmony_ci
387e5c31af7Sopenharmony_ci		if (m_supportsQueries)
388e5c31af7Sopenharmony_ci			DestroyVideoQueries();
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ci		m_ownedByDisplayMask = 0;
391e5c31af7Sopenharmony_ci		m_frameNumInDecodeOrder = 0;
392e5c31af7Sopenharmony_ci		m_frameNumInDisplayOrder = 0;
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci		if (m_queryPool != VK_NULL_HANDLE) {
395e5c31af7Sopenharmony_ci			m_vkDevCtx.getDeviceDriver().destroyQueryPool(m_vkDevCtx.device, m_queryPool, nullptr);
396e5c31af7Sopenharmony_ci			m_queryPool = VK_NULL_HANDLE;
397e5c31af7Sopenharmony_ci		}
398e5c31af7Sopenharmony_ci	};
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	int32_t QueueDecodedPictureForDisplay(int8_t picId, VulkanVideoDisplayPictureInfo* pDispInfo) override {
401e5c31af7Sopenharmony_ci		DE_ASSERT((deUint32)picId < m_perFrameDecodeImageSet.size());
402e5c31af7Sopenharmony_ci
403e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
404e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].m_displayOrder = m_frameNumInDisplayOrder++;
405e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].m_timestamp = pDispInfo->timestamp;
406e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].AddRef();
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ci		m_displayFrames.push((deUint8)picId);
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci		if (videoLoggingEnabled()) {
411e5c31af7Sopenharmony_ci			std::cout << "==> Queue Display Picture picIdx: " << (deUint32)picId
412e5c31af7Sopenharmony_ci					  << "\t\tdisplayOrder: " << m_perFrameDecodeImageSet[picId].m_displayOrder
413e5c31af7Sopenharmony_ci					  << "\tdecodeOrder: " << m_perFrameDecodeImageSet[picId].m_decodeOrder << "\ttimestamp "
414e5c31af7Sopenharmony_ci					  << m_perFrameDecodeImageSet[picId].m_timestamp << std::endl;
415e5c31af7Sopenharmony_ci		}
416e5c31af7Sopenharmony_ci		return picId;
417e5c31af7Sopenharmony_ci	}
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci	int32_t QueuePictureForDecode(int8_t picId, VkParserDecodePictureInfo* pDecodePictureInfo,
420e5c31af7Sopenharmony_ci										  ReferencedObjectsInfo* pReferencedObjectsInfo,
421e5c31af7Sopenharmony_ci										  FrameSynchronizationInfo* pFrameSynchronizationInfo) override;
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci	size_t GetDisplayedFrameCount() const override { return m_displayFrames.size(); }
424e5c31af7Sopenharmony_ci
425e5c31af7Sopenharmony_ci	// dequeue
426e5c31af7Sopenharmony_ci	int32_t DequeueDecodedPicture(DecodedFrame* pDecodedFrame) override;
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci	int32_t ReleaseDisplayedPicture(DecodedFrameRelease** pDecodedFramesRelease, deUint32 numFramesToRelease) override;
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci	int32_t GetDpbImageResourcesByIndex(deUint32 numResources, const int8_t* referenceSlotIndexes,
431e5c31af7Sopenharmony_ci												VkVideoPictureResourceInfoKHR* dpbPictureResources,
432e5c31af7Sopenharmony_ci												PictureResourceInfo* dpbPictureResourcesInfo,
433e5c31af7Sopenharmony_ci												VkImageLayout newDpbImageLayerLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR) override;
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci	int32_t GetCurrentImageResourceByIndex(int8_t referenceSlotIndex, VkVideoPictureResourceInfoKHR* dpbPictureResource,
436e5c31af7Sopenharmony_ci												   PictureResourceInfo* dpbPictureResourceInfo,
437e5c31af7Sopenharmony_ci												   VkImageLayout newDpbImageLayerLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
438e5c31af7Sopenharmony_ci												   VkVideoPictureResourceInfoKHR* outputPictureResource = nullptr,
439e5c31af7Sopenharmony_ci												   PictureResourceInfo* outputPictureResourceInfo = nullptr,
440e5c31af7Sopenharmony_ci												   VkImageLayout newOutputImageLayerLayout = VK_IMAGE_LAYOUT_MAX_ENUM) override;
441e5c31af7Sopenharmony_ci
442e5c31af7Sopenharmony_ci	int32_t ReleaseImageResources(deUint32 numResources, const deUint32* indexes) override {
443e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
444e5c31af7Sopenharmony_ci		for (unsigned int resId = 0; resId < numResources; resId++) {
445e5c31af7Sopenharmony_ci			if ((deUint32)indexes[resId] < m_perFrameDecodeImageSet.size()) {
446e5c31af7Sopenharmony_ci				m_perFrameDecodeImageSet[indexes[resId]].Deinit();
447e5c31af7Sopenharmony_ci			}
448e5c31af7Sopenharmony_ci		}
449e5c31af7Sopenharmony_ci		return (int32_t)m_perFrameDecodeImageSet.size();
450e5c31af7Sopenharmony_ci	}
451e5c31af7Sopenharmony_ci
452e5c31af7Sopenharmony_ci	int32_t SetPicNumInDecodeOrder(int32_t picId, int32_t picNumInDecodeOrder) override {
453e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
454e5c31af7Sopenharmony_ci		if ((deUint32)picId < m_perFrameDecodeImageSet.size()) {
455e5c31af7Sopenharmony_ci			int32_t oldPicNumInDecodeOrder = m_perFrameDecodeImageSet[picId].m_decodeOrder;
456e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[picId].m_decodeOrder = picNumInDecodeOrder;
457e5c31af7Sopenharmony_ci			return oldPicNumInDecodeOrder;
458e5c31af7Sopenharmony_ci		}
459e5c31af7Sopenharmony_ci		DE_ASSERT(false);
460e5c31af7Sopenharmony_ci		return -1;
461e5c31af7Sopenharmony_ci	}
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	int32_t SetPicNumInDisplayOrder(int32_t picId, int32_t picNumInDisplayOrder) override {
464e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
465e5c31af7Sopenharmony_ci		if ((deUint32)picId < m_perFrameDecodeImageSet.size()) {
466e5c31af7Sopenharmony_ci			int32_t oldPicNumInDisplayOrder = m_perFrameDecodeImageSet[picId].m_displayOrder;
467e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[picId].m_displayOrder = picNumInDisplayOrder;
468e5c31af7Sopenharmony_ci			return oldPicNumInDisplayOrder;
469e5c31af7Sopenharmony_ci		}
470e5c31af7Sopenharmony_ci		DE_ASSERT(false);
471e5c31af7Sopenharmony_ci		return -1;
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_ci	virtual const VkSharedBaseObj<VkImageResourceView>& GetImageResourceByIndex(int8_t picId) {
475e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
476e5c31af7Sopenharmony_ci		if ((deUint32)picId < m_perFrameDecodeImageSet.size()) {
477e5c31af7Sopenharmony_ci			return m_perFrameDecodeImageSet[picId].GetFrameImageView();
478e5c31af7Sopenharmony_ci		}
479e5c31af7Sopenharmony_ci		DE_ASSERT(false);
480e5c31af7Sopenharmony_ci		return emptyImageView;
481e5c31af7Sopenharmony_ci	}
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ci	vkPicBuffBase* ReservePictureBuffer() override {
484e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
485e5c31af7Sopenharmony_ci		int foundPicId = -1;
486e5c31af7Sopenharmony_ci		for (int picId = 0; picId < m_perFrameDecodeImageSet.size(); picId++) {
487e5c31af7Sopenharmony_ci			if (m_perFrameDecodeImageSet[picId].IsAvailable()) {
488e5c31af7Sopenharmony_ci				foundPicId = picId;
489e5c31af7Sopenharmony_ci				break;
490e5c31af7Sopenharmony_ci			}
491e5c31af7Sopenharmony_ci		}
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci		if (foundPicId >= 0) {
494e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[foundPicId].Reset();
495e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[foundPicId].AddRef();
496e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[foundPicId].m_picIdx = foundPicId;
497e5c31af7Sopenharmony_ci			return &m_perFrameDecodeImageSet[foundPicId];
498e5c31af7Sopenharmony_ci		}
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_ci		DE_ASSERT(foundPicId >= 0);
501e5c31af7Sopenharmony_ci		return nullptr;
502e5c31af7Sopenharmony_ci	}
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	size_t GetSize() override {
505e5c31af7Sopenharmony_ci		std::lock_guard<std::mutex> lock(m_displayQueueMutex);
506e5c31af7Sopenharmony_ci		return m_perFrameDecodeImageSet.size();
507e5c31af7Sopenharmony_ci	}
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ci	virtual ~VkVideoFrameBuffer() { Deinitialize(); }
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ciprivate:
512e5c31af7Sopenharmony_ci	DeviceContext& m_vkDevCtx;
513e5c31af7Sopenharmony_ci	std::atomic<int32_t> m_refCount;
514e5c31af7Sopenharmony_ci	std::mutex m_displayQueueMutex;
515e5c31af7Sopenharmony_ci	NvPerFrameDecodeImageSet m_perFrameDecodeImageSet;
516e5c31af7Sopenharmony_ci	std::queue<deUint8> m_displayFrames;
517e5c31af7Sopenharmony_ci	bool m_supportsQueries;
518e5c31af7Sopenharmony_ci	VkQueryPool m_queryPool;
519e5c31af7Sopenharmony_ci	deUint32 m_ownedByDisplayMask;
520e5c31af7Sopenharmony_ci	int32_t m_frameNumInDecodeOrder;
521e5c31af7Sopenharmony_ci	int32_t m_frameNumInDisplayOrder;
522e5c31af7Sopenharmony_ci	VkExtent2D m_codedExtent;  // for the codedExtent, not the max image resolution
523e5c31af7Sopenharmony_ci	deUint32 m_numberParameterUpdates;
524e5c31af7Sopenharmony_ci};
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ciVkResult VulkanVideoFrameBuffer::Create(DeviceContext* vkDevCtx,
527e5c31af7Sopenharmony_ci										bool supportsQueries,
528e5c31af7Sopenharmony_ci										VkSharedBaseObj<VulkanVideoFrameBuffer>& vkVideoFrameBuffer)
529e5c31af7Sopenharmony_ci{
530e5c31af7Sopenharmony_ci	VkSharedBaseObj<VkVideoFrameBuffer> videoFrameBuffer(new VkVideoFrameBuffer(*vkDevCtx, supportsQueries));
531e5c31af7Sopenharmony_ci	if (videoFrameBuffer) {
532e5c31af7Sopenharmony_ci		vkVideoFrameBuffer = videoFrameBuffer;
533e5c31af7Sopenharmony_ci		return VK_SUCCESS;
534e5c31af7Sopenharmony_ci	}
535e5c31af7Sopenharmony_ci	return VK_ERROR_OUT_OF_HOST_MEMORY;
536e5c31af7Sopenharmony_ci}
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::AddRef()
539e5c31af7Sopenharmony_ci{
540e5c31af7Sopenharmony_ci	return ++m_refCount;
541e5c31af7Sopenharmony_ci}
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::Release()
544e5c31af7Sopenharmony_ci{
545e5c31af7Sopenharmony_ci	deUint32 ret;
546e5c31af7Sopenharmony_ci	ret = --m_refCount;
547e5c31af7Sopenharmony_ci	// Destroy the device if refcount reaches zero
548e5c31af7Sopenharmony_ci	if (ret == 0) {
549e5c31af7Sopenharmony_ci		delete this;
550e5c31af7Sopenharmony_ci	}
551e5c31af7Sopenharmony_ci	return ret;
552e5c31af7Sopenharmony_ci}
553e5c31af7Sopenharmony_ci
554e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::QueuePictureForDecode(int8_t picId, VkParserDecodePictureInfo* pDecodePictureInfo, VulkanVideoFrameBuffer::ReferencedObjectsInfo* pReferencedObjectsInfo, VulkanVideoFrameBuffer::FrameSynchronizationInfo* pFrameSynchronizationInfo)
555e5c31af7Sopenharmony_ci{
556e5c31af7Sopenharmony_ci	DE_ASSERT((deUint32)picId < m_perFrameDecodeImageSet.size());
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	std::lock_guard<std::mutex> lock(m_displayQueueMutex);
559e5c31af7Sopenharmony_ci	m_perFrameDecodeImageSet[picId].m_picDispInfo = *pDecodePictureInfo;
560e5c31af7Sopenharmony_ci	m_perFrameDecodeImageSet[picId].m_decodeOrder = m_frameNumInDecodeOrder++;
561e5c31af7Sopenharmony_ci	m_perFrameDecodeImageSet[picId].stdPps = const_cast<VkVideoRefCountBase*>(pReferencedObjectsInfo->pStdPps);
562e5c31af7Sopenharmony_ci	m_perFrameDecodeImageSet[picId].stdSps = const_cast<VkVideoRefCountBase*>(pReferencedObjectsInfo->pStdSps);
563e5c31af7Sopenharmony_ci	m_perFrameDecodeImageSet[picId].stdVps = const_cast<VkVideoRefCountBase*>(pReferencedObjectsInfo->pStdVps);
564e5c31af7Sopenharmony_ci	m_perFrameDecodeImageSet[picId].bitstreamData = const_cast<VkVideoRefCountBase*>(pReferencedObjectsInfo->pBitstreamData);
565e5c31af7Sopenharmony_ci
566e5c31af7Sopenharmony_ci	if (videoLoggingEnabled()) {
567e5c31af7Sopenharmony_ci		std::cout << std::dec << "==> Queue Decode Picture picIdx: " << (deUint32)picId
568e5c31af7Sopenharmony_ci				  << "\t\tdisplayOrder: " << m_perFrameDecodeImageSet[picId].m_displayOrder
569e5c31af7Sopenharmony_ci				  << "\tdecodeOrder: " << m_perFrameDecodeImageSet[picId].m_decodeOrder << "\tFrameType "
570e5c31af7Sopenharmony_ci				  << m_perFrameDecodeImageSet[picId].m_picDispInfo.videoFrameType << std::endl;
571e5c31af7Sopenharmony_ci	}
572e5c31af7Sopenharmony_ci
573e5c31af7Sopenharmony_ci	if (pFrameSynchronizationInfo->hasFrameCompleteSignalFence) {
574e5c31af7Sopenharmony_ci		pFrameSynchronizationInfo->frameCompleteFence = m_perFrameDecodeImageSet[picId].m_frameCompleteFence;
575e5c31af7Sopenharmony_ci		if (!!pFrameSynchronizationInfo->frameCompleteFence) {
576e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[picId].m_hasFrameCompleteSignalFence = true;
577e5c31af7Sopenharmony_ci		}
578e5c31af7Sopenharmony_ci	}
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci	if (m_perFrameDecodeImageSet[picId].m_hasConsummerSignalFence) {
581e5c31af7Sopenharmony_ci		pFrameSynchronizationInfo->frameConsumerDoneFence = m_perFrameDecodeImageSet[picId].m_frameConsumerDoneFence;
582e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].m_hasConsummerSignalFence = false;
583e5c31af7Sopenharmony_ci	}
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_ci	if (pFrameSynchronizationInfo->hasFrameCompleteSignalSemaphore) {
586e5c31af7Sopenharmony_ci		pFrameSynchronizationInfo->frameCompleteSemaphore = m_perFrameDecodeImageSet[picId].m_frameCompleteSemaphore;
587e5c31af7Sopenharmony_ci		if (!!pFrameSynchronizationInfo->frameCompleteSemaphore) {
588e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[picId].m_hasFrameCompleteSignalSemaphore = true;
589e5c31af7Sopenharmony_ci		}
590e5c31af7Sopenharmony_ci	}
591e5c31af7Sopenharmony_ci
592e5c31af7Sopenharmony_ci	if (m_perFrameDecodeImageSet[picId].m_hasConsummerSignalSemaphore) {
593e5c31af7Sopenharmony_ci		pFrameSynchronizationInfo->frameConsumerDoneSemaphore = m_perFrameDecodeImageSet[picId].m_frameConsumerDoneSemaphore;
594e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].m_hasConsummerSignalSemaphore = false;
595e5c31af7Sopenharmony_ci	}
596e5c31af7Sopenharmony_ci
597e5c31af7Sopenharmony_ci	pFrameSynchronizationInfo->queryPool = m_queryPool;
598e5c31af7Sopenharmony_ci	pFrameSynchronizationInfo->startQueryId = picId;
599e5c31af7Sopenharmony_ci	pFrameSynchronizationInfo->numQueries = 1;
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_ci	return picId;
602e5c31af7Sopenharmony_ci}
603e5c31af7Sopenharmony_ci
604e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::DequeueDecodedPicture(DecodedFrame* pDecodedFrame)
605e5c31af7Sopenharmony_ci{
606e5c31af7Sopenharmony_ci	int numberofPendingFrames = 0;
607e5c31af7Sopenharmony_ci	int pictureIndex = -1;
608e5c31af7Sopenharmony_ci	std::lock_guard<std::mutex> lock(m_displayQueueMutex);
609e5c31af7Sopenharmony_ci	if (!m_displayFrames.empty()) {
610e5c31af7Sopenharmony_ci		numberofPendingFrames = (int)m_displayFrames.size();
611e5c31af7Sopenharmony_ci		pictureIndex = m_displayFrames.front();
612e5c31af7Sopenharmony_ci		DE_ASSERT((pictureIndex >= 0) && ((deUint32)pictureIndex < m_perFrameDecodeImageSet.size()));
613e5c31af7Sopenharmony_ci		DE_ASSERT(!(m_ownedByDisplayMask & (1 << pictureIndex)));
614e5c31af7Sopenharmony_ci		m_ownedByDisplayMask |= (1 << pictureIndex);
615e5c31af7Sopenharmony_ci		m_displayFrames.pop();
616e5c31af7Sopenharmony_ci	}
617e5c31af7Sopenharmony_ci
618e5c31af7Sopenharmony_ci	if ((deUint32)pictureIndex < m_perFrameDecodeImageSet.size()) {
619e5c31af7Sopenharmony_ci		pDecodedFrame->pictureIndex = pictureIndex;
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ci		pDecodedFrame->imageLayerIndex = m_perFrameDecodeImageSet[pictureIndex].m_picDispInfo.imageLayerIndex;
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci		pDecodedFrame->decodedImageView = m_perFrameDecodeImageSet[pictureIndex].GetFrameImageView();
624e5c31af7Sopenharmony_ci		pDecodedFrame->outputImageView = m_perFrameDecodeImageSet[pictureIndex].GetDisplayImageView();
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_ci		pDecodedFrame->displayWidth = m_perFrameDecodeImageSet[pictureIndex].m_picDispInfo.displayWidth;
627e5c31af7Sopenharmony_ci		pDecodedFrame->displayHeight = m_perFrameDecodeImageSet[pictureIndex].m_picDispInfo.displayHeight;
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci		if (m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalFence) {
630e5c31af7Sopenharmony_ci			pDecodedFrame->frameCompleteFence = m_perFrameDecodeImageSet[pictureIndex].m_frameCompleteFence;
631e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalFence = false;
632e5c31af7Sopenharmony_ci		} else {
633e5c31af7Sopenharmony_ci			pDecodedFrame->frameCompleteFence = VK_NULL_HANDLE;
634e5c31af7Sopenharmony_ci		}
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci		if (m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalSemaphore) {
637e5c31af7Sopenharmony_ci			pDecodedFrame->frameCompleteSemaphore = m_perFrameDecodeImageSet[pictureIndex].m_frameCompleteSemaphore;
638e5c31af7Sopenharmony_ci			m_perFrameDecodeImageSet[pictureIndex].m_hasFrameCompleteSignalSemaphore = false;
639e5c31af7Sopenharmony_ci		} else {
640e5c31af7Sopenharmony_ci			pDecodedFrame->frameCompleteSemaphore = VK_NULL_HANDLE;
641e5c31af7Sopenharmony_ci		}
642e5c31af7Sopenharmony_ci
643e5c31af7Sopenharmony_ci		pDecodedFrame->frameConsumerDoneFence = m_perFrameDecodeImageSet[pictureIndex].m_frameConsumerDoneFence;
644e5c31af7Sopenharmony_ci		pDecodedFrame->frameConsumerDoneSemaphore = m_perFrameDecodeImageSet[pictureIndex].m_frameConsumerDoneSemaphore;
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci		pDecodedFrame->timestamp = m_perFrameDecodeImageSet[pictureIndex].m_timestamp;
647e5c31af7Sopenharmony_ci		pDecodedFrame->decodeOrder = m_perFrameDecodeImageSet[pictureIndex].m_decodeOrder;
648e5c31af7Sopenharmony_ci		pDecodedFrame->displayOrder = m_perFrameDecodeImageSet[pictureIndex].m_displayOrder;
649e5c31af7Sopenharmony_ci
650e5c31af7Sopenharmony_ci		pDecodedFrame->queryPool = m_queryPool;
651e5c31af7Sopenharmony_ci		pDecodedFrame->startQueryId = pictureIndex;
652e5c31af7Sopenharmony_ci		pDecodedFrame->numQueries = 1;
653e5c31af7Sopenharmony_ci	}
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_ci	if (videoLoggingEnabled()) {
656e5c31af7Sopenharmony_ci		std::cout << "<<<<<<<<<<< Dequeue from Display: " << pictureIndex << " out of " << numberofPendingFrames
657e5c31af7Sopenharmony_ci				  << " ===========" << std::endl;
658e5c31af7Sopenharmony_ci	}
659e5c31af7Sopenharmony_ci	return numberofPendingFrames;
660e5c31af7Sopenharmony_ci}
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::ReleaseDisplayedPicture(DecodedFrameRelease** pDecodedFramesRelease, deUint32 numFramesToRelease)
663e5c31af7Sopenharmony_ci{
664e5c31af7Sopenharmony_ci	std::lock_guard<std::mutex> lock(m_displayQueueMutex);
665e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < numFramesToRelease; i++) {
666e5c31af7Sopenharmony_ci		const DecodedFrameRelease* pDecodedFrameRelease = pDecodedFramesRelease[i];
667e5c31af7Sopenharmony_ci		int picId = pDecodedFrameRelease->pictureIndex;
668e5c31af7Sopenharmony_ci		DE_ASSERT((picId >= 0) && ((deUint32)picId < m_perFrameDecodeImageSet.size()));
669e5c31af7Sopenharmony_ci
670e5c31af7Sopenharmony_ci		DE_ASSERT(m_perFrameDecodeImageSet[picId].m_decodeOrder == pDecodedFrameRelease->decodeOrder);
671e5c31af7Sopenharmony_ci		DE_ASSERT(m_perFrameDecodeImageSet[picId].m_displayOrder == pDecodedFrameRelease->displayOrder);
672e5c31af7Sopenharmony_ci
673e5c31af7Sopenharmony_ci		DE_ASSERT(m_ownedByDisplayMask & (1 << picId));
674e5c31af7Sopenharmony_ci		m_ownedByDisplayMask &= ~(1 << picId);
675e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].bitstreamData = nullptr;
676e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].stdPps = nullptr;
677e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].stdSps = nullptr;
678e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].stdVps = nullptr;
679e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].Release();
680e5c31af7Sopenharmony_ci
681e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].m_hasConsummerSignalFence = pDecodedFrameRelease->hasConsummerSignalFence;
682e5c31af7Sopenharmony_ci		m_perFrameDecodeImageSet[picId].m_hasConsummerSignalSemaphore = pDecodedFrameRelease->hasConsummerSignalSemaphore;
683e5c31af7Sopenharmony_ci	}
684e5c31af7Sopenharmony_ci	return 0;
685e5c31af7Sopenharmony_ci}
686e5c31af7Sopenharmony_ci
687e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::GetDpbImageResourcesByIndex(deUint32 numResources, const int8_t* referenceSlotIndexes, VkVideoPictureResourceInfoKHR* dpbPictureResources, VulkanVideoFrameBuffer::PictureResourceInfo* dpbPictureResourcesInfo, VkImageLayout newDpbImageLayerLayout)
688e5c31af7Sopenharmony_ci{
689e5c31af7Sopenharmony_ci	DE_ASSERT(dpbPictureResources);
690e5c31af7Sopenharmony_ci	std::lock_guard<std::mutex> lock(m_displayQueueMutex);
691e5c31af7Sopenharmony_ci	for (unsigned int resId = 0; resId < numResources; resId++) {
692e5c31af7Sopenharmony_ci		if ((deUint32)referenceSlotIndexes[resId] < m_perFrameDecodeImageSet.size()) {
693e5c31af7Sopenharmony_ci			VkResult result =
694e5c31af7Sopenharmony_ci				m_perFrameDecodeImageSet.GetImageSetNewLayout(m_vkDevCtx, referenceSlotIndexes[resId], newDpbImageLayerLayout,
695e5c31af7Sopenharmony_ci															  &dpbPictureResources[resId], &dpbPictureResourcesInfo[resId]);
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci			DE_ASSERT(result == VK_SUCCESS);
698e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS) {
699e5c31af7Sopenharmony_ci				return -1;
700e5c31af7Sopenharmony_ci			}
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci			DE_ASSERT(dpbPictureResources[resId].sType == VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR);
703e5c31af7Sopenharmony_ci			dpbPictureResources[resId].codedOffset = {
704e5c31af7Sopenharmony_ci				0, 0};  // FIXME: This parameter must to be adjusted based on the interlaced mode.
705e5c31af7Sopenharmony_ci			dpbPictureResources[resId].codedExtent = m_codedExtent;
706e5c31af7Sopenharmony_ci		}
707e5c31af7Sopenharmony_ci	}
708e5c31af7Sopenharmony_ci	return numResources;
709e5c31af7Sopenharmony_ci}
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::GetCurrentImageResourceByIndex(int8_t referenceSlotIndex, VkVideoPictureResourceInfoKHR* dpbPictureResource, VulkanVideoFrameBuffer::PictureResourceInfo* dpbPictureResourceInfo, VkImageLayout newDpbImageLayerLayout, VkVideoPictureResourceInfoKHR* outputPictureResource, VulkanVideoFrameBuffer::PictureResourceInfo* outputPictureResourceInfo, VkImageLayout newOutputImageLayerLayout)
712e5c31af7Sopenharmony_ci{
713e5c31af7Sopenharmony_ci	DE_ASSERT(dpbPictureResource);
714e5c31af7Sopenharmony_ci	std::lock_guard<std::mutex> lock(m_displayQueueMutex);
715e5c31af7Sopenharmony_ci	if ((deUint32)referenceSlotIndex < m_perFrameDecodeImageSet.size()) {
716e5c31af7Sopenharmony_ci		VkResult result = m_perFrameDecodeImageSet.GetImageSetNewLayout(
717e5c31af7Sopenharmony_ci			m_vkDevCtx, referenceSlotIndex, newDpbImageLayerLayout, dpbPictureResource, dpbPictureResourceInfo,
718e5c31af7Sopenharmony_ci			newOutputImageLayerLayout, outputPictureResource, outputPictureResourceInfo);
719e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_SUCCESS);
720e5c31af7Sopenharmony_ci		if (result != VK_SUCCESS) {
721e5c31af7Sopenharmony_ci			return -1;
722e5c31af7Sopenharmony_ci		}
723e5c31af7Sopenharmony_ci
724e5c31af7Sopenharmony_ci		DE_ASSERT(dpbPictureResource->sType == VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR);
725e5c31af7Sopenharmony_ci		dpbPictureResource->codedOffset = {0, 0};  // FIXME: This parameter must to be adjusted based on the interlaced mode.
726e5c31af7Sopenharmony_ci		dpbPictureResource->codedExtent = m_codedExtent;
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci		if (outputPictureResource) {
729e5c31af7Sopenharmony_ci			DE_ASSERT(outputPictureResource->sType == VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR);
730e5c31af7Sopenharmony_ci			outputPictureResource->codedOffset = {
731e5c31af7Sopenharmony_ci				0, 0};  // FIXME: This parameter must to be adjusted based on the interlaced mode.
732e5c31af7Sopenharmony_ci			outputPictureResource->codedExtent = m_codedExtent;
733e5c31af7Sopenharmony_ci		}
734e5c31af7Sopenharmony_ci	}
735e5c31af7Sopenharmony_ci	return referenceSlotIndex;
736e5c31af7Sopenharmony_ci}
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ciint32_t VkVideoFrameBuffer::InitImagePool(const VkVideoProfileInfoKHR* pDecodeProfile, deUint32 numImages, VkFormat dpbImageFormat, VkFormat outImageFormat, const VkExtent2D& codedExtent, const VkExtent2D& maxImageExtent, VkImageUsageFlags dpbImageUsage, VkImageUsageFlags outImageUsage, deUint32 queueFamilyIndex, bool useImageArray, bool useImageViewArray, bool useSeparateOutputImage, bool useLinearOutput)
739e5c31af7Sopenharmony_ci{
740e5c31af7Sopenharmony_ci	std::lock_guard<std::mutex> lock(m_displayQueueMutex);
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci	DE_ASSERT(numImages && (numImages <= maxFramebufferImages) && pDecodeProfile);
743e5c31af7Sopenharmony_ci
744e5c31af7Sopenharmony_ci	if (m_supportsQueries)
745e5c31af7Sopenharmony_ci		VK_CHECK(CreateVideoQueries(numImages, m_vkDevCtx, pDecodeProfile));
746e5c31af7Sopenharmony_ci
747e5c31af7Sopenharmony_ci	// m_extent is for the codedExtent, not the max image resolution
748e5c31af7Sopenharmony_ci	m_codedExtent = codedExtent;
749e5c31af7Sopenharmony_ci
750e5c31af7Sopenharmony_ci	int32_t imageSetCreateResult = m_perFrameDecodeImageSet.init(
751e5c31af7Sopenharmony_ci		m_vkDevCtx, pDecodeProfile, numImages, dpbImageFormat, outImageFormat, maxImageExtent, dpbImageUsage, outImageUsage,
752e5c31af7Sopenharmony_ci		queueFamilyIndex,
753e5c31af7Sopenharmony_ci		useImageArray, useImageViewArray, useSeparateOutputImage, useLinearOutput);
754e5c31af7Sopenharmony_ci	m_numberParameterUpdates++;
755e5c31af7Sopenharmony_ci
756e5c31af7Sopenharmony_ci	return imageSetCreateResult;
757e5c31af7Sopenharmony_ci}
758e5c31af7Sopenharmony_ci
759e5c31af7Sopenharmony_ciVkResult NvPerFrameDecodeResources::CreateImage( DeviceContext& vkDevCtx,
760e5c31af7Sopenharmony_ci												const VkImageCreateInfo* pDpbImageCreateInfo,
761e5c31af7Sopenharmony_ci												const VkImageCreateInfo* pOutImageCreateInfo,
762e5c31af7Sopenharmony_ci												deUint32 imageIndex,
763e5c31af7Sopenharmony_ci												VkSharedBaseObj<VkImageResource>& imageArrayParent,
764e5c31af7Sopenharmony_ci												VkSharedBaseObj<VkImageResourceView>& imageViewArrayParent,
765e5c31af7Sopenharmony_ci												bool useSeparateOutputImage,
766e5c31af7Sopenharmony_ci												bool useLinearOutput)
767e5c31af7Sopenharmony_ci{
768e5c31af7Sopenharmony_ci	VkResult result = VK_SUCCESS;
769e5c31af7Sopenharmony_ci
770e5c31af7Sopenharmony_ci	if (!ImageExist() || m_recreateImage) {
771e5c31af7Sopenharmony_ci
772e5c31af7Sopenharmony_ci		DE_ASSERT(m_vkDevCtx != nullptr);
773e5c31af7Sopenharmony_ci
774e5c31af7Sopenharmony_ci		m_currentDpbImageLayerLayout = pDpbImageCreateInfo->initialLayout;
775e5c31af7Sopenharmony_ci		m_currentOutputImageLayout   = pOutImageCreateInfo->initialLayout;
776e5c31af7Sopenharmony_ci
777e5c31af7Sopenharmony_ci		VkSharedBaseObj<VkImageResource> imageResource;
778e5c31af7Sopenharmony_ci		if (!imageArrayParent) {
779e5c31af7Sopenharmony_ci			result = VkImageResource::Create(vkDevCtx,
780e5c31af7Sopenharmony_ci											 pDpbImageCreateInfo,
781e5c31af7Sopenharmony_ci											 imageResource);
782e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS) {
783e5c31af7Sopenharmony_ci				return result;
784e5c31af7Sopenharmony_ci			}
785e5c31af7Sopenharmony_ci		} else {
786e5c31af7Sopenharmony_ci			// We are using a parent array image
787e5c31af7Sopenharmony_ci			imageResource = imageArrayParent;
788e5c31af7Sopenharmony_ci		}
789e5c31af7Sopenharmony_ci
790e5c31af7Sopenharmony_ci		if (!imageViewArrayParent) {
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci			deUint32 baseArrayLayer = imageArrayParent ? imageIndex : 0;
793e5c31af7Sopenharmony_ci			VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, baseArrayLayer, 1 };
794e5c31af7Sopenharmony_ci			result = VkImageResourceView::Create(vkDevCtx, imageResource,
795e5c31af7Sopenharmony_ci												   subresourceRange,
796e5c31af7Sopenharmony_ci												   m_frameDpbImageView);
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS) {
799e5c31af7Sopenharmony_ci				return result;
800e5c31af7Sopenharmony_ci			}
801e5c31af7Sopenharmony_ci
802e5c31af7Sopenharmony_ci			if (!(useSeparateOutputImage || useLinearOutput)) {
803e5c31af7Sopenharmony_ci				m_outImageView = m_frameDpbImageView;
804e5c31af7Sopenharmony_ci			}
805e5c31af7Sopenharmony_ci
806e5c31af7Sopenharmony_ci		} else {
807e5c31af7Sopenharmony_ci
808e5c31af7Sopenharmony_ci			m_frameDpbImageView = imageViewArrayParent;
809e5c31af7Sopenharmony_ci
810e5c31af7Sopenharmony_ci			if (!(useSeparateOutputImage || useLinearOutput)) {
811e5c31af7Sopenharmony_ci				VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, imageIndex, 1 };
812e5c31af7Sopenharmony_ci				result = VkImageResourceView::Create(vkDevCtx, imageResource,
813e5c31af7Sopenharmony_ci													   subresourceRange,
814e5c31af7Sopenharmony_ci													   m_outImageView);
815e5c31af7Sopenharmony_ci				if (result != VK_SUCCESS) {
816e5c31af7Sopenharmony_ci					return result;
817e5c31af7Sopenharmony_ci				}
818e5c31af7Sopenharmony_ci			}
819e5c31af7Sopenharmony_ci		}
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ci		if (useSeparateOutputImage || useLinearOutput) {
822e5c31af7Sopenharmony_ci
823e5c31af7Sopenharmony_ci			VkSharedBaseObj<VkImageResource> displayImageResource;
824e5c31af7Sopenharmony_ci			result = VkImageResource::Create(vkDevCtx,
825e5c31af7Sopenharmony_ci											 pOutImageCreateInfo,
826e5c31af7Sopenharmony_ci											 displayImageResource);
827e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS) {
828e5c31af7Sopenharmony_ci				return result;
829e5c31af7Sopenharmony_ci			}
830e5c31af7Sopenharmony_ci
831e5c31af7Sopenharmony_ci			VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
832e5c31af7Sopenharmony_ci			result = VkImageResourceView::Create(vkDevCtx, displayImageResource,
833e5c31af7Sopenharmony_ci												   subresourceRange,
834e5c31af7Sopenharmony_ci												   m_outImageView);
835e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS) {
836e5c31af7Sopenharmony_ci				return result;
837e5c31af7Sopenharmony_ci			}
838e5c31af7Sopenharmony_ci		}
839e5c31af7Sopenharmony_ci	}
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci	m_currentDpbImageLayerLayout = VK_IMAGE_LAYOUT_UNDEFINED;
842e5c31af7Sopenharmony_ci	m_currentOutputImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
843e5c31af7Sopenharmony_ci	m_recreateImage = false;
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_ci	return result;
846e5c31af7Sopenharmony_ci}
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_ciVkResult NvPerFrameDecodeResources::init(DeviceContext& vkDevCtx)
849e5c31af7Sopenharmony_ci{
850e5c31af7Sopenharmony_ci	m_vkDevCtx = &vkDevCtx;
851e5c31af7Sopenharmony_ci	auto& vk = vkDevCtx.getDeviceDriver();
852e5c31af7Sopenharmony_ci	auto device = vkDevCtx.device;
853e5c31af7Sopenharmony_ci
854e5c31af7Sopenharmony_ci	// The fence waited on for the first frame should be signaled.
855e5c31af7Sopenharmony_ci	const VkFenceCreateInfo fenceFrameCompleteInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr,
856e5c31af7Sopenharmony_ci													  VK_FENCE_CREATE_SIGNALED_BIT };
857e5c31af7Sopenharmony_ci	VkResult result = vk.createFence(device, &fenceFrameCompleteInfo, nullptr, &m_frameCompleteFence);
858e5c31af7Sopenharmony_ci
859e5c31af7Sopenharmony_ci	VkFenceCreateInfo fenceInfo{};
860e5c31af7Sopenharmony_ci	fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
861e5c31af7Sopenharmony_ci	result = vk.createFence(device, &fenceInfo, nullptr, &m_frameConsumerDoneFence);
862e5c31af7Sopenharmony_ci	DE_ASSERT(result == VK_SUCCESS);
863e5c31af7Sopenharmony_ci
864e5c31af7Sopenharmony_ci	VkSemaphoreCreateInfo semInfo{};
865e5c31af7Sopenharmony_ci	semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
866e5c31af7Sopenharmony_ci	result = vk.createSemaphore(device, &semInfo, nullptr, &m_frameCompleteSemaphore);
867e5c31af7Sopenharmony_ci	DE_ASSERT(result == VK_SUCCESS);
868e5c31af7Sopenharmony_ci	result = vk.createSemaphore(device, &semInfo, nullptr, &m_frameConsumerDoneSemaphore);
869e5c31af7Sopenharmony_ci	DE_ASSERT(result == VK_SUCCESS);
870e5c31af7Sopenharmony_ci
871e5c31af7Sopenharmony_ci	Reset();
872e5c31af7Sopenharmony_ci
873e5c31af7Sopenharmony_ci	return result;
874e5c31af7Sopenharmony_ci}
875e5c31af7Sopenharmony_ci
876e5c31af7Sopenharmony_civoid NvPerFrameDecodeResources::Deinit()
877e5c31af7Sopenharmony_ci{
878e5c31af7Sopenharmony_ci	bitstreamData = nullptr;
879e5c31af7Sopenharmony_ci	stdPps = nullptr;
880e5c31af7Sopenharmony_ci	stdSps = nullptr;
881e5c31af7Sopenharmony_ci	stdVps = nullptr;
882e5c31af7Sopenharmony_ci
883e5c31af7Sopenharmony_ci	if (m_vkDevCtx == nullptr) {
884e5c31af7Sopenharmony_ci		assert ((m_frameCompleteFence == VK_NULL_HANDLE) &&
885e5c31af7Sopenharmony_ci			   (m_frameConsumerDoneFence == VK_NULL_HANDLE) &&
886e5c31af7Sopenharmony_ci			   (m_frameCompleteSemaphore == VK_NULL_HANDLE) &&
887e5c31af7Sopenharmony_ci			   (m_frameConsumerDoneSemaphore == VK_NULL_HANDLE) &&
888e5c31af7Sopenharmony_ci			   !m_frameDpbImageView &&
889e5c31af7Sopenharmony_ci			   !m_outImageView);
890e5c31af7Sopenharmony_ci		return;
891e5c31af7Sopenharmony_ci	}
892e5c31af7Sopenharmony_ci
893e5c31af7Sopenharmony_ci	DE_ASSERT(m_vkDevCtx);
894e5c31af7Sopenharmony_ci	auto& vk = m_vkDevCtx->getDeviceDriver();
895e5c31af7Sopenharmony_ci	auto device = m_vkDevCtx->device;
896e5c31af7Sopenharmony_ci
897e5c31af7Sopenharmony_ci	if (m_frameCompleteFence != VK_NULL_HANDLE) {
898e5c31af7Sopenharmony_ci		vk.destroyFence(device, m_frameCompleteFence, nullptr);
899e5c31af7Sopenharmony_ci		m_frameCompleteFence = VK_NULL_HANDLE;
900e5c31af7Sopenharmony_ci	}
901e5c31af7Sopenharmony_ci
902e5c31af7Sopenharmony_ci	if (m_frameConsumerDoneFence != VK_NULL_HANDLE) {
903e5c31af7Sopenharmony_ci		vk.destroyFence(device, m_frameConsumerDoneFence, nullptr);
904e5c31af7Sopenharmony_ci		m_frameConsumerDoneFence = VK_NULL_HANDLE;
905e5c31af7Sopenharmony_ci	}
906e5c31af7Sopenharmony_ci
907e5c31af7Sopenharmony_ci	if (m_frameCompleteSemaphore != VK_NULL_HANDLE) {
908e5c31af7Sopenharmony_ci		vk.destroySemaphore(device, m_frameCompleteSemaphore, nullptr);
909e5c31af7Sopenharmony_ci		m_frameCompleteSemaphore = VK_NULL_HANDLE;
910e5c31af7Sopenharmony_ci	}
911e5c31af7Sopenharmony_ci
912e5c31af7Sopenharmony_ci	if (m_frameConsumerDoneSemaphore != VK_NULL_HANDLE) {
913e5c31af7Sopenharmony_ci		vk.destroySemaphore(device, m_frameConsumerDoneSemaphore, nullptr);
914e5c31af7Sopenharmony_ci		m_frameConsumerDoneSemaphore = VK_NULL_HANDLE;
915e5c31af7Sopenharmony_ci	}
916e5c31af7Sopenharmony_ci
917e5c31af7Sopenharmony_ci	m_frameDpbImageView = nullptr;
918e5c31af7Sopenharmony_ci	m_outImageView = nullptr;
919e5c31af7Sopenharmony_ci
920e5c31af7Sopenharmony_ci	m_vkDevCtx = nullptr;
921e5c31af7Sopenharmony_ci
922e5c31af7Sopenharmony_ci	Reset();
923e5c31af7Sopenharmony_ci}
924e5c31af7Sopenharmony_ci
925e5c31af7Sopenharmony_ciint32_t NvPerFrameDecodeImageSet::init(DeviceContext& vkDevCtx,
926e5c31af7Sopenharmony_ci									   const VkVideoProfileInfoKHR* pDecodeProfile,
927e5c31af7Sopenharmony_ci									   deUint32                 numImages,
928e5c31af7Sopenharmony_ci									   VkFormat                 dpbImageFormat,
929e5c31af7Sopenharmony_ci									   VkFormat                 outImageFormat,
930e5c31af7Sopenharmony_ci									   const VkExtent2D&        maxImageExtent,
931e5c31af7Sopenharmony_ci									   VkImageUsageFlags        dpbImageUsage,
932e5c31af7Sopenharmony_ci									   VkImageUsageFlags        outImageUsage,
933e5c31af7Sopenharmony_ci									   deUint32                 queueFamilyIndex,
934e5c31af7Sopenharmony_ci									   bool                     useImageArray,
935e5c31af7Sopenharmony_ci									   bool                     useImageViewArray,
936e5c31af7Sopenharmony_ci									   bool                     useSeparateOutputImage,
937e5c31af7Sopenharmony_ci									   bool                     useLinearOutput)
938e5c31af7Sopenharmony_ci{
939e5c31af7Sopenharmony_ci	if (numImages > m_perFrameDecodeResources.size()) {
940e5c31af7Sopenharmony_ci		DE_ASSERT(!"Number of requested images exceeds the max size of the image array");
941e5c31af7Sopenharmony_ci		return -1;
942e5c31af7Sopenharmony_ci	}
943e5c31af7Sopenharmony_ci
944e5c31af7Sopenharmony_ci	const bool reconfigureImages = (m_numImages &&
945e5c31af7Sopenharmony_ci									(m_dpbImageCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)) &&
946e5c31af7Sopenharmony_ci								   ((m_dpbImageCreateInfo.format != dpbImageFormat) ||
947e5c31af7Sopenharmony_ci									(m_dpbImageCreateInfo.extent.width < maxImageExtent.width) ||
948e5c31af7Sopenharmony_ci									(m_dpbImageCreateInfo.extent.height < maxImageExtent.height));
949e5c31af7Sopenharmony_ci
950e5c31af7Sopenharmony_ci	for (deUint32 imageIndex = m_numImages; imageIndex < numImages; imageIndex++) {
951e5c31af7Sopenharmony_ci		VkResult result = m_perFrameDecodeResources[imageIndex].init(vkDevCtx);
952e5c31af7Sopenharmony_ci		DE_ASSERT(result == VK_SUCCESS);
953e5c31af7Sopenharmony_ci		if (result != VK_SUCCESS) {
954e5c31af7Sopenharmony_ci			return -1;
955e5c31af7Sopenharmony_ci		}
956e5c31af7Sopenharmony_ci	}
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_ci	if (useImageViewArray) {
959e5c31af7Sopenharmony_ci		useImageArray = true;
960e5c31af7Sopenharmony_ci	}
961e5c31af7Sopenharmony_ci
962e5c31af7Sopenharmony_ci	m_videoProfile.InitFromProfile(pDecodeProfile);
963e5c31af7Sopenharmony_ci
964e5c31af7Sopenharmony_ci	m_queueFamilyIndex = queueFamilyIndex;
965e5c31af7Sopenharmony_ci
966e5c31af7Sopenharmony_ci	// Image create info for the DPBs
967e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
968e5c31af7Sopenharmony_ci	// m_imageCreateInfo.pNext = m_videoProfile.GetProfile();
969e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.pNext = m_videoProfile.GetProfileListInfo();
970e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
971e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.format = dpbImageFormat;
972e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.extent = { maxImageExtent.width, maxImageExtent.height, 1 };
973e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.mipLevels = 1;
974e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.arrayLayers = useImageArray ? numImages : 1;
975e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
976e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
977e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.usage = dpbImageUsage;
978e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
979e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.queueFamilyIndexCount = 1;
980e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.pQueueFamilyIndices = &m_queueFamilyIndex;
981e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
982e5c31af7Sopenharmony_ci	m_dpbImageCreateInfo.flags = 0;
983e5c31af7Sopenharmony_ci
984e5c31af7Sopenharmony_ci	// Image create info for the output
985e5c31af7Sopenharmony_ci	if (useSeparateOutputImage || useLinearOutput) {
986e5c31af7Sopenharmony_ci		m_outImageCreateInfo = m_dpbImageCreateInfo;
987e5c31af7Sopenharmony_ci		m_outImageCreateInfo.format = outImageFormat;
988e5c31af7Sopenharmony_ci		m_outImageCreateInfo.arrayLayers = 1;
989e5c31af7Sopenharmony_ci		m_outImageCreateInfo.tiling = useLinearOutput ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
990e5c31af7Sopenharmony_ci		m_outImageCreateInfo.usage = outImageUsage;
991e5c31af7Sopenharmony_ci
992e5c31af7Sopenharmony_ci		if ((outImageUsage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) == 0) {
993e5c31af7Sopenharmony_ci			// A simple output image not directly used by the decoder
994e5c31af7Sopenharmony_ci			m_outImageCreateInfo.pNext = nullptr;
995e5c31af7Sopenharmony_ci		}
996e5c31af7Sopenharmony_ci	}
997e5c31af7Sopenharmony_ci
998e5c31af7Sopenharmony_ci	if (useImageArray) {
999e5c31af7Sopenharmony_ci		// Create an image that has the same number of layers as the DPB images required.
1000e5c31af7Sopenharmony_ci		VkResult result = VkImageResource::Create(vkDevCtx,
1001e5c31af7Sopenharmony_ci												  &m_dpbImageCreateInfo,
1002e5c31af7Sopenharmony_ci												  m_imageArray);
1003e5c31af7Sopenharmony_ci		if (result != VK_SUCCESS) {
1004e5c31af7Sopenharmony_ci			return -1;
1005e5c31af7Sopenharmony_ci		}
1006e5c31af7Sopenharmony_ci	} else {
1007e5c31af7Sopenharmony_ci		m_imageArray = nullptr;
1008e5c31af7Sopenharmony_ci	}
1009e5c31af7Sopenharmony_ci
1010e5c31af7Sopenharmony_ci	if (useImageViewArray) {
1011e5c31af7Sopenharmony_ci		DE_ASSERT(m_imageArray);
1012e5c31af7Sopenharmony_ci		// Create an image view that has the same number of layers as the image.
1013e5c31af7Sopenharmony_ci		// In that scenario, while specifying the resource, the API must specifically choose the image layer.
1014e5c31af7Sopenharmony_ci		VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, numImages };
1015e5c31af7Sopenharmony_ci		VkResult result = VkImageResourceView::Create(vkDevCtx, m_imageArray,
1016e5c31af7Sopenharmony_ci													   subresourceRange,
1017e5c31af7Sopenharmony_ci													   m_imageViewArray);
1018e5c31af7Sopenharmony_ci
1019e5c31af7Sopenharmony_ci		if (result != VK_SUCCESS) {
1020e5c31af7Sopenharmony_ci			return -1;
1021e5c31af7Sopenharmony_ci		}
1022e5c31af7Sopenharmony_ci	}
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci	deUint32 firstIndex = reconfigureImages ? 0 : m_numImages;
1025e5c31af7Sopenharmony_ci	deUint32 maxNumImages = std::max(m_numImages, numImages);
1026e5c31af7Sopenharmony_ci	for (deUint32 imageIndex = firstIndex; imageIndex < maxNumImages; imageIndex++) {
1027e5c31af7Sopenharmony_ci
1028e5c31af7Sopenharmony_ci		if (m_perFrameDecodeResources[imageIndex].ImageExist() && reconfigureImages) {
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_ci			m_perFrameDecodeResources[imageIndex].m_recreateImage = true;
1031e5c31af7Sopenharmony_ci
1032e5c31af7Sopenharmony_ci		} else if (!m_perFrameDecodeResources[imageIndex].ImageExist()) {
1033e5c31af7Sopenharmony_ci
1034e5c31af7Sopenharmony_ci			VkResult result =
1035e5c31af7Sopenharmony_ci				m_perFrameDecodeResources[imageIndex].CreateImage(vkDevCtx,
1036e5c31af7Sopenharmony_ci																  &m_dpbImageCreateInfo,
1037e5c31af7Sopenharmony_ci																  &m_outImageCreateInfo,
1038e5c31af7Sopenharmony_ci																  imageIndex,
1039e5c31af7Sopenharmony_ci																  m_imageArray,
1040e5c31af7Sopenharmony_ci																  m_imageViewArray,
1041e5c31af7Sopenharmony_ci																  useSeparateOutputImage,
1042e5c31af7Sopenharmony_ci																  useLinearOutput);
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci			DE_ASSERT(result == VK_SUCCESS);
1045e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS) {
1046e5c31af7Sopenharmony_ci				return -1;
1047e5c31af7Sopenharmony_ci			}
1048e5c31af7Sopenharmony_ci		}
1049e5c31af7Sopenharmony_ci	}
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ci	m_numImages               = numImages;
1052e5c31af7Sopenharmony_ci	m_usesImageArray          = useImageArray;
1053e5c31af7Sopenharmony_ci	m_usesImageViewArray      = useImageViewArray;
1054e5c31af7Sopenharmony_ci	m_usesSeparateOutputImage = useSeparateOutputImage;
1055e5c31af7Sopenharmony_ci	m_usesLinearOutput        = useLinearOutput;
1056e5c31af7Sopenharmony_ci
1057e5c31af7Sopenharmony_ci	return (int32_t)numImages;
1058e5c31af7Sopenharmony_ci}
1059e5c31af7Sopenharmony_ci
1060e5c31af7Sopenharmony_ci} // namespace video
1061e5c31af7Sopenharmony_ci} // namespace vkt
1062