blob: 8c540fffee1b2bae9ac31170476b6bc8a13a0a6f [file] [log] [blame]
/*
* 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();
}
}