| /* |
| * Copyright (c) 2017, Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| //! |
| //! \file codechal_allocator.cpp |
| //! \brief Class that provides a generic resource allocation service |
| //! |
| |
| #include "codechal_allocator.h" |
| |
| uint64_t CodechalAllocator::GetResourceTag(uint16_t resourceID, Match level) |
| { |
| if (!m_resourceList.empty()) |
| { |
| for (auto& res : m_resourceList) |
| { |
| if (resourceID == GetResourceID(res.first, level)) |
| return res.first; |
| } |
| } |
| |
| return 0; |
| } |
| |
| void* CodechalAllocator::GetResourcePointer(uint16_t resourceID, Match level) |
| { |
| if (!m_resourceList.empty()) |
| { |
| for (auto& res : m_resourceList) |
| { |
| if (resourceID == GetResourceID(res.first, level)) |
| return res.second; |
| } |
| } |
| |
| return nullptr; |
| } |
| |
| void* CodechalAllocator::Allocate1DBuffer(uint64_t resourceTag, uint32_t size, |
| const char* bufName, bool zeroOnAllocation, uint32_t dwMemType) |
| { |
| MOS_RESOURCE* resource = MOS_New(MOS_RESOURCE); |
| MOS_ZeroMemory(resource, sizeof(MOS_RESOURCE)); |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParams; |
| MOS_ZeroMemory(&allocParams, sizeof(allocParams)); |
| allocParams.Type = MOS_GFXRES_BUFFER; |
| allocParams.Format = Format_Buffer; |
| allocParams.TileType = MOS_TILE_LINEAR; |
| allocParams.dwBytes = size; |
| allocParams.pBufName = bufName; |
| allocParams.dwMemType = dwMemType; |
| |
| if (MOS_STATUS_SUCCESS != m_osInterface->pfnAllocateResource( |
| m_osInterface, &allocParams, resource)) |
| { |
| MOS_Delete(resource); |
| MOS_OS_ASSERTMESSAGE("allocate 1D buffer error!"); |
| return nullptr; |
| } |
| |
| // place the newly allocated resource onto the list |
| m_resourceList[resourceTag] = resource; |
| MOS_OS_NORMALMESSAGE("allocate 1D buffer = 0x%x, tag = 0x%llx", resource, (long long)resourceTag); |
| |
| if (zeroOnAllocation) |
| { |
| ClearResource(resource, size); |
| } |
| |
| return resource; |
| } |
| |
| void* CodechalAllocator::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) |
| { |
| MOS_SURFACE* surface = MOS_New(MOS_SURFACE); |
| MOS_ZeroMemory(surface, sizeof(MOS_SURFACE)); |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParams; |
| MOS_ZeroMemory(&allocParams, sizeof(allocParams)); |
| allocParams.Type = MOS_GFXRES_2D; |
| allocParams.Format = format; |
| allocParams.TileType = tile; |
| allocParams.dwWidth = width; |
| allocParams.dwHeight = height; |
| allocParams.pBufName = bufName; |
| allocParams.dwMemType = dwMemType; |
| |
| if (MOS_STATUS_SUCCESS != m_osInterface->pfnAllocateResource( |
| m_osInterface, &allocParams, &surface->OsResource)) |
| { |
| MOS_Delete(surface); |
| MOS_OS_ASSERTMESSAGE("allocate 2D buffer error!"); |
| return nullptr; |
| } |
| |
| // place the newly allocated resource onto the list |
| m_resourceList[resourceTag] = surface; |
| MOS_OS_NORMALMESSAGE("allocate 2D buffer = 0x%x, tag = 0x%llx", surface, (long long)resourceTag); |
| |
| if (zeroOnAllocation) |
| { |
| ClearResource(&surface->OsResource, width * height); |
| } |
| |
| return surface; |
| } |
| |
| void* CodechalAllocator::AllocateBatchBuffer(uint64_t resourceTag, uint32_t size, bool zeroOnAllocation) |
| { |
| MHW_BATCH_BUFFER* batch = MOS_New(MHW_BATCH_BUFFER); |
| MOS_ZeroMemory(batch, sizeof(MHW_BATCH_BUFFER)); |
| |
| if (MOS_STATUS_SUCCESS != Mhw_AllocateBb(m_osInterface, batch, nullptr, size)) |
| { |
| MOS_Delete(batch); |
| MOS_OS_ASSERTMESSAGE("allocate batch buffer error!"); |
| return nullptr; |
| } |
| |
| // place the newly allocated resource onto the list |
| m_resourceList[resourceTag] = batch; |
| MOS_OS_NORMALMESSAGE("allocate batch buffer = 0x%x, tag = 0x%llx", batch, (long long)resourceTag); |
| |
| if (zeroOnAllocation) |
| { |
| Mhw_LockBb(m_osInterface, batch); |
| |
| MOS_ZeroMemory(batch->pData, size); |
| |
| Mhw_UnlockBb(m_osInterface, batch, false); |
| } |
| |
| return batch; |
| } |
| |
| void CodechalAllocator::ReleaseResource(uint16_t resourceID, Match level) |
| { |
| if (!m_resourceList.empty()) |
| { |
| uint64_t tag = 0; |
| void* pointer = nullptr; |
| |
| for (auto& res : m_resourceList) |
| { |
| if (resourceID == GetResourceID(res.first, level)) |
| { |
| tag = res.first; |
| pointer = res.second; |
| break; |
| } |
| } |
| |
| if (tag) |
| { |
| // deallocate the matched resource |
| Deallocate(tag, pointer); |
| |
| // remove from resource list |
| m_resourceList.erase(tag); |
| } |
| } |
| } |
| |
| bool CodechalAllocator::Is1DBuffer(uint64_t resourceTag) |
| { |
| uint16_t typeID = (uint16_t)resourceTag; |
| return (typeID >> 14 & 3) == 0; |
| } |
| |
| bool CodechalAllocator::Is2DBuffer(uint64_t resourceTag) |
| { |
| uint16_t typeID = (uint16_t)resourceTag; |
| return (typeID >> 14 & 3) == 1; |
| } |
| |
| bool CodechalAllocator::IsBatchBuffer(uint64_t resourceTag) |
| { |
| uint16_t typeID = (uint16_t)resourceTag; |
| return (typeID >> 14 & 3) == 2; |
| } |
| |
| void CodechalAllocator::ClearResource(MOS_RESOURCE* resource, size_t size) |
| { |
| MOS_LOCK_PARAMS LockFlags; |
| MOS_ZeroMemory(&LockFlags, sizeof(LockFlags)); |
| LockFlags.WriteOnly = 1; |
| |
| uint8_t* ptr = (uint8_t*)m_osInterface->pfnLockResource( |
| m_osInterface, resource, &LockFlags); |
| |
| MOS_ZeroMemory(ptr, size); |
| |
| m_osInterface->pfnUnlockResource(m_osInterface, resource); |
| } |
| |
| void CodechalAllocator::Deallocate(uint64_t tag, void* pointer) |
| { |
| if (Is1DBuffer(tag)) |
| { |
| MOS_RESOURCE* ptr = (MOS_RESOURCE*)pointer; |
| m_osInterface->pfnFreeResource(m_osInterface, ptr); |
| MOS_OS_NORMALMESSAGE("free 1D buffer = 0x%x", ptr); |
| |
| // free resource container |
| MOS_Delete(ptr); |
| } |
| else if (Is2DBuffer(tag)) |
| { |
| MOS_SURFACE* ptr = (MOS_SURFACE*)pointer; |
| m_osInterface->pfnFreeResource(m_osInterface, &ptr->OsResource); |
| MOS_OS_NORMALMESSAGE("free 2D buffer = 0x%x", ptr); |
| |
| // free resource container |
| MOS_Delete(ptr); |
| } |
| else if (IsBatchBuffer(tag)) |
| { |
| MHW_BATCH_BUFFER* ptr = (MHW_BATCH_BUFFER*)pointer; |
| Mhw_FreeBb(m_osInterface, ptr, nullptr); |
| MOS_OS_NORMALMESSAGE("free batch buffer = 0x%x", ptr); |
| |
| // free resource container |
| MOS_Delete(ptr); |
| } |
| else |
| { |
| MOS_OS_ASSERTMESSAGE("Unknown resource = 0x%x", pointer); |
| } |
| } |
| |
| CodechalAllocator::CodechalAllocator(MOS_INTERFACE* osInterface) |
| : m_osInterface(osInterface), |
| m_resourceList{} |
| { |
| } |
| |
| CodechalAllocator::~CodechalAllocator() |
| { |
| if (!m_resourceList.empty()) |
| { |
| for (auto& res : m_resourceList) |
| { |
| Deallocate(res.first, res.second); |
| } |
| |
| m_resourceList.clear(); |
| } |
| } |