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 }