| /* |
| * 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)); |
| } |
| } |
| } |