1 /*
2 * Copyright (c) 2017, 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 codechal_allocator.cpp
24 //! \brief Class that provides a generic resource allocation service
25 //!
26
27 #include "codechal_allocator.h"
28
GetResourceTag(uint16_t resourceID,Match level)29 uint64_t CodechalAllocator::GetResourceTag(uint16_t resourceID, Match level)
30 {
31 if (!m_resourceList.empty())
32 {
33 for (auto& res : m_resourceList)
34 {
35 if (resourceID == GetResourceID(res.first, level))
36 return res.first;
37 }
38 }
39
40 return 0;
41 }
42
GetResourcePointer(uint16_t resourceID,Match level)43 void* CodechalAllocator::GetResourcePointer(uint16_t resourceID, Match level)
44 {
45 if (!m_resourceList.empty())
46 {
47 for (auto& res : m_resourceList)
48 {
49 if (resourceID == GetResourceID(res.first, level))
50 return res.second;
51 }
52 }
53
54 return nullptr;
55 }
56
Allocate1DBuffer(uint64_t resourceTag,uint32_t size,const char * bufName,bool zeroOnAllocation,uint32_t dwMemType)57 void* CodechalAllocator::Allocate1DBuffer(uint64_t resourceTag, uint32_t size,
58 const char* bufName, bool zeroOnAllocation, uint32_t dwMemType)
59 {
60 MOS_RESOURCE* resource = MOS_New(MOS_RESOURCE);
61 MOS_ZeroMemory(resource, sizeof(MOS_RESOURCE));
62
63 MOS_ALLOC_GFXRES_PARAMS allocParams;
64 MOS_ZeroMemory(&allocParams, sizeof(allocParams));
65 allocParams.Type = MOS_GFXRES_BUFFER;
66 allocParams.Format = Format_Buffer;
67 allocParams.TileType = MOS_TILE_LINEAR;
68 allocParams.dwBytes = size;
69 allocParams.pBufName = bufName;
70 allocParams.dwMemType = dwMemType;
71
72 if (MOS_STATUS_SUCCESS != m_osInterface->pfnAllocateResource(
73 m_osInterface, &allocParams, resource))
74 {
75 MOS_Delete(resource);
76 MOS_OS_ASSERTMESSAGE("allocate 1D buffer error!");
77 return nullptr;
78 }
79
80 // place the newly allocated resource onto the list
81 m_resourceList[resourceTag] = resource;
82 MOS_OS_NORMALMESSAGE("allocate 1D buffer = 0x%x, tag = 0x%llx", resource, (long long)resourceTag);
83
84 if (zeroOnAllocation)
85 {
86 ClearResource(resource, size);
87 }
88
89 return resource;
90 }
91
Allocate2DBuffer(uint64_t resourceTag,uint32_t width,uint32_t height,MOS_FORMAT format,MOS_TILE_TYPE tile,const char * bufName,bool zeroOnAllocation,uint32_t dwMemType)92 void* CodechalAllocator::Allocate2DBuffer(
93 uint64_t resourceTag, uint32_t width, uint32_t height, MOS_FORMAT format,
94 MOS_TILE_TYPE tile, const char* bufName, bool zeroOnAllocation, uint32_t dwMemType)
95 {
96 MOS_SURFACE* surface = MOS_New(MOS_SURFACE);
97 MOS_ZeroMemory(surface, sizeof(MOS_SURFACE));
98
99 MOS_ALLOC_GFXRES_PARAMS allocParams;
100 MOS_ZeroMemory(&allocParams, sizeof(allocParams));
101 allocParams.Type = MOS_GFXRES_2D;
102 allocParams.Format = format;
103 allocParams.TileType = tile;
104 allocParams.dwWidth = width;
105 allocParams.dwHeight = height;
106 allocParams.pBufName = bufName;
107 allocParams.dwMemType = dwMemType;
108
109 if (MOS_STATUS_SUCCESS != m_osInterface->pfnAllocateResource(
110 m_osInterface, &allocParams, &surface->OsResource))
111 {
112 MOS_Delete(surface);
113 MOS_OS_ASSERTMESSAGE("allocate 2D buffer error!");
114 return nullptr;
115 }
116
117 // place the newly allocated resource onto the list
118 m_resourceList[resourceTag] = surface;
119 MOS_OS_NORMALMESSAGE("allocate 2D buffer = 0x%x, tag = 0x%llx", surface, (long long)resourceTag);
120
121 if (zeroOnAllocation)
122 {
123 ClearResource(&surface->OsResource, width * height);
124 }
125
126 return surface;
127 }
128
AllocateBatchBuffer(uint64_t resourceTag,uint32_t size,bool zeroOnAllocation)129 void* CodechalAllocator::AllocateBatchBuffer(uint64_t resourceTag, uint32_t size, bool zeroOnAllocation)
130 {
131 MHW_BATCH_BUFFER* batch = MOS_New(MHW_BATCH_BUFFER);
132 MOS_ZeroMemory(batch, sizeof(MHW_BATCH_BUFFER));
133
134 if (MOS_STATUS_SUCCESS != Mhw_AllocateBb(m_osInterface, batch, nullptr, size))
135 {
136 MOS_Delete(batch);
137 MOS_OS_ASSERTMESSAGE("allocate batch buffer error!");
138 return nullptr;
139 }
140
141 // place the newly allocated resource onto the list
142 m_resourceList[resourceTag] = batch;
143 MOS_OS_NORMALMESSAGE("allocate batch buffer = 0x%x, tag = 0x%llx", batch, (long long)resourceTag);
144
145 if (zeroOnAllocation)
146 {
147 Mhw_LockBb(m_osInterface, batch);
148
149 MOS_ZeroMemory(batch->pData, size);
150
151 Mhw_UnlockBb(m_osInterface, batch, false);
152 }
153
154 return batch;
155 }
156
ReleaseResource(uint16_t resourceID,Match level)157 void CodechalAllocator::ReleaseResource(uint16_t resourceID, Match level)
158 {
159 if (!m_resourceList.empty())
160 {
161 uint64_t tag = 0;
162 void* pointer = nullptr;
163
164 for (auto& res : m_resourceList)
165 {
166 if (resourceID == GetResourceID(res.first, level))
167 {
168 tag = res.first;
169 pointer = res.second;
170 break;
171 }
172 }
173
174 if (tag)
175 {
176 // deallocate the matched resource
177 Deallocate(tag, pointer);
178
179 // remove from resource list
180 m_resourceList.erase(tag);
181 }
182 }
183 }
184
Is1DBuffer(uint64_t resourceTag)185 bool CodechalAllocator::Is1DBuffer(uint64_t resourceTag)
186 {
187 uint16_t typeID = (uint16_t)resourceTag;
188 return (typeID >> 14 & 3) == 0;
189 }
190
Is2DBuffer(uint64_t resourceTag)191 bool CodechalAllocator::Is2DBuffer(uint64_t resourceTag)
192 {
193 uint16_t typeID = (uint16_t)resourceTag;
194 return (typeID >> 14 & 3) == 1;
195 }
196
IsBatchBuffer(uint64_t resourceTag)197 bool CodechalAllocator::IsBatchBuffer(uint64_t resourceTag)
198 {
199 uint16_t typeID = (uint16_t)resourceTag;
200 return (typeID >> 14 & 3) == 2;
201 }
202
ClearResource(MOS_RESOURCE * resource,size_t size)203 void CodechalAllocator::ClearResource(MOS_RESOURCE* resource, size_t size)
204 {
205 MOS_LOCK_PARAMS LockFlags;
206 MOS_ZeroMemory(&LockFlags, sizeof(LockFlags));
207 LockFlags.WriteOnly = 1;
208
209 uint8_t* ptr = (uint8_t*)m_osInterface->pfnLockResource(
210 m_osInterface, resource, &LockFlags);
211
212 MOS_ZeroMemory(ptr, size);
213
214 m_osInterface->pfnUnlockResource(m_osInterface, resource);
215 }
216
Deallocate(uint64_t tag,void * pointer)217 void CodechalAllocator::Deallocate(uint64_t tag, void* pointer)
218 {
219 if (Is1DBuffer(tag))
220 {
221 MOS_RESOURCE* ptr = (MOS_RESOURCE*)pointer;
222 m_osInterface->pfnFreeResource(m_osInterface, ptr);
223 MOS_OS_NORMALMESSAGE("free 1D buffer = 0x%x", ptr);
224
225 // free resource container
226 MOS_Delete(ptr);
227 }
228 else if (Is2DBuffer(tag))
229 {
230 MOS_SURFACE* ptr = (MOS_SURFACE*)pointer;
231 m_osInterface->pfnFreeResource(m_osInterface, &ptr->OsResource);
232 MOS_OS_NORMALMESSAGE("free 2D buffer = 0x%x", ptr);
233
234 // free resource container
235 MOS_Delete(ptr);
236 }
237 else if (IsBatchBuffer(tag))
238 {
239 MHW_BATCH_BUFFER* ptr = (MHW_BATCH_BUFFER*)pointer;
240 Mhw_FreeBb(m_osInterface, ptr, nullptr);
241 MOS_OS_NORMALMESSAGE("free batch buffer = 0x%x", ptr);
242
243 // free resource container
244 MOS_Delete(ptr);
245 }
246 else
247 {
248 MOS_OS_ASSERTMESSAGE("Unknown resource = 0x%x", pointer);
249 }
250 }
251
CodechalAllocator(MOS_INTERFACE * osInterface)252 CodechalAllocator::CodechalAllocator(MOS_INTERFACE* osInterface)
253 : m_osInterface(osInterface),
254 m_resourceList{}
255 {
256 }
257
~CodechalAllocator()258 CodechalAllocator::~CodechalAllocator()
259 {
260 if (!m_resourceList.empty())
261 {
262 for (auto& res : m_resourceList)
263 {
264 Deallocate(res.first, res.second);
265 }
266
267 m_resourceList.clear();
268 }
269 }
270