blob: f14c750a7de1c1402c3b10f6dbfed68bfcb3f1ce [file] [log] [blame]
/*
* Copyright (c) 2019-2020, 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 vphal_render_vebox_memdecomp.cpp
//! \brief Defines data structures and interfaces for media memory decompression.
//! \details
//!
#include "vphal_render_vebox_memdecomp.h"
#include "vphal_debug.h"
MediaVeboxDecompState::MediaVeboxDecompState():
MediaMemDecompBaseState(),
m_osInterface(nullptr),
m_veboxInterface(nullptr),
m_mhwMiInterface(nullptr),
m_cpInterface(nullptr)
{
m_veboxMMCResolveEnabled = false;
}
MediaVeboxDecompState::~MediaVeboxDecompState()
{
MOS_STATUS eStatus;
if (m_cpInterface)
{
Delete_MhwCpInterface(m_cpInterface);
m_cpInterface = nullptr;
}
if (m_veboxInterface)
{
#if (_DEBUG || _RELEASE_INTERNAL)
if (m_surfaceDumper)
{
MOS_Delete(m_surfaceDumper);
m_surfaceDumper = nullptr;
}
#endif
eStatus = m_veboxInterface->DestroyHeap();
MOS_Delete(m_veboxInterface);
m_veboxInterface = nullptr;
if (eStatus != MOS_STATUS_SUCCESS)
{
VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to destroy Vebox Interface, eStatus:%d.\n", eStatus);
}
}
if (m_mhwMiInterface)
{
MOS_Delete(m_mhwMiInterface);
m_mhwMiInterface = nullptr;
}
if (m_osInterface)
{
m_osInterface->pfnDestroy(m_osInterface, false);
MOS_FreeMemory(m_osInterface);
m_osInterface = nullptr;
}
}
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_STATUS CloneResourceInfo(PVPHAL_SURFACE pVphalSurface, PMOS_SURFACE pMosSurface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(pVphalSurface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(pMosSurface);
pVphalSurface->SurfType = SURF_NONE;
pVphalSurface->OsResource = pMosSurface->OsResource;
pVphalSurface->dwWidth = pMosSurface->dwWidth;
pVphalSurface->dwHeight = pMosSurface->dwHeight;
pVphalSurface->dwPitch = pMosSurface->dwPitch;
pVphalSurface->Format = pMosSurface->Format;
pVphalSurface->TileType = pMosSurface->TileType;
pVphalSurface->TileModeGMM = pMosSurface->TileModeGMM;
pVphalSurface->bGMMTileEnabled = pMosSurface->bGMMTileEnabled;
pVphalSurface->dwDepth = pMosSurface->dwDepth;
pVphalSurface->dwSlicePitch = pMosSurface->dwSlicePitch;
pVphalSurface->dwOffset = pMosSurface->dwOffset;
pVphalSurface->bCompressible = pMosSurface->bCompressible;
pVphalSurface->bIsCompressed = pMosSurface->bIsCompressed;
pVphalSurface->CompressionMode = pMosSurface->CompressionMode;
pVphalSurface->CompressionFormat = pMosSurface->CompressionFormat;
pVphalSurface->YPlaneOffset.iLockSurfaceOffset = pMosSurface->YPlaneOffset.iLockSurfaceOffset;
pVphalSurface->YPlaneOffset.iSurfaceOffset = pMosSurface->YPlaneOffset.iSurfaceOffset;
pVphalSurface->YPlaneOffset.iXOffset = pMosSurface->YPlaneOffset.iXOffset;
pVphalSurface->YPlaneOffset.iYOffset = pMosSurface->YPlaneOffset.iYOffset;
pVphalSurface->UPlaneOffset.iLockSurfaceOffset = pMosSurface->UPlaneOffset.iLockSurfaceOffset;
pVphalSurface->UPlaneOffset.iSurfaceOffset = pMosSurface->UPlaneOffset.iSurfaceOffset;
pVphalSurface->UPlaneOffset.iXOffset = pMosSurface->UPlaneOffset.iXOffset;
pVphalSurface->UPlaneOffset.iYOffset = pMosSurface->UPlaneOffset.iYOffset;
pVphalSurface->VPlaneOffset.iLockSurfaceOffset = pMosSurface->VPlaneOffset.iLockSurfaceOffset;
pVphalSurface->VPlaneOffset.iSurfaceOffset = pMosSurface->VPlaneOffset.iSurfaceOffset;
pVphalSurface->VPlaneOffset.iXOffset = pMosSurface->VPlaneOffset.iXOffset;
pVphalSurface->VPlaneOffset.iYOffset = pMosSurface->VPlaneOffset.iYOffset;
return eStatus;
}
#define DumpSurfaceMemDecomp(MosSurface, SurfaceCounter, BufferCopy, Location) \
{ \
VPHAL_SURFACE VphalSurface = {}; \
CloneResourceInfo(&VphalSurface, &MosSurface); \
if (m_surfaceDumper) \
{ \
m_surfaceDumper->DumpSurface(&VphalSurface, SurfaceCounter, BufferCopy, Location); \
} \
}
#else
#define DumpSurfaceMemDecomp(MosSurface, surfaceCounter, DoubleCopy, Locationlocation) {}
#endif
MOS_STATUS MediaVeboxDecompState::MemoryDecompress(PMOS_RESOURCE targetResource)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MOS_SURFACE TargetSurface;
MHW_FUNCTION_ENTER;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(targetResource);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
#if MOS_MEDIASOLO_SUPPORTED
if (m_osInterface->bSoloInUse)
{
// Bypass
}
else
#endif
{
if (m_veboxMMCResolveEnabled)
{
MOS_ZeroMemory(&TargetSurface, sizeof(MOS_SURFACE));
TargetSurface.Format = Format_Invalid;
TargetSurface.OsResource = *targetResource;
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&TargetSurface));
//Get context before proceeding
auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
if (TargetSurface.bCompressible)
{
DumpSurfaceMemDecomp(TargetSurface, m_surfaceDumpCounter, 0, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDecompCMD(&TargetSurface));
DumpSurfaceMemDecomp(TargetSurface, m_surfaceDumpCounter++, 0, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
}
}
}
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return eStatus;
}
MOS_STATUS MediaVeboxDecompState::MediaMemoryCopy(
PMOS_RESOURCE inputResource,
PMOS_RESOURCE outputResource,
bool outputCompressed)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputResource);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputResource);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
MOS_SURFACE sourceSurface;
MOS_SURFACE targetSurface;
MOS_ZeroMemory(&targetSurface, sizeof(MOS_SURFACE));
MOS_ZeroMemory(&sourceSurface, sizeof(MOS_SURFACE));
targetSurface.Format = Format_Invalid;
targetSurface.OsResource = *outputResource;
#if !defined(LINUX) && !defined(ANDROID) && !EMUL
// for Double Buffer copy, clear the allocationInfo temply
MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
#endif
sourceSurface.Format = Format_Invalid;
sourceSurface.OsResource = *inputResource;
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&targetSurface));
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&sourceSurface));
#if (_DEBUG || _RELEASE_INTERNAL)
{
// Read user feature key to force outputCompressed
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
nullptr,
__VPHAL_VEBOX_FORCE_VP_MEMCOPY_OUTPUTCOMPRESSED_ID,
&userFeatureData,
m_osInterface ? m_osInterface->pOsContext : nullptr));
outputCompressed = userFeatureData.bData ? true : false;
}
#endif
if (!outputCompressed && targetSurface.CompressionMode != MOS_MMC_DISABLED)
{
targetSurface.CompressionMode = MOS_MMC_RC;
}
//if surface is linear buffer, use mos copy
if (sourceSurface.TileType == MOS_TILE_LINEAR &&
targetSurface.TileType == MOS_TILE_LINEAR &&
sourceSurface.Type == MOS_GFXRES_BUFFER &&
targetSurface.Type == MOS_GFXRES_BUFFER )
{
DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
do
{
MOS_LOCK_PARAMS lockSourceFlags;
MOS_ZeroMemory(&lockSourceFlags, sizeof(MOS_LOCK_PARAMS));
lockSourceFlags.ReadOnly = 1;
lockSourceFlags.WriteOnly = 0;
MOS_LOCK_PARAMS lockTargetFlags;
MOS_ZeroMemory(&lockTargetFlags, sizeof(MOS_LOCK_PARAMS));
lockTargetFlags.ReadOnly = 0;
lockTargetFlags.WriteOnly = 1;
uint8_t *lockedSrcAddr = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &sourceSurface.OsResource, &lockSourceFlags);
if (lockedSrcAddr == nullptr)
{
//non lockable resource enabled, we can't lock source surface
eStatus = MOS_STATUS_NULL_POINTER;
VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to lock non-lockable input resource, buffer copy failed, eStatus:%d.\n", eStatus);
break;
}
uint8_t *lockedTarAddr = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &targetSurface.OsResource, &lockTargetFlags);
if (lockedTarAddr == nullptr)
{
eStatus = MOS_STATUS_NULL_POINTER;
m_osInterface->pfnUnlockResource(m_osInterface, &sourceSurface.OsResource);
VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to lock non-lockable output resource, buffer copy failed, eStatus:%d.\n", eStatus);
break;
}
// This resource is a series of bytes. Is not 2 dimensional.
uint32_t sizeSrcMain = sourceSurface.dwWidth;
uint32_t sizeTargetMain = targetSurface.dwWidth;
eStatus = MOS_SecureMemcpy(lockedTarAddr, sizeTargetMain, lockedSrcAddr, sizeSrcMain);
m_osInterface->pfnUnlockResource(m_osInterface, &sourceSurface.OsResource);
m_osInterface->pfnUnlockResource(m_osInterface, &targetSurface.OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to copy linear buffer from source to target, eStatus:%d.\n", eStatus);
break;
}
} while (false);
DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return eStatus;
}
//Get context before proceeding
auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
// Sync for Vebox read
m_osInterface->pfnSyncOnResource(
m_osInterface,
&sourceSurface.OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
// Sync for Vebox write
m_osInterface->pfnSyncOnResource(
m_osInterface,
&targetSurface.OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDoubleBufferDecompCMD(&sourceSurface, &targetSurface));
DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return eStatus;
}
MOS_STATUS MediaVeboxDecompState::MediaMemoryCopy2D(
PMOS_RESOURCE inputResource,
PMOS_RESOURCE outputResource,
uint32_t copyWidth,
uint32_t copyHeight,
uint32_t copyInputOffset,
uint32_t copyOutputOffset,
uint32_t bpp,
bool outputCompressed)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputResource);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputResource);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
MOS_SURFACE sourceSurface;
MOS_SURFACE targetSurface;
MOS_ZeroMemory(&targetSurface, sizeof(MOS_SURFACE));
MOS_ZeroMemory(&sourceSurface, sizeof(MOS_SURFACE));
targetSurface.Format = Format_Invalid;
targetSurface.OsResource = *outputResource;
#if !defined(LINUX) && !defined(ANDROID) && !EMUL
// for Double Buffer copy, clear the allocationInfo temply
MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
#endif
sourceSurface.Format = Format_Invalid;
sourceSurface.OsResource = *inputResource;
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&targetSurface));
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&sourceSurface));
#if (_DEBUG || _RELEASE_INTERNAL)
{
// Read user feature key to Force outputCompressed
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
nullptr,
__VPHAL_VEBOX_FORCE_VP_MEMCOPY_OUTPUTCOMPRESSED_ID,
&userFeatureData,
m_osInterface ? m_osInterface->pOsContext : nullptr));
outputCompressed = userFeatureData.bData ? true : false;
}
#endif
if (!outputCompressed && targetSurface.CompressionMode != MOS_MMC_DISABLED)
{
targetSurface.CompressionMode = MOS_MMC_RC;
}
//Get context before proceeding
auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
uint32_t pixelInByte = 1;
switch (bpp)
{
case 8:
targetSurface.Format = Format_Y8;
sourceSurface.Format = Format_Y8;
pixelInByte = 1;
break;
case 16:
targetSurface.Format = Format_Y16U;
sourceSurface.Format = Format_Y16U;
pixelInByte = 2;
break;
case 32:
targetSurface.Format = Format_AYUV;
sourceSurface.Format = Format_AYUV;
pixelInByte = 4;
break;
case 64:
targetSurface.Format = Format_Y416;
sourceSurface.Format = Format_Y416;
pixelInByte = 8;
break;
default:
targetSurface.Format = Format_Y8;
sourceSurface.Format = Format_Y8;
pixelInByte = 1;
break;
}
sourceSurface.dwOffset = copyInputOffset;
targetSurface.dwOffset = copyOutputOffset;
sourceSurface.dwWidth = copyWidth / pixelInByte;
sourceSurface.dwHeight = copyHeight;
targetSurface.dwWidth = copyWidth / pixelInByte;
targetSurface.dwHeight = copyHeight;
// Sync for Vebox write
m_osInterface->pfnSyncOnResource(
m_osInterface,
&sourceSurface.OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDoubleBufferDecompCMD(&sourceSurface, &targetSurface));
DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return eStatus;
}
MOS_STATUS MediaVeboxDecompState::MediaMemoryTileConvert(
PMOS_RESOURCE inputResource,
PMOS_RESOURCE outputResource,
uint32_t copyWidth,
uint32_t copyHeight,
uint32_t copyInputOffset,
uint32_t copyOutputOffset,
bool isTileToLinear,
bool outputCompressed)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputResource);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputResource);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
MOS_SURFACE sourceSurface;
MOS_SURFACE targetSurface;
MOS_ZeroMemory(&targetSurface, sizeof(MOS_SURFACE));
MOS_ZeroMemory(&sourceSurface, sizeof(MOS_SURFACE));
targetSurface.Format = Format_Invalid;
targetSurface.OsResource = *outputResource;
#if !defined(LINUX) && !defined(ANDROID) && !EMUL
// for Double Buffer copy, clear the allocationInfo temply
MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
#endif
sourceSurface.Format = Format_Invalid;
sourceSurface.OsResource = *inputResource;
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&targetSurface));
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&sourceSurface));
if (targetSurface.TileType == MOS_TILE_LINEAR &&
sourceSurface.TileType == MOS_TILE_LINEAR)
{
VPHAL_MEMORY_DECOMP_NORMALMESSAGE("unsupport linear to linear convert, return unsupport feature");
return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
}
MOS_FORMAT format = Format_Any;
if (isTileToLinear)
{
if (!IsFormatSupported(&sourceSurface))
{
VPHAL_MEMORY_DECOMP_NORMALMESSAGE("unsupport processing format, return unsupport feature");
return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
}
format = sourceSurface.Format;
copyHeight = sourceSurface.dwHeight;
}
else
{
if (!IsFormatSupported(&targetSurface))
{
VPHAL_MEMORY_DECOMP_NORMALMESSAGE("unsupport processing format, return unsupport feature");
return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
}
format = targetSurface.Format;
copyHeight = targetSurface.dwHeight;
}
if (!outputCompressed && targetSurface.CompressionMode != MOS_MMC_DISABLED)
{
targetSurface.CompressionMode = MOS_MMC_RC;
}
//Get context before proceeding
auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
targetSurface.Format = format;
sourceSurface.Format = format;
sourceSurface.dwOffset = copyInputOffset;
targetSurface.dwOffset = copyOutputOffset;
sourceSurface.dwWidth = copyWidth;
sourceSurface.dwHeight = copyHeight;
targetSurface.dwWidth = copyWidth;
targetSurface.dwHeight = copyHeight;
// Sync for Vebox write
m_osInterface->pfnSyncOnResource(
m_osInterface,
&targetSurface.OsResource,
MOS_GPU_CONTEXT_VEBOX,
false);
DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDoubleBufferDecompCMD(&sourceSurface, &targetSurface));
DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
return eStatus;
}
MOS_STATUS MediaVeboxDecompState::Initialize(
PMOS_INTERFACE osInterface,
MhwCpInterface *cpInterface,
PMHW_MI_INTERFACE mhwMiInterface,
PMHW_VEBOX_INTERFACE veboxInterface)
{
MOS_STATUS eStatus;
MHW_VEBOX_GPUNODE_LIMIT GpuNodeLimit;
MOS_GPU_NODE VeboxGpuNode;
MOS_GPU_CONTEXT VeboxGpuContext;
RENDERHAL_SETTINGS RenderHalSettings;
eStatus = MOS_STATUS_SUCCESS;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(osInterface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(cpInterface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(mhwMiInterface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(veboxInterface);
m_osInterface = osInterface;
m_cpInterface = cpInterface;
m_mhwMiInterface = mhwMiInterface;
m_veboxInterface = veboxInterface;
// Set-Up Vebox decompression enable or not
IsVeboxDecompressionEnabled();
if (m_veboxInterface)
{
GpuNodeLimit.bCpEnabled = (m_osInterface->osCpInterface->IsCpEnabled())? true : false;
// Check GPU Node decide logic together in this function
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_veboxInterface->FindVeboxGpuNodeToUse(&GpuNodeLimit));
VeboxGpuNode = (MOS_GPU_NODE)(GpuNodeLimit.dwGpuNodeToUse);
VeboxGpuContext = (VeboxGpuNode == MOS_GPU_NODE_VE) ? MOS_GPU_CONTEXT_VEBOX : MOS_GPU_CONTEXT_VEBOX2;
// Create VEBOX/VEBOX2 Context
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_veboxInterface->CreateGpuContext(
m_osInterface,
VeboxGpuContext,
VeboxGpuNode));
// Register Vebox GPU context with the Batch Buffer completion event
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
m_osInterface,
MOS_GPU_CONTEXT_VEBOX));
if (m_veboxInterface->m_veboxHeap == nullptr)
{
m_veboxInterface->CreateHeap();
}
#if (_DEBUG || _RELEASE_INTERNAL)
CreateSurfaceDumper();
if (m_surfaceDumper)
{
m_surfaceDumper->GetSurfaceDumpSpec();
}
else
{
VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("surface dumpper creation failed.");
}
#endif
}
return eStatus;
}
#if (_DEBUG || _RELEASE_INTERNAL)
void MediaVeboxDecompState::CreateSurfaceDumper()
{
m_surfaceDumper = MOS_New(VphalSurfaceDumper, m_osInterface);
}
#endif
MOS_STATUS MediaVeboxDecompState::GetResourceInfo(PMOS_SURFACE surface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(surface);
MOS_SURFACE resDetails;
MOS_ZeroMemory(&resDetails, sizeof(resDetails));
resDetails.Format = Format_Invalid;
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(
m_osInterface,
&surface->OsResource,
&resDetails));
surface->Format = resDetails.Format;
surface->dwWidth = resDetails.dwWidth;
surface->dwHeight = resDetails.dwHeight;
surface->dwPitch = resDetails.dwPitch;
surface->dwDepth = resDetails.dwDepth;
surface->bArraySpacing = resDetails.bArraySpacing;
surface->TileType = resDetails.TileType;
surface->TileModeGMM = resDetails.TileModeGMM;
surface->bGMMTileEnabled = resDetails.bGMMTileEnabled;
surface->bCompressible = resDetails.bCompressible;
surface->bIsCompressed = resDetails.bIsCompressed;
surface->dwOffset = resDetails.RenderOffset.YUV.Y.BaseOffset;
surface->UPlaneOffset.iSurfaceOffset = resDetails.RenderOffset.YUV.U.BaseOffset;
surface->UPlaneOffset.iXOffset = resDetails.RenderOffset.YUV.U.XOffset;
surface->UPlaneOffset.iYOffset = resDetails.RenderOffset.YUV.U.YOffset;
surface->VPlaneOffset.iSurfaceOffset = resDetails.RenderOffset.YUV.V.BaseOffset;
surface->VPlaneOffset.iXOffset = resDetails.RenderOffset.YUV.V.XOffset;
surface->VPlaneOffset.iYOffset = resDetails.RenderOffset.YUV.V.YOffset;
surface->dwSize = (uint32_t)surface->OsResource.pGmmResInfo->GetSizeMainSurface();
MOS_MEMCOMP_STATE mmcMode;
MOS_ZeroMemory(&mmcMode, sizeof(mmcMode));
m_osInterface->pfnGetMemoryCompressionMode(m_osInterface, &surface->OsResource, &mmcMode);
surface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode;
if (mmcMode)
{
m_osInterface->pfnGetMemoryCompressionFormat(m_osInterface, &surface->OsResource, &surface->CompressionFormat);
if ((surface->TileType == MOS_TILE_Y ||
surface->TileType == MOS_TILE_YS))
{
surface->bCompressible = true;
surface->bIsCompressed = true;
surface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode;
}
}
return eStatus;
}
#define SURFACE_DW_UY_OFFSET(pSurface) \
((pSurface) != nullptr ? ((pSurface)->UPlaneOffset.iSurfaceOffset - (pSurface)->dwOffset) / (pSurface)->dwPitch + (pSurface)->UPlaneOffset.iYOffset : 0)
#define SURFACE_DW_VY_OFFSET(pSurface) \
((pSurface) != nullptr ? ((pSurface)->VPlaneOffset.iSurfaceOffset - (pSurface)->dwOffset) / (pSurface)->dwPitch + (pSurface)->VPlaneOffset.iYOffset : 0)
MOS_STATUS MediaVeboxDecompState::SetupVeboxSurfaceState(
PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS mhwVeboxSurfaceStateCmdParams,
PMOS_SURFACE inputSurface,
PMOS_SURFACE outputSurface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
bool inputIsLinearBuffer = false;
bool outputIsLinearBuffer = false;
uint32_t bpp = 1;
uint32_t inputWidth = 0;
uint32_t outputWidth = 0;
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputSurface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(mhwVeboxSurfaceStateCmdParams);
MOS_ZeroMemory(mhwVeboxSurfaceStateCmdParams, sizeof(*mhwVeboxSurfaceStateCmdParams));
mhwVeboxSurfaceStateCmdParams->SurfInput.bActive = mhwVeboxSurfaceStateCmdParams->SurfOutput.bActive = true;
mhwVeboxSurfaceStateCmdParams->SurfInput.dwBitDepth = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwBitDepth = inputSurface->dwDepth;
mhwVeboxSurfaceStateCmdParams->SurfInput.dwHeight = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwHeight =
MOS_MIN(inputSurface->dwHeight, ((outputSurface!= nullptr) ? outputSurface->dwHeight : inputSurface->dwHeight));
mhwVeboxSurfaceStateCmdParams->SurfInput.dwWidth = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwWidth =
MOS_MIN(inputSurface->dwWidth, ((outputSurface != nullptr) ? outputSurface->dwWidth : inputSurface->dwWidth));
mhwVeboxSurfaceStateCmdParams->SurfInput.Format = mhwVeboxSurfaceStateCmdParams->SurfOutput.Format = inputSurface->Format;
MOS_SURFACE inputDetails, outputDetails;
MOS_ZeroMemory(&inputDetails, sizeof(inputDetails));
MOS_ZeroMemory(&outputDetails, sizeof(outputDetails));
inputDetails.Format = Format_Invalid;
outputDetails.Format = Format_Invalid;
if (inputSurface)
{
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(
m_osInterface,
&inputSurface->OsResource,
&inputDetails));
}
if (outputSurface)
{
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(
m_osInterface,
&outputSurface->OsResource,
&outputDetails));
// Following settings are enabled only when outputSurface is availble
inputIsLinearBuffer = (inputDetails.dwHeight == 1) ? true : false;
outputIsLinearBuffer = (outputDetails.dwHeight == 1) ? true : false;
inputWidth = inputSurface->dwWidth;
outputWidth = outputSurface->dwWidth;
if (inputIsLinearBuffer)
{
bpp = outputDetails.dwPitch / outputDetails.dwWidth;
if (outputDetails.dwPitch % outputDetails.dwWidth != 0)
{
inputWidth = outputDetails.dwPitch / bpp;
}
}
else if (outputIsLinearBuffer)
{
bpp = inputDetails.dwPitch / inputDetails.dwWidth;
if (inputDetails.dwPitch % inputDetails.dwWidth != 0)
{
outputWidth = inputDetails.dwPitch / bpp;
}
}
else
{
VPHAL_MEMORY_DECOMP_NORMALMESSAGE("2D to 2D, no need for bpp setting.");
}
}
if (inputSurface->dwPitch > 0 &&
(inputSurface->Format == Format_P010 ||
inputSurface->Format == Format_P016 ||
inputSurface->Format == Format_NV12))
{
mhwVeboxSurfaceStateCmdParams->SurfInput.dwUYoffset = (!inputIsLinearBuffer) ? SURFACE_DW_UY_OFFSET(inputSurface) :
inputSurface->dwHeight;
if (outputSurface)
{
mhwVeboxSurfaceStateCmdParams->SurfOutput.dwUYoffset = (!outputIsLinearBuffer) ? SURFACE_DW_UY_OFFSET(outputSurface) :
outputSurface->dwHeight;
}
else
{
mhwVeboxSurfaceStateCmdParams->SurfOutput.dwUYoffset = mhwVeboxSurfaceStateCmdParams->SurfInput.dwUYoffset;
}
}
mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.left = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.left = 0;
mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.right = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.right = (long)(mhwVeboxSurfaceStateCmdParams->SurfInput.dwWidth);
mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.top = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.top = 0;
mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.bottom = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.bottom = (long)(mhwVeboxSurfaceStateCmdParams->SurfInput.dwHeight);
mhwVeboxSurfaceStateCmdParams->bOutputValid = true;
// if output surface is null, then Inplace resolve happens
if (!outputSurface)
{
mhwVeboxSurfaceStateCmdParams->SurfInput.TileType = mhwVeboxSurfaceStateCmdParams->SurfOutput.TileType = inputSurface->TileType;
mhwVeboxSurfaceStateCmdParams->SurfInput.TileModeGMM = mhwVeboxSurfaceStateCmdParams->SurfOutput.TileModeGMM = inputSurface->TileModeGMM;
mhwVeboxSurfaceStateCmdParams->SurfInput.bGMMTileEnabled = mhwVeboxSurfaceStateCmdParams->SurfOutput.bGMMTileEnabled = inputSurface->bGMMTileEnabled;
mhwVeboxSurfaceStateCmdParams->SurfOutput.dwPitch = mhwVeboxSurfaceStateCmdParams->SurfInput.dwPitch = inputSurface->dwPitch;
mhwVeboxSurfaceStateCmdParams->SurfInput.pOsResource = mhwVeboxSurfaceStateCmdParams->SurfOutput.pOsResource = &(inputSurface->OsResource);
mhwVeboxSurfaceStateCmdParams->SurfInput.dwYoffset = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwYoffset = inputSurface->YPlaneOffset.iYOffset;
mhwVeboxSurfaceStateCmdParams->SurfInput.dwCompressionFormat = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwCompressionFormat =
inputSurface->CompressionFormat;
}
else
// double buffer resolve
{
mhwVeboxSurfaceStateCmdParams->SurfInput.TileType = inputSurface->TileType;
mhwVeboxSurfaceStateCmdParams->SurfInput.TileModeGMM = inputSurface->TileModeGMM;
mhwVeboxSurfaceStateCmdParams->SurfInput.bGMMTileEnabled = inputSurface->bGMMTileEnabled;
mhwVeboxSurfaceStateCmdParams->SurfOutput.TileType = outputSurface->TileType;
mhwVeboxSurfaceStateCmdParams->SurfOutput.TileModeGMM = outputSurface->TileModeGMM;
mhwVeboxSurfaceStateCmdParams->SurfOutput.bGMMTileEnabled = outputSurface->bGMMTileEnabled;
// When surface is 1D but processed as 2D, fake a min(pitch, width) is needed as the pitch API passed may less surface width in 1D surface
mhwVeboxSurfaceStateCmdParams->SurfInput.dwPitch = (inputIsLinearBuffer) ?
MOS_MIN(inputWidth * bpp, inputSurface->dwPitch) : inputSurface->dwPitch;
mhwVeboxSurfaceStateCmdParams->SurfOutput.dwPitch = (outputIsLinearBuffer) ?
MOS_MIN(outputWidth * bpp, outputSurface->dwPitch) : outputSurface->dwPitch;
mhwVeboxSurfaceStateCmdParams->SurfInput.pOsResource = &(inputSurface->OsResource);
mhwVeboxSurfaceStateCmdParams->SurfOutput.pOsResource = &(outputSurface->OsResource);
mhwVeboxSurfaceStateCmdParams->SurfInput.dwYoffset = inputSurface->YPlaneOffset.iYOffset;
mhwVeboxSurfaceStateCmdParams->SurfOutput.dwYoffset = outputSurface->YPlaneOffset.iYOffset;
mhwVeboxSurfaceStateCmdParams->SurfInput.dwCompressionFormat = inputSurface->CompressionFormat;
mhwVeboxSurfaceStateCmdParams->SurfOutput.dwCompressionFormat = outputSurface->CompressionFormat;
}
return eStatus;
}
MOS_STATUS MediaVeboxDecompState::InitCommandBuffer(
PMOS_COMMAND_BUFFER cmdBuffer)
{
PMOS_INTERFACE pOsInterface;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t iRemaining;
RENDERHAL_GENERIC_PROLOG_PARAMS GenericPrologParams = {};
PMOS_RESOURCE gpuStatusBuffer = nullptr;
//---------------------------------------------
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(cmdBuffer);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface);
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_mhwMiInterface);
//---------------------------------------------
eStatus = MOS_STATUS_SUCCESS;
pOsInterface = m_osInterface;
MOS_GPU_CONTEXT gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
#ifndef EMUL
if (pOsInterface->bEnableKmdMediaFrameTracking)
{
// Get GPU Status buffer
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(pOsInterface->pfnGetGpuStatusBufferResource(pOsInterface, gpuStatusBuffer));
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(gpuStatusBuffer);
// Register the buffer
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(pOsInterface->pfnRegisterResource(pOsInterface, gpuStatusBuffer, true, true));
GenericPrologParams.bEnableMediaFrameTracking = true;
GenericPrologParams.presMediaFrameTrackingSurface = gpuStatusBuffer;
GenericPrologParams.dwMediaFrameTrackingTag = pOsInterface->pfnGetGpuStatusTag(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
GenericPrologParams.dwMediaFrameTrackingAddrOffset = pOsInterface->pfnGetGpuStatusTagOffset(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
// Increment GPU Status Tag
pOsInterface->pfnIncrementGpuStatusTag(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
}
#endif
if (GenericPrologParams.bEnableMediaFrameTracking)
{
VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(GenericPrologParams.presMediaFrameTrackingSurface);
cmdBuffer->Attributes.bEnableMediaFrameTracking = GenericPrologParams.bEnableMediaFrameTracking;
cmdBuffer->Attributes.dwMediaFrameTrackingTag = GenericPrologParams.dwMediaFrameTrackingTag;
cmdBuffer->Attributes.dwMediaFrameTrackingAddrOffset = GenericPrologParams.dwMediaFrameTrackingAddrOffset;
cmdBuffer->Attributes.resMediaFrameTrackingSurface = GenericPrologParams.presMediaFrameTrackingSurface;
}
// initialize command buffer attributes
cmdBuffer->Attributes.bTurboMode = false;
cmdBuffer->Attributes.bMediaPreemptionEnabled = false;
cmdBuffer->Attributes.dwMediaFrameTrackingAddrOffset = 0;
MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
genericPrologParams.pOsInterface = m_osInterface;
genericPrologParams.pvMiInterface = m_mhwMiInterface;
genericPrologParams.bMmcEnabled = true;
VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmd(
cmdBuffer,
&genericPrologParams));
return eStatus;
}
bool MediaVeboxDecompState::IsFormatSupported(PMOS_SURFACE surface)
{
bool bRet = false;
if (surface->Format == Format_R10G10B10A2 ||
surface->Format == Format_B10G10R10A2 ||
surface->Format == Format_Y410 ||
surface->Format == Format_Y210)
{
// Re-map RGB10/RGB10/Y410/Y210 as AYUV
surface->Format = Format_AYUV;
}
if (surface->Format == Format_A8 ||
surface->Format == Format_Y8 ||
surface->Format == Format_L8 ||
surface->Format == Format_P8 ||
surface->Format == Format_STMM)
{
surface->Format = Format_P8;
}
if (surface->Format == Format_IMC3 ||
surface->Format == Format_444P ||
surface->Format == Format_422H ||
surface->Format == Format_422V ||
surface->Format == Format_411P ||
surface->Format == Format_411R ||
surface->Format == Format_444P ||
surface->Format == Format_RGBP ||
surface->Format == Format_BGRP ||
surface->Format == Format_400P ||
surface->Format == Format_420O )
{
surface->Format = Format_P8;
surface->dwHeight = surface->dwSize / surface->dwPitch;
}
// Check if Sample Format is supported for decompression
if (surface->Format != Format_NV12 &&
surface->Format != Format_AYUV &&
surface->Format != Format_Y416 &&
surface->Format != Format_P010 &&
surface->Format != Format_P016 &&
!IS_PA_FORMAT(surface->Format) &&
surface->Format != Format_A8R8G8B8 &&
surface->Format != Format_A8B8G8R8 &&
surface->Format != Format_X8R8G8B8 &&
surface->Format != Format_X8B8G8R8 &&
surface->Format != Format_P8 &&
surface->Format != Format_Y16U)
{
VPHAL_MEMORY_DECOMP_NORMALMESSAGE("Unsupported Source Format '0x%08x' for VEBOX Decompression.", surface->Format);
goto finish;
}
bRet = true;
finish:
return bRet;
}