blob: 80295b00f239a58a79fce465513cd4d9c56f9b2c [file] [log] [blame]
/*
* Copyright (c) 2015-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 renderhal_dsh.cpp
//! \brief This module implements render engine state heap management functions based on dynamic state heap (DSH) infrastructure, rather than static state heap. It allows dynamic allocation and expansion of general state heap (media states) and instraction state heaps (media kernels) based on demand. It also allows dynamic configuration of media states based on specific workload requirements, as well as dynamic allocation of kernel scratch space (spill area).
//!
#include "renderhal.h"
#include "renderhal_platform_interface.h"
// Defined in renderhal.c
extern const RENDERHAL_SURFACE_STATE_ENTRY g_cInitSurfaceStateEntry;
MOS_STATUS RenderHal_AllocateDebugSurface(
PRENDERHAL_INTERFACE pRenderHal);
//!
//! \brief Extend the media state pool
//! \details Extends the media state pool by adding 16 media state objects
//! \param PRENDERHAL_STATE_HEAP pStateHeap
//! [in] Pointer to the state heap
//! \return MOS_STATUS
//! SUCCESS if media state pool was successfully extended
//! NO_SPACE if the pool of objects cannot be extended
//!
MOS_STATUS RenderHal_DSH_ExtendMediaStatePool(
PRENDERHAL_STATE_HEAP pStateHeap)
{
int32_t iSize;
uint8_t *pPtr;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//---------------------------------------
MHW_RENDERHAL_CHK_NULL_RETURN(pStateHeap);
MHW_RENDERHAL_CHK_NULL_RETURN(pStateHeap->pMediaStatesMemPool);
//---------------------------------------
int32_t iCount = RENDERHAL_DSH_DYN_STATE_INC;
// Extend pool and get pointer to first element of the new pool object
PRENDERHAL_MEDIA_STATE pFirst, pLast, pPrev;
PRENDERHAL_MEDIA_STATE_LIST pList = &pStateHeap->FreeStates;
uint32_t ID = pStateHeap->pMediaStatesMemPool->m_dwObjCount;
pLast = pFirst = (PRENDERHAL_MEDIA_STATE)(pStateHeap->pMediaStatesMemPool->Allocate(iCount));
if (!pLast)
{
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// Increment size of the list
pList->iCount += iCount;
// Initialize new doubled linked list and internal structure
iSize = pStateHeap->pMediaStatesMemPool->m_dwObjSize; // enough for media state and dynamic state objects
pPtr = (uint8_t*) pFirst;
for (pPrev = nullptr; iCount > 0; iCount--, pPtr += iSize, pPrev = pLast)
{
// Create doubled linked list
pLast = (PRENDERHAL_MEDIA_STATE) pPtr;
pLast->Reserved = ID++;
pLast->pPrev = pPrev;
if (pPrev) pPrev->pNext = pLast;
// Point to dynamic states (co-located)
pLast->pDynamicState = (PRENDERHAL_DYNAMIC_STATE) (pLast + 1);
}
pLast->pNext = nullptr;
// Attach to end of existing pool
pFirst->pPrev = pList->pTail;
pList->pTail = pLast;
if (pFirst->pPrev)
pFirst->pPrev->pNext = pFirst;
else
pList->pHead = pFirst;
finish:
return eStatus;
}
//!
//! \brief Get a media state from the pool
//! \details Returns a pointer to a media state from the pool
//! If pool is empty, the pool is extended (adds 16 media states)
//! \param PRENDERHAL_STATE_HEAP pStateHeap
//! [in] Pointer to the state heap
//! \return PRENDERHAL_MEDIA_STATE pointer to a media state
//!
PRENDERHAL_MEDIA_STATE RenderHal_DSH_GetMediaStateFromPool(
PRENDERHAL_STATE_HEAP pStateHeap)
{
MOS_STATUS eStatus;
PRENDERHAL_MEDIA_STATE pMediaState = nullptr;
//---------------------------------------
if (pStateHeap == nullptr)
{
MHW_RENDERHAL_ASSERTMESSAGE("Null pointer detected!");
return nullptr;
}
//---------------------------------------
PRENDERHAL_MEDIA_STATE_LIST pList = &pStateHeap->FreeStates;
// If pool is empty, extend pool of free media states
if (pList->iCount == 0)
{
MHW_RENDERHAL_CHK_STATUS(RenderHal_DSH_ExtendMediaStatePool(pStateHeap));
}
// Get Element from the head of the list
pMediaState = pList->pHead;
// Detach element from the list
if (pMediaState)
{
pList->iCount--;
pList->pHead = pMediaState->pNext;
if (pMediaState->pNext)
{
pMediaState->pNext->pPrev = nullptr;
}
else
{ // List is now empty - last element was removed
pList->pTail = nullptr;
MHW_ASSERT(pList->iCount == 0);
}
pMediaState->pNext = pMediaState->pPrev = nullptr;
}
finish:
return pMediaState;
}
//!
//! \brief Returns a media state to the pool
//! \details Returns the media state to the pool list
//! \param PRENDERHAL_STATE_HEAP pStateHeap
//! [in] Pointer to the state heap
//! \param PRENDERHAL_MEDIA_STATE pMediaState
//! [in] Pointer to the media state
//! \return NONE
//!
void RenderHal_DSH_ReturnMediaStateToPool(
PRENDERHAL_STATE_HEAP pStateHeap,
PRENDERHAL_MEDIA_STATE pMediaState)
{
//---------------------------------------
MHW_RENDERHAL_CHK_NULL_NO_STATUS_RETURN(pStateHeap);
MHW_RENDERHAL_CHK_NULL_NO_STATUS_RETURN(pMediaState);
//---------------------------------------
PRENDERHAL_MEDIA_STATE_LIST pList = &pStateHeap->FreeStates;
// Attach element to the head of the list
pMediaState->pPrev = pList->pTail;
pList->pTail = pMediaState;
if (pMediaState->pPrev)
{
pMediaState->pPrev->pNext = pMediaState;
}
else
{ // List was empty - insert first element
MHW_ASSERT(pList->iCount == 0);
pList->pHead = pMediaState;
}
pList->iCount++;
return;
}
//!
//! \brief Extend the kernel allocation pool
//! \details Extends the kernel allocation pool by adding 16 kernel allocations
//! \param PRENDERHAL_STATE_HEAP pStateHeap
//! [in] Pointer to the state heap
//! \return MOS_STATUS
//! SUCCESS if kernel allocation pool was successfully extended
//! NO_SPACE if the pool of objects cannot be extended
//!
MOS_STATUS RenderHal_DSH_ExtendKernelAllocPool(
PRENDERHAL_STATE_HEAP pStateHeap)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//---------------------------------------
MHW_RENDERHAL_CHK_NULL_RETURN(pStateHeap);
MHW_RENDERHAL_CHK_NULL_RETURN(pStateHeap->pKernelAllocMemPool);
//---------------------------------------
int32_t iCount = RENDERHAL_DSH_KRN_ALLOC_INC;
// Extend pool and get pointer to first element of the new pool object
PRENDERHAL_KRN_ALLOCATION pFirst, pLast;
PRENDERHAL_KRN_ALLOC_LIST pList = &pStateHeap->KernelAllocationPool;
uint32_t ObjID = pStateHeap->pKernelAllocMemPool->m_dwObjCount;
pLast = pFirst = (PRENDERHAL_KRN_ALLOCATION)(pStateHeap->pKernelAllocMemPool->Allocate(iCount));
if (!pLast)
{
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// Increment size of the list
pList->iCount += iCount;
// Initialize new doubled linked list
for ( ; iCount > 0; iCount--, pLast++)
{
pLast->Reserved = ObjID++;
pLast->pPrev = pLast - 1;
pLast->pNext = pLast + 1;
pLast->pList = pList;
pLast->szKernelName = nullptr;
}
pLast--;
pLast->pNext = nullptr;
// Attach to end of existing pool
pFirst->pPrev = pList->pTail;
pList->pTail = pLast;
if (pFirst->pPrev)
{
pFirst->pPrev->pNext = pFirst;
}
else
{
pList->pHead = pFirst;
}
finish:
return eStatus;
}
//!
//! \brief Detach kernel allocation
//! \details Removes the kernel allocation from the current list
//! \param PRENDERHAL_KRN_ALLOCATION pKernel
//! [in] Pointer to the kernel allocation
//! \return NONE
//!
void RenderHal_DSH_KernelDetach(PRENDERHAL_KRN_ALLOCATION pKernel)
{
PRENDERHAL_KRN_ALLOC_LIST pList;
if (!pKernel || !pKernel->pList) return;
pList = pKernel->pList;
// Kernel is last in its list
if (pKernel->pNext == nullptr)
{
pList->pTail = pKernel->pPrev;
}
else
{
pKernel->pNext->pPrev = pKernel->pPrev;
}
// Kernel is first in its list
if (pKernel->pPrev == nullptr)
{
pList->pHead = pKernel->pNext;
}
else
{
pKernel->pPrev->pNext = pKernel->pNext;
}
pKernel->pNext = nullptr;
pKernel->pPrev = nullptr;
pKernel->pList = nullptr;
pList->iCount--;
}
//!
//! \brief Removes kernel allocation from current list and attaches to designated list
//! \details Removes the kernel allocation from the current list (pKernel->pList)
//| and attaches kernel to pList (passed in as a parameter)
//! \param PRENDERHAL_KRN_ALLOC_LIST pList
//! [in] Pointer to the kernel allocation list to attach to
//! \param PRENDERHAL_KRN_ALLOCATION pKernel
//! [in] Pointer to the kernel allocation
//! \param bool bHead
//! [in] Indicates whether to attach to head of list or tail
//! \return NONE
//!
void RenderHal_DSH_KernelAttach(PRENDERHAL_KRN_ALLOC_LIST pList, PRENDERHAL_KRN_ALLOCATION pKernel, bool bHead)
{
if (!pList || !pKernel) return;
// Detach from current list
if (pKernel->pList)
{
RenderHal_DSH_KernelDetach(pKernel);
}
if (bHead)
{
pKernel->pPrev = nullptr;
pKernel->pNext = pList->pHead;
pList->pHead = pKernel;
if (pKernel->pNext)
{
pKernel->pNext->pPrev = pKernel;
}
else
{
pList->pTail = pKernel;
}
}
else
{
pKernel->pPrev = pList->pTail;
pKernel->pNext = nullptr;
pList->pTail = pKernel;
if (pKernel->pPrev)
{
pKernel->pPrev->pNext = pKernel;
}
else
{
pList->pHead = pKernel;
}
}
pKernel->pList = pList;
pList->iCount++;
}
//!
//! \brief Get a kernel allocation from the pool
//! \details Returns a pointer to the kernel allocation from the pool
//! If pool is empty, the pool is extended (adds 16 kernel allocations)
//! \param PRENDERHAL_STATE_HEAP pStateHeap
//! [in] Pointer to the state heap
//! \return PRENDERHAL_KRN_ALLOCATION pointer to a kernel allocation
//!
PRENDERHAL_KRN_ALLOCATION RenderHal_DSH_GetKernelAllocationFromPool(PRENDERHAL_STATE_HEAP pStateHeap)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PRENDERHAL_KRN_ALLOCATION pKernelAllocation = nullptr;
MHW_RENDERHAL_CHK_NULL(pStateHeap);
if (pStateHeap->KernelAllocationPool.iCount == 0)
{
MHW_RENDERHAL_CHK_STATUS(RenderHal_DSH_ExtendKernelAllocPool(pStateHeap));
}
pKernelAllocation = pStateHeap->KernelAllocationPool.pHead;
RenderHal_DSH_KernelDetach(pKernelAllocation);
finish:
return pKernelAllocation;
}
//!
//! \brief Touch dynamic kernel
//! \details Updates sync tag on kernel allocation
//! Moves kernel to the tail of the pStateHeap->KernelsSubmitted list
//! Submits the dynamic memory block
//! Updates kernel usage
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to the renderhal interface
//! \param PRENDERHAL_KRN_ALLOCATION pKernelAllocation
//! [in] Pointer to the kernel allocation
//! \return NONE
//!
void RenderHal_DSH_TouchDynamicKernel(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_KRN_ALLOCATION pKernelAllocation)
{
PRENDERHAL_STATE_HEAP pStateHeap;
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
if (pRenderHal == nullptr || pRenderHal->pStateHeap == nullptr || pKernelAllocation == nullptr)
{
return;
}
pStateHeap = pRenderHal->pStateHeap;
pMhwStateHeap = pRenderHal->pMhwStateHeap;
// Set sync tag, for deallocation control
pKernelAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_LOCKED;
FrameTrackerTokenFlat_SetProducer(&pKernelAllocation->trackerToken, &pRenderHal->trackerProducer);
FrameTrackerTokenFlat_Merge(&pKernelAllocation->trackerToken,
pRenderHal->currentTrackerIndex,
pRenderHal->trackerProducer.GetNextTracker(pRenderHal->currentTrackerIndex));
// Move kernel to the tail of the submitted list (list is sorted with the most recently used at the end)
RenderHal_DSH_KernelAttach(&pStateHeap->KernelsSubmitted, pKernelAllocation, false);
// Update memory block
pMhwStateHeap->SubmitDynamicBlockDyn(MHW_ISH_TYPE, pKernelAllocation->pMemoryBlock, &pKernelAllocation->trackerToken);
// Update kernel usage - this is where kernels age if they are not constantly used, and may be removed
pKernelAllocation->dwCount++;
}
//!
//! \brief Searches the hash table for the kernel
//! \details Searches the hash table for the kernel using the UniqID and CacheID to determine if the
//! kernel is already allocated in the ISH
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to the renderhal interface
//! \param int32_t iUniqID
//! [in] unique kernel identifier
//! \param int32_t iCacheID
//! [in] cache identifier
//! \return PRENDERHAL_KRN_ALLOCATION
//! pKernelAllocation if kernel is found in hash table
//! nullptr otherwise
//!
PRENDERHAL_KRN_ALLOCATION RenderHal_DSH_SearchDynamicKernel(PRENDERHAL_INTERFACE pRenderHal, int32_t iUniqID, int32_t iCacheID)
{
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_KRN_ALLOCATION pKernelAllocation = nullptr;
pStateHeap = (pRenderHal) ? pRenderHal->pStateHeap : nullptr;
if (pStateHeap)
{
uint16_t wSearchIndex = 0;
pKernelAllocation = (PRENDERHAL_KRN_ALLOCATION) pStateHeap->kernelHashTable.Search(iUniqID, iCacheID, wSearchIndex);
}
return pKernelAllocation;
}
//!
//! \brief Allocates a kernel allocation
//! \details Searches the hash table for the kernel and if not found
//! gets a kernel allocation from the pool then
//! registers it in the hash table and attaches it to the allocated list
//! returns a pointer to the kernel allocation
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to the renderhal interface
//! \param int32_t iUniqID
//! [in] unique kernel identifier
//! \param int32_t iCacheID
//! [in] cache identifier
//! \return PRENDERHAL_KRN_ALLOCATION
//!
PRENDERHAL_KRN_ALLOCATION RenderHal_DSH_AllocateDynamicKernel(PRENDERHAL_INTERFACE pRenderHal, int32_t iUniqID, int32_t iCacheID)
{
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_KRN_ALLOCATION pKernelAllocation = nullptr;
uint16_t wSearchIndex = 0;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
pStateHeap = (pRenderHal) ? pRenderHal->pStateHeap : nullptr;
if (pStateHeap == nullptr)
{
goto finish;
}
pKernelAllocation = (PRENDERHAL_KRN_ALLOCATION)pStateHeap->kernelHashTable.Search(iUniqID, iCacheID, wSearchIndex);
if (!pKernelAllocation)
{
// Get new kernel allocation entry
pKernelAllocation = RenderHal_DSH_GetKernelAllocationFromPool(pStateHeap);
MHW_RENDERHAL_CHK_NULL(pKernelAllocation);
// Clear kernel allocation entry, setup kernel uniq id
uint32_t Reserved = pKernelAllocation->Reserved; // Preserve before
MOS_ZeroMemory(pKernelAllocation, sizeof(RENDERHAL_KRN_ALLOCATION));
pKernelAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_FREE; // Krn allocation does not point to a kernel
pKernelAllocation->Reserved = Reserved;
pKernelAllocation->iKUID = iUniqID;
pKernelAllocation->iKCID = iCacheID;
// Register kernel in hash table to speed up future search
pStateHeap->kernelHashTable.Register(iUniqID, iCacheID, pKernelAllocation);
// Insert kernel in allocated list
RenderHal_DSH_KernelAttach(&pStateHeap->KernelsAllocated, pKernelAllocation, false);
}
finish:
return pKernelAllocation;
}
//!
//! \brief Unregister a kernel
//! \details Frees the memory block of the kernel in the ISH
//! removes the kernel from the hash table and
//! attaches the kernel to the allocation pool
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to the renderhal interface
//! \param PRENDERHAL_KRN_ALLOCATION pKernelAllocation
//! [in] Pointer to the kernel allocation
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_UnregisterKernel(PRENDERHAL_INTERFACE pRenderHal, PRENDERHAL_KRN_ALLOCATION pKernelAllocation)
{
PRENDERHAL_STATE_HEAP pStateHeap;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
pStateHeap = (pRenderHal) ? pRenderHal->pStateHeap : nullptr;
if (pStateHeap == nullptr)
{
goto finish;
}
// Free kernel before releasing
if (pKernelAllocation->pMemoryBlock)
{
// Get new kernel allocation entry
pRenderHal->pMhwStateHeap->FreeDynamicBlockDyn(MHW_ISH_TYPE, pKernelAllocation->pMemoryBlock);
pKernelAllocation->pMemoryBlock = nullptr;
}
pStateHeap->kernelHashTable.Unregister(pKernelAllocation->iKUID, pKernelAllocation->iKCID);
// Return the kernel allocation to pool
RenderHal_DSH_KernelAttach(&pStateHeap->KernelAllocationPool, pKernelAllocation, false);
finish:
return eStatus;
}
//!
//! \brief Allocate GSH, SSH, ISH control structures and heaps
//! \details Allocates State Heap control structure (system memory)
//! and associated State Buffer in gfx/sys memory (GSH,ISH,SSH)
//! initializes the State Heap control structure and state buffers
//!
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Rendering Interface Structure
//! \param PRENDERHAL_STATE_HEAP_SETTINGS pSettings
//! [in] Pointer to state heap settings (GSH/SSH/ISH)
//! \return MOS_STATUS
//! SUCCESS if state heaps were successfully allocated and initialized
//! OTHER if bad parameters or allocation failed
//!
MOS_STATUS RenderHal_DSH_AllocateStateHeaps(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_STATE_HEAP_SETTINGS pSettings)
{
MHW_STATE_HEAP_SETTINGS MhwStateHeapSettings;
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
MhwRenderInterface *pMhwRender;
PMHW_RENDER_STATE_SIZES pHwSizes;
PRENDERHAL_STATE_HEAP pStateHeap = nullptr;
MOS_STATUS eStatus;
int32_t iSize;
// Initialize locals
eStatus = MOS_STATUS_UNKNOWN;
//---------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pSettings);
// verify GSH parameters and alignments
MHW_RENDERHAL_ASSERT((pSettings->iSyncSize % RENDERHAL_SYNC_BLOCK_ALIGN) == 0);
MHW_RENDERHAL_ASSERT((pSettings->iCurbeSize % RENDERHAL_URB_BLOCK_ALIGN) == 0);
MHW_RENDERHAL_ASSERT((pSettings->iKernelHeapSize % RENDERHAL_KERNEL_BLOCK_ALIGN) == 0);
MHW_RENDERHAL_ASSERT((pSettings->iKernelBlockSize % RENDERHAL_KERNEL_BLOCK_ALIGN) == 0);
// verify SSH parameters
MHW_RENDERHAL_ASSERT(pSettings->iBindingTables >= RENDERHAL_SSH_BINDING_TABLES_MIN);
MHW_RENDERHAL_ASSERT(pSettings->iBindingTables <= RENDERHAL_SSH_BINDING_TABLES_MAX);
MHW_RENDERHAL_ASSERT(pSettings->iSurfaceStates >= RENDERHAL_SSH_SURFACE_STATES_MIN);
MHW_RENDERHAL_ASSERT(pSettings->iSurfaceStates <= RENDERHAL_SSH_SURFACE_STATES_MAX);
MHW_RENDERHAL_ASSERT(pSettings->iSurfacesPerBT >= RENDERHAL_SSH_SURFACES_PER_BT_MIN);
MHW_RENDERHAL_ASSERT(pSettings->iSurfacesPerBT <= RENDERHAL_SSH_SURFACES_PER_BT_MAX);
//---------------------------------------
pMhwRender = pRenderHal->pMhwRenderInterface;
pStateHeap = pRenderHal->pStateHeap;
pHwSizes = pRenderHal->pHwSizes;
// Reset media state lists
MOS_ZeroMemory(&pStateHeap->FreeStates , sizeof(RENDERHAL_MEDIA_STATE_LIST));
MOS_ZeroMemory(&pStateHeap->ReservedStates , sizeof(RENDERHAL_MEDIA_STATE_LIST));
MOS_ZeroMemory(&pStateHeap->SubmittedStates , sizeof(RENDERHAL_MEDIA_STATE_LIST));
MOS_ZeroMemory(&pStateHeap->KernelsAllocated , sizeof(RENDERHAL_KRN_ALLOC_LIST));
MOS_ZeroMemory(&pStateHeap->KernelsSubmitted , sizeof(RENDERHAL_KRN_ALLOC_LIST));
MOS_ZeroMemory(&pStateHeap->KernelAllocationPool , sizeof(RENDERHAL_KRN_ALLOC_LIST));
// Create pool of media state objects
iSize = sizeof(RENDERHAL_MEDIA_STATE) + sizeof(RENDERHAL_DYNAMIC_STATE) + 16; // Media state object + Dynamic states object (co-located)
pStateHeap->pMediaStatesMemPool = MOS_New(MHW_MEMORY_POOL, iSize, sizeof(void *));
MHW_RENDERHAL_CHK_NULL(pStateHeap->pMediaStatesMemPool);
MHW_RENDERHAL_CHK_STATUS(RenderHal_DSH_ExtendMediaStatePool(pStateHeap));
//-------------------------------------------------------------------------
// Calculate offsets/sizes in GSH
//-------------------------------------------------------------------------
// Synchronization, debugging data
pStateHeap->dwOffsetSync = 0;
pStateHeap->dwSizeSync = pSettings->iSyncSize;
// Synchronization
pStateHeap->dwNextTag = 0;
pStateHeap->dwSyncTag = 0;
pStateHeap->dwFrameId = 0;
//----------------------------------
// Instruction State Heap
//----------------------------------
// Kernel Spill Area - allocated on demand
pStateHeap->dwScratchSpaceSize = 0;
//----------------------------------
// Surface State Heap
//----------------------------------
// Reset initial SSH allocations
pStateHeap->iCurSshBufferIndex = 0;
pStateHeap->iCurrentBindingTable = 0;
pStateHeap->iCurrentSurfaceState = 0;
// Calculate size of each Binding Table
pStateHeap->iBindingTableSize =
MOS_ALIGN_CEIL(pSettings->iSurfacesPerBT * pHwSizes->dwSizeBindingTableState, pSettings->iBTAlignment);
// Calculate memory size to store all binding tables and surface states
pStateHeap->dwSizeSSH = pSettings->iBindingTables * pStateHeap->iBindingTableSize +
pSettings->iSurfaceStates *
pRenderHal->pRenderHalPltInterface->GetSurfaceStateCmdSize();
pRenderHal->dwIndirectHeapSize = MOS_ALIGN_CEIL(pStateHeap->dwSizeSSH, MHW_PAGE_SIZE);
// Allocate local copy of SSH
pStateHeap->pSshBuffer = (uint8_t*)MOS_AllocAndZeroMemory(pStateHeap->dwSizeSSH);
if (!pStateHeap->pSshBuffer)
{
MHW_RENDERHAL_ASSERTMESSAGE("Fail to Allocate SSH buffer.");
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
pStateHeap->iBindingTableOffset = 0;
pStateHeap->iSurfaceStateOffset = pSettings->iBindingTables * pStateHeap->iBindingTableSize;
pStateHeap->pSurfaceEntry = (PRENDERHAL_SURFACE_STATE_ENTRY) MOS_AllocAndZeroMemory(pSettings->iSurfaceStates * sizeof(RENDERHAL_SURFACE_STATE_ENTRY));
MHW_RENDERHAL_CHK_NULL(pStateHeap->pSurfaceEntry);
//----------------------------------
// Allocate Instruction State Heap in MHW
//----------------------------------
MhwStateHeapSettings.dwIshSize = pRenderHal->DynamicHeapSettings.dwIshInitialSize;
MhwStateHeapSettings.m_keepIshLocked = true;
MhwStateHeapSettings.dwNumSyncTags = pSettings->iSyncSize;
MhwStateHeapSettings.dwIshIncrement = pRenderHal->DynamicHeapSettings.dwIshSizeIncrement;
MhwStateHeapSettings.dwIshMaxSize = pRenderHal->DynamicHeapSettings.dwIshMaximumSize;
MHW_RENDERHAL_CHK_STATUS(pMhwRender->AllocateHeaps(MhwStateHeapSettings));
MHW_RENDERHAL_CHK_NULL(pMhwRender->m_stateHeapInterface);
pMhwStateHeap = pRenderHal->pMhwStateHeap = pMhwRender->m_stateHeapInterface->pStateHeapInterface;
// Size of a Media ID entry
pStateHeap->dwSizeMediaID = pHwSizes->dwSizeInterfaceDescriptor;
// Not used in Dynamic mode - heaps may change
Mos_ResetResource(&pStateHeap->GshOsResource);
pStateHeap->pGshBuffer = nullptr;
pStateHeap->bGshLocked = false;
Mos_ResetResource(&pStateHeap->IshOsResource);
pStateHeap->pIshBuffer = nullptr;
pStateHeap->bIshLocked = false;
// Setup pointer to sync tags
pStateHeap->pSync = (uint32_t *)pRenderHal->pMhwStateHeap->GetCmdBufIdGlobalPointer();
// Reset pool of Kernel allocations objects
pStateHeap->pKernelAllocMemPool = MOS_New(MHW_MEMORY_POOL,
sizeof(RENDERHAL_KRN_ALLOCATION),
sizeof(void *));
MHW_RENDERHAL_CHK_NULL(pStateHeap->pKernelAllocMemPool);
MHW_RENDERHAL_CHK_STATUS(RenderHal_DSH_ExtendKernelAllocPool(pStateHeap));
eStatus = MOS_STATUS_SUCCESS;
finish:
if (eStatus != MOS_STATUS_SUCCESS)
{
// Free SSH buffer
if (pStateHeap)
{
if (pStateHeap->pSurfaceEntry)
{
MOS_FreeMemory(pStateHeap->pSurfaceEntry);
}
if (pStateHeap->pSshBuffer)
{
MOS_FreeMemory(pStateHeap->pSshBuffer);
}
}
}
return eStatus;
}
//!
//! \brief Free State Heaps (including MHW interfaces)
//! \details Free State Heap resources allocated by RenderHal
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Render Hal Interface
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_FreeStateHeaps(PRENDERHAL_INTERFACE pRenderHal)
{
PMOS_INTERFACE pOsInterface;
PRENDERHAL_STATE_HEAP pStateHeap;
MOS_STATUS eStatus;
//------------------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
//------------------------------------------------
eStatus = MOS_STATUS_UNKNOWN;
pOsInterface = pRenderHal->pOsInterface;
pStateHeap = pRenderHal->pStateHeap;
// Free Surface State Entries
if (pStateHeap->pSurfaceEntry)
{
// Free MOS surface in surface state entry
for (int32_t index = 0; index < pRenderHal->StateHeapSettings.iSurfaceStates; ++index) {
PRENDERHAL_SURFACE_STATE_ENTRY entry = pStateHeap->pSurfaceEntry + index;
MOS_SafeFreeMemory(entry->pSurface);
entry->pSurface = nullptr;
}
MOS_FreeMemory(pStateHeap->pSurfaceEntry);
pStateHeap->pSurfaceEntry = nullptr;
}
// Free SSH Resource
if (pStateHeap->pSshBuffer)
{
MOS_FreeMemory(pStateHeap->pSshBuffer);
pStateHeap->pSshBuffer = nullptr;
}
if(pStateHeap->pMediaStatesMemPool)
{
MOS_Delete(pStateHeap->pMediaStatesMemPool);
pStateHeap->pMediaStatesMemPool = nullptr;
}
if(pStateHeap->pKernelAllocMemPool)
{
MOS_Delete(pStateHeap->pKernelAllocMemPool);
pStateHeap->pKernelAllocMemPool = nullptr;
}
// Free kernel hash table
pRenderHal->pStateHeap->kernelHashTable.Free();
// Free State Heap Control structure
MOS_AlignedFreeMemory(pStateHeap);
pRenderHal->pStateHeap = nullptr;
pRenderHal->pRenderHalPltInterface->FreeScratchSpaceBuffer(pRenderHal);
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Assign memory block in state heap
//! \param RENDERHAL_TR_RESOURCE trackerInfo
//! [in] Pointer to tracker resource
//! \param HeapManager heapManager
//! [in] Pointer to heap manager
//! \param MemoryBlock block
//! [out] Pointer to memory block
//! \param uint32_t size
//! [in] size of requested memory block
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_AssignSpaceInStateHeap(
uint32_t trackerIndex,
FrameTrackerProducer *trackerProducer,
HeapManager *heapManager,
MemoryBlock *block,
uint32_t size)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t spaceNeeded = 0;
std::vector<MemoryBlock> blocks;
std::vector<uint32_t> blockSizes;
MemoryBlockManager::AcquireParams acquireParams =
MemoryBlockManager::AcquireParams(trackerProducer->GetNextTracker(trackerIndex),
blockSizes);
acquireParams.m_trackerIndex = trackerIndex; // use the first tracker only
MHW_RENDERHAL_CHK_NULL(heapManager);
MHW_RENDERHAL_CHK_NULL(block);
MHW_RENDERHAL_CHK_NULL(trackerProducer);
if (blockSizes.empty())
{
blockSizes.emplace_back(size);
}
else
{
blockSizes[0] = size;
}
MHW_RENDERHAL_CHK_STATUS(heapManager->AcquireSpace(acquireParams, blocks, spaceNeeded));
if (blocks.empty())
{
MHW_RENDERHAL_ASSERTMESSAGE("No blocks were acquired");
return MOS_STATUS_UNKNOWN;
}
if (!(blocks[0].IsValid()))
{
MHW_RENDERHAL_ASSERTMESSAGE("No blocks were acquired");
return MOS_STATUS_UNKNOWN;
}
*block = blocks[0];
// zero memory block
block->AddData(nullptr, 0, 0, true);
finish:
return eStatus;
}
//!
//! \brief Refresh Sync
//! \details Update Sync tags
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_RefreshSync(PRENDERHAL_INTERFACE pRenderHal)
{
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_MEDIA_STATE pCurMediaState;
PRENDERHAL_MEDIA_STATE pNextMediaState;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
PMHW_BATCH_BUFFER pBatchBuffer;
uint32_t dwCurrentTag;
uint32_t dwCurrentFrameId;
int32_t iStatesInUse;
int32_t iBuffersInUse;
int32_t iKernelsInUse;
MOS_STATUS eStatus;
MOS_NULL_RENDERING_FLAGS NullRenderingFlags;
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
PRENDERHAL_MEDIA_STATE_LIST pList;
PRENDERHAL_KRN_ALLOCATION pKrnAllocation, pNext;
//----------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
//----------------------------------
eStatus = MOS_STATUS_UNKNOWN;
// GSH must be locked
pStateHeap = pRenderHal->pStateHeap;
pMhwStateHeap = pRenderHal->pMhwStateHeap;
if (!pMhwStateHeap->GetCmdBufIdGlobalPointer())
{
goto finish;
}
// Most recent tags
pStateHeap->dwSyncTag = dwCurrentTag = pStateHeap->pSync[0];
// Refresh batch buffers
iBuffersInUse = 0;
pBatchBuffer = pRenderHal->pBatchBufferList;
NullRenderingFlags = pRenderHal->pOsInterface->pfnGetNullHWRenderFlags(pRenderHal->pOsInterface);
for (; pBatchBuffer != nullptr; pBatchBuffer = pBatchBuffer->pNext)
{
if (!pBatchBuffer->bBusy) continue;
// Clear BB busy flag when Sync Tag is reached
if ((int32_t)(dwCurrentTag - pBatchBuffer->dwSyncTag) > 0 ||
NullRenderingFlags.VPGobal)
{
pBatchBuffer->bBusy = false;
}
else
{
iBuffersInUse++;
}
}
// Refresh media states
pList = &(pStateHeap->SubmittedStates);
pNextMediaState = nullptr;
pCurMediaState = pList->pHead;
iStatesInUse = 0;
for (; pCurMediaState != nullptr; pCurMediaState = pNextMediaState)
{
// Save next media state before moving current state back to pool (if complete)
pNextMediaState = pCurMediaState->pNext;
if (!pCurMediaState->bBusy) continue;
// The condition below is valid when sync tag wraps from 2^32-1 to 0
if (FrameTrackerTokenFlat_IsExpired(&pCurMediaState->trackerToken))
{
pDynamicState = pCurMediaState->pDynamicState;
pCurMediaState->bBusy = false;
if (pRenderHal->bKerneltimeDump)
{
uint64_t uiNS;
uint8_t *pCurrentPtr;
uint64_t uiStartTime;
uint64_t uiEndTime;
uint64_t uiDiff;
double TimeMS;
uint32_t uiComponent;
uint32_t performanceSize = sizeof(uint64_t) * 2 + sizeof(RENDERHAL_COMPONENT);
uint8_t *data = (uint8_t*)MOS_AllocAndZeroMemory(performanceSize);
if (data == nullptr)
{
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// Dump Kernel execution time when media state is being freed
pDynamicState->memoryBlock.ReadData(data, pDynamicState->Performance.dwOffset, performanceSize);
pCurrentPtr = data;
uiStartTime = *((uint64_t *)pCurrentPtr);
pCurrentPtr += sizeof(uint64_t);
uiEndTime = *((uint64_t *)pCurrentPtr);
pCurrentPtr += sizeof(uint64_t);
uiComponent = *((RENDERHAL_COMPONENT *)pCurrentPtr);
if (uiComponent < (uint32_t)RENDERHAL_COMPONENT_COUNT)
{
// Convert ticks to ns
uiDiff = uiEndTime - uiStartTime;
uiNS = 0;
pRenderHal->pfnConvertToNanoSeconds(pRenderHal, uiDiff, &uiNS);
TimeMS = ((double)uiNS) / (1000 * 1000); // Convert to ms (double)
pRenderHal->kernelTime[uiComponent] += TimeMS;
}
MOS_SafeFreeMemory(data);
}
// Detach from submitted states, return to pool
*((pCurMediaState->pNext) ? &(pCurMediaState->pNext->pPrev) : &(pList->pTail)) = pCurMediaState->pPrev;
*((pCurMediaState->pPrev) ? &(pCurMediaState->pPrev->pNext) : &(pList->pHead)) = pCurMediaState->pNext;
pCurMediaState->pPrev = pCurMediaState->pNext = nullptr;
pList->iCount--;
// Return media state object back to pool
RenderHal_DSH_ReturnMediaStateToPool(pStateHeap, pCurMediaState);
}
else
{
iStatesInUse++;
}
}
// Refresh kernels
iKernelsInUse = 0;
pKrnAllocation = pStateHeap->KernelsSubmitted.pHead;
for ( ; pKrnAllocation != nullptr; pKrnAllocation = pNext)
{
pNext = pKrnAllocation->pNext;
// Move kernels back to allocated list (kernel remains cached)
if (FrameTrackerTokenFlat_IsExpired(&pKrnAllocation->trackerToken))
{
RenderHal_DSH_KernelAttach(&pStateHeap->KernelsAllocated, pKrnAllocation, false);
// Kernel block is flagged for removal (growing ISH) - delete block, mark kernel as stale
if (pKrnAllocation->pMemoryBlock && pKrnAllocation->pMemoryBlock->bDelete)
{
pMhwStateHeap->FreeDynamicBlockDyn(MHW_ISH_TYPE, pKrnAllocation->pMemoryBlock);
pKrnAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_USED;
}
else
{
// Mark kernel as in use, not locked
pKrnAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_USED;
}
}
else
{
iKernelsInUse++;
}
}
// Refresh blocks
pMhwStateHeap->RefreshDynamicHeapDyn(MHW_ISH_TYPE);
// Save number of states/buffers in use
pRenderHal->iBuffersInUse = iBuffersInUse;
pRenderHal->iKernelsInUse = iKernelsInUse;
pRenderHal->iMediaStatesInUse = iStatesInUse;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Extend the kernel state heap
//! \details Increases the size of the ISH (up to the maximum size)
//! Flags all submitted and allocated kernels as "stale" so can reload into new heap
//! Allocates new ISH and deletes old heap
//! Moves SIP binary to new heap
//! \param PRENDERHAL_STATE_HEAP pStateHeap
//! [in] Pointer to the state heap
//! \param uint32_t dwAdditionalKernelSpaceNeeded
//! [in] amount of additional space needed for kernel
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_ExpandKernelStateHeap(
PRENDERHAL_INTERFACE pRenderHal,
uint32_t dwAdditionalKernelSpaceNeeded)
{
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
PRENDERHAL_KRN_ALLOCATION pKrnAllocation;
PRENDERHAL_STATE_HEAP pStateHeap;
uint32_t dwNewSize;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PMHW_STATE_HEAP pOldInstructionHeap;
PMHW_STATE_HEAP_MEMORY_BLOCK pOldSipKernelBlock;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
pMhwStateHeap = pRenderHal->pMhwStateHeap;
pStateHeap = pRenderHal->pStateHeap;
// Increase size of the ISH (up to max size)
dwNewSize = MOS_ALIGN_CEIL(pMhwStateHeap->GetISHPointer()->dwSize + dwAdditionalKernelSpaceNeeded,
pRenderHal->DynamicHeapSettings.dwIshSizeIncrement);
if (dwNewSize > pRenderHal->DynamicHeapSettings.dwIshMaximumSize)
{
goto finish;
}
// Flag all submitted kernels as "stale", so they can be reloaded into the new heap
for (pKrnAllocation = pStateHeap->KernelsSubmitted.pHead; pKrnAllocation != nullptr; pKrnAllocation = pKrnAllocation->pNext)
{
pKrnAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_STALE;
if (pKrnAllocation->pMemoryBlock)
{
pKrnAllocation->pMemoryBlock->bStatic = false;
MHW_RENDERHAL_CHK_STATUS(pMhwStateHeap->FreeDynamicBlockDyn(MHW_ISH_TYPE, pKrnAllocation->pMemoryBlock));
pKrnAllocation->pMemoryBlock = nullptr;
}
}
// Flag all kernels allocated as "stale", so they can be reloaded into the new heap
for (pKrnAllocation = pStateHeap->KernelsAllocated.pHead; pKrnAllocation != nullptr; pKrnAllocation = pKrnAllocation->pNext)
{
pKrnAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_STALE;
if (pKrnAllocation->pMemoryBlock)
{
MHW_RENDERHAL_CHK_STATUS(pMhwStateHeap->FreeDynamicBlockDyn(MHW_ISH_TYPE, pKrnAllocation->pMemoryBlock));
pKrnAllocation->pMemoryBlock = nullptr;
}
}
// Get SIP kernel block prior to expansion
// NOTE: SIP kernel block is NOT associated with any KRN allocation and will be freed after copying to the new heap
pOldInstructionHeap = pMhwStateHeap->GetISHPointer();
pOldSipKernelBlock = pOldInstructionHeap->pDebugKernel;
// Allocate new instruction state heap
MHW_RENDERHAL_CHK_STATUS(pMhwStateHeap->ExtendStateHeap(MHW_ISH_TYPE, dwNewSize));
// Copy SIP kernel into the newly loaded ISH, mark old SIP block to be released when no longer in use
if (pOldSipKernelBlock)
{
MHW_RENDERHAL_CHK_STATUS(pRenderHal->pfnLoadSipKernel(pRenderHal, pOldSipKernelBlock->pDataPtr, pOldSipKernelBlock->dwDataSize));
pOldSipKernelBlock->bStatic = false;
pOldInstructionHeap->pDebugKernel = nullptr;
}
// Free old instruction state heap
MHW_RENDERHAL_CHK_STATUS(pMhwStateHeap->ReleaseStateHeapDyn(pOldInstructionHeap));
finish:
return eStatus;
}
//!
//! \brief Refresh available space in Dynamic ISH, create space by either unloading
//! expired kernels or expanding the ISH (up to its max size)
//! \details Refresh space in Dynamic ISH, creating contiguous space for kernel load
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param uint32_t dwSpaceNeeded
//! [in] Space needed in dynamic ISH for new kernel to be loaded
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_RefreshDynamicKernels(
PRENDERHAL_INTERFACE pRenderHal,
uint32_t dwSpaceNeeded,
uint32_t *pdwSizes,
int32_t iCount)
{
uint32_t TempArray[1] = { dwSpaceNeeded };
MHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS Params;
PRENDERHAL_STATE_HEAP pStateHeap;
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
PRENDERHAL_KRN_ALLOCATION pKrnAllocation, pNext;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
pStateHeap = pRenderHal->pStateHeap;
pMhwStateHeap = pRenderHal->pMhwStateHeap;
// Release move kernels from submitted back to allocated list according to Sync Tag
pRenderHal->pfnRefreshSync(pRenderHal);
// No block sizes provided, assume that the space requested must be contiguous
if (!pdwSizes)
{
pdwSizes = TempArray;
iCount = 1;
}
// The function below will calculate how much space is still needed in state heap
// considering the size of the blocks provided. This function accounts for fragmentation,
// so even if the heap has enough space, the call may still return a non-zero value.
Params.piSizes = (int32_t*)pdwSizes;
Params.iCount = iCount;
Params.dwAlignment = 0;
Params.bHeapAffinity = true;
Params.pHeapAffinity = pMhwStateHeap->GetISHPointer(); // only search for space in active heap
Params.dwScratchSpace= 0;
dwSpaceNeeded = pMhwStateHeap->CalculateSpaceNeededDyn(MHW_ISH_TYPE, &Params);
// Implementation note:
// Kernels are moved from the KernelsAllocated list to the KernelsSubmitted
// list whenever they are used via pfnTouchDynamicKernel function. When complete
// they are moved back to end end of the KernelsAllocated list via pfnRefreshSync.
// As a result, the allocation list is always sorted based on recent usage
// (older kernels remain at the head of the list)
//
// The caching algorithm tries to find a balance between amount of times
// the kernels was used, and how recently it was used - so kernels that are
// heavily used but at the beginning of the list are less likely to be removed
// compared with a kernel that was barely used (dwCount)
//
// IMPORTANT - Only one kernel allocation entry per Kernel UID (1:1 mapping)
//
pKrnAllocation = pStateHeap->KernelsAllocated.pHead;
for ( ; (pKrnAllocation != nullptr) && (dwSpaceNeeded > 0); pKrnAllocation = pNext)
{
pNext = pKrnAllocation->pNext;
if (pKrnAllocation->pMemoryBlock && pKrnAllocation->dwFlags != RENDERHAL_KERNEL_ALLOCATION_LOCKED)
{
// Only count this as available space if the block is in current heap!
if (pKrnAllocation->pMemoryBlock->pStateHeap == pMhwStateHeap->GetISHPointer())
{
dwSpaceNeeded -= MOS_MIN(dwSpaceNeeded, pKrnAllocation->pMemoryBlock->dwBlockSize);
}
MHW_RENDERHAL_CHK_STATUS(pMhwStateHeap->FreeDynamicBlockDyn(MHW_ISH_TYPE, pKrnAllocation->pMemoryBlock));
pKrnAllocation->pMemoryBlock = nullptr;
pKrnAllocation->dwOffset = 0;
pKrnAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_REMOVED;
}
}
// Failed to remove enough kernels
if (dwSpaceNeeded > 0)
{
eStatus = MOS_STATUS_UNKNOWN;
}
finish:
return eStatus;
}
void RenderHal_DSH_ResetDynamicKernels(
PRENDERHAL_INTERFACE pRenderHal)
{
return;
}
//!
//! \brief Load Kernel using dynamic state heap model
//! \details Load a kernel from cache into GSH; do not unload kernels
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param PCRENDERHAL_KERNEL_PARAM pParameters
//! [in] Pointer to Kernel Parameters
//! \param PMHW_KERNEL_PARAMS pKernel
//! [in] Pointer to Kernel entry
//! \param Kdll_CacheEntry pKernelEntry
//! [in] The cache entry pointer maintaining the load status.
//! For cache entries from local variable,
//! set it to nullptr to avoid memory corruption
//! \return int32_t
//! Index to a kernel allocation index
//! -1 if invalid parameters, no available space and no
//! deallocation possible
//!
PRENDERHAL_KRN_ALLOCATION RenderHal_DSH_LoadDynamicKernel(
PRENDERHAL_INTERFACE pRenderHal,
PCRENDERHAL_KERNEL_PARAM pParameters,
PMHW_KERNEL_PARAM pKernel,
uint32_t *pdwLoaded)
{
MHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS Params; // Block allocation parameters
PRENDERHAL_STATE_HEAP pStateHeap; // Renderhal State Heap control structure
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap; // Dynamic MHW state heap interface
PRENDERHAL_KRN_ALLOCATION pKernelAllocation = nullptr; // Kernel Allocation
PMHW_STATE_HEAP_MEMORY_BLOCK pKernelMemoryBlock; // Memory block in ISH where kernel is loaded
int32_t iKernelSize; // Kernel size
int32_t iKernelUniqueID; // Kernel unique ID
int32_t iKernelCacheID; // Kernel cache ID
uint16_t wSearchIndex = 0;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pParameters);
MHW_RENDERHAL_CHK_NULL(pKernel);
pStateHeap = pRenderHal->pStateHeap;
pMhwStateHeap = pRenderHal->pMhwStateHeap;
// Validate parameters
if (pKernel->iSize == 0)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
MHW_RENDERHAL_NORMALMESSAGE("Failed to load kernel - invalid parameters.");
goto finish;
}
// Kernel parameters
iKernelSize = pKernel->iSize;
iKernelUniqueID = pKernel->iKUID;
iKernelCacheID = pKernel->iKCID;
pKernelAllocation = (PRENDERHAL_KRN_ALLOCATION)pStateHeap->kernelHashTable.Search(iKernelUniqueID, iKernelCacheID, wSearchIndex);
// Kernel already loaded
if (pKernelAllocation)
{
// found match and Update kernel usage
pRenderHal->pfnTouchDynamicKernel(pRenderHal, pKernelAllocation);
// Increment reference counter
pKernel->bLoaded = 1;
goto finish;
}
// Get new kernel allocation entry
pKernelAllocation = RenderHal_DSH_GetKernelAllocationFromPool(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pKernelAllocation);
// Simple allocation - get next kernel allocation entry available from pool
// Prepare Media State Allocation in DSH
Params.piSizes = &iKernelSize;
Params.iCount = 1;
Params.dwAlignment = RENDERHAL_KERNEL_BLOCK_ALIGN;
Params.bHeapAffinity = 0;
Params.pHeapAffinity = 0;
Params.dwScratchSpace = 0;
Params.pScratchSpace = nullptr;
Params.bZeroAssignedMem = 0;
Params.bStatic = true;
Params.bGrow = 0;
pKernelMemoryBlock = pMhwStateHeap->AllocateDynamicBlockDyn(MHW_ISH_TYPE, &Params);
// Here is where the dynamic state heap comes into play - by expanding ISH on demand to load a new kernel (ISH can literally start from size 0)
if (!pKernelMemoryBlock)
{
// Extend ISH, making enough room to load the new kernel
MHW_RENDERHAL_CHK_STATUS(RenderHal_DSH_ExpandKernelStateHeap(pRenderHal, iKernelSize));
// Try again to load the kernel - this should now work, unless something went wrong with the allocation (max size reached)
pKernelMemoryBlock = pMhwStateHeap->AllocateDynamicBlockDyn(MHW_ISH_TYPE, &Params);
}
// Failed to load kernel
if (!pKernelMemoryBlock)
{
MHW_RENDERHAL_NORMALMESSAGE("Failed to load kernel - no space available in GSH.");
// Return the kernel allocation to pool
RenderHal_DSH_KernelAttach(&pStateHeap->KernelAllocationPool, pKernelAllocation, false);
pKernelAllocation = nullptr;
goto finish;
}
// Allocate kernel
pKernelAllocation->iKID = -1;
pKernelAllocation->iKUID = iKernelUniqueID;
pKernelAllocation->iKCID = iKernelCacheID;
FrameTrackerTokenFlat_Clear(&pKernelAllocation->trackerToken);
pKernelAllocation->dwOffset = pKernelMemoryBlock->dwDataOffset; // NOT USED IN DSH - KEPT FOR DEBUG SUPPORT
pKernelAllocation->iSize = pKernelMemoryBlock->dwDataSize; // NOT USED IN DSH - KEPT FOR DEBUG SUPPORT
pKernelAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_USED;
pKernelAllocation->dwCount = 0; // will be updated by "TouchKernel"
pKernelAllocation->Params = *pParameters;
pKernelAllocation->pKernelEntry = nullptr; // CURRENTLY NOT USED
pKernelAllocation->iAllocIndex = -1; // DSH NOT USED
pKernelAllocation->pMemoryBlock = pKernelMemoryBlock;
// Copy kernel data - securely erase unused part of the block
MOS_SecureMemcpy(pKernelMemoryBlock->pDataPtr, iKernelSize, pKernel->pBinary, iKernelSize);
if (iKernelSize < (int32_t)pKernelMemoryBlock->dwDataSize)
{
MOS_ZeroMemory((uint8_t*)pKernelMemoryBlock->pDataPtr + iKernelSize, pKernelMemoryBlock->dwDataSize - iKernelSize);
}
finish:
// Move kernel to the tail of the list of kernels (head of the list contains oldest kernels)
if (pKernelAllocation)
{
// Move kernel allocation to end of list of kernels (sorted by usage)
pRenderHal->pfnTouchDynamicKernel(pRenderHal, pKernelAllocation);
}
// Return kernel allocation
return pKernelAllocation;
}
//!
//! \brief Unload Kernel using dynamic model
//! \details Unload a kernel from GSH, free kernel heap space
//! Notify that the kernel has been unloaded (for tracking)
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param int32_t iKernelAllocationID
//! [in] Kernel allocation index in GSH
//! \return MOS_STATUS
//! true if success
//! false if invalid parameters or if kernel cannot be unloaded
//!
MOS_STATUS RenderHal_DSH_UnloadDynamicKernel(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_KRN_ALLOCATION pKernelAllocation)
{
PRENDERHAL_STATE_HEAP pStateHeap;
MOS_STATUS eStatus;
//---------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pKernelAllocation);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
//---------------------------------------
eStatus = MOS_STATUS_UNKNOWN;
pStateHeap = pRenderHal->pStateHeap;
//---------------------------------------
MHW_RENDERHAL_CHK_NULL(pStateHeap->pKernelAllocation);
//---------------------------------------
// Kernel already free - return it to pool
if (pKernelAllocation->dwFlags == RENDERHAL_KERNEL_ALLOCATION_FREE)
{
goto finish;
}
// Update Sync tags
MHW_RENDERHAL_CHK_STATUS(pRenderHal->pfnRefreshSync(pRenderHal));
// Check if kernel may be unloaded
if (!FrameTrackerTokenFlat_IsExpired(&pKernelAllocation->trackerToken))
{
goto finish;
}
// Release kernel entry (Offset/size may be used for reallocation)
pKernelAllocation->iKID = -1;
pKernelAllocation->iKUID = -1;
pKernelAllocation->iKCID = -1;
FrameTrackerTokenFlat_Clear(&pKernelAllocation->trackerToken);
pKernelAllocation->dwFlags = RENDERHAL_KERNEL_ALLOCATION_FREE;
pKernelAllocation->dwCount = 0;
pKernelAllocation->pKernelEntry = nullptr;
eStatus = MOS_STATUS_SUCCESS;
finish:
return eStatus;
}
//!
//! \brief Load Debug Kernel
//! \details Load SIP Debug kernel from cache into GSH.
//! Replace debug surface binding table index with the specified value.
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param void *pSipKernel
//! [in] Pointer to Debug (Sip) Kernel binary
//! \param uint32_t dwSipSize
//! [in] Debug (Sip) Kernel size
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_LoadSipKernel(
PRENDERHAL_INTERFACE pRenderHal,
void *pSipKernel,
uint32_t dwSipSize)
{
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
PMHW_STATE_HEAP pInstructionStateHeap = nullptr;
PMHW_STATE_HEAP_MEMORY_BLOCK pIshMemoryBlock;
MHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS Params;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
pMhwStateHeap = pRenderHal->pMhwStateHeap;
// Mark previous SIP kernel for auto-release so it can be replaced
pInstructionStateHeap = pMhwStateHeap->GetISHPointer();
MHW_RENDERHAL_CHK_NULL(pInstructionStateHeap);
if (pInstructionStateHeap->pDebugKernel)
{
pInstructionStateHeap->pDebugKernel->bStatic = false;
pInstructionStateHeap->pDebugKernel = nullptr;
}
// If SIP size is zero or binary is nullptr, goto finish (SIP kernel unloaded)
if (dwSipSize == 0 || pSipKernel == nullptr)
{
goto finish;
}
// Allocate new block for Debug (SIP) kernel
MOS_ZeroMemory(&Params, sizeof(Params));
Params.piSizes = (int32_t*)&dwSipSize;
Params.iCount = 1;
Params.dwAlignment = RENDERHAL_KERNEL_BLOCK_ALIGN;
Params.bHeapAffinity = true;
Params.pHeapAffinity = pInstructionStateHeap;
Params.dwScratchSpace = 0;
Params.pScratchSpace = nullptr;
Params.bZeroAssignedMem = false;
Params.bStatic = true;
Params.bGrow = false;
#ifdef MHW_DYNAMIC_STATE_HEAP_DEBUGGING
Params.dwBlockType = MHW_BLOCK_DATA_SIP_KERNEL;
Params.pClientObject = nullptr;
#endif
pIshMemoryBlock = pInstructionStateHeap->pDebugKernel = pMhwStateHeap->AllocateDynamicBlockDyn(MHW_ISH_TYPE, &Params);
if (!pIshMemoryBlock)
{
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// Copy SIP Debug kernel into SIP location in ISH (Instruction State Heap)
MOS_SecureMemcpy(pIshMemoryBlock->pDataPtr, dwSipSize, pSipKernel, dwSipSize);
finish:
return eStatus;
}
//!
//! \brief Send SIP state command
//! \details Send SIP state command pointing to the SIP kernel.
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Pointer to Command Buffer
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SendSipStateCmd(
PRENDERHAL_INTERFACE pRenderHal,
PMOS_COMMAND_BUFFER pCmdBuffer)
{
PMHW_STATE_HEAP_MEMORY_BLOCK pSipMemoryBlock;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface);
pSipMemoryBlock = pRenderHal->pMhwStateHeap->GetISHPointer()->pDebugKernel;
if ((pRenderHal->bSIPKernel || pRenderHal->bCSRKernel) && pSipMemoryBlock != nullptr)
{
MhwRenderInterface *pMhwRender = pRenderHal->pMhwRenderInterface;
pRenderHal->SipStateParams.bSipKernel = true;
pRenderHal->SipStateParams.dwSipBase = pSipMemoryBlock->dwDataOffset;
eStatus = pMhwRender->AddSipStateCmd(pCmdBuffer, &pRenderHal->SipStateParams);
}
else
{ // Fail - SIP kernel not loaded
eStatus = MOS_STATUS_UNKNOWN;
}
finish:
return eStatus;
}
//!
//! \brief Allocate Media ID
//! \details Allocates an setup Interface Descriptor for Media Pipeline
//! Kernel must be preloaded using pfnLoadKernel
//! Curbe must be allocated using pfnAllocateCurbe
//! Binding Table must be allocated using pfnAllocateBindingTable
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param int32_t iKernelAllocationID
//! [in] Kernel Allocation ID
//! \param int32_t iBindingTableID
//! [in] Binding Table ID
//! \param int32_t iCurbeOffset
//! [in] Curbe Offset (from Curbe base)
//! \param int32_t iCurbeLength
//! [in] Curbe Length
//! \param int32_t iCrsThrdConstDataLn
//! [in] Cross Thread constant data length
//! \param PMHW_GPGPU_WALKER_PARAMS pGpGpuWalkerParams
//! [in] Pointer to GpGpu Walker Params
//! \return int32_t
//! Media Interface descriptor ID
//! -1 if invalid parameters, no ID entry available in GSH
//!
int32_t RenderHal_DSH_AllocateDynamicMediaID(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_KRN_ALLOCATION pKernelAllocation,
int32_t iBindingTableID,
int32_t iCurbeOffset,
int32_t iCurbeLength,
int32_t iCrsThrdConstDataLn,
PMHW_GPGPU_WALKER_PARAMS pGpGpuWalkerParams)
{
PRENDERHAL_MEDIA_STATE pMediaState;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
PRENDERHAL_KRN_ALLOCATION *pKrnAllocationTable;
int32_t iCurbeSize;
int32_t iInterfaceDescriptor;
RENDERHAL_INTERFACE_DESCRIPTOR_PARAMS InterfaceDescriptorParams;
iInterfaceDescriptor = -1;
// Validate Renderhal and state heap
if (pRenderHal == nullptr || pRenderHal->pStateHeap == nullptr)
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid State.");
goto finish;
}
// Obtain pointer to current media state
pMediaState = pRenderHal->pStateHeap->pCurMediaState;
if (pMediaState == nullptr || pMediaState->pDynamicState == nullptr)
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid Media State.");
goto finish;
}
// Obtain pointer to dynamic media state
pDynamicState = pMediaState->pDynamicState;
// Validate kernel allocation ID (kernel must be pre-loaded into GSH)
if (pKernelAllocation == nullptr || // Allocation must be valid
pKernelAllocation->pMemoryBlock == nullptr || // Kernel must be loaded
//pKernelAllocation->dwFlags == RENDERHAL_KERNEL_ALLOCATION_FREE || kernel may be reused
pKernelAllocation->iSize == 0) // Size must be valid
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid Kernel Allocation");
goto finish;
}
// Check Curbe allocation (CURBE_Lenght is in 256-bit count -> convert to bytes)
iCurbeSize = iCurbeLength;
if (iCurbeSize <= 0)
{
// Curbe is not used by the kernel
iCurbeSize = iCurbeOffset = 0;
}
// Validate Curbe Offset (curbe must be pre-allocated)
else if ( iCurbeOffset < 0 || // Not allocated
(iCurbeOffset & 0x1F) != 0 || // Invalid alignment
(iCurbeOffset + iCurbeSize) > pDynamicState->Curbe.iCurrent) // Invalid size
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid Curbe Allocation.");
goto finish;
}
// Try to reuse interface descriptor (for 2nd level buffer optimizations)
// Check if ID already in use by another kernel - must use a different ID
pKrnAllocationTable = pDynamicState->pKrnAllocations;
iInterfaceDescriptor = pKernelAllocation->iKID;
if (iInterfaceDescriptor >= 0 && // If kernel has a preferred interface descriptor
pKrnAllocationTable[iInterfaceDescriptor] != pKernelAllocation) // AND the interface descriptor is used by another kernel ....
{
iInterfaceDescriptor = -1; // Choose another media interface descriptor
}
// Search available ID in current media state heap
if (iInterfaceDescriptor < 0)
{
int32_t iMax = pDynamicState->MediaID.iCount;
for (iInterfaceDescriptor = 0;
iInterfaceDescriptor < iMax;
iInterfaceDescriptor++)
{
if (pKrnAllocationTable[iInterfaceDescriptor] == nullptr)
{
break;
}
}
// All IDs are in use - fail
if (iInterfaceDescriptor >= iMax)
{
MHW_RENDERHAL_ASSERTMESSAGE("No Interface Descriptor available.");
iInterfaceDescriptor = -1;
goto finish;
}
}
if (iInterfaceDescriptor >= pDynamicState->MediaID.iCount)
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid Interface Descriptor.");
iInterfaceDescriptor = -1;
goto finish;
}
MOS_ZeroMemory((void *)&InterfaceDescriptorParams, sizeof(InterfaceDescriptorParams));
InterfaceDescriptorParams.iMediaID = iInterfaceDescriptor;
InterfaceDescriptorParams.iBindingTableID = iBindingTableID;
InterfaceDescriptorParams.iCurbeOffset = iCurbeOffset;
InterfaceDescriptorParams.iCurbeLength = iCurbeLength;
InterfaceDescriptorParams.iCrsThrdConstDataLn = iCrsThrdConstDataLn;
// barrier and slm
if (pGpGpuWalkerParams && pGpGpuWalkerParams->GpGpuEnable)
{
InterfaceDescriptorParams.blBarrierEnable = true;
InterfaceDescriptorParams.iNumberThreadsInGroup = pGpGpuWalkerParams->ThreadWidth * pGpGpuWalkerParams->ThreadHeight;
InterfaceDescriptorParams.iSLMSize = pGpGpuWalkerParams->SLMSize; // The shift will be handled by pfnEncodeSLMSize()
InterfaceDescriptorParams.blGlobalBarrierEnable = false; // BDW+, default is 0
}
else //Reset barrier and slm setting since they may be set before
{
InterfaceDescriptorParams.blBarrierEnable = false;
InterfaceDescriptorParams.iNumberThreadsInGroup = pRenderHal->dwMinNumberThreadsInGroup;
InterfaceDescriptorParams.iSLMSize = 0;
InterfaceDescriptorParams.iCrsThrdConstDataLn &= pRenderHal->dwMaskCrsThdConDataRdLn;
InterfaceDescriptorParams.blGlobalBarrierEnable = false; // BDW+, default is 0
}
// Setup Media ID entry - this call could be HW dependent
if (MOS_STATUS_SUCCESS != pRenderHal->pfnSetupInterfaceDescriptor(
pRenderHal,
pMediaState,
pKernelAllocation,
&InterfaceDescriptorParams))
{
MHW_RENDERHAL_ASSERTMESSAGE("Failed to setup Interface Descriptor.");
iInterfaceDescriptor = -1;
goto finish;
}
// Set kernel allocation for the current Media ID
pKrnAllocationTable[iInterfaceDescriptor] = pKernelAllocation;
// Set preferred Media ID for the current kernel
// This is necessary for 2nd level BB optimization.
if (pKernelAllocation->iKID < 0)
{
pKernelAllocation->iKID = iInterfaceDescriptor;
}
// Update kernel usage
pRenderHal->pfnTouchDynamicKernel(pRenderHal, pKernelAllocation);
finish:
return iInterfaceDescriptor;
}
//!
//! \brief Get a media ID
//! \details Returns an interface descriptor for this media state
//! sets kernel allocation for the media ID
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to the renderhal interface
//! \param PRENDERHAL_MEDIA_STATE pMediaState
//! [in] Pointer to the media state
//! \param PRENDERHAL_KRN_ALLOCATION pKernelAllocation
//! [in] Pointer to the kernel allocation
//! \return int32_t mediaID
//!
int32_t RenderHal_DSH_GetMediaID(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_MEDIA_STATE pMediaState,
PRENDERHAL_KRN_ALLOCATION pKernelAllocation)
{
PRENDERHAL_KRN_ALLOCATION *pKrnAllocations;
int32_t iInterfaceDescriptor = -1;
MOS_STATUS eStatus = MOS_STATUS_UNKNOWN;
MHW_RENDERHAL_CHK_NULL(pMediaState);
MHW_RENDERHAL_CHK_NULL(pMediaState->pDynamicState);
MHW_RENDERHAL_CHK_NULL(pMediaState->pDynamicState->pKrnAllocations);
MHW_RENDERHAL_CHK_NULL(pKernelAllocation);
iInterfaceDescriptor = pKernelAllocation->iKID;
pKrnAllocations = pMediaState->pDynamicState->pKrnAllocations;
// Try to reuse interface descriptor (for 2nd level buffer optimizations)
// Check if ID already in use by another kernel - must use a different ID
if (iInterfaceDescriptor >= 0 &&
pKrnAllocations[iInterfaceDescriptor] != nullptr &&
pKrnAllocations[iInterfaceDescriptor] != pKernelAllocation)
{
iInterfaceDescriptor = -1;
}
// Search available ID in current media state heap
if (iInterfaceDescriptor < 0)
{
int32_t iMax = pMediaState->pDynamicState->MediaID.iCount;
for (iInterfaceDescriptor = 0;
iInterfaceDescriptor < iMax;
iInterfaceDescriptor++)
{
if (pKrnAllocations[iInterfaceDescriptor] == nullptr)
{
break;
}
}
// All IDs are in use - fail
if (iInterfaceDescriptor >= iMax)
{
MHW_RENDERHAL_ASSERT("No Interface Descriptor available.");
iInterfaceDescriptor = -1;
goto finish;
}
}
// Set kernel allocation for the current Media ID
pKrnAllocations[iInterfaceDescriptor] = pKernelAllocation;
// Set preferred Media ID for the current kernel
// This is necessary for 2nd level BB optimization.
if (pKernelAllocation->iKID < 0)
{
pKernelAllocation->iKID = iInterfaceDescriptor;
}
finish:
return iInterfaceDescriptor;
}
//!
//! \brief Assign Dynamic Media State
//! \details Gets a pointer to the next available media state in GSH;
//! fails if not available
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hadrware Interface Structure
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hadrware Interface Structure
//! \param RENDERHAL_COMPONENT componentID
//! [in] Identifier of the requesting component
//! \return PRENDERHAL_MEDIA_STATE
//! gets a new Media State, returns pointer to Media State structure
//! nullptr - invalid, no states available + timeout
//!
PRENDERHAL_MEDIA_STATE RenderHal_DSH_AssignDynamicState(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_DYNAMIC_MEDIA_STATE_PARAMS pParams,
RENDERHAL_COMPONENT componentID)
{
MHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS Params; // Block allocation parameters
PRENDERHAL_MEDIA_STATE pMediaState = nullptr; // Media state structure
PRENDERHAL_DYNAMIC_STATE pDynamicState; // Dynamic media state structure
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
PMHW_RENDER_STATE_SIZES pHwSizes;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t dwSizeMediaState = 0;
uint32_t dwMediaStateAlign;
uint32_t dwSamplerStateAlign;
uint8_t *pCurrentPtr;
uint8_t *performanceMemory = nullptr;
uint32_t performanceSize;
uint32_t currentExtendSize = 0;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pOsInterface);
// Assign new media state (get from pool)
pMediaState = RenderHal_DSH_GetMediaStateFromPool(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pMediaState);
MHW_RENDERHAL_CHK_NULL(pMediaState->pDynamicState);
// Get pointer to state heap interface
pMhwStateHeap = pRenderHal->pMhwStateHeap;
// Get hw structure sizes
pHwSizes = pRenderHal->pHwSizes;
// Point to dynamic state
pDynamicState = pMediaState->pDynamicState;
MOS_ZeroMemory(pDynamicState, sizeof(RENDERHAL_DYNAMIC_STATE));
// Reset some states
pMediaState->bBusy = false; // will be busy after submission
// Setup parameters
pDynamicState->Curbe.dwOffset = dwSizeMediaState;
pDynamicState->Curbe.dwSize = (uint32_t)MOS_MAX(pParams->iMaxCurbeSize, pParams->iMaxCurbeOffset);
// Align media state for CURBE
dwMediaStateAlign = pRenderHal->dwCurbeBlockAlign;
dwSizeMediaState = MOS_ALIGN_CEIL(pDynamicState->Curbe.dwSize, dwMediaStateAlign);
// Align media states for Samplers
dwSamplerStateAlign = MHW_SAMPLER_STATE_ALIGN;
dwSizeMediaState = MOS_ALIGN_CEIL(dwSizeMediaState, dwSamplerStateAlign);
// Allocate Samplers
if (pRenderHal->bHasCombinedAVSSamplerState == false)
{
uint32_t dwSamplerSize = 0;
// This is needed regardless of 3D samplers
/// Used to calculate offset to sampler area during interface descriptor setup
pDynamicState->Sampler3D.dwOffset = dwSizeMediaState;
// 3D Sampler states
if (pParams->iMaxSamplerIndex3D > 0)
{
pDynamicState->Sampler3D.iCount = pParams->iMaxSamplerIndex3D;
pDynamicState->Sampler3D.dwSize = MOS_ALIGN_CEIL(pParams->iMaxSamplerIndex3D * pHwSizes->dwSizeSamplerState, MHW_SAMPLER_STATE_ALIGN);
dwSamplerSize = pDynamicState->Sampler3D.dwSize;
}
// AVS sampler states (colocated with 3D => make sure the area is large enough for both)
if (pParams->iMaxSamplerIndexAVS > 0)
{
pDynamicState->SamplerAVS.dwOffset = dwSizeMediaState;
pDynamicState->SamplerAVS.iCount = pParams->iMaxSamplerIndexAVS;
pDynamicState->SamplerAVS.dwSize = MOS_ALIGN_CEIL(pParams->iMaxSamplerIndexAVS * pHwSizes->dwSizeSamplerStateAvs, MHW_SAMPLER_STATE_ALIGN);
dwSamplerSize = MOS_MAX(dwSamplerSize, pDynamicState->SamplerAVS.dwSize);
}
// Sampler Indirect State (border color associated with each 3D sampler)
if (pParams->iMaxSamplerIndex3D > 0)
{
pDynamicState->SamplerInd.dwOffset = MOS_ALIGN_CEIL(dwSizeMediaState + dwSamplerSize, MHW_SAMPLER_STATE_ALIGN);
pDynamicState->SamplerInd.iCount = pParams->iMaxSamplerIndex3D;
pDynamicState->SamplerInd.dwSize = MOS_ALIGN_CEIL(pParams->iMaxSamplerIndex3D * pHwSizes->dwSizeSamplerIndirectState, MHW_SAMPLER_STATE_ALIGN);
dwSamplerSize += pDynamicState->SamplerInd.dwSize;
}
pDynamicState->dwSizeSamplers = dwSamplerSize = MOS_ALIGN_CEIL(dwSamplerSize, dwSamplerStateAlign);
dwSamplerSize *= pParams->iMaxMediaIDs; // Move tables to end of all sampler states
// 8x8 tables
if (pParams->iMax8x8Tables > 0)
{
pDynamicState->Table8x8.dwOffset = MOS_ALIGN_CEIL(dwSizeMediaState + dwSamplerSize, MHW_SAMPLER_STATE_ALIGN);
pDynamicState->Table8x8.iCount = pParams->iMax8x8Tables;
pDynamicState->Table8x8.dwSize = MOS_ALIGN_CEIL(pHwSizes->dwSizeSamplerStateTable8x8, MHW_SAMPLER_STATE_ALIGN);
dwSamplerSize += pParams->iMax8x8Tables * pDynamicState->Table8x8.dwSize;
}
dwSamplerSize = MOS_ALIGN_CEIL(dwSamplerSize, dwSamplerStateAlign);
dwSizeMediaState += dwSamplerSize;
}
else
{
uint32_t dwSamplerSize = 0;
// common base for all sampler types
pDynamicState->Sampler3D .dwOffset = dwSizeMediaState;
pDynamicState->SamplerAVS .dwOffset = dwSizeMediaState;
pDynamicState->SamplerConv.dwOffset = dwSizeMediaState;
pDynamicState->SamplerMisc.dwOffset = dwSizeMediaState;
// 3D sampler
pDynamicState->Sampler3D.iCount = pParams->iMaxSamplerIndex3D;
pDynamicState->Sampler3D.dwSize = pParams->iMaxSamplerIndex3D * pHwSizes->dwSizeSamplerState;
// Misc (VA) sampler
if (pParams->iMaxSamplerIndexMisc > 0)
{
dwSamplerStateAlign = MOS_MAX(dwMediaStateAlign, MHW_SAMPLER_STATE_VA_ALIGN);
pDynamicState->SamplerMisc.iCount = pParams->iMaxSamplerIndexMisc;
pDynamicState->SamplerMisc.dwSize = pParams->iMaxSamplerIndexMisc * pHwSizes->dwSizeSamplerStateVA;
}
// AVS sampler
if (pParams->iMaxSamplerIndexAVS > 0)
{
uint32_t dwAlign = GFX_IS_GEN_9_OR_LATER(pRenderHal->Platform) ? MHW_SAMPLER_STATE_AVS_ALIGN_G9 : MHW_SAMPLER_STATE_AVS_ALIGN;
uint32_t dwInc = pRenderHal->pMhwRenderInterface->GetSamplerStateAVSIncUnit();
dwSamplerStateAlign = MOS_MAX(dwMediaStateAlign, dwAlign);
pDynamicState->SamplerAVS.iCount = pParams->iMaxSamplerIndexAVS;
pDynamicState->SamplerAVS.dwSize = (pParams->iMaxSamplerIndexAVS - 1) * dwInc + pHwSizes->dwSizeSamplerStateAvs;
}
// Conv sampler
if (pParams->iMaxSamplerIndexConv > 0)
{
uint32_t dwAlign = GFX_IS_GEN_9_OR_LATER(pRenderHal->Platform) ? MHW_SAMPLER_STATE_AVS_ALIGN_G9 : MHW_SAMPLER_STATE_AVS_ALIGN;
uint32_t dwInc = pRenderHal->pMhwRenderInterface->GetSamplerStateConvIncUnit();
dwSamplerStateAlign = MOS_MAX(dwMediaStateAlign, dwAlign);
pDynamicState->SamplerConv.iCount = pParams->iMaxSamplerIndexConv;
pDynamicState->SamplerConv.dwSize = (pParams->iMaxSamplerIndexConv - 1) * dwInc + pHwSizes->dwSizeSamplerStateVAConvolve;
}
// Get largest of all
dwSamplerSize = MOS_MAX(pDynamicState->Sampler3D.dwSize, pDynamicState->SamplerMisc.dwSize);
dwSamplerSize = MOS_MAX(pDynamicState->SamplerAVS.dwSize, dwSamplerSize);
dwSamplerSize = MOS_MAX(pDynamicState->SamplerConv.dwSize, dwSamplerSize);
// Sampler Indirect State (border color associated with each 3D sampler)
if (pParams->iMaxSamplerIndex3D > 0)
{
dwSamplerSize = MOS_ALIGN_CEIL(dwSamplerSize, MHW_SAMPLER_STATE_ALIGN);
pDynamicState->SamplerInd.dwOffset = dwSizeMediaState + dwSamplerSize;
pDynamicState->SamplerInd.iCount = pParams->iMaxSamplerIndex3D;
pDynamicState->SamplerInd.dwSize = pParams->iMaxSamplerIndex3D * pHwSizes->dwSizeSamplerIndirectState;
dwSamplerSize += pDynamicState->SamplerInd.dwSize;
}
dwSamplerSize = MOS_ALIGN_CEIL(dwSamplerSize, dwSamplerStateAlign);
pDynamicState->dwSizeSamplers = dwSamplerSize;
dwSizeMediaState += pParams->iMaxMediaIDs * pDynamicState->dwSizeSamplers;
}
// Interface Descriptors
pDynamicState->MediaID.iCount = pParams->iMaxMediaIDs;
pDynamicState->MediaID.dwOffset = dwSizeMediaState;
pDynamicState->MediaID.dwSize = pParams->iMaxMediaIDs * pHwSizes->dwSizeInterfaceDescriptor;
dwSizeMediaState += pDynamicState->MediaID.dwSize;
// Area for Performance collection
pDynamicState->Performance.iCount = 1;
pDynamicState->Performance.dwOffset = dwSizeMediaState;
pDynamicState->Performance.dwSize = 64;
dwSizeMediaState += pDynamicState->Performance.dwSize;
// Kernel Spill Area
if (pParams->iMaxSpillSize > 0)
{
// per thread scratch space must be 1K*(2^n), (2K*(2^n) for BDW A0), alignment is 1kB
int iPerThreadScratchSpace = 0;
if (pRenderHal->pfnPerThreadScratchSpaceStart2K(pRenderHal))
{
iPerThreadScratchSpace = 2048;
}
else if (pRenderHal->pRenderHalPltInterface
->PerThreadScratchSpaceStart64Byte(pRenderHal))
{
iPerThreadScratchSpace = 64;
}
else
{
iPerThreadScratchSpace = 1024;
}
for (iPerThreadScratchSpace; iPerThreadScratchSpace < pParams->iMaxSpillSize; iPerThreadScratchSpace <<= 1);
pDynamicState->iMaxScratchSpacePerThread = pParams->iMaxSpillSize
= iPerThreadScratchSpace;
MOS_STATUS result = pRenderHal->pRenderHalPltInterface
->AllocateScratchSpaceBuffer(iPerThreadScratchSpace, pRenderHal);
if (MOS_STATUS_UNIMPLEMENTED == result) // Scratch space buffer is not supported
{
pDynamicState->dwScratchSpace
= pRenderHal->pfnGetScratchSpaceSize(pRenderHal,
iPerThreadScratchSpace);
pDynamicState->scratchSpaceOffset = dwSizeMediaState;
// Allocate more 1k space in state heap, which is used to make scratch space offset 1k-aligned.
dwSizeMediaState += pDynamicState->dwScratchSpace + MHW_SCRATCH_SPACE_ALIGN;
currentExtendSize = pRenderHal->dgsheapManager->GetExtendSize();
if (currentExtendSize < pDynamicState->dwScratchSpace)
{
// update extend size for scratch space
MHW_RENDERHAL_CHK_STATUS(
pRenderHal->dgsheapManager->SetExtendHeapSize(
pDynamicState->dwScratchSpace));
}
}
else
{
MHW_RENDERHAL_CHK_STATUS(result);
}
}
// Use generic heap manager to allocate memory block for dynamic general state heap
MHW_RENDERHAL_CHK_STATUS(pRenderHal->pfnAssignSpaceInStateHeap(
pRenderHal->currentTrackerIndex,
&pRenderHal->trackerProducer,
pRenderHal->dgsheapManager,
&pDynamicState->memoryBlock,
dwSizeMediaState));
if (pParams->iMaxSpillSize > 0 && currentExtendSize > 0)
{
// Restore original extend heap size
MHW_RENDERHAL_CHK_STATUS(
pRenderHal->dgsheapManager->SetExtendHeapSize(
currentExtendSize));
// Specifies the 1k-byte aligned address offset to scratch space for
// use by the kernel. This pointer is relative to the
// General State Base Address (1k aligned)
// Format = GeneralStateOffset[31:10]
pDynamicState->scratchSpaceOffset += pDynamicState->memoryBlock.GetOffset();
pDynamicState->scratchSpaceOffset = MOS_ALIGN_CEIL(pDynamicState->scratchSpaceOffset, MHW_SCRATCH_SPACE_ALIGN);
}
// set the sync tag for the media state
FrameTrackerTokenFlat_SetProducer(&pMediaState->trackerToken, &pRenderHal->trackerProducer);
FrameTrackerTokenFlat_Merge(&pMediaState->trackerToken,
pRenderHal->currentTrackerIndex,
pRenderHal->trackerProducer.GetNextTracker(pRenderHal->currentTrackerIndex));
// Reset HW allocations
pRenderHal->iChromaKeyCount = 0;
for (int32_t i = 0; i < pRenderHal->iMaxPalettes; i++)
{
pRenderHal->Palette[i].iNumEntries = 0;
}
// Zero Memory start time and end time
performanceSize = (sizeof(uint64_t) * 2) + sizeof(RENDERHAL_COMPONENT);
performanceMemory = (uint8_t*)MOS_AllocAndZeroMemory(performanceSize);
pCurrentPtr = performanceMemory;
pCurrentPtr += (sizeof(uint64_t) * 2);
*((RENDERHAL_COMPONENT *)pCurrentPtr) = componentID;
pDynamicState->memoryBlock.AddData(
performanceMemory,
pDynamicState->Performance.dwOffset,
performanceSize);
finish:
MOS_SafeFreeMemory(performanceMemory);
if (eStatus == MOS_STATUS_SUCCESS)
{
if (pRenderHal && pRenderHal->pStateHeap)
{
pRenderHal->pStateHeap->pCurMediaState = pMediaState;
}
if (pRenderHal)
{
// Refresh sync tag for all media states in submitted queue
pRenderHal->pfnRefreshSync(pRenderHal);
}
}
else
{
RenderHal_DSH_ReturnMediaStateToPool(pRenderHal->pStateHeap, pMediaState);
pMediaState = nullptr;
}
return pMediaState;
}
//!
//! \brief Releases the dynamic state
//! \details Returns the media state to the pool
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to renderhal interface
//! \param PRENDERHAL_MEDIA_STATE pMediaState
//! [in] Pointer to media state
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_ReleaseDynamicState(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_MEDIA_STATE pMediaState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pMediaState);
// Media state cannot be busy or attached to any list (free/submitted)
if (pMediaState->bBusy || pMediaState->pNext || pMediaState->pPrev)
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid Media State object");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
// Return media state to pool for reuse
RenderHal_DSH_ReturnMediaStateToPool(pRenderHal->pStateHeap, pMediaState);
finish:
return eStatus;
}
//!
//! \brief Submit the dynamic state
//! \details Move memory block to the submitted queue
//! Updates the sync tag for the scratch space
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to renderhal interface
//! \param PRENDERHAL_MEDIA_STATE pMediaState
//! [in] Pointer to media state
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SubmitDynamicState(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_MEDIA_STATE pMediaState)
{
PRENDERHAL_MEDIA_STATE_LIST pList;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
std::vector<MemoryBlock> blocks;
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
MHW_RENDERHAL_CHK_NULL(pMediaState);
MHW_RENDERHAL_CHK_NULL(pMediaState->pDynamicState);
// Media state cannot be attached to any list (free/submitted)
if (pMediaState->pNext || pMediaState->pPrev)
{
MHW_RENDERHAL_ASSERTMESSAGE("Invalid Media State object");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
// Flag as busy (should be already)
pMediaState->bBusy = true;
blocks.push_back(pMediaState->pDynamicState->memoryBlock);
pRenderHal->dgsheapManager->SubmitBlocks(blocks);
// Attached to end of submitted queue (media state in execution queue)
pList = &pRenderHal->pStateHeap->SubmittedStates;
pMediaState->pPrev = pList->pTail;
pList->pTail = pMediaState;
if (pMediaState->pPrev)
{
pMediaState->pPrev->pNext = pMediaState;
}
else
{ // List was empty - insert first element
MHW_ASSERT(pList->iCount == 0);
pList->pHead = pMediaState;
}
pList->iCount++;
finish:
return eStatus;
}
//!
//! \brief Load Curbe Data
//! \details Allocates and load CURBE data for Media
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RenderHal Interface structure
//! \param PRENDERHAL_MEDIA_STATE pCurMediaState
//! [out] Pointer to Current Media State structure
//! \param void *pData
//! [in] Pointer to Data
//! \param int32_t iSize
//! [in] Number of bytes to allocate
//! \return int32_t
//! Offset of the CURBE block from CURBE base (in bytes)
//! -1 if no CURBE space available in GSH
//!
int32_t RenderHal_DSH_LoadCurbeData(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_MEDIA_STATE pMediaState,
void *pData,
int32_t iSize)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t iOffset;
int32_t iCurbeSize;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
uint8_t* pRemainingCurbe;
iOffset = -1;
pRemainingCurbe = nullptr;
if (pRenderHal == nullptr || pMediaState == nullptr || pData == nullptr)
{
MHW_RENDERHAL_ASSERTMESSAGE("Null pointer found.");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
if (pMediaState && pMediaState->pDynamicState)
{
// Check if dynamic state is valid
pDynamicState = pMediaState->pDynamicState;
if (!pDynamicState->memoryBlock.IsValid())
{
goto finish;
}
iCurbeSize = MOS_ALIGN_CEIL(iSize, pRenderHal->dwCurbeBlockAlign);
if (pDynamicState->Curbe.iCurrent + iCurbeSize <= (int)pDynamicState->Curbe.dwSize)
{
iOffset = pDynamicState->Curbe.iCurrent;
pDynamicState->Curbe.iCurrent += iCurbeSize;
if (pData)
{
MHW_RENDERHAL_CHK_STATUS(pDynamicState->memoryBlock.AddData(
pData,
pDynamicState->Curbe.dwOffset + iOffset,
iSize));
// Zero remaining CURBE (for buffer alignment)
iCurbeSize -= iSize;
if (iCurbeSize > 0)
{
pRemainingCurbe = (uint8_t*)MOS_AllocAndZeroMemory(sizeof(uint8_t)*iCurbeSize);
MHW_RENDERHAL_CHK_STATUS(pDynamicState->memoryBlock.AddData(
pRemainingCurbe,
pDynamicState->Curbe.dwOffset + iOffset + iSize,
iCurbeSize));
}
}
}
}
finish:
if(pRemainingCurbe)
{
MOS_SafeFreeMemory(pRemainingCurbe);
}
if (eStatus != MOS_STATUS_SUCCESS)
{
iOffset = -1;
}
return iOffset;
}
//!
//! \brief Send Curbe Load
//! \details Send Curbe Load command
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Pointer to Command Buffer
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SendCurbeLoad(
PRENDERHAL_INTERFACE pRenderHal,
PMOS_COMMAND_BUFFER pCmdBuffer)
{
MHW_CURBE_LOAD_PARAMS CurbeLoadParams;
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_MEDIA_STATE pMediaState;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//-----------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pCmdBuffer);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap->pCurMediaState);
//-----------------------------------------
pMediaState = pRenderHal->pStateHeap->pCurMediaState;
MHW_RENDERHAL_CHK_NULL(pMediaState->pDynamicState);
eStatus = MOS_STATUS_SUCCESS;
pStateHeap = pRenderHal->pStateHeap;
pDynamicState = pMediaState->pDynamicState;
// CURBE size is in bytes
if (pDynamicState->Curbe.iCurrent != 0)
{
CurbeLoadParams.pKernelState = nullptr;
CurbeLoadParams.bOldInterface = false;
CurbeLoadParams.dwCURBETotalDataLength = pDynamicState->Curbe.iCurrent;
CurbeLoadParams.dwCURBEDataStartAddress = pDynamicState->memoryBlock.GetOffset() + // media state offset from GSH base
pDynamicState->Curbe.dwOffset; // curbe data offset in media state
MHW_RENDERHAL_CHK_STATUS(pRenderHal->pMhwRenderInterface->AddMediaCurbeLoadCmd(pCmdBuffer, &CurbeLoadParams));
}
finish:
return eStatus;
}
//!
//! \brief Send state base address
//! \details Send state base address command
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Pointer to Command Buffer
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SendStateBaseAddress(PRENDERHAL_INTERFACE pRenderHal, PMOS_COMMAND_BUFFER pCmdBuffer)
{
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
PMOS_RESOURCE pGshResource;
uint32_t dwGshSize;
PMOS_RESOURCE pIshResource;
uint32_t dwIshSize;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//----------------------------------------
MHW_RENDERHAL_CHK_NULL(pCmdBuffer);
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap->pCurMediaState);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwRenderInterface);
//----------------------------------------
pStateHeap = pRenderHal->pStateHeap;
pDynamicState = pStateHeap->pCurMediaState->pDynamicState;
MHW_RENDERHAL_CHK_NULL(pDynamicState);
pGshResource = pDynamicState->memoryBlock.GetResource();
dwGshSize = pDynamicState->memoryBlock.GetHeapSize();
pIshResource = &(pRenderHal->pMhwStateHeap->GetISHPointer()->resHeap);
dwIshSize = pRenderHal->pMhwStateHeap->GetISHPointer()->dwSize;
pRenderHal->StateBaseAddressParams.presGeneralState = pGshResource;
pRenderHal->StateBaseAddressParams.dwGeneralStateSize = dwGshSize;
pRenderHal->StateBaseAddressParams.presDynamicState = pGshResource;
pRenderHal->StateBaseAddressParams.dwDynamicStateSize = dwGshSize;
pRenderHal->StateBaseAddressParams.bDynamicStateRenderTarget = false;
pRenderHal->StateBaseAddressParams.presIndirectObjectBuffer = pGshResource;
pRenderHal->StateBaseAddressParams.dwIndirectObjectBufferSize = dwGshSize;
pRenderHal->StateBaseAddressParams.presInstructionBuffer = pIshResource;
pRenderHal->StateBaseAddressParams.dwInstructionBufferSize = dwIshSize;
eStatus = pRenderHal->pMhwRenderInterface->AddStateBaseAddrCmd(pCmdBuffer,
&pRenderHal->StateBaseAddressParams);
finish:
return eStatus;
}
//!
//! \brief Reset RenderHal States
//! \details Reset RenderHal States in preparation for a new command buffer
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RenderHal Interface Structure
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_Reset(
PRENDERHAL_INTERFACE pRenderHal)
{
MOS_STATUS eStatus;
//----------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
//----------------------------------
eStatus = MOS_STATUS_SUCCESS;
// Do not register GSH resource until we allocate the Media State
// Media State can be in any of the current DSH instances
// Do not register ISH resource until we load all kernels
// ISH could be reallocated to accomodate kernels being loaded in heap
//MHW_RENDERHAL_CHK_STATUS(pOsInterface->pfnRegisterResource(pOsInterface,
// &pStateHeap->IshOsResource,
// true,
// true));
// Reset Slice Shutdown Mode
pRenderHal->bRequestSingleSlice = false;
pRenderHal->PowerOption.nSlice = 0;
pRenderHal->PowerOption.nEU = 0;
pRenderHal->PowerOption.nSubSlice = 0;
finish:
return eStatus;
}
//!
//! \brief Send Sync Tag
//! \details Sends Synchronization Tags for G75
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RenderHal Interface Structure
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Pointer to Command Buffer
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SendSyncTag(
PRENDERHAL_INTERFACE pRenderHal,
PMOS_COMMAND_BUFFER pCmdBuffer)
{
PRENDERHAL_STATE_HEAP pStateHeap;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PXMHW_STATE_HEAP_INTERFACE pMhwStateHeap;
PMHW_MI_INTERFACE pMhwMiInterface;
MHW_PIPE_CONTROL_PARAMS PipeCtl;
//-------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
//-------------------------------------
pStateHeap = pRenderHal->pStateHeap;
pMhwStateHeap = pRenderHal->pMhwStateHeap;
pMhwMiInterface = pRenderHal->pMhwMiInterface;
// Send PIPE_CONTROL Token
// CMD_MI_FLUSH is disabled by default on GT, use PIPE_CONTROL
// Requires a token and the actual pipe control command
// Flush write caches
PipeCtl = g_cRenderHal_InitPipeControlParams;
PipeCtl.presDest = pMhwStateHeap->GetResCmdBufIdGlobal();
PipeCtl.dwPostSyncOp = MHW_FLUSH_NOWRITE;
PipeCtl.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
MHW_RENDERHAL_CHK_STATUS(pMhwMiInterface->AddPipeControl(pCmdBuffer, nullptr, &PipeCtl));
// Invalidate read-only caches and perform a post sync write
PipeCtl = g_cRenderHal_InitPipeControlParams;
PipeCtl.presDest = pMhwStateHeap->GetResCmdBufIdGlobal();
PipeCtl.dwResourceOffset = pStateHeap->dwOffsetSync;
PipeCtl.dwPostSyncOp = MHW_FLUSH_WRITE_IMMEDIATE_DATA;
PipeCtl.dwFlushMode = MHW_FLUSH_READ_CACHE;
PipeCtl.dwDataDW1 = pStateHeap->dwNextTag;
MHW_RENDERHAL_CHK_STATUS(pMhwMiInterface->AddPipeControl(pCmdBuffer, nullptr, &PipeCtl));
finish:
return eStatus;
}
//!
//! \brief Sets Sampler States
//! \details Initialize and set sampler states
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to HW interface
//! \param int32_t iMediaID
//! [in] Media ID
//! \param PRENDERHAL_SAMPLER_STATE_PARAMS pSamplerParams
//! [in] Pointer to Sampler parameters
//! \param int32_t iSamplers
//! [in] Number of samplers
//! \return MOS_STATUS MOS_STATUS_SUCCESS if success, otherwise MOS_STATUS_UNKNOWN
//!
MOS_STATUS RenderHal_DSH_SetSamplerStates(
PRENDERHAL_INTERFACE pRenderHal,
int32_t iMediaID,
PMHW_SAMPLER_STATE_PARAM pSamplerParams,
int32_t iSamplers)
{
MHW_RENDERHAL_ASSERT(true);
return MOS_STATUS_UNIMPLEMENTED;
}
//!
//! \brief Setup Interface Descriptor
//! \details Set interface descriptor
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to HW interface
//! \param PRENDERHAL_MEDIA_STATE pMediaState
//! [in] Pointer to media state
//! \param PRENDERHAL_KRN_ALLOCATION pKernelAllocation
//! [in] Pointer to kernel allocation
//! \param PRENDERHAL_INTERFACE_DESCRIPTOR_PARAMS pInterfaceDescriptorParams
//! [in] Pointer to interface descriptor parameters
//! \param PMHW_GPGPU_WALKER_PARAMS pGpGpuWalkerParams
//! [in] Pointer to gpgpu walker parameters
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SetupInterfaceDescriptor(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_MEDIA_STATE pMediaState,
PRENDERHAL_KRN_ALLOCATION pKernelAllocation,
PRENDERHAL_INTERFACE_DESCRIPTOR_PARAMS pInterfaceDescriptorParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_ID_ENTRY_PARAMS Params;
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
uint32_t dwMediaStateOffset;
//-----------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pMhwStateHeap);
MHW_RENDERHAL_CHK_NULL(pMediaState);
MHW_RENDERHAL_CHK_NULL(pMediaState->pDynamicState);
MHW_RENDERHAL_CHK_NULL(pKernelAllocation);
MHW_RENDERHAL_CHK_NULL(pKernelAllocation->pMemoryBlock);
MHW_RENDERHAL_CHK_NULL(pInterfaceDescriptorParams);
//-----------------------------------------
// Get states, params
pStateHeap = pRenderHal->pStateHeap;
pDynamicState = pMediaState->pDynamicState;
dwMediaStateOffset = pDynamicState->memoryBlock.GetOffset();
Params.dwMediaIdOffset = dwMediaStateOffset + pDynamicState->MediaID.dwOffset;
Params.iMediaId = pInterfaceDescriptorParams->iMediaID;
Params.dwKernelOffset = pKernelAllocation->dwOffset;
Params.dwSamplerOffset = dwMediaStateOffset + pDynamicState->Sampler3D.dwOffset +
pInterfaceDescriptorParams->iMediaID * pDynamicState->dwSizeSamplers;
Params.dwSamplerCount = pKernelAllocation->Params.Sampler_Count;
Params.dwBindingTableOffset = pInterfaceDescriptorParams->iBindingTableID * pStateHeap->iBindingTableSize;
Params.iCurbeOffset = pInterfaceDescriptorParams->iCurbeOffset;
Params.iCurbeLength = pInterfaceDescriptorParams->iCurbeLength;
Params.bBarrierEnable = pInterfaceDescriptorParams->blBarrierEnable;
Params.bGlobalBarrierEnable = pInterfaceDescriptorParams->blGlobalBarrierEnable; //It's only applied for BDW+
Params.dwNumberofThreadsInGPGPUGroup = pInterfaceDescriptorParams->iNumberThreadsInGroup;
Params.dwSharedLocalMemorySize = pRenderHal->pfnEncodeSLMSize(pRenderHal, pInterfaceDescriptorParams->iSLMSize);
Params.iCrsThdConDataRdLn = pInterfaceDescriptorParams->iCrsThrdConstDataLn;
Params.memoryBlock = &pDynamicState->memoryBlock;
MHW_RENDERHAL_CHK_STATUS(pRenderHal->pMhwStateHeap->AddInterfaceDescriptorData(&Params));
pDynamicState->MediaID.iCurrent++;
finish:
return eStatus;
}
//!
//! \brief Set Vfe State Params
//! \details Sets VFE State parameters
//! this functions must be called to setup
//! parameters for pMhwRender->AddMediaVfeCmd()
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to Hardware Interface Structure
//! \param uint32_t dwDebugCounterControl
//! [in] Debug Counter Control
//! \param uint32_t dwMaximumNumberofThreads
//! [in] Maximum Number of Threads
//! \param uint32_t dwCURBEAllocationSize
//! [in] CURBE Allocation Size
//! \param uint32_t dwURBEntryAllocationSize
//! [in] URB Entry Allocation Size
//! \param PRENDERHAL_SCOREBOARD_PARAMS pScoreboardParams
//! [in] Pointer to Scoreboard Params
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SetVfeStateParams(
PRENDERHAL_INTERFACE pRenderHal,
uint32_t dwDebugCounterControl,
uint32_t dwMaximumNumberofThreads,
uint32_t dwCURBEAllocationSize,
uint32_t dwURBEntryAllocationSize,
PMHW_VFE_SCOREBOARD pScoreboardParams)
{
PMHW_VFE_PARAMS pVfeParams;
PRENDERHAL_STATE_HEAP pStateHeap;
PRENDERHAL_DYNAMIC_STATE pDynamicState;
PMHW_RENDER_ENGINE_CAPS pHwCaps;
PRENDERHAL_STATE_HEAP_SETTINGS pSettings;
uint32_t dwMaxURBSize;
uint32_t dwMaxCURBEAllocationSize;
uint32_t dwMaxURBEntryAllocationSize;
uint32_t dwNumberofURBEntries;
uint32_t dwMaxURBEntries;
uint32_t dwMaxInterfaceDescriptorEntries;
MOS_STATUS eStatus;
uint32_t i;
//---------------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pWaTable);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pStateHeap);
MHW_RENDERHAL_CHK_NULL(pRenderHal->pHwCaps);
//---------------------------------------------
eStatus = MOS_STATUS_SUCCESS;
pStateHeap = pRenderHal->pStateHeap;
pHwCaps = pRenderHal->pHwCaps;
pVfeParams = pRenderHal->pRenderHalPltInterface->GetVfeStateParameters();
pSettings = &(pRenderHal->StateHeapSettings);
pVfeParams->pKernelState = nullptr;
pVfeParams->eVfeSliceDisable = MHW_VFE_SLICE_ALL;
// Get pointer to current dynamic state
MHW_RENDERHAL_CHK_NULL(pStateHeap->pCurMediaState);
MHW_RENDERHAL_CHK_NULL(pStateHeap->pCurMediaState->pDynamicState);
pDynamicState = pStateHeap->pCurMediaState->pDynamicState;
//-------------------------------------------------------------------------
// In this calculation, URBEntryAllocationSize and CURBEAllocationSize are
// in 256-bit units:
// (URBEntryAllocationSize * NumberofURBEntries + CURBEAllocationSize +
// MaxInterfaceDescriptorEntries) <= 2048
//-------------------------------------------------------------------------
// get the Max for all the fields
dwMaxURBSize = pHwCaps->dwMaxURBSize;
dwMaxURBEntries = pHwCaps->dwMaxURBEntries;
dwMaxURBEntryAllocationSize = pHwCaps->dwMaxURBEntryAllocationSize;
dwMaxCURBEAllocationSize = pHwCaps->dwMaxCURBEAllocationSize;
dwMaxInterfaceDescriptorEntries = pHwCaps->dwMaxInterfaceDescriptorEntries;
dwCURBEAllocationSize = MOS_MAX(dwCURBEAllocationSize, (uint32_t)pDynamicState->Curbe.iCurrent);
dwCURBEAllocationSize = MOS_ROUNDUP_SHIFT(dwCURBEAllocationSize, 5);
dwURBEntryAllocationSize = MOS_ROUNDUP_SHIFT(dwURBEntryAllocationSize, 5);
dwURBEntryAllocationSize = MOS_MAX(1, dwURBEntryAllocationSize);
dwNumberofURBEntries = (dwMaxURBSize - dwCURBEAllocationSize - dwMaxInterfaceDescriptorEntries) / dwURBEntryAllocationSize;
dwNumberofURBEntries = MOS_CLAMP_MIN_MAX(dwNumberofURBEntries, 1, 32);
pVfeParams->dwDebugCounterControl = dwDebugCounterControl;
pVfeParams->dwNumberofURBEntries = dwNumberofURBEntries;
pVfeParams->dwMaximumNumberofThreads = (dwMaximumNumberofThreads == RENDERHAL_USE_MEDIA_THREADS_MAX) ?
pHwCaps->dwMaxThreads : MOS_MIN(dwMaximumNumberofThreads, pHwCaps->dwMaxThreads);
pVfeParams->dwCURBEAllocationSize = dwCURBEAllocationSize << 5;
pVfeParams->dwURBEntryAllocationSize = dwURBEntryAllocationSize;
MHW_RENDERHAL_ASSERT(dwNumberofURBEntries <= dwMaxURBEntries);
MHW_RENDERHAL_ASSERT(dwCURBEAllocationSize <= dwMaxCURBEAllocationSize);
MHW_RENDERHAL_ASSERT(dwURBEntryAllocationSize <= dwMaxURBEntryAllocationSize);
MHW_RENDERHAL_ASSERT(dwNumberofURBEntries * dwURBEntryAllocationSize + dwCURBEAllocationSize + dwMaxInterfaceDescriptorEntries <= dwMaxURBSize);
// Setup Scoreboard Parameters
if (pScoreboardParams)
{
MHW_RENDERHAL_ASSERT(pScoreboardParams->ScoreboardMask < 8);
pRenderHal->VfeScoreboard.ScoreboardEnable = true;
pRenderHal->VfeScoreboard.ScoreboardMask = (1 << pScoreboardParams->ScoreboardMask) - 1;
pRenderHal->VfeScoreboard.ScoreboardType = pScoreboardParams->ScoreboardType;
for (i = 0; i < pScoreboardParams->ScoreboardMask; i++)
{
pRenderHal->VfeScoreboard.ScoreboardDelta[i].x = pScoreboardParams->ScoreboardDelta[i].x;
pRenderHal->VfeScoreboard.ScoreboardDelta[i].y = pScoreboardParams->ScoreboardDelta[i].y;
}
}
else
{
pRenderHal->VfeScoreboard.ScoreboardEnable = true;
pRenderHal->VfeScoreboard.ScoreboardMask = 0x0;
}
// Setup VFE Scoreboard parameters
pVfeParams->Scoreboard = pRenderHal->VfeScoreboard;
// Setup Kernel Scratch Space
if (pDynamicState->dwScratchSpace > 0)
{
int32_t iSize;
int32_t iRemain;
int32_t iPerThreadScratchSize;
MHW_RENDERHAL_ASSERT(pDynamicState->iMaxScratchSpacePerThread ==
MOS_ALIGN_CEIL(pDynamicState->iMaxScratchSpacePerThread, 1024));
if (pRenderHal->pfnPerThreadScratchSpaceStart2K(pRenderHal))
iPerThreadScratchSize = pDynamicState->iMaxScratchSpacePerThread >> 10;
else
iPerThreadScratchSize = pDynamicState->iMaxScratchSpacePerThread >> 9;
iRemain = iPerThreadScratchSize % 2;
iPerThreadScratchSize = iPerThreadScratchSize / 2;
iSize = 0;
while (!iRemain && (iPerThreadScratchSize / 2))
{
iSize++;
iRemain = iPerThreadScratchSize % 2;
iPerThreadScratchSize = iPerThreadScratchSize / 2;
}
MHW_RENDERHAL_ASSERT(!iRemain && iPerThreadScratchSize);
MHW_RENDERHAL_ASSERT(iSize < 12);
pVfeParams->dwPerThreadScratchSpace = (uint32_t)iSize;
pVfeParams->dwScratchSpaceBasePointer = pDynamicState->scratchSpaceOffset;
}
else
{
pVfeParams->dwPerThreadScratchSpace = 0;
pVfeParams->dwScratchSpaceBasePointer = 0;
}
finish:
return eStatus;
}
//!
//! \brief Get offset and/or pointer to sampler state
//! \details Get offset and/or pointer to sampler state in General State Heap
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RenderHal Interface
//! \param int32_t iMediaID
//! [in] Media ID associated with sampler
//! \param int32_t iSamplerID
//! [in] Sampler ID
//! \param uint32_t *pdwSamplerOffset
//! [out] optional; offset of sampler state from GSH base
//! \param void **ppSampler
//! [out] optional; pointer to sampler state in GSH
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_GetSamplerOffsetAndPtr(
PRENDERHAL_INTERFACE pRenderHal,
int32_t iMediaID,
int32_t iSamplerID,
PMHW_SAMPLER_STATE_PARAM pSamplerParams,
uint32_t *pdwSamplerOffset,
void **ppSampler)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_RENDERHAL_CHK_NULL(pRenderHal->pRenderHalPltInterface);
MHW_RENDERHAL_CHK_STATUS( pRenderHal->pRenderHalPltInterface->GetSamplerOffsetAndPtr_DSH(
pRenderHal,
iMediaID,
iSamplerID,
pSamplerParams,
pdwSamplerOffset,
ppSampler));
finish:
return eStatus;
}
//!
//! \brief Initialize
//! \details Initialize HW states
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RenderHal Interface Structure
//! \param PCRENDERHAL_SETTINGS pSettings
//! [in] Pointer to Settings
//! \return MOS_STATUS
//! true if succeeded
//! false if failed to allocate/initialize HW commands
//!
MOS_STATUS RenderHal_DSH_Initialize(
PRENDERHAL_INTERFACE pRenderHal,
PRENDERHAL_SETTINGS pSettings)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PRENDERHAL_STATE_HEAP pStateHeap;
//------------------------------------------------
MHW_RENDERHAL_CHK_NULL(pRenderHal);
//------------------------------------------------
// Allocate State Heap control structure (aligned)
pRenderHal->pStateHeap = pStateHeap = (PRENDERHAL_STATE_HEAP)MOS_AlignedAllocMemory(sizeof(RENDERHAL_STATE_HEAP), 16);
pRenderHal->dwStateHeapSize = sizeof(RENDERHAL_STATE_HEAP);
MHW_RENDERHAL_CHK_NULL(pStateHeap);
pRenderHal->pStateHeap->kernelHashTable = CmHashTable();
pRenderHal->pStateHeap->kernelHashTable.Init();
// Apply state heap settings (iMediaStates not actually used in DSH)
if (pSettings)
{
pRenderHal->StateHeapSettings.iMediaStateHeaps = pSettings->iMediaStates;
}
// Apply Dynamic state heap settings
if (pSettings && pSettings->pDynSettings)
{
pRenderHal->DynamicHeapSettings = *(pSettings->pDynSettings);
}
// Apply SSH settings for the current platform
pRenderHal->StateHeapSettings.iSurfaceStateHeaps =
pRenderHal->StateHeapSettings.iMediaStateHeaps;
// Allocate and initialize state heaps (GSH, SSH, ISH)
MHW_RENDERHAL_CHK_STATUS(pRenderHal->pfnAllocateStateHeaps(pRenderHal, &pRenderHal->StateHeapSettings));
// If ASM debug is enabled, allocate debug resource
MHW_RENDERHAL_CHK_STATUS(RenderHal_AllocateDebugSurface(pRenderHal));
finish:
return eStatus;
}
//!
//! \brief Issue command to write timestamp
//! \param [in] pRenderHal
//! \param [in] pCmdBuffer
//! \param [in] bStartTime
//! \return MOS_STATUS
//!
MOS_STATUS RenderHal_DSH_SendTimingData(
PRENDERHAL_INTERFACE pRenderHal,
PMOS_COMMAND_BUFFER pCmdBuffer,
bool bStartTime);
//! Following functions are defined in RenderHal and are not used by RenderHal_DSH
//! ------------------------------------------------------------------------------
PRENDERHAL_MEDIA_STATE RenderHal_DSH_AssignMediaState(
PRENDERHAL_INTERFACE pRenderHal,
RENDERHAL_COMPONENT componentID)
{
MHW_RENDERHAL_ASSERT( true );
return nullptr;
}
int32_t RenderHal_DSH_AllocateMediaID(
PRENDERHAL_INTERFACE pRenderHal,
int32_t iKernelAllocationID,
int32_t iBindingTableID,
int32_t iCurbeOffset,
int32_t iCurbeLength,
int32_t iCrsThrdConstDataLn,
PMHW_GPGPU_WALKER_PARAMS pGpGpuWalkerParams)
{
MHW_RENDERHAL_ASSERT( true );
return -1;
}
int32_t RenderHal_DSH_LoadKernel(
PRENDERHAL_INTERFACE pRenderHal,
PCRENDERHAL_KERNEL_PARAM pParameters,
PMHW_KERNEL_PARAM pKernel,
Kdll_CacheEntry *pKernelEntry)
{
MHW_RENDERHAL_ASSERT( true );
return -1;
}
MOS_STATUS RenderHal_DSH_UnloadKernel(
PRENDERHAL_INTERFACE pRenderHal,
int32_t iKernelAllocationID)
{
MHW_RENDERHAL_ASSERT( true );
return MOS_STATUS_UNIMPLEMENTED;
}
void RenderHal_DSH_ResetKernels(
PRENDERHAL_INTERFACE pRenderHal)
{
MHW_RENDERHAL_ASSERT( true );
return;
}
void RenderHal_DSH_TouchKernel(
PRENDERHAL_INTERFACE pRenderHal,
int32_t iKernelAllocationID)
{
MHW_RENDERHAL_ASSERT( true );
return;
}
int32_t RenderHal_DSH_GetKernelOffset(
PRENDERHAL_INTERFACE pRenderHal,
int32_t iKernelAllocationIndex)
{
MHW_RENDERHAL_ASSERT( true );
return 0;
}
//! ------------------------------------------------------------------------------
void RenderHal_InitInterfaceEx(PRENDERHAL_INTERFACE pRenderHal);
//!
//! \brief Init Interface using Dynamic State Heap
//! \details Initializes RenderHal Interface structure, responsible for HW
//! abstraction of HW Rendering Engine for CM(MDF) and VP.
//! \param PRENDERHAL_INTERFACE pRenderHal
//! [in] Pointer to RenderHal Interface Structure
//! \param MhwCpInterface** ppCpInterface
//! [in/out] Pointer of pointer to MHW CP Interface Structure, which
//! is created during renderhal initialization
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface Structure
//! \return MOS_STATUS
//! MOS_STATUS_UNKNOWN : Invalid parameters
//!
MOS_STATUS RenderHal_InitInterface_Dynamic(
PRENDERHAL_INTERFACE pRenderHal,
MhwCpInterface **ppCpInterface,
PMOS_INTERFACE pOsInterface)
{
MOS_STATUS eStatus;
//---------------------------------------
MHW_RENDERHAL_ASSERT(pRenderHal);
//---------------------------------------
// Init interfaces - some of which will be later replaced for DSH
MHW_RENDERHAL_CHK_STATUS(RenderHal_InitInterface(pRenderHal, ppCpInterface, pOsInterface));
// Initialization/Cleanup function
pRenderHal->pfnInitialize = RenderHal_DSH_Initialize;
// Allocate/Destroy state heaps
pRenderHal->pfnAllocateStateHeaps = RenderHal_DSH_AllocateStateHeaps;
pRenderHal->pfnFreeStateHeaps = RenderHal_DSH_FreeStateHeaps;
pRenderHal->pfnAssignSpaceInStateHeap = RenderHal_DSH_AssignSpaceInStateHeap;
// Media states management functions
pRenderHal->pfnAssignMediaState = RenderHal_DSH_AssignMediaState;
pRenderHal->pfnAllocateMediaID = RenderHal_DSH_AllocateMediaID;
pRenderHal->pfnGetMediaID = RenderHal_DSH_GetMediaID;
pRenderHal->pfnAssignDynamicState = RenderHal_DSH_AssignDynamicState;
pRenderHal->pfnReleaseDynamicState = RenderHal_DSH_ReleaseDynamicState;
pRenderHal->pfnSubmitDynamicState = RenderHal_DSH_SubmitDynamicState;
pRenderHal->pfnAllocateDynamicMediaID = RenderHal_DSH_AllocateDynamicMediaID;
// Kernel management functions
pRenderHal->pfnRefreshSync = RenderHal_DSH_RefreshSync;
pRenderHal->pfnLoadKernel = RenderHal_DSH_LoadKernel;
pRenderHal->pfnUnloadKernel = RenderHal_DSH_UnloadKernel;
pRenderHal->pfnResetKernels = RenderHal_DSH_ResetKernels;
pRenderHal->pfnTouchKernel = RenderHal_DSH_TouchKernel;
pRenderHal->pfnGetKernelOffset = RenderHal_DSH_GetKernelOffset;
pRenderHal->pfnUnregisterKernel = RenderHal_DSH_UnregisterKernel;
// Dynamic Kernel management functions (not implemented here)
pRenderHal->pfnLoadDynamicKernel = RenderHal_DSH_LoadDynamicKernel;
pRenderHal->pfnAllocateDynamicKernel = RenderHal_DSH_AllocateDynamicKernel;
pRenderHal->pfnSearchDynamicKernel = RenderHal_DSH_SearchDynamicKernel;
pRenderHal->pfnUnloadDynamicKernel = RenderHal_DSH_UnloadDynamicKernel;
pRenderHal->pfnRefreshDynamicKernels = RenderHal_DSH_RefreshDynamicKernels;
pRenderHal->pfnResetDynamicKernels = RenderHal_DSH_ResetDynamicKernels;
pRenderHal->pfnTouchDynamicKernel = RenderHal_DSH_TouchDynamicKernel;
pRenderHal->pfnExpandKernelStateHeap = RenderHal_DSH_ExpandKernelStateHeap;
// ISA ASM Debug support functions
pRenderHal->pfnLoadSipKernel = RenderHal_DSH_LoadSipKernel;
pRenderHal->pfnSendSipStateCmd = RenderHal_DSH_SendSipStateCmd;
// Command buffer programming functions
pRenderHal->pfnLoadCurbeData = RenderHal_DSH_LoadCurbeData;
pRenderHal->pfnSendCurbeLoad = RenderHal_DSH_SendCurbeLoad;
pRenderHal->pfnSendStateBaseAddress = RenderHal_DSH_SendStateBaseAddress;
// Initialize OS dependent RenderHal Interfaces common to all platforms
pRenderHal->pfnReset = RenderHal_DSH_Reset;
pRenderHal->pfnSendTimingData = RenderHal_DSH_SendTimingData;
pRenderHal->pfnSendSyncTag = RenderHal_DSH_SendSyncTag;
// Sampler state, interface descriptor, VFE params
pRenderHal->pfnSetSamplerStates = RenderHal_DSH_SetSamplerStates;
pRenderHal->pfnSetupInterfaceDescriptor = RenderHal_DSH_SetupInterfaceDescriptor;
pRenderHal->pfnSetVfeStateParams = RenderHal_DSH_SetVfeStateParams;
// Hardware dependent calls
pRenderHal->pfnGetSamplerOffsetAndPtr = RenderHal_DSH_GetSamplerOffsetAndPtr;
// Special functions
RenderHal_InitInterfaceEx(pRenderHal);
// Initialize the DSH settings
pRenderHal->pRenderHalPltInterface->InitDynamicHeapSettings(pRenderHal);
finish:
return eStatus;
}