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