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 CTS implementation of the NVIDIA BitstreamBuffer interface.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci /*
24e5c31af7Sopenharmony_ci * Copyright 2023 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 "vktBitstreamBufferImpl.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include <cstring>
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_cinamespace vkt
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_cinamespace video
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ciVkResult
49e5c31af7Sopenharmony_ciBitstreamBufferImpl::Create(DeviceContext* devctx, deUint32 queueFamilyIndex, VkDeviceSize bufferSize, VkDeviceSize bufferOffsetAlignment, VkDeviceSize bufferSizeAlignment, VkSharedBaseObj<BitstreamBufferImpl>& vulkanBitstreamBuffer, const VkVideoProfileListInfoKHR* profileList)
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci	VkSharedBaseObj<BitstreamBufferImpl> vkBitstreamBuffer(new BitstreamBufferImpl(devctx,
52e5c31af7Sopenharmony_ci																				   queueFamilyIndex,
53e5c31af7Sopenharmony_ci																				   bufferOffsetAlignment,
54e5c31af7Sopenharmony_ci																				   bufferSizeAlignment,
55e5c31af7Sopenharmony_ci																				   profileList));
56e5c31af7Sopenharmony_ci	DE_ASSERT(vkBitstreamBuffer);
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci	VK_CHECK(vkBitstreamBuffer->Initialize(bufferSize));
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ci	vulkanBitstreamBuffer = vkBitstreamBuffer;
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ci	return VK_SUCCESS;
63e5c31af7Sopenharmony_ci}
64e5c31af7Sopenharmony_ci
65e5c31af7Sopenharmony_ciVkResult BitstreamBufferImpl::Initialize(VkDeviceSize bufferSize)
66e5c31af7Sopenharmony_ci{
67e5c31af7Sopenharmony_ci	auto& vk	 = m_devctx->getDeviceDriver();
68e5c31af7Sopenharmony_ci	auto  device = m_devctx->device;
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci	if (m_bufferSize >= bufferSize)
71e5c31af7Sopenharmony_ci	{
72e5c31af7Sopenharmony_ci		VkDeviceSize size = MemsetData(0x00, 0, m_bufferSize);
73e5c31af7Sopenharmony_ci		DE_ASSERT(size == m_bufferSize);
74e5c31af7Sopenharmony_ci		DE_UNREF(size);
75e5c31af7Sopenharmony_ci		return VK_SUCCESS;
76e5c31af7Sopenharmony_ci	}
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci	VkBufferCreateInfo createBufferInfo	   = {};
79e5c31af7Sopenharmony_ci	createBufferInfo.sType				   = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
80e5c31af7Sopenharmony_ci	createBufferInfo.pNext				   = m_profileList;
81e5c31af7Sopenharmony_ci	createBufferInfo.size				   = deAlignSize(bufferSize, m_bufferSizeAlignment);
82e5c31af7Sopenharmony_ci	createBufferInfo.usage				   = VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR;
83e5c31af7Sopenharmony_ci	createBufferInfo.flags				   = 0;
84e5c31af7Sopenharmony_ci	createBufferInfo.sharingMode		   = VK_SHARING_MODE_EXCLUSIVE;
85e5c31af7Sopenharmony_ci	createBufferInfo.queueFamilyIndexCount = 1;
86e5c31af7Sopenharmony_ci	createBufferInfo.pQueueFamilyIndices   = &m_queueFamilyIndex;
87e5c31af7Sopenharmony_ci	m_bitstreamBuffer					   = BufferPtr(new BufferWithMemory(vk, device, m_devctx->allocator(), createBufferInfo, MemoryRequirement::HostVisible | MemoryRequirement::Coherent | MemoryRequirement::Cached));
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci	m_bufferSize						   = bufferSize;
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci	return VK_SUCCESS;
92e5c31af7Sopenharmony_ci}
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ciVkResult BitstreamBufferImpl::CopyDataToBuffer(const deUint8* pData,
95e5c31af7Sopenharmony_ci											   VkDeviceSize	  size,
96e5c31af7Sopenharmony_ci											   VkDeviceSize&  dstBufferOffset) const
97e5c31af7Sopenharmony_ci{
98e5c31af7Sopenharmony_ci	DE_ASSERT((pData != nullptr) && (size > 0) && (size < 10 * 1024 * 1024)); // 10 MiB should be big enough for any CTS test.
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci	dstBufferOffset = deAlignSize(dstBufferOffset, m_bufferOffsetAlignment);
101e5c31af7Sopenharmony_ci	DE_ASSERT((dstBufferOffset + size) <= m_bufferSize);
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_ci	auto* bitstreamBasePtr = static_cast<deUint8*>(m_bitstreamBuffer->getAllocation().getHostPtr());
104e5c31af7Sopenharmony_ci	deMemcpy(bitstreamBasePtr + dstBufferOffset, pData, size);
105e5c31af7Sopenharmony_ci	vk::flushAlloc(m_devctx->getDeviceDriver(), m_devctx->device, m_bitstreamBuffer->getAllocation());
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	return VK_SUCCESS;
108e5c31af7Sopenharmony_ci}
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ciVkDeviceSize BitstreamBufferImpl::GetMaxSize() const
111e5c31af7Sopenharmony_ci{
112e5c31af7Sopenharmony_ci	return m_bufferSize;
113e5c31af7Sopenharmony_ci}
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ciVkDeviceSize BitstreamBufferImpl::GetOffsetAlignment() const
116e5c31af7Sopenharmony_ci{
117e5c31af7Sopenharmony_ci	return m_bufferOffsetAlignment;
118e5c31af7Sopenharmony_ci}
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ciVkDeviceSize BitstreamBufferImpl::GetSizeAlignment() const
121e5c31af7Sopenharmony_ci{
122e5c31af7Sopenharmony_ci	// REVIEW: Cache this?
123e5c31af7Sopenharmony_ci	auto reqs = getBufferMemoryRequirements(m_devctx->getDeviceDriver(), m_devctx->device, m_bitstreamBuffer->get());
124e5c31af7Sopenharmony_ci	return reqs.alignment;
125e5c31af7Sopenharmony_ci}
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ciVkDeviceSize BitstreamBufferImpl::Resize(VkDeviceSize, VkDeviceSize, VkDeviceSize)
128e5c31af7Sopenharmony_ci{
129e5c31af7Sopenharmony_ci	TCU_THROW(InternalError, "Bitstream buffers should never need to be resized in the CTS");
130e5c31af7Sopenharmony_ci}
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_ciVkDeviceSize BitstreamBufferImpl::Clone(VkDeviceSize, VkDeviceSize, VkDeviceSize,
133e5c31af7Sopenharmony_ci										VkSharedBaseObj<VulkanBitstreamBuffer>&)
134e5c31af7Sopenharmony_ci{
135e5c31af7Sopenharmony_ci	TCU_THROW(InternalError, "Presentation only interface from the samples app should not be needed in CTS");
136e5c31af7Sopenharmony_ci}
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_cideUint8* BitstreamBufferImpl::CheckAccess(VkDeviceSize offset, VkDeviceSize size) const
140e5c31af7Sopenharmony_ci{
141e5c31af7Sopenharmony_ci	DE_ASSERT(size > 0 && offset + size < m_bufferSize);
142e5c31af7Sopenharmony_ci	DE_UNREF(size);
143e5c31af7Sopenharmony_ci	auto* bitstreamBasePtr = static_cast<deUint8*>(m_bitstreamBuffer->getAllocation().getHostPtr());
144e5c31af7Sopenharmony_ci	return static_cast<deUint8*>(bitstreamBasePtr + offset);
145e5c31af7Sopenharmony_ci}
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_ciint64_t BitstreamBufferImpl::MemsetData(deUint32 value, VkDeviceSize offset, VkDeviceSize size)
148e5c31af7Sopenharmony_ci{
149e5c31af7Sopenharmony_ci	if (size == 0)
150e5c31af7Sopenharmony_ci	{
151e5c31af7Sopenharmony_ci		return 0;
152e5c31af7Sopenharmony_ci	}
153e5c31af7Sopenharmony_ci	auto* bitstreamBasePtr = static_cast<deUint8*>(m_bitstreamBuffer->getAllocation().getHostPtr());
154e5c31af7Sopenharmony_ci	deMemset(bitstreamBasePtr + offset, value, size);
155e5c31af7Sopenharmony_ci	vk::flushAlloc(m_devctx->getDeviceDriver(), m_devctx->device, m_bitstreamBuffer->getAllocation());
156e5c31af7Sopenharmony_ci	return size;
157e5c31af7Sopenharmony_ci}
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ciint64_t BitstreamBufferImpl::CopyDataToBuffer(deUint8* dstBuffer, VkDeviceSize dstOffset, VkDeviceSize srcOffset, VkDeviceSize size) const
160e5c31af7Sopenharmony_ci{
161e5c31af7Sopenharmony_ci	if (size == 0)
162e5c31af7Sopenharmony_ci	{
163e5c31af7Sopenharmony_ci		return 0;
164e5c31af7Sopenharmony_ci	}
165e5c31af7Sopenharmony_ci	auto* bitstreamBasePtr = static_cast<deUint8*>(m_bitstreamBuffer->getAllocation().getHostPtr());
166e5c31af7Sopenharmony_ci	deMemcpy(dstBuffer + dstOffset, bitstreamBasePtr + srcOffset, size);
167e5c31af7Sopenharmony_ci	return size;
168e5c31af7Sopenharmony_ci}
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ciint64_t BitstreamBufferImpl::CopyDataToBuffer(VkSharedBaseObj<VulkanBitstreamBuffer>& dstBuffer, VkDeviceSize dstOffset, VkDeviceSize srcOffset, VkDeviceSize size) const
171e5c31af7Sopenharmony_ci{
172e5c31af7Sopenharmony_ci	if (size == 0)
173e5c31af7Sopenharmony_ci	{
174e5c31af7Sopenharmony_ci		return 0;
175e5c31af7Sopenharmony_ci	}
176e5c31af7Sopenharmony_ci	const deUint8* readData = CheckAccess(srcOffset, size);
177e5c31af7Sopenharmony_ci	DE_ASSERT(readData);
178e5c31af7Sopenharmony_ci	return dstBuffer->CopyDataFromBuffer(readData, 0, dstOffset, size);
179e5c31af7Sopenharmony_ci}
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ciint64_t BitstreamBufferImpl::CopyDataFromBuffer(const deUint8* sourceBuffer, VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size)
182e5c31af7Sopenharmony_ci{
183e5c31af7Sopenharmony_ci	if (size == 0)
184e5c31af7Sopenharmony_ci	{
185e5c31af7Sopenharmony_ci		return 0;
186e5c31af7Sopenharmony_ci	}
187e5c31af7Sopenharmony_ci	auto* bitstreamBasePtr = static_cast<deUint8*>(m_bitstreamBuffer->getAllocation().getHostPtr());
188e5c31af7Sopenharmony_ci	deMemcpy(bitstreamBasePtr + dstOffset, sourceBuffer + srcOffset, size);
189e5c31af7Sopenharmony_ci	return size;
190e5c31af7Sopenharmony_ci}
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ciint64_t BitstreamBufferImpl::CopyDataFromBuffer(const VkSharedBaseObj<VulkanBitstreamBuffer>& sourceBuffer,
193e5c31af7Sopenharmony_ci												VkDeviceSize								  srcOffset,
194e5c31af7Sopenharmony_ci												VkDeviceSize								  dstOffset,
195e5c31af7Sopenharmony_ci												VkDeviceSize								  size)
196e5c31af7Sopenharmony_ci{
197e5c31af7Sopenharmony_ci	if (size == 0)
198e5c31af7Sopenharmony_ci	{
199e5c31af7Sopenharmony_ci		return 0;
200e5c31af7Sopenharmony_ci	}
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ci	const deUint8* readData = sourceBuffer->GetReadOnlyDataPtr(srcOffset, size);
203e5c31af7Sopenharmony_ci	DE_ASSERT(readData);
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci	auto* bitstreamBasePtr = static_cast<deUint8*>(m_bitstreamBuffer->getAllocation().getHostPtr());
206e5c31af7Sopenharmony_ci	deMemcpy(bitstreamBasePtr + dstOffset, readData + srcOffset, size);
207e5c31af7Sopenharmony_ci	return size;
208e5c31af7Sopenharmony_ci}
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_cideUint8* BitstreamBufferImpl::GetDataPtr(VkDeviceSize offset, VkDeviceSize& maxSize)
211e5c31af7Sopenharmony_ci{
212e5c31af7Sopenharmony_ci	deUint8* readData = CheckAccess(offset, 1);
213e5c31af7Sopenharmony_ci	DE_ASSERT(readData);
214e5c31af7Sopenharmony_ci	maxSize = m_bufferSize - offset;
215e5c31af7Sopenharmony_ci	return readData;
216e5c31af7Sopenharmony_ci}
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ciconst deUint8* BitstreamBufferImpl::GetReadOnlyDataPtr(VkDeviceSize offset, VkDeviceSize& maxSize) const
219e5c31af7Sopenharmony_ci{
220e5c31af7Sopenharmony_ci	deUint8* readData = CheckAccess(offset, 1);
221e5c31af7Sopenharmony_ci	DE_ASSERT(readData);
222e5c31af7Sopenharmony_ci	maxSize = m_bufferSize - offset;
223e5c31af7Sopenharmony_ci	return readData;
224e5c31af7Sopenharmony_ci}
225e5c31af7Sopenharmony_ci
226e5c31af7Sopenharmony_civoid BitstreamBufferImpl::FlushRange(VkDeviceSize /*offset*/, VkDeviceSize size) const
227e5c31af7Sopenharmony_ci{
228e5c31af7Sopenharmony_ci	if (size == 0)
229e5c31af7Sopenharmony_ci	{
230e5c31af7Sopenharmony_ci		return;
231e5c31af7Sopenharmony_ci	}
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci	// TOOD: Plumb the size and offset alignment caps into this class to invalidate just the range asked for in the API, rather than the whole range.
234e5c31af7Sopenharmony_ci	vk::flushAlloc(m_devctx->getDeviceDriver(), m_devctx->device, m_bitstreamBuffer->getAllocation());
235e5c31af7Sopenharmony_ci}
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_civoid BitstreamBufferImpl::InvalidateRange(VkDeviceSize /*offset*/, VkDeviceSize size) const
238e5c31af7Sopenharmony_ci{
239e5c31af7Sopenharmony_ci	if (size == 0)
240e5c31af7Sopenharmony_ci	{
241e5c31af7Sopenharmony_ci		return;
242e5c31af7Sopenharmony_ci	}
243e5c31af7Sopenharmony_ci	// TOOD: Plumb the size and offset alignment caps into this class to invalidate just the range asked for in the API, rather than the whole range.
244e5c31af7Sopenharmony_ci	vk::flushAlloc(m_devctx->getDeviceDriver(), m_devctx->device, m_bitstreamBuffer->getAllocation());
245e5c31af7Sopenharmony_ci}
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_cideUint32 BitstreamBufferImpl::AddStreamMarker(deUint32 streamOffset)
248e5c31af7Sopenharmony_ci{
249e5c31af7Sopenharmony_ci	m_streamMarkers.push_back(streamOffset);
250e5c31af7Sopenharmony_ci	return (deUint32)(m_streamMarkers.size() - 1);
251e5c31af7Sopenharmony_ci}
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_cideUint32 BitstreamBufferImpl::SetStreamMarker(deUint32 streamOffset, deUint32 index)
254e5c31af7Sopenharmony_ci{
255e5c31af7Sopenharmony_ci	DE_ASSERT(index < (deUint32)m_streamMarkers.size());
256e5c31af7Sopenharmony_ci	if (!(index < (deUint32)m_streamMarkers.size()))
257e5c31af7Sopenharmony_ci	{
258e5c31af7Sopenharmony_ci		return deUint32(-1);
259e5c31af7Sopenharmony_ci	}
260e5c31af7Sopenharmony_ci	m_streamMarkers[index] = streamOffset;
261e5c31af7Sopenharmony_ci	return index;
262e5c31af7Sopenharmony_ci}
263e5c31af7Sopenharmony_ci
264e5c31af7Sopenharmony_cideUint32 BitstreamBufferImpl::GetStreamMarker(deUint32 index) const
265e5c31af7Sopenharmony_ci{
266e5c31af7Sopenharmony_ci	DE_ASSERT(index < (deUint32)m_streamMarkers.size());
267e5c31af7Sopenharmony_ci	return m_streamMarkers[index];
268e5c31af7Sopenharmony_ci}
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_cideUint32 BitstreamBufferImpl::GetStreamMarkersCount() const
271e5c31af7Sopenharmony_ci{
272e5c31af7Sopenharmony_ci	return (deUint32)m_streamMarkers.size();
273e5c31af7Sopenharmony_ci}
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ciconst deUint32* BitstreamBufferImpl::GetStreamMarkersPtr(deUint32 startIndex, deUint32& maxCount) const
276e5c31af7Sopenharmony_ci{
277e5c31af7Sopenharmony_ci	maxCount = (deUint32)m_streamMarkers.size() - startIndex;
278e5c31af7Sopenharmony_ci	return m_streamMarkers.data() + startIndex;
279e5c31af7Sopenharmony_ci}
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_cideUint32 BitstreamBufferImpl::ResetStreamMarkers()
282e5c31af7Sopenharmony_ci{
283e5c31af7Sopenharmony_ci	deUint32 oldSize = (deUint32)m_streamMarkers.size();
284e5c31af7Sopenharmony_ci	m_streamMarkers.clear();
285e5c31af7Sopenharmony_ci	return oldSize;
286e5c31af7Sopenharmony_ci}
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_ci} // namespace video
289e5c31af7Sopenharmony_ci} // namespace vkt
290