xref: /aosp_15_r20/external/intel-media-driver/media_softlet/agnostic/common/os/mos_cmdbufmgr_next.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2019, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file    mos_cmdbufmgr_next.cpp
24 //! \brief   Container class for the basic command buffer manager
25 //!
26 #include "mos_cmdbufmgr_next.h"
27 #include "mos_context_next.h"
28 
CmdBufMgrNext()29 CmdBufMgrNext::CmdBufMgrNext()
30 {
31     MOS_OS_FUNCTION_ENTER;
32 
33     m_availableCmdBufPool.clear();
34     m_inUseCmdBufPool.clear();
35     m_initialized = false;
36 }
37 
~CmdBufMgrNext()38 CmdBufMgrNext::~CmdBufMgrNext()
39 {
40     MOS_OS_FUNCTION_ENTER;
41 }
42 
GetObject()43 CmdBufMgrNext* CmdBufMgrNext::GetObject()
44 {
45     MOS_OS_FUNCTION_ENTER;
46     return MOS_New(CmdBufMgrNext);
47 }
48 
Initialize(OsContextNext * osContext,uint32_t cmdBufSize)49 MOS_STATUS CmdBufMgrNext::Initialize(OsContextNext *osContext, uint32_t cmdBufSize)
50 {
51     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
52 
53     MOS_OS_FUNCTION_ENTER;
54     MOS_OS_CHK_NULL_RETURN(osContext);
55 
56     if (!m_initialized)
57     {
58         m_osContext          = osContext;
59 
60         m_inUsePoolMutex     = MosUtilities::MosCreateMutex();
61         MOS_OS_CHK_NULL_RETURN(m_inUsePoolMutex);
62 
63         m_availablePoolMutex = MosUtilities::MosCreateMutex();
64         MOS_OS_CHK_NULL_RETURN(m_availablePoolMutex);
65 
66         for (uint32_t i = 0; i < m_initBufNum; i++)
67         {
68             auto cmdBuf = CommandBufferNext::CreateCmdBuf(this);
69             if (cmdBuf == nullptr)
70             {
71                 MOS_OS_ASSERTMESSAGE("input nullptr returned by CommandBuffer::CreateCmdBuf.");
72                 return MOS_STATUS_INVALID_HANDLE;
73             }
74 
75             eStatus = cmdBuf->Allocate(m_osContext, cmdBufSize);
76             if (eStatus != MOS_STATUS_SUCCESS)
77             {
78                 cmdBuf->Free();
79                 MOS_Delete(cmdBuf);
80                 MOS_OS_ASSERTMESSAGE("Allocate CmdBuf#%d failed", i);
81                 return MOS_STATUS_INVALID_HANDLE;
82             }
83 
84             MosUtilities::MosLockMutex(m_availablePoolMutex);
85             m_availableCmdBufPool.push_back(cmdBuf);
86             MosUtilities::MosUnlockMutex(m_availablePoolMutex);
87 
88             m_cmdBufTotalNum++;
89         }
90 
91         m_initialized = true;
92     }
93 
94     return MOS_STATUS_SUCCESS;
95 }
96 
Reset()97 MOS_STATUS CmdBufMgrNext::Reset()
98 {
99     MOS_OS_FUNCTION_ENTER;
100 
101     CommandBufferNext *cmdBuf = nullptr;
102     auto gpuContextMgr      = m_osContext->GetGpuContextMgr();
103     MOS_OS_CHK_NULL_RETURN(gpuContextMgr);
104     std::vector<CommandBufferNext *> tmpInUseCmdBufPool = {};
105 
106     MosUtilities::MosLockMutex(m_inUsePoolMutex);
107 
108     if (!m_inUseCmdBufPool.empty())
109     {
110         tmpInUseCmdBufPool = std::move(m_inUseCmdBufPool);
111     }
112 
113     // clear in-use command buffer pool
114     m_inUseCmdBufPool.clear();
115     MosUtilities::MosUnlockMutex(m_inUsePoolMutex);
116 
117     MosUtilities::MosLockMutex(m_availablePoolMutex);
118     if (!tmpInUseCmdBufPool.empty())
119     {
120         for (auto& cmdBuf : tmpInUseCmdBufPool)
121         {
122             UpperInsert(cmdBuf);
123         }
124     }
125 
126     for (auto& cmdBuf : m_availableCmdBufPool)
127     {
128         if (cmdBuf != nullptr)
129         {
130             auto nativeGpuContext         = cmdBuf->GetLastNativeGpuContext();
131             auto nativeGpuContextHandle   = cmdBuf->GetLastNativeGpuContextHandle();
132             if (nativeGpuContext != nullptr && nativeGpuContext == gpuContextMgr->GetGpuContext(nativeGpuContextHandle))
133             {
134                 cmdBuf->UnBindToGpuContext(true);
135                 nativeGpuContext->ResetCmdBuffer();
136             }
137             cmdBuf->ResetLastNativeGpuContext();
138 
139             auto gpuContext         = cmdBuf->GetGpuContext();
140             auto gpuContextHandle   = cmdBuf->GetGpuContextHandle();
141             if (gpuContext != nullptr && gpuContext == gpuContextMgr->GetGpuContext(gpuContextHandle))
142             {
143                 cmdBuf->UnBindToGpuContext(false);
144                 gpuContext->ResetCmdBuffer();
145             }
146             cmdBuf->ResetGpuContext();
147         }
148         else
149         {
150             MOS_OS_ASSERTMESSAGE("Unexpected, found null command buffer!");
151         }
152     }
153     m_cmdBufTotalNum = m_availableCmdBufPool.size();
154     MosUtilities::MosUnlockMutex(m_availablePoolMutex);
155     return MOS_STATUS_SUCCESS;
156 }
157 
CleanUp()158 void CmdBufMgrNext::CleanUp()
159 {
160     MOS_OS_FUNCTION_ENTER;
161 
162     CommandBufferNext *cmdBuf = nullptr;
163     MosUtilities::MosLockMutex(m_availablePoolMutex);
164 
165     for (auto& cmdBuf : m_availableCmdBufPool)
166     {
167         if (cmdBuf != nullptr)
168         {
169             auto gpuContext         = cmdBuf->GetLastNativeGpuContext();
170             auto gpuContextHandle   = cmdBuf->GetLastNativeGpuContextHandle();
171             auto gpuContextMgr      = m_osContext->GetGpuContextMgr();
172             if (gpuContext != nullptr && gpuContextMgr && gpuContext == gpuContextMgr->GetGpuContext(gpuContextHandle))
173             {
174                 cmdBuf->UnBindToGpuContext(true);
175             }
176             cmdBuf->Free();
177             MOS_Delete(cmdBuf);
178         }
179         else
180         {
181             MOS_OS_ASSERTMESSAGE("Unexpected, found null command buffer!");
182         }
183     }
184 
185     // clear available command buffer pool
186     m_availableCmdBufPool.clear();
187     MosUtilities::MosUnlockMutex(m_availablePoolMutex);
188     MosUtilities::MosLockMutex(m_inUsePoolMutex);
189 
190     if (!m_inUseCmdBufPool.empty())
191     {
192         for (auto& cmdBuf : m_inUseCmdBufPool)
193         {
194             if (cmdBuf != nullptr)
195             {
196                 cmdBuf->Free();
197                 MOS_Delete(cmdBuf);
198             }
199         }
200     }
201 
202     // clear in-use command buffer pool
203     m_inUseCmdBufPool.clear();
204     MosUtilities::MosUnlockMutex(m_inUsePoolMutex);
205 
206     m_cmdBufTotalNum = 0;
207     m_initialized    = false;
208     MosUtilities::MosDestroyMutex(m_inUsePoolMutex);
209     m_inUsePoolMutex = nullptr;
210     MosUtilities::MosDestroyMutex(m_availablePoolMutex);
211     m_availablePoolMutex = nullptr;
212 }
213 
PickupOneCmdBuf(uint32_t size)214 CommandBufferNext *CmdBufMgrNext::PickupOneCmdBuf(uint32_t size)
215 {
216     MOS_OS_FUNCTION_ENTER;
217 
218     if (!m_initialized)
219     {
220         MOS_OS_ASSERTMESSAGE("cmd buf pool need be initialized before buffer picking up!");
221         return nullptr;
222     }
223 
224     // lock for both in-use and available command buffer pool before pick up
225     MosUtilities::MosLockMutex(m_inUsePoolMutex);
226     MosUtilities::MosLockMutex(m_availablePoolMutex);
227 
228     CommandBufferNext* cmdBuf = nullptr;
229     CommandBufferNext* retbuf  = nullptr;
230     MOS_STATUS     eStatus = MOS_STATUS_SUCCESS;
231 
232     if (!m_availableCmdBufPool.empty())
233     {
234         cmdBuf = *(m_availableCmdBufPool.begin());
235         if (cmdBuf == nullptr)
236         {
237             MOS_OS_ASSERTMESSAGE("available command buf pool is null.");
238             MosUtilities::MosUnlockMutex(m_inUsePoolMutex);
239             MosUtilities::MosUnlockMutex(m_availablePoolMutex);
240             return nullptr;
241         }
242 
243         // find available buf
244         if (size <= cmdBuf->GetCmdBufSize() && !cmdBuf->IsUsedByHw() && !cmdBuf->IsInCmdList())
245         {
246             m_inUseCmdBufPool.push_back(cmdBuf);
247 
248             m_availableCmdBufPool.erase(m_availableCmdBufPool.begin());
249 
250             MOS_OS_VERBOSEMESSAGE("successfully get available buf from pool");
251         }
252         // available buf  is not large enough, need reallocate
253         else
254         {
255             MOS_OS_VERBOSEMESSAGE("find available buf, but is not large enough or it is still used by HW");
256 
257             cmdBuf = CommandBufferNext::CreateCmdBuf(this);
258             if (cmdBuf == nullptr)
259             {
260                 MOS_OS_ASSERTMESSAGE("input nullptr returned by CommandBuffer::CreateCmdBuf.");
261             }
262             else
263             {
264                 eStatus = cmdBuf->Allocate(m_osContext, size);
265                 if (eStatus != MOS_STATUS_SUCCESS)
266                 {
267                     MOS_OS_ASSERTMESSAGE("Allocate CmdBuf failed");
268                 }
269 
270                 // directly push into inuse pool
271                 m_inUseCmdBufPool.push_back(cmdBuf);
272                 m_cmdBufTotalNum++;
273 
274             }
275         }
276 
277         retbuf = cmdBuf;
278     }
279     // no available buf in the pool, will allocate in batch
280     else
281     {
282         MOS_OS_VERBOSEMESSAGE("No more cmd buf in the pool");
283 
284         if (m_cmdBufTotalNum < m_maxPoolSize)
285         {
286             MOS_OS_VERBOSEMESSAGE("Increase the cmd buf pool size by %d", m_bufIncStepSize);
287             for (uint32_t i = 0; i < m_bufIncStepSize; i++)
288             {
289                 cmdBuf = CommandBufferNext::CreateCmdBuf(this);
290                 if (cmdBuf == nullptr)
291                 {
292                     MOS_OS_ASSERTMESSAGE("input nullptr returned by CommandBuffer::CreateCmdBuf.");
293                     continue;
294                 }
295 
296                 eStatus = cmdBuf->Allocate(m_osContext, size);
297                 if (eStatus != MOS_STATUS_SUCCESS)
298                 {
299                     MOS_OS_ASSERTMESSAGE("Allocate CmdBuf#%d failed", i);
300                     cmdBuf->Free();
301                     MOS_Delete(cmdBuf);
302                     continue;
303                 }
304 
305                 if (i == 0)
306                 {
307                     // directly push into inuse pool
308                     m_inUseCmdBufPool.push_back(cmdBuf);
309                     retbuf = cmdBuf;
310                 }
311                 else
312                 {
313                     m_availableCmdBufPool.insert(m_availableCmdBufPool.begin(), cmdBuf);
314                 }
315                 m_cmdBufTotalNum++;
316             }
317 
318             // sort by decent order
319             std::sort(m_availableCmdBufPool.begin(), m_availableCmdBufPool.end(), &CmdBufMgrNext::GreaterSizeSort);
320         }
321         else
322         {
323             MOS_OS_ASSERTMESSAGE("No availabe cmd buf in pool and the total buf num hit the ceiling, may need wait for a while.");
324             retbuf = nullptr;
325         }
326     }
327 
328     // unlock after got return buffer
329     MosUtilities::MosUnlockMutex(m_inUsePoolMutex);
330     MosUtilities::MosUnlockMutex(m_availablePoolMutex);
331 
332     return retbuf;
333 }
334 
UpperInsert(CommandBufferNext * cmdBuf)335 void CmdBufMgrNext::UpperInsert(CommandBufferNext *cmdBuf)
336 {
337     auto it = std::find_if(m_availableCmdBufPool.begin(), m_availableCmdBufPool.end(), [=](CommandBufferNext * p1){return p1->GetCmdBufSize() < cmdBuf->GetCmdBufSize();});
338     m_availableCmdBufPool.emplace(it, cmdBuf);
339 }
340 
ReleaseCmdBuf(CommandBufferNext * cmdBuf)341 MOS_STATUS CmdBufMgrNext::ReleaseCmdBuf(CommandBufferNext *cmdBuf)
342 {
343     MOS_OS_FUNCTION_ENTER;
344 
345     MOS_STATUS     eStatus = MOS_STATUS_SUCCESS;
346 
347     if (!m_initialized)
348     {
349         MOS_OS_ASSERTMESSAGE("cmd buf pool need be initialized before buffer release!");
350         return MOS_STATUS_NULL_POINTER;
351     }
352 
353     MOS_OS_CHK_NULL_RETURN(cmdBuf);
354 
355     // lock for both in-use and available command buffer pool before release
356     MosUtilities::MosLockMutex(m_inUsePoolMutex);
357     MosUtilities::MosLockMutex(m_availablePoolMutex);
358 
359     bool           found = false;
360     for (auto iter = m_inUseCmdBufPool.begin(); iter != m_inUseCmdBufPool.end(); iter++)
361     {
362         if (cmdBuf == *iter)
363         {
364             found = true;
365             m_inUseCmdBufPool.erase(iter);
366             break;
367         }
368     }
369 
370     if (!found)
371     {
372         MOS_OS_ASSERTMESSAGE("Cannot find the specified cmdbuf in inusepool, sth must be wrong!");
373         eStatus = MOS_STATUS_UNKNOWN;
374     }
375     else
376     {
377         UpperInsert(cmdBuf);
378     }
379 
380     // unlock after release buffer
381     MosUtilities::MosUnlockMutex(m_availablePoolMutex);
382     MosUtilities::MosUnlockMutex(m_inUsePoolMutex);
383 
384     return eStatus;
385 }
386 
ResizeOneCmdBuf(CommandBufferNext * cmdBufToResize,uint32_t newSize)387 MOS_STATUS CmdBufMgrNext::ResizeOneCmdBuf(CommandBufferNext *cmdBufToResize, uint32_t newSize)
388 {
389     MOS_OS_FUNCTION_ENTER;
390 
391     MOS_OS_CHK_NULL_RETURN(cmdBufToResize);
392 
393     if (!m_initialized)
394     {
395         MOS_OS_ASSERTMESSAGE("cmd buf pool need be initialized before buffer resize!");
396         return MOS_STATUS_UNKNOWN;
397     }
398 
399     return cmdBufToResize->ReSize(newSize);
400 }
401 
402 
GreaterSizeSort(CommandBufferNext * a,CommandBufferNext * b)403 bool CmdBufMgrNext::GreaterSizeSort(CommandBufferNext *a, CommandBufferNext *b)
404 {
405     return (a->GetCmdBufSize() > b->GetCmdBufSize());
406 }