blob: bf68ba0a67684e72bddd163c7b29f39f7fdefe89 [file] [log] [blame]
/*
* Copyright (c) 2014-2018, 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 mhw_vebox.cpp
//! \brief MHW interface for constructing commands for the VEBOX
//! \details Impelements the functionalities common across all platforms for MHW_VEBOX
//!
#include "mhw_utilities.h"
#include "mhw_vebox.h"
#include "hal_oca_interface.h"
void MhwVeboxInterface::RefreshVeboxSync()
{
PMHW_VEBOX_HEAP pVeboxHeap;
PMHW_VEBOX_HEAP_STATE pCurInstance;
PMOS_INTERFACE pOsInterface;
uint32_t dwCurrentTag;
int32_t i;
int32_t iInstanceInUse;
MOS_NULL_RENDERING_FLAGS NullRenderingFlags;
MHW_FUNCTION_ENTER;
if (m_veboxHeap == nullptr ||
m_osInterface == nullptr )
{
MHW_ASSERTMESSAGE("RefreshVeboxSync failed due to m_veboxHeap or m_osInterface is invalid ");
return;
}
iInstanceInUse = 0;
// Vebox Heap will always be locked by driver
pVeboxHeap = m_veboxHeap;
pOsInterface = m_osInterface;
// Most recent tag
if (pOsInterface->bEnableKmdMediaFrameTracking)
{
dwCurrentTag = pOsInterface->pfnGetGpuStatusSyncTag(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
}
else
{
dwCurrentTag = pVeboxHeap->pSync[0];
}
pVeboxHeap->dwSyncTag = dwCurrentTag - 1;
NullRenderingFlags = m_osInterface->pfnGetNullHWRenderFlags(
m_osInterface);
// Refresh VeboxHeap states
pCurInstance = pVeboxHeap->pStates;
for (i = m_veboxSettings.uiNumInstances; i > 0; i--, pCurInstance++)
{
if (!pCurInstance->bBusy) continue;
// The condition below is valid when sync tag wraps from 2^32-1 to 0
if (((int32_t)(dwCurrentTag - pCurInstance->dwSyncTag) >= 0) ||
NullRenderingFlags.VPGobal ||
NullRenderingFlags.VPDnDi)
{
pCurInstance->bBusy = false;
}
else
{
iInstanceInUse++;
}
}
// Save number of instance in use
m_veboxHeapInUse = iInstanceInUse;
}
MOS_STATUS MhwVeboxInterface::AssignVeboxState()
{
uint32_t dwWaitMs, dwWaitTag;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PMOS_INTERFACE pOsInterface;
PMHW_VEBOX_HEAP_STATE pVeboxCurState;
PMHW_VEBOX_HEAP pVeboxHeap;
uint32_t uiOffset;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(m_veboxHeap);
MHW_CHK_NULL(m_osInterface);
pVeboxHeap = m_veboxHeap;
pVeboxCurState = &m_veboxHeap->pStates[pVeboxHeap->uiNextState];
pOsInterface = m_osInterface;
// Refresh sync tag for all vebox heap instance
RefreshVeboxSync();
// Check validity of current vebox heap instance
// The code below is unlikely to be executed - unless all Vebox states are in use
// If this ever happens, please consider increasing the number of media states
MHW_CHK_NULL(pVeboxCurState);
if (pVeboxCurState->bBusy)
{
// Get current vebox instance sync tag
dwWaitTag = pVeboxCurState->dwSyncTag;
// Wait for Batch Buffer complete event OR timeout
for (dwWaitMs = MHW_TIMEOUT_MS_DEFAULT; dwWaitMs > 0; dwWaitMs--)
{
uint32_t dwCurrentTag;
MHW_CHK_STATUS(pOsInterface->pfnWaitForBBCompleteNotifyEvent(
pOsInterface,
MOS_GPU_CONTEXT_VEBOX,
MHW_EVENT_TIMEOUT_MS));
if (pOsInterface->bEnableKmdMediaFrameTracking)
{
dwCurrentTag = pOsInterface->pfnGetGpuStatusSyncTag(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
}
else
{
dwCurrentTag = pVeboxHeap->pSync[0];
}
// Mark current instance status as availabe. Wait if this sync tag came back from GPU
if ((int32_t)(dwCurrentTag - dwWaitTag) >= 0)
{
pVeboxCurState->bBusy = false;
break;
}
}
// Timeout
if (dwWaitMs == 0)
{
MHW_ASSERTMESSAGE("Timeout on waiting for free Vebox Heap.");
eStatus = MOS_STATUS_UNKNOWN;
goto finish;
}
}
// Prepare syncTag for GPU write back
if (pOsInterface->bEnableKmdMediaFrameTracking)
{
pVeboxCurState->dwSyncTag = pOsInterface->pfnGetGpuStatusTag(pOsInterface, MOS_GPU_CONTEXT_VEBOX);
}
else
{
pVeboxCurState->dwSyncTag = pVeboxHeap->dwNextTag;
}
// Assign current state and increase next state
pVeboxHeap->uiCurState = pVeboxHeap->uiNextState;
pVeboxHeap->uiNextState = (pVeboxHeap->uiNextState + 1) %
(m_veboxSettings.uiNumInstances);
//Clean the memory of current veboxheap to avoid the history states
uiOffset = pVeboxHeap->uiCurState * pVeboxHeap->uiInstanceSize;
MOS_ZeroMemory(pVeboxHeap->pLockedDriverResourceMem + uiOffset, pVeboxHeap->uiInstanceSize);
finish:
return eStatus;
}
MOS_STATUS MhwVeboxInterface::UpdateVeboxSync()
{
PMHW_VEBOX_HEAP pVeboxHeap;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PMOS_INTERFACE pOsInterface;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(m_veboxHeap);
MHW_CHK_NULL(m_osInterface);
pVeboxHeap = m_veboxHeap;
pOsInterface = m_osInterface;
// If KMD frame tracking is on, the dwSyncTag has been set to gpu status tag
// in Mhw_VeboxInterface_AssignVeboxState(). dwNextTag is not used anymore.
if (!pOsInterface->bEnableKmdMediaFrameTracking)
{
pVeboxHeap->pStates[pVeboxHeap->uiCurState].dwSyncTag =
pVeboxHeap->dwNextTag++;
}
pVeboxHeap->pStates[pVeboxHeap->uiCurState].bBusy = true;
finish:
return eStatus;
}
MOS_STATUS MhwVeboxInterface::GetVeboxHeapInfo(
const MHW_VEBOX_HEAP **ppVeboxHeap)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(ppVeboxHeap);
*ppVeboxHeap = (const MHW_VEBOX_HEAP *)m_veboxHeap;
finish:
return eStatus;
}
MOS_STATUS MhwVeboxInterface::CreateHeap( )
{
MOS_STATUS eStatus;
uint8_t *pMem;
uint32_t uiSize;
uint32_t uiOffset;
MOS_ALLOC_GFXRES_PARAMS AllocParams;
MOS_LOCK_PARAMS LockFlags;
MEDIA_FEATURE_TABLE *skuTable = nullptr;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(m_osInterface);
MHW_CHK_NULL(m_osInterface->pfnGetSkuTable);
skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
MHW_CHK_NULL(skuTable);
eStatus = MOS_STATUS_SUCCESS;
uiSize = sizeof(MHW_VEBOX_HEAP);
uiSize += m_veboxSettings.uiNumInstances *
sizeof(MHW_VEBOX_HEAP_STATE);
// Allocate memory for VEBOX
pMem = (uint8_t*)MOS_AllocAndZeroMemory(uiSize);
MHW_CHK_NULL(pMem);
m_veboxHeap = (PMHW_VEBOX_HEAP)pMem;
m_veboxHeap->pStates =
(PMHW_VEBOX_HEAP_STATE)(pMem + sizeof(MHW_VEBOX_HEAP));
// Assign offsets and sizes
uiOffset = 0;
m_veboxHeap->uiDndiStateOffset = uiOffset;
uiOffset += m_veboxSettings.uiDndiStateSize;
m_veboxHeap->uiIecpStateOffset = uiOffset;
uiOffset += m_veboxSettings.uiIecpStateSize;
m_veboxHeap->uiGamutStateOffset = uiOffset;
uiOffset += m_veboxSettings.uiGamutStateSize;
m_veboxHeap->uiVertexTableOffset = uiOffset;
uiOffset += m_veboxSettings.uiVertexTableSize;
m_veboxHeap->uiCapturePipeStateOffset = uiOffset;
uiOffset += m_veboxSettings.uiCapturePipeStateSize;
m_veboxHeap->uiGammaCorrectionStateOffset = uiOffset;
uiOffset += m_veboxSettings.uiGammaCorrectionStateSize;
m_veboxHeap->uiHdrStateOffset = uiOffset;
uiOffset += m_veboxSettings.uiHdrStateSize;
m_veboxHeap->uiInstanceSize = uiOffset;
// Appending VeboxHeap sync data after all vebox heap instances
m_veboxHeap->uiOffsetSync =
m_veboxHeap->uiInstanceSize *
m_veboxSettings.uiNumInstances;
// Allocate GPU memory
uiSize = m_veboxHeap->uiInstanceSize *
m_veboxSettings.uiNumInstances +
m_veboxSettings.uiSyncSize;
// for using vdbox copy, the size have to be cache line aligned
MOS_ALIGN_CEIL(uiSize, MHW_CACHELINE_SIZE);
m_veboxHeap->uiStateHeapSize = uiSize;
MOS_ZeroMemory(&AllocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
AllocParams.Type = MOS_GFXRES_BUFFER;
AllocParams.TileType = MOS_TILE_LINEAR;
AllocParams.Format = Format_Buffer;
AllocParams.dwBytes = uiSize;
AllocParams.pBufName = "VphalVeboxHeap";
AllocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_FF;
if (MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar))
{
AllocParams.dwMemType = MOS_MEMPOOL_SYSTEMMEMORY;
}
MHW_CHK_STATUS(m_osInterface->pfnAllocateResource(
m_osInterface,
&AllocParams,
&m_veboxHeap->DriverResource));
if (MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar))
{
// Use device memory for vebox heap kernel resource, as no cpu access on it.
AllocParams.dwMemType = MOS_MEMPOOL_DEVICEMEMORY;
AllocParams.Flags.bNotLockable = 1;
}
MHW_CHK_STATUS(m_osInterface->pfnAllocateResource(
m_osInterface,
&AllocParams,
&m_veboxHeap->KernelResource));
// Lock the driver resource
MOS_ZeroMemory(&LockFlags, sizeof(MOS_LOCK_PARAMS));
LockFlags.NoOverWrite = 1;
m_veboxHeap->pLockedDriverResourceMem =
(uint8_t*)m_osInterface->pfnLockResource(
m_osInterface,
&m_veboxHeap->DriverResource,
&LockFlags);
MHW_CHK_NULL(m_veboxHeap->pLockedDriverResourceMem);
// Initialize VeboxHeap controls that depend on mapping
m_veboxHeap->pSync =
(uint32_t*) (m_veboxHeap->pLockedDriverResourceMem +
m_veboxHeap->uiOffsetSync);
finish:
if (eStatus != MOS_STATUS_SUCCESS)
{
DestroyHeap();
}
return eStatus;
}
MOS_STATUS MhwVeboxInterface::DestroyHeap()
{
PMOS_INTERFACE pOsInterface;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_CHK_NULL(m_osInterface);
pOsInterface = m_osInterface;
if (m_veboxHeap)
{
if (!Mos_ResourceIsNull(&m_veboxHeap->DriverResource))
{
if (m_veboxHeap->pLockedDriverResourceMem)
{
pOsInterface->pfnUnlockResource(
pOsInterface,
&m_veboxHeap->DriverResource);
}
pOsInterface->pfnFreeResource(
pOsInterface,
&m_veboxHeap->DriverResource);
}
if (!Mos_ResourceIsNull(&m_veboxHeap->KernelResource))
{
pOsInterface->pfnFreeResource(
pOsInterface,
&m_veboxHeap->KernelResource);
}
MOS_FreeMemory(m_veboxHeap);
m_veboxHeap = nullptr;
}
finish:
return eStatus;
}
MhwVeboxInterface::MhwVeboxInterface(PMOS_INTERFACE pOsInterface)
{
MHW_FUNCTION_ENTER;
MOS_ZeroMemory(&m_veboxSettings, sizeof(m_veboxSettings));
pfnAddResourceToCmd = nullptr;
if (pOsInterface == nullptr)
{
MHW_ASSERTMESSAGE("Invalid input pointers provided");
return;
}
m_osInterface = pOsInterface;
if (m_osInterface->bUsesGfxAddress)
{
pfnAddResourceToCmd = Mhw_AddResourceToCmd_GfxAddress;
}
else //PatchList
{
pfnAddResourceToCmd = Mhw_AddResourceToCmd_PatchList;
}
}
void MhwVeboxInterface::TraceIndirectStateInfo(MOS_COMMAND_BUFFER &cmdBuffer, MOS_CONTEXT &mosContext, bool isCmBuffer, bool useVeboxHeapKernelResource)
{
if (isCmBuffer)
{
char ocaLog[] = "Vebox indirect state use CmBuffer";
HalOcaInterface::TraceMessage(cmdBuffer, mosContext, ocaLog, sizeof(ocaLog));
}
else
{
if (useVeboxHeapKernelResource)
{
char ocaLog[] = "Vebox indirect state use KernelResource";
HalOcaInterface::TraceMessage(cmdBuffer, mosContext, ocaLog, sizeof(ocaLog));
}
else
{
char ocaLog[] = "Vebox indirect state use DriverResource";
HalOcaInterface::TraceMessage(cmdBuffer, mosContext, ocaLog, sizeof(ocaLog));
}
}
}