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