blob: 3d8a73df5da64480ccc6af9abbba4d6f42a4a4be [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 CMRTKernelBase.cpp
//! \brief HEVC FEI MDF structure base class for GEN9 SKL.
//!
#include "CMRTKernelBase.h"
CMRTKernelBase::CMRTKernelBase()
{
m_cmDev = nullptr;
m_cmProgram = nullptr;
m_cmQueue = nullptr;
m_cmTask = nullptr; //Can be reused for each kernel
m_cmThreadSpace = nullptr;
m_cmKernel = nullptr;
m_cmSurface2D = nullptr;
m_cmSurfaceRef0 = nullptr;
m_cmSurfaceRef1 = nullptr;
m_cmBuffer = nullptr;
m_cmVmeSurf = nullptr;
m_surfIndex = nullptr;
m_isaName = nullptr;
m_kernelName = nullptr;
m_curbe = nullptr;
m_isaSize = 0;
m_cmSurface2DCount = 0;
m_cmSurfaceRef0Count = 0;
m_cmSurfaceRef1Count = 0;
m_cmBufferCount = 0;
m_cmVmeSurfCount = 0;
}
CMRTKernelBase::~CMRTKernelBase()
{
}
CM_RETURN_CODE CMRTKernelBase::LoadProgramISA(const uint32_t *isaCode, uint32_t isaSize, CmProgram * &program)
{
int32_t result;
// Load Program
result = m_cmDev->LoadProgram((void *)isaCode, isaSize, program, "-nojitter");
if (result != CM_SUCCESS)
{
printf("MDF LoadProgram error: %d\n", result);
}
return CM_SUCCESS;
}
CM_RETURN_CODE CMRTKernelBase::Init(void *osContext, CmDevice *cmDev, CmQueue *cmQueue, CmTask *cmTask, CmProgram *cmProgram)
{
int32_t result;
if (cmDev)
{
m_cmDev = cmDev;
}
else
{
#ifdef ENABLE_CMRT_KERNEL_ULT
uint32_t version = 0;
result = CreateCmDevice(m_cmDev, version);
#else
result = CreateCmDevice((PMOS_CONTEXT)osContext, m_cmDev, CM_DEVICE_CREATE_OPTION_FOR_HEVC);
#endif
if (result != CM_SUCCESS)
{
printf("CmDevice creation error\n");
return CM_FAILURE;
}
}
if (cmQueue)
{
m_cmQueue = cmQueue;
}
else
{
#ifdef ENABLE_CMRT_KERNEL_ULT
result = m_cmDev->CreateQueue(m_cmQueue);
#else
result = m_cmDev->CreateQueue(m_cmQueue);
#endif
if (result != CM_SUCCESS)
{
printf("CM CreateQueue error\n");
return CM_FAILURE;
}
}
if (cmTask)
{
m_cmTask = cmTask;
}
else
{
#ifdef ENABLE_CMRT_KERNEL_ULT
result = m_cmDev->CreateTask(m_cmTask);
#else
result = m_cmDev->CreateTask(m_cmTask);
#endif
if (result != CM_SUCCESS)
{
printf("CmDevice CreateTask error\n");
return CM_FAILURE;
}
}
if (cmProgram)
{
m_cmProgram = cmProgram;
}
else
{
result = LoadProgramISA(m_isaName, m_isaSize, m_cmProgram);
if (result != CM_SUCCESS)
{
printf("CmDevice LoadProgramISA error\n");
return CM_FAILURE;
}
}
result = m_cmDev->CreateKernel(m_cmProgram, m_kernelName, m_cmKernel);
if (result != CM_SUCCESS)
{
printf("CmDevice CreateKernel error\n");
return CM_FAILURE;
}
return CM_SUCCESS;
}
int32_t CMRTKernelBase::CreateThreadSpace(uint32_t threadSpaceWidth, uint32_t threadSpaceHeight)
{
int32_t result = CM_SUCCESS;
if (!m_cmThreadSpace)
{
result = m_cmDev->CreateThreadSpace(threadSpaceWidth, threadSpaceHeight, m_cmThreadSpace);
}
else
{
//Destory thread space used before
result = m_cmDev->DestroyThreadSpace(m_cmThreadSpace);
if (result != CM_SUCCESS)
{
printf("CM Destroy ThreadSpace error : %d", result);
return (CM_RETURN_CODE)result;
}
result = m_cmDev->CreateThreadSpace(threadSpaceWidth, threadSpaceHeight, m_cmThreadSpace);
}
return result;
}
CM_RETURN_CODE CMRTKernelBase::AddKernel(CmEvent *&cmEvent, bool destroyEvent, bool isEnqueue)
{
if (m_cmTask == nullptr)
{
CM_CHK_STATUS_RETURN(m_cmDev->CreateTask(m_cmTask));
}
if (m_cmQueue == nullptr)
{
CM_CHK_STATUS_RETURN(m_cmDev->CreateQueue(m_cmQueue));//CreateQueue is just get queue of CmDev, so just need call once.
}
CM_CHK_STATUS_RETURN(m_cmKernel->AssociateThreadSpace(m_cmThreadSpace));
CM_CHK_STATUS_RETURN(m_cmTask->AddKernel(m_cmKernel));
if (isEnqueue)
{
CM_CHK_STATUS_RETURN(m_cmQueue->Enqueue(m_cmTask, cmEvent));
CM_CHK_STATUS_RETURN(m_cmTask->Reset());
if(destroyEvent)
{
CM_CHK_STATUS_RETURN(m_cmQueue->DestroyEvent(cmEvent));
}
}
else
{
CM_CHK_STATUS_RETURN(m_cmTask->AddSync());
}
return CM_SUCCESS;
}
CM_RETURN_CODE CMRTKernelBase::WaitAndDestroyEvent(CmEvent *&cmEvent)
{
int32_t dwTimeOutMs = -1;
CM_CHK_STATUS_RETURN(cmEvent->WaitForTaskFinished(dwTimeOutMs));
CM_CHK_STATUS_RETURN(m_cmQueue->DestroyEvent(cmEvent));
cmEvent = nullptr;
return CM_SUCCESS;
}
//This is kernelbased, We need to call for all the kernels in the kernellist.
void CMRTKernelBase::DestroySurfResources()
{
uint32_t i = 0;
for (i = 0; i < m_cmSurface2DCount; i++)
{
if (m_cmSurface2D[i])
{
m_cmDev->DestroySurface(m_cmSurface2D[i]);
m_cmSurface2D[i] = nullptr;
}
}
for (i = 0; i < m_cmSurfaceRef0Count; i++)
{
if (m_cmSurfaceRef0[i])
{
m_cmDev->DestroySurface(m_cmSurfaceRef0[i]);
m_cmSurfaceRef0[i] = nullptr;
}
}
for (i = 0; i < m_cmSurfaceRef1Count; i++)
{
if (m_cmSurfaceRef1[i])
{
m_cmDev->DestroySurface(m_cmSurfaceRef1[i]);
m_cmSurfaceRef1[i] = nullptr;
}
}
for (i = 0; i < m_cmBufferCount; i++)
{
if (m_cmBuffer[i])
{
m_cmDev->DestroySurface(m_cmBuffer[i]);
m_cmBuffer[i] = nullptr;
}
}
for (i = 0; i < m_cmVmeSurfCount; i++)
{
if (m_cmVmeSurf[i])
{
m_cmDev->DestroyVmeSurfaceG7_5(m_cmVmeSurf[i]);
m_cmVmeSurf[i] = nullptr;
}
}
}
//IF called init for /kernel/program/TS per frame, then we call this per frame;
//if called init for all the kernels per process, then call this per process.
//We can also init every first the kernel is called, then we just need to call this per process for all the kernels in kernelList.
void CMRTKernelBase::DestroyKernelResources()
{
if(m_cmKernel)
{
m_cmDev->DestroyKernel(m_cmKernel);
m_cmKernel = nullptr;
}
if (m_cmThreadSpace)
{
m_cmDev->DestroyThreadSpace(m_cmThreadSpace);
m_cmThreadSpace = nullptr;
}
}
void CMRTKernelBase::DestroyProgramResources()
{
if(m_cmProgram)
{
m_cmDev->DestroyProgram(m_cmProgram);
m_cmProgram = nullptr;
}
}
void CMRTKernelBase::Destroy()
{
//Only keep one Task/Dev/Queue in one Process.
if (m_cmTask)
{
m_cmDev->DestroyTask(m_cmTask);
m_cmTask = nullptr;
}
if(m_cmDev)
{
DestroyCmDevice(m_cmDev);
m_cmDev = nullptr;
}
}