1 /*
2 * Copyright (c) 2024, 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     surface_state_heap_mgr.cpp
24 //! \brief    Render Engine state heap manager for VP and CM
25 //! \details  Platform/OS Independent Render Engine state heap management interfaces
26 //!
27 #include "surface_state_heap_mgr.h"
28 #include "vp_utils.h"
29 
SurfaceStateHeapManager(PMOS_INTERFACE pOsInterface)30 SurfaceStateHeapManager::SurfaceStateHeapManager(PMOS_INTERFACE pOsInterface) : m_osInterface(pOsInterface)
31 {
32 }
33 
~SurfaceStateHeapManager()34 SurfaceStateHeapManager::~SurfaceStateHeapManager()
35 {
36     DestroyHeap();
37 }
38 
CreateHeap(size_t surfStateSize)39 MOS_STATUS SurfaceStateHeapManager::CreateHeap(size_t surfStateSize)
40 {
41     uint8_t                *pMem;
42     uint32_t                uiSize;
43     uint32_t                uiOffset;
44     MOS_ALLOC_GFXRES_PARAMS AllocParams;
45     MOS_LOCK_PARAMS         LockFlags;
46     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
47 
48     uiSize = sizeof(SURFACE_STATES_HEAP_OBJ);
49     uiSize += MAX_SURFACE_STATES *
50               sizeof(SURFACE_STATES_OBJ);
51 
52     // Allocate memory for render surface state heap
53     pMem = (uint8_t *)MOS_AllocAndZeroMemory(uiSize);
54     MHW_CHK_NULL_RETURN(pMem);
55 
56     m_surfStateHeap = (SURFACE_STATES_HEAP_OBJ *)pMem;
57 
58     m_surfStateHeap->pSurfStateObj =
59         (SURFACE_STATES_OBJ *)(pMem + sizeof(SURFACE_STATES_HEAP_OBJ));
60 
61     // Appending sync data after all heap instances
62     m_surfStateHeap->uiOffsetSync = surfStateSize * MAX_SURFACE_STATES;
63 
64     // Allocate GPU memory
65     uiSize = surfStateSize * MAX_SURFACE_STATES + SYNC_SIZE;
66 
67     m_surfStateHeap->uiStateHeapSize = uiSize;
68     m_surfStateHeap->uiInstanceSize = surfStateSize;
69 
70     MOS_ZeroMemory(&AllocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
71 
72     AllocParams.Type         = MOS_GFXRES_BUFFER;
73     AllocParams.TileType     = MOS_TILE_LINEAR;
74     AllocParams.Format       = Format_Buffer;
75     AllocParams.dwBytes      = uiSize;
76     AllocParams.pBufName     = "VphalSurfaceState";
77     AllocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_RENDER;
78     AllocParams.dwMemType    = MOS_MEMPOOL_VIDEOMEMORY;
79 
80     MHW_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
81         m_osInterface,
82         &AllocParams,
83         &m_surfStateHeap->osResource));
84 
85     // Lock the driver resource
86     MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
87 
88     LockFlags.NoOverWrite = 1;
89 
90     m_surfStateHeap->pLockedOsResourceMem =
91         (uint8_t *)m_osInterface->pfnLockResource(
92             m_osInterface,
93             &m_surfStateHeap->osResource,
94             &LockFlags);
95     MHW_CHK_NULL_RETURN(m_surfStateHeap->pLockedOsResourceMem);
96 
97     // Initialize VeboxHeap controls that depend on mapping
98     m_surfStateHeap->pSync =
99         (uint32_t *)(m_surfStateHeap->pLockedOsResourceMem +
100                      m_surfStateHeap->uiOffsetSync);
101 
102     return eStatus;
103 }
104 
DestroyHeap()105 MOS_STATUS SurfaceStateHeapManager::DestroyHeap()
106 {
107     if (m_surfStateHeap)
108     {
109         if (!Mos_ResourceIsNull(&m_surfStateHeap->osResource))
110         {
111             if (m_surfStateHeap->pLockedOsResourceMem)
112             {
113                 m_osInterface->pfnUnlockResource(
114                     m_osInterface,
115                     &m_surfStateHeap->osResource);
116             }
117 
118             m_osInterface->pfnFreeResource(
119                 m_osInterface,
120                 &m_surfStateHeap->osResource);
121         }
122 
123         MOS_FreeMemory(m_surfStateHeap);
124         m_surfStateHeap = nullptr;
125     }
126     return MOS_STATUS_SUCCESS;
127 }
128 
RefreshSync()129 void SurfaceStateHeapManager::RefreshSync()
130 {
131     SURFACE_STATES_OBJ      *pCurInstance;
132     SURFACE_STATES_HEAP_OBJ *pSurfStateHeap;
133     uint32_t                 dwCurrentTag;
134     int32_t                  i;
135     int32_t                  iInstanceInUse;
136     MOS_NULL_RENDERING_FLAGS NullRenderingFlags;
137 
138     MHW_FUNCTION_ENTER;
139     if (m_surfStateHeap == nullptr ||
140         m_osInterface == nullptr)
141     {
142         MHW_ASSERTMESSAGE("RefreshSync failed due to m_veboxHeap or m_osInterface is invalid ");
143         return;
144     }
145     iInstanceInUse = 0;
146 
147     // Vebox Heap will always be locked by driver
148     pSurfStateHeap = m_surfStateHeap;
149 
150     // Most recent tag
151     if (m_osInterface->bEnableKmdMediaFrameTracking)
152     {
153         dwCurrentTag = m_osInterface->pfnGetGpuStatusSyncTag(m_osInterface, MOS_GPU_CONTEXT_COMPUTE);
154     }
155     else
156     {
157         dwCurrentTag = pSurfStateHeap->pSync[0];
158     }
159     pSurfStateHeap->dwSyncTag = dwCurrentTag - 1;
160 
161     NullRenderingFlags = m_osInterface->pfnGetNullHWRenderFlags(
162         m_osInterface);
163 
164     // Refresh VeboxHeap states
165     pCurInstance = pSurfStateHeap->pSurfStateObj;
166     for (i = MAX_SURFACE_STATES; i > 0; i--, pCurInstance++)
167     {
168         if (!pCurInstance->bBusy)
169             continue;
170 
171         // The condition below is valid when sync tag wraps from 2^32-1 to 0
172         if (((int32_t)(dwCurrentTag - pCurInstance->dwSyncTag) >= 0) ||
173             NullRenderingFlags.VPGobal)
174         {
175             pCurInstance->bBusy = false;
176         }
177         else
178         {
179             iInstanceInUse++;
180         }
181     }
182 
183     // Save number of instance in use
184     m_surfHeapInUse = iInstanceInUse;
185 }
186 
AssignSurfaceState()187 MOS_STATUS SurfaceStateHeapManager::AssignSurfaceState()
188 {
189     VP_FUNC_CALL();
190 
191     uint32_t   dwWaitMs, dwWaitTag;
192     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
193 
194     SURFACE_STATES_OBJ      *pSurfStateCurObj;
195     SURFACE_STATES_HEAP_OBJ *pSurfStateHeap;
196     uint32_t                 uiOffset;
197 
198     MHW_FUNCTION_ENTER;
199     MHW_CHK_NULL_RETURN(m_surfStateHeap);
200     MHW_CHK_NULL_RETURN(m_osInterface);
201 
202     pSurfStateHeap = m_surfStateHeap;
203     pSurfStateCurObj = &m_surfStateHeap->pSurfStateObj[m_surfStateHeap->uiNextState];
204 
205     // Refresh sync tag for all heap instance
206     RefreshSync();
207 
208     // Check validity of  current vebox heap instance
209     // The code below is unlikely to be executed - unless all Vebox states are in use
210     // If this ever happens, please consider increasing the number of media states
211     MHW_CHK_NULL_RETURN(pSurfStateCurObj);
212     if (pSurfStateCurObj->bBusy)
213     {
214         // Get current vebox instance sync tag
215         dwWaitTag = pSurfStateCurObj->dwSyncTag;
216 
217         // Wait for Batch Buffer complete event OR timeout
218         for (dwWaitMs = MHW_TIMEOUT_MS_DEFAULT; dwWaitMs > 0; dwWaitMs--)
219         {
220             uint32_t dwCurrentTag;
221 
222             MHW_CHK_STATUS_RETURN(m_osInterface->pfnWaitForBBCompleteNotifyEvent(
223                 m_osInterface,
224                 MOS_GPU_CONTEXT_COMPUTE,
225                 MHW_EVENT_TIMEOUT_MS));
226 
227             if (m_osInterface->bEnableKmdMediaFrameTracking)
228             {
229                 dwCurrentTag = m_osInterface->pfnGetGpuStatusSyncTag(m_osInterface, MOS_GPU_CONTEXT_COMPUTE);
230             }
231             else
232             {
233                 dwCurrentTag = pSurfStateHeap->pSync[0];
234             }
235             // Mark current instance status as availabe. Wait if this sync tag came back from GPU
236             if ((int32_t)(dwCurrentTag - dwWaitTag) >= 0)
237             {
238                 pSurfStateCurObj->bBusy = false;
239                 break;
240             }
241         }
242 
243         // Timeout
244         if (dwWaitMs == 0)
245         {
246             MHW_ASSERTMESSAGE("Timeout on waiting for free Vebox Heap.");
247             eStatus = MOS_STATUS_UNKNOWN;
248             return eStatus;
249         }
250     }
251 
252     // Prepare syncTag for GPU write back
253     if (m_osInterface->bEnableKmdMediaFrameTracking)
254     {
255         pSurfStateCurObj->dwSyncTag = m_osInterface->pfnGetGpuStatusTag(m_osInterface, MOS_GPU_CONTEXT_COMPUTE);
256     }
257     else
258     {
259         pSurfStateCurObj->dwSyncTag = pSurfStateHeap->dwNextTag;
260     }
261 
262     // Assign current state and increase next state
263     pSurfStateHeap->uiCurState  = pSurfStateHeap->uiNextState;
264     pSurfStateHeap->uiNextState = (pSurfStateHeap->uiNextState + 1) % MAX_SURFACE_STATES;
265 
266     //Clean the memory of current veboxheap to avoid the history states
267     uiOffset = pSurfStateHeap->uiCurState * pSurfStateHeap->uiInstanceSize;
268     MOS_ZeroMemory(pSurfStateHeap->pLockedOsResourceMem + uiOffset, pSurfStateHeap->uiInstanceSize);
269 
270     return eStatus;
271 }