/*
* Copyright (c) 2014-2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file      mhw_state_heap.c 
//! \brief         This modules implements HW interface layer to be used on all platforms on     all operating systems/DDIs, across MHW components. 
//!
#include "mhw_state_heap.h"
#include "mhw_utilities.h"
#include "mhw_block_manager.h"
#include "media_interfaces_mhw.h"
#include "mhw_mi.h"
#include "mhw_cp_interface.h"
#include "mos_interface.h"

extern const uint8_t g_cMhw_VDirection[MHW_NUM_FRAME_FIELD_TYPES] = {
    MEDIASTATE_VDIRECTION_FULL_FRAME,
    MEDIASTATE_VDIRECTION_TOP_FIELD,
    MEDIASTATE_VDIRECTION_BOTTOM_FIELD
};

extern const MHW_SAMPLER_STATE_UNORM_PARAM g_cInit_MhwSamplerStateUnormParam =
{
    MHW_SAMPLER_FILTER_CUSTOM,                      // SamplerFilterMode
    MHW_GFX3DSTATE_MAPFILTER_LINEAR,                // MagFilter
    MHW_GFX3DSTATE_MAPFILTER_LINEAR,                // MinFilter
    MHW_GFX3DSTATE_TEXCOORDMODE_CLAMP,              // AddressU
    MHW_GFX3DSTATE_TEXCOORDMODE_CLAMP,              // AddressV
    MHW_GFX3DSTATE_TEXCOORDMODE_CLAMP,              // AddressW
    MHW_SAMPLER_SURFACE_PIXEL_UINT,
    {0},
    {0},
    {0},
    {0},
    0,
    0,
    0
};

extern const MHW_SURFACE_STATE_PARAMS g_cInit_MhwSurfaceStateParams =
{
    nullptr,     // pSurfaceState

    0,        // dwCacheabilityControl
    0,        // dwFormat
    0,        // dwWidth
    0,        // dwHeight
    0,        // dwDepth
    0,        // dwPitch
    0,        // dwQPitch
    0,        // bUseAdvState
    0,        // AddressControl
    0,        // SurfaceType3D
    false,    // bTiledSurface
    false,    // bTileWalk
    false,    // bVerticalLineStride
    false,    // bVerticalLineStrideOffset
    false,    // bCompressionEnabled
    false,    // bCompressionMode
    0,        // MmcState
    false,    // bInterleaveChroma
    false,    // bHalfPitchChroma
    false,    // bSeperateUVPlane
    0,        // UVPixelOffsetUDirection
    0,        // UVPixelOffsetVDirection
    0,        // RotationMode
    0,        // bSurfaceArraySpacing
    false,    // bBoardColorOGL
    0,        // iXOffset
    0,        // iYOffset
    0,        // dwXOffsetForU
    0,        // dwYOffsetForU
    0,        // dwXOffsetForV
    0,        // dwYOffsetForV
    0,        // Compression Format
    0,        // L1CacheConfig

    nullptr,     // [out] pdwCmd
    0         // [out] dwLocationInCmd
};

extern const MHW_ID_ENTRY_PARAMS g_cInit_MhwIdEntryParams =
{
    0,       // dwMediaIdOffset
    0,       // iMediaId
    0,       // dwKernelOffset
    0,       // dwSamplerOffset
    0,       // dwSamplerCount
    0,       // dwBindingTableOffset
    0,       // iCurbeOffset
    0,       // iCurbeLength
    false,   // bBarrierEnable
    0,       // bGlobalBarrierEnable
    0,       // dwNumberofThreadsInGPGPUGroup
    0,       // dwSharedLocalMemorySize
    0        // iCrsThdConDataRdLn
};

//!
//! \brief    Assigns space in a state heap to a kernel state
//! \details  Client facing function to assign as space in a state heap a kernel state;
//!           if no space is available, a clean up is attempted 
//! \param    PMHW_STATE_HEAP_INTERFACE pCommonStateHeapInterface
//!           [in] State heap interface
//! \param    MHW_STATE_HEAP_TYPE StateHeapType
//!           [in] The state heap type requested (ISH/DSH)
//! \param    PMHW_KERNEL_STATE pKernelState
//!           [in] Kernel state to which a state heap space will be assigned
//! \param    uint32_t dwSpaceRequested
//!           [in] The amount of space requested from the state heap
//! \param    bool bStatic
//!           [in] Whether or not the space requested is static
//! \param    bool bZeroAssignedMem
//!           [in] Whether or not acquired memory should be zeroed
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, MOS_STATUS_CLIENT_AR_NO_SPACE if no space
//!           is available but it is possible for the client to wait, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_AssignSpaceInStateHeap(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    MHW_STATE_HEAP_TYPE         StateHeapType,
    PMHW_KERNEL_STATE           pKernelState,
    uint32_t                    dwSpaceRequested,
    bool                        bStatic,
    bool                        bZeroAssignedMem)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->AssignSpaceInStateHeap(
                  StateHeapType,
                  pKernelState,
                  dwSpaceRequested,
                  bStatic,
                  bZeroAssignedMem));

finish:
    return eStatus;
}

//!
//! \brief    Assigns space in a state heap to a kernel state
//! \details  Client facing function to assign as space in a state heap a kernel state;
//!           if no space is available, a clean up is attempted 
//! \param    [in] pCommonStateHeapInterface
//!           State heap interface
//! \param    [in] pKernelState
//!           Kernel state containing all memory blocks to submit
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success
//!
MOS_STATUS Mhw_StateHeapInterface_SubmitBlocks(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_KERNEL_STATE           pKernelState)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SubmitBlocks(pKernelState));

finish:
    return eStatus;
}

//!
//! \brief    Locks requested state heap
//! \details  Client facing function to lock a state heap
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    PMHW_STATE_HEAP pStateHeap
//!           [in] The state heap to be locked
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success
//!
MOS_STATUS Mhw_StateHeapInterface_LockStateHeap(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_STATE_HEAP                    pStateHeap)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->LockStateHeap(
                   pStateHeap));

finish:
    return eStatus;
}

//!
//! \brief    Unlocks requested state heap
//! \details  Client facing function to unlock a state heap
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    PMHW_STATE_HEAP pStateHeap
//!           [in] The state heap to be locked
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success
//!
MOS_STATUS Mhw_StateHeapInterface_UnlockStateHeap(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_STATE_HEAP             pStateHeap)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->UnLockStateHeap(
                   pStateHeap));

finish:
    return eStatus;
}

//!
//! \brief    Allocates a state heap of the requested type
//! \details  Client facing function to extend a state heap of the requested time, which
//!           involves allocating state heap and added it to the state heap liked list.
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    MHW_STATE_HEAP_TYPE StateHeapType
//!           [in] The state heap type requested (ISH/DSH)
//! \param    uint32_t dwSizeRequested
//!           [in] The size of the state heap
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_ExtendStateHeap(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    MHW_STATE_HEAP_TYPE         StateHeapType,
    uint32_t                    dwSizeRequested)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->ExtendStateHeap(
                   StateHeapType, dwSizeRequested));

finish:
    return eStatus;
}

//!
//! \brief    Update CmdBufIdGlobal
//! \details  Client facing function to update CmdBufIdGlobal
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    PMOS_COMMAND_BUFFER pCmdBuffer
//!           [in] The command buffer containing the kernel workload
//! \param    void  *pvRenderEngineInterface
//!           [in] Render engine interface
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_UpdateGlobalCmdBufId(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->UpdateGlobalCmdBufId());

finish:
    return eStatus;
}

//!
//! \brief    Set command buffer status pointer
//! \details  Client facing function to set command buffer status pointer
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    void  *pvCmdBufStatus
//!           [in] command buffer status pointer
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_SetCmdBufStatusPtr(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    void                        *pvCmdBufStatus)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetCmdBufStatusPtr(
        pvCmdBufStatus));

finish:
    return eStatus;
}

//!
//! \brief    Calculate the space needed in the SSH
//! \details  Client facing function to calculate the space needed in the SSH
//!           given the number of binding table entries
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    uint32_t dwBtEntriesRequested
//!           [in] Binding table entries requested in the SSH
//! \param    uint32_t *pdwSshSize
//!           [out] The size needed in the SSH
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_CalculateSshAndBtSizesRequested(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    uint32_t                    dwBtEntriesRequested,
    uint32_t                    *pdwSshSize,
    uint32_t                    *pdwBtSize)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->CalculateSshAndBtSizesRequested(
                   dwBtEntriesRequested, pdwSshSize, pdwBtSize));

finish:
    return eStatus;
}

//!
//! \brief    Request SSH space for a command buffer.
//! \details  Client facing function to request SSH space for a command buffer, if not enough
//!           space is available, more will be requested.
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    uint32_t dwBtEntriesRequested
//!           [in] Binding table entries requested in the SSH
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_RequestSshSpaceForCmdBuf(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    uint32_t                    dwBtEntriesRequested)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->RequestSshSpaceForCmdBuf(
                   dwBtEntriesRequested));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetInterfaceDescriptor (
        PMHW_STATE_HEAP_INTERFACE    pCommonStateHeapInterface,
        uint32_t                            dwNumIdsToSet,
        PMHW_INTERFACE_DESCRIPTOR_PARAMS    pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetInterfaceDescriptor(
                   dwNumIdsToSet, pParams));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetInterfaceDescriptorEntry (
    PMHW_STATE_HEAP_INTERFACE    pCommonStateHeapInterface,
    PMHW_ID_ENTRY_PARAMS                pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetInterfaceDescriptorEntry(
                   pParams));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetBindingTable (
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_KERNEL_STATE                  pKernelState)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetBindingTable(
                   pKernelState));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetBindingTableEntry (
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_BINDING_TABLE_PARAMS          pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetBindingTableEntry(
                   pParams));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SendBindingTableEntry (
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_BINDING_TABLE_SEND_PARAMS     pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SendBindingTableEntry (
                   pParams));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetSurfaceState(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    PMHW_KERNEL_STATE           pKernelState,
    PMOS_COMMAND_BUFFER         pCmdBuffer,
    uint32_t                    dwNumSurfaceStatesToSet,
    PMHW_RCS_SURFACE_PARAMS     pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetSurfaceState (
                   pKernelState,pCmdBuffer, dwNumSurfaceStatesToSet, pParams));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetSurfaceStateEntry(
    PMHW_STATE_HEAP_INTERFACE    pCommonStateHeapInterface,
    PMHW_SURFACE_STATE_PARAMS           pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetSurfaceStateEntry(
                   pParams));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_InitSamplerStates(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    void                        *pSampler,
    int32_t                     iSamplers)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->InitSamplerStates(
                   pSampler,iSamplers));

finish:
    return eStatus;
}

MOS_STATUS Mhw_StateHeapInterface_SetSamplerState(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface,
    void                               *pSampler,
    PMHW_SAMPLER_STATE_PARAM           pParams)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pCommonStateHeapInterface);

    MHW_CHK_NULL(pCommonStateHeapInterface->pStateHeapInterface);

    MHW_CHK_STATUS(pCommonStateHeapInterface->pStateHeapInterface->SetSamplerState(
                   pSampler,pParams));

finish:
    return eStatus;
}

uint32_t Mhw_StateHeapInterface_DSH_CalculateSpaceNeeded(
    PMHW_STATE_HEAP_INTERFACE            pStateHeapInterface,
    MHW_STATE_HEAP_TYPE                  StateHeapType,
    PMHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS pParams)
{
    if (pStateHeapInterface == nullptr)
    {
        MHW_ASSERTMESSAGE("Invalid Input Parameter");
        return 0;
    }
    else
    {
        if (pStateHeapInterface->pStateHeapInterface == nullptr)
        {
            MHW_ASSERTMESSAGE("Invalid Input Parameter");
            return 0;
        }
    }

    return  pStateHeapInterface->pStateHeapInterface->CalculateSpaceNeededDyn(
            StateHeapType,  pParams);
}

PMHW_STATE_HEAP_MEMORY_BLOCK Mhw_StateHeapInterface_DSH_AllocateDynamicBlock(
        PMHW_STATE_HEAP_INTERFACE            pStateHeapInterface,
        MHW_STATE_HEAP_TYPE                  StateHeapType,
        PMHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS pParams)
{
    if (pStateHeapInterface == nullptr)
    {
        MHW_ASSERTMESSAGE("Invalid Input Parameter");
        return (PMHW_STATE_HEAP_MEMORY_BLOCK)0;
    }
    else
    {
        if (pStateHeapInterface->pStateHeapInterface == nullptr)
        {
            MHW_ASSERTMESSAGE("Invalid Input Parameter");
            return (PMHW_STATE_HEAP_MEMORY_BLOCK)0;
        }
    }

    return pStateHeapInterface->pStateHeapInterface->AllocateDynamicBlockDyn(
        StateHeapType,  pParams);
}

MOS_STATUS Mhw_StateHeapInterface_DSH_SubmitDynamicBlock(
        PMHW_STATE_HEAP_INTERFACE            pStateHeapInterface,
        MHW_STATE_HEAP_TYPE                  StateHeapType,
        PMHW_STATE_HEAP_MEMORY_BLOCK         pBlock,
        FrameTrackerTokenFlat                *trackerToken)
{
    MHW_CHK_NULL_RETURN(pStateHeapInterface);
    MHW_CHK_NULL_RETURN(pStateHeapInterface->pStateHeapInterface);

    return pStateHeapInterface->pStateHeapInterface->SubmitDynamicBlockDyn(
        StateHeapType,  pBlock,  trackerToken);
}

MOS_STATUS Mhw_StateHeapInterface_DSH_FreeDynamicBlock(
        PMHW_STATE_HEAP_INTERFACE            pStateHeapInterface,
        MHW_STATE_HEAP_TYPE                  StateHeapType,
        PMHW_STATE_HEAP_MEMORY_BLOCK         pBlock)
{
    MHW_CHK_NULL_RETURN(pStateHeapInterface);
    MHW_CHK_NULL_RETURN(pStateHeapInterface->pStateHeapInterface);

    return pStateHeapInterface->pStateHeapInterface->FreeDynamicBlockDyn(
        StateHeapType,  pBlock);
}

MOS_STATUS Mhw_StateHeapInterface_DSH_RefreshDynamicHeap (
    PMHW_STATE_HEAP_INTERFACE   pStateHeapInterface,
    MHW_STATE_HEAP_TYPE         StateHeapType)
{
    MHW_CHK_NULL_RETURN(pStateHeapInterface);
    MHW_CHK_NULL_RETURN(pStateHeapInterface->pStateHeapInterface);

    return pStateHeapInterface->pStateHeapInterface->RefreshDynamicHeapDyn(
         StateHeapType);
}

MOS_STATUS Mhw_StateHeapInterface_DSH_ReleaseStateHeap(
    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface,
    PMHW_STATE_HEAP pStateHeap)
{
    MHW_CHK_NULL_RETURN(pStateHeapInterface);
    MHW_CHK_NULL_RETURN(pStateHeapInterface->pStateHeapInterface);

    return pStateHeapInterface->pStateHeapInterface->ReleaseStateHeapDyn(pStateHeap);
}

//!
//! \brief    Allocates the state heap interface internal parameters
//! \details  Internal MHW function to allocate all parameters needed for the
//!           state heap interface
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \param    MHW_STATE_HEAP_SETTINGS StateHeapSettings
//!           [in] Setting used to initialize the state heap interface
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_Create(
    PMHW_STATE_HEAP_INTERFACE   *ppStateHeapInterface,
    MHW_STATE_HEAP_SETTINGS     StateHeapSettings)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;
    MHW_CHK_NULL(ppStateHeapInterface);
    MHW_CHK_NULL(*ppStateHeapInterface);

    MHW_CHK_NULL((*ppStateHeapInterface)->pStateHeapInterface);

    MHW_CHK_STATUS((*ppStateHeapInterface)->pStateHeapInterface->InitializeInterface(
        StateHeapSettings));

finish:
    return eStatus;
}
//!
//! \brief    Destroys the state heap interface
//! \details  Internal MHW function to destroy the state heap interface
//! \param    PMHW_STATE_HEAP_INTERFACE pStateHeapInterface
//!           [in] State heap interface
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_Destroy(
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    if (pCommonStateHeapInterface)
    {
        if (pCommonStateHeapInterface->pStateHeapInterface)
        {
            MOS_Delete(pCommonStateHeapInterface->pStateHeapInterface);
        }
        MOS_FreeMemory(pCommonStateHeapInterface);
    }

    return eStatus;
}

//!
//! \brief    Initializes the state heap interface
//! \details  Internal MHW function to initialize all function pointers and some parameters
//! \param    PMHW_STATE_HEAP_INTERFACE* ppStateHeapInterface
//!           [in/out] Poitner to state heap interface pointer to be allocated
//! \param    PMOS_INTERFACE pOsInterface
//!           [in] OS interface
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if success, else fail reason
//!
MOS_STATUS Mhw_StateHeapInterface_InitInterface(
    PMHW_STATE_HEAP_INTERFACE   *ppCommonStateHeapInterface,
    PMOS_INTERFACE              pOsInterface,
    uint8_t                     bDynamicMode)
{
    PMHW_STATE_HEAP_INTERFACE   pCommonStateHeapInterface = nullptr;
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
    MhwInterfaces::CreateParams params;
    MhwInterfaces               *mhwInterfaces = nullptr;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(ppCommonStateHeapInterface);
    MHW_CHK_NULL(pOsInterface);

    pCommonStateHeapInterface =
        (PMHW_STATE_HEAP_INTERFACE)MOS_AllocAndZeroMemory(sizeof(MHW_STATE_HEAP_INTERFACE));
    MHW_CHK_NULL(pCommonStateHeapInterface);

    //Common Interfaces
    pCommonStateHeapInterface->pfnCreate                          = Mhw_StateHeapInterface_Create;
    pCommonStateHeapInterface->pfnDestroy                         = Mhw_StateHeapInterface_Destroy;
    pCommonStateHeapInterface->pfnLockStateHeap                   = Mhw_StateHeapInterface_LockStateHeap;
    pCommonStateHeapInterface->pfnUnlockStateHeap                 = Mhw_StateHeapInterface_UnlockStateHeap;
    pCommonStateHeapInterface->pfnAssignSpaceInStateHeap          = Mhw_StateHeapInterface_AssignSpaceInStateHeap;
    pCommonStateHeapInterface->pfnSubmitBlocks                    = Mhw_StateHeapInterface_SubmitBlocks;
    pCommonStateHeapInterface->pfnExtendStateHeap                 = Mhw_StateHeapInterface_ExtendStateHeap;
    pCommonStateHeapInterface->pfnUpdateGlobalCmdBufId            = Mhw_StateHeapInterface_UpdateGlobalCmdBufId;
    pCommonStateHeapInterface->pfnSetCmdBufStatusPtr              = Mhw_StateHeapInterface_SetCmdBufStatusPtr;
    pCommonStateHeapInterface->pfnRequestSshSpaceForCmdBuf        = Mhw_StateHeapInterface_RequestSshSpaceForCmdBuf;
    pCommonStateHeapInterface->pfnCalculateSshAndBtSizesRequested = Mhw_StateHeapInterface_CalculateSshAndBtSizesRequested;

    //Interfaces in dynamic mode
    pCommonStateHeapInterface->pfnCalculateDynamicSpaceNeeded     = Mhw_StateHeapInterface_DSH_CalculateSpaceNeeded;
    pCommonStateHeapInterface->pfnAllocateDynamicBlock            = Mhw_StateHeapInterface_DSH_AllocateDynamicBlock;
    pCommonStateHeapInterface->pfnSubmitDynamicBlock              = Mhw_StateHeapInterface_DSH_SubmitDynamicBlock;
    pCommonStateHeapInterface->pfnFreeDynamicBlock                = Mhw_StateHeapInterface_DSH_FreeDynamicBlock;
    pCommonStateHeapInterface->pfnRefreshDynamicHeap              = Mhw_StateHeapInterface_DSH_RefreshDynamicHeap;
    pCommonStateHeapInterface->pfnReleaseStateHeap                = Mhw_StateHeapInterface_DSH_ReleaseStateHeap;

    //Generic Interfaces
    pCommonStateHeapInterface->pfnSetInterfaceDescriptor      = Mhw_StateHeapInterface_SetInterfaceDescriptor;
    pCommonStateHeapInterface->pfnSetInterfaceDescriptorEntry = Mhw_StateHeapInterface_SetInterfaceDescriptorEntry;
    pCommonStateHeapInterface->pfnSetBindingTable             = Mhw_StateHeapInterface_SetBindingTable;
    pCommonStateHeapInterface->pfnSetSurfaceState             = Mhw_StateHeapInterface_SetSurfaceState;
    pCommonStateHeapInterface->pfnSetBindingTableEntry        = Mhw_StateHeapInterface_SetBindingTableEntry;
    pCommonStateHeapInterface->pfnSendBindingTableEntry       = Mhw_StateHeapInterface_SendBindingTableEntry;
    pCommonStateHeapInterface->pfnSetSurfaceStateEntry        = Mhw_StateHeapInterface_SetSurfaceStateEntry;
    pCommonStateHeapInterface->pfnInitSamplerStates           = Mhw_StateHeapInterface_InitSamplerStates;
    pCommonStateHeapInterface->pfnSetSamplerState             = Mhw_StateHeapInterface_SetSamplerState;

    MOS_ZeroMemory(&params, sizeof(params));
    params.Flags.m_stateHeap = true;
    params.m_heapMode = bDynamicMode;
    mhwInterfaces = MhwInterfaces::CreateFactory(params, pOsInterface);
    if (mhwInterfaces)
    {
        MHW_CHK_NULL(mhwInterfaces->m_stateHeapInterface);
        pCommonStateHeapInterface->pStateHeapInterface = mhwInterfaces->m_stateHeapInterface;
        // MhwInterfaces always create CP and MI interfaces, so we have to delete those we don't need.
        MOS_Delete(mhwInterfaces->m_miInterface);
        Delete_MhwCpInterface(mhwInterfaces->m_cpInterface);
        mhwInterfaces->m_cpInterface = NULL;
        MOS_Delete(mhwInterfaces);
    }
    else
    {
        MHW_ASSERTMESSAGE("Allocate MhwInterfaces failed");
        eStatus = MOS_STATUS_NO_SPACE;
        goto finish;
    }

    *ppCommonStateHeapInterface = pCommonStateHeapInterface;

finish:
    if (eStatus != MOS_STATUS_SUCCESS && pCommonStateHeapInterface)
    {
        pCommonStateHeapInterface->pfnDestroy(pCommonStateHeapInterface);
        *ppCommonStateHeapInterface = nullptr;
    }
    return eStatus;
}

XMHW_STATE_HEAP_INTERFACE::XMHW_STATE_HEAP_INTERFACE(
    PMOS_INTERFACE pInputOSInterface,
    int8_t         bDynamicMode):
    m_pWaTable(nullptr),
    m_pdwCmdBufIdGlobal(nullptr),
    m_dwCurrCmdBufId(0),
    m_pSyncTags(nullptr),
    m_dwCurrSyncTag(0),
    m_dwInvalidSyncTagId(0),
    m_bRegisteredBBCompleteNotifyEvent(false),
    m_pInstructionStateHeaps(nullptr),
    m_dwNumIsh(0),
    m_dwNumDsh(0),
    m_pDynamicStateHeaps(nullptr),
    m_bDynamicMode(bDynamicMode),
    m_pIshBlockManager(nullptr),
    m_pDshBlockManager(nullptr),
    m_pOsInterface(pInputOSInterface),
    m_wIdAlignment(0),
    m_wBtIdxAlignment(0),
    m_wCurbeAlignment(0),
    m_wSizeOfCmdSamplerState(0),
    m_dwMaxSurfaceStateSize(0),
    m_pfnAddResourceToCmd(nullptr),
    m_wSizeOfCmdInterfaceDescriptorData(0)
{
    MHW_FUNCTION_ENTER;

    MOS_ZeroMemory(&m_resCmdBufIdGlobal, sizeof(m_resCmdBufIdGlobal));
    MOS_ZeroMemory(&m_SurfaceStateHeap, sizeof(m_SurfaceStateHeap));
    MOS_ZeroMemory(&m_HwSizes, sizeof(m_HwSizes));
    MOS_ZeroMemory(&m_StateHeapSettings, sizeof(m_StateHeapSettings));
}

XMHW_STATE_HEAP_INTERFACE::~XMHW_STATE_HEAP_INTERFACE()
{
    MHW_FUNCTION_ENTER;

    if (m_bDynamicMode == MHW_DGSH_MODE)
    {
        // heap manager destructors called automatically
        return;
    }

    PMHW_STATE_HEAP              pStateHeapPtr, pStateHeapNext;
    PMHW_STATE_HEAP_MEMORY_BLOCK pMemBlkPtr, pMemBlkNext;

    //Release m_SyncTags
    MOS_FreeMemory(m_pSyncTags);

    // Destroy all memory block objects and block manager objects for ISH, DSH
    if(m_bDynamicMode == MHW_DSH_MODE)
    {
        MOS_Delete(m_pIshBlockManager);
        MOS_Delete(m_pDshBlockManager);
    }

    //Release m_resCmdBufIdGlobal
    if (m_pOsInterface != nullptr)
    {
        m_pOsInterface->pfnUnlockResource(m_pOsInterface, &m_resCmdBufIdGlobal);
        m_pOsInterface->pfnFreeResource(m_pOsInterface, &m_resCmdBufIdGlobal);
    }

    //Free ISH
    pStateHeapPtr = m_pInstructionStateHeaps;
    for (uint32_t i = 0; i < m_dwNumIsh; i++)
    {
        pStateHeapNext = pStateHeapPtr->pNext;
        if (m_pOsInterface != nullptr)
        {
            if (pStateHeapPtr->bKeepLocked)
            {
                pStateHeapPtr->bKeepLocked = false;
                UnLockStateHeap(pStateHeapPtr);
            }
            m_pOsInterface->pfnFreeResource(m_pOsInterface, &pStateHeapPtr->resHeap);
        }

        if(m_bDynamicMode == MHW_RENDER_HAL_MODE)
        {
            pMemBlkPtr = pStateHeapPtr->pMemoryHead;
            while (pMemBlkPtr)
            {
                pMemBlkNext = pMemBlkPtr->pNext;
                MOS_FreeMemory(pMemBlkPtr);
                pMemBlkPtr = pMemBlkNext;
            }
        }
        MOS_FreeMemory(pStateHeapPtr);
        pStateHeapPtr = pStateHeapNext;
    }

    // Free DSH
    pStateHeapPtr = m_pDynamicStateHeaps;
    for (uint32_t i = 0; i < m_dwNumDsh; i++)
    {
        if (pStateHeapPtr == nullptr)
        {
             break;
        }

        pStateHeapNext = pStateHeapPtr->pNext;
        if (m_pOsInterface != nullptr)
        {
            if (pStateHeapPtr->bKeepLocked)
            {
                pStateHeapPtr->bKeepLocked = false;
                UnLockStateHeap(pStateHeapPtr);
            }
            m_pOsInterface->pfnFreeResource(m_pOsInterface, &pStateHeapPtr->resHeap);
        }

        if(m_bDynamicMode == MHW_RENDER_HAL_MODE)
        {
            pMemBlkPtr = pStateHeapPtr->pMemoryHead;
            while (pMemBlkPtr)
            {
                pMemBlkNext = pMemBlkPtr->pNext;
                MOS_FreeMemory(pMemBlkPtr);
                pMemBlkPtr = pMemBlkNext;
            }
        }

        MOS_FreeMemory(pStateHeapPtr);
        pStateHeapPtr = pStateHeapNext;
    }

    return ;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::InitializeInterface(
    MHW_STATE_HEAP_SETTINGS StateHeapSettings)
{
    MOS_ALLOC_GFXRES_PARAMS     AllocParams;
    MOS_LOCK_PARAMS             LockParams;
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    //state heap settings
    m_StateHeapSettings = StateHeapSettings;

    MHW_CHK_NULL(m_pOsInterface);

    m_pWaTable  = m_pOsInterface->pfnGetWaTable(m_pOsInterface);

    if (m_pOsInterface->bUsesGfxAddress)
    {
        m_pfnAddResourceToCmd = Mhw_AddResourceToCmd_GfxAddress;
    }
    else if (m_pOsInterface->bUsesPatchList)
    {
        m_pfnAddResourceToCmd = Mhw_AddResourceToCmd_PatchList;
    }
    else
    {
        // No addressing method selected
        eStatus = MOS_STATUS_UNKNOWN;
        goto finish;
    }

    if (m_bDynamicMode == MHW_DGSH_MODE)
    {
        m_ishManager.RegisterOsInterface(m_pOsInterface);
        m_ishManager.SetDefaultBehavior(StateHeapSettings.m_ishBehavior);
        m_ishManager.SetInitialHeapSize(StateHeapSettings.dwIshSize);
        if (StateHeapSettings.m_ishBehavior == HeapManager::Behavior::extend ||
            StateHeapSettings.m_ishBehavior == HeapManager::Behavior::destructiveExtend ||
            StateHeapSettings.m_ishBehavior == HeapManager::Behavior::waitAndExtend)
        {
            m_ishManager.SetExtendHeapSize(StateHeapSettings.dwIshIncrement);
        }
        if (StateHeapSettings.m_keepIshLocked)
        {
            MHW_MI_CHK_STATUS(m_ishManager.LockHeapsOnAllocate());
        }

        m_dshManager.RegisterOsInterface(m_pOsInterface);
        m_dshManager.SetDefaultBehavior(StateHeapSettings.m_dshBehavior);
        m_dshManager.SetInitialHeapSize(StateHeapSettings.dwDshSize);
        if (StateHeapSettings.m_dshBehavior == HeapManager::Behavior::extend ||
            StateHeapSettings.m_dshBehavior == HeapManager::Behavior::destructiveExtend ||
            StateHeapSettings.m_dshBehavior == HeapManager::Behavior::waitAndExtend)
        {
            m_dshManager.SetExtendHeapSize(StateHeapSettings.dwDshIncrement);
        }
        if (StateHeapSettings.m_keepDshLocked)
        {
            MHW_MI_CHK_STATUS(m_dshManager.LockHeapsOnAllocate());
        }

        return MOS_STATUS_SUCCESS;
    }

    //Sync tags and sync tag id
    m_pSyncTags = (PMHW_SYNC_TAG)MOS_AllocAndZeroMemory(sizeof(MHW_SYNC_TAG) *
                        StateHeapSettings.dwNumSyncTags);
    MHW_CHK_NULL(m_pSyncTags);

    if(m_bDynamicMode == MHW_DSH_MODE)
    {
        m_dwInvalidSyncTagId = 0;

        //Allocate block manager for ISH
        m_pIshBlockManager = MOS_New(MHW_BLOCK_MANAGER, nullptr);
        MHW_CHK_NULL(m_pIshBlockManager);


    }
    else // m_bDynamicMode == MHW_RENDER_HAL_MODE
    {
        m_dwInvalidSyncTagId = StateHeapSettings.dwNumSyncTags;

        //Extend state heap for DSH
        MHW_CHK_STATUS(ExtendStateHeap(
            MHW_DSH_TYPE,
            StateHeapSettings.dwDshSize));
        if (StateHeapSettings.m_keepDshLocked)
        {
            MHW_CHK_STATUS(LockStateHeap(m_pDynamicStateHeaps));
            m_pDynamicStateHeaps->bKeepLocked = true;
        }
    }

    //Allocate resCmdBufIdGlobal
    MOS_ZeroMemory(&AllocParams, sizeof(AllocParams));
    AllocParams.Type = MOS_GFXRES_BUFFER;
    AllocParams.TileType = MOS_TILE_LINEAR;
    AllocParams.Format = Format_Buffer;
    AllocParams.dwBytes = MHW_CACHELINE_SIZE;
    AllocParams.pBufName = "CmdBufIdGlobal";
    MHW_CHK_STATUS(m_pOsInterface->pfnAllocateResource(
        m_pOsInterface,
        &AllocParams,
        &m_resCmdBufIdGlobal));
    m_dwCurrCmdBufId = 1;

    MOS_ZeroMemory(&LockParams, sizeof(LockParams));
    LockParams.WriteOnly = 1;
    m_pdwCmdBufIdGlobal = (uint32_t*)m_pOsInterface->pfnLockResource(
        m_pOsInterface,
        &m_resCmdBufIdGlobal,
        &LockParams);
    MHW_CHK_NULL(m_pdwCmdBufIdGlobal);
    MOS_ZeroMemory(m_pdwCmdBufIdGlobal, AllocParams.dwBytes);
    m_dwCurrCmdBufId = 1;

    //Extend state heap for ISH
    MHW_CHK_STATUS(ExtendStateHeap(
        MHW_ISH_TYPE,
        StateHeapSettings.dwIshSize));
    if (StateHeapSettings.m_keepIshLocked)
    {
        MHW_CHK_NULL(m_pInstructionStateHeaps);
        MHW_CHK_STATUS(LockStateHeap(m_pInstructionStateHeaps));
        m_pInstructionStateHeaps->bKeepLocked = true;
    }

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::InitMemoryBlock(
    PMHW_STATE_HEAP                 pStateHeap,
    PMHW_STATE_HEAP_MEMORY_BLOCK    *ppMemoryBlock,
    uint32_t                        dwRequestedSize,
    bool                            bStatic)
{
    PMHW_STATE_HEAP_MEMORY_BLOCK    pMemoryBlock;
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    MHW_CHK_NULL(ppMemoryBlock);

    if (dwRequestedSize > 0)
    {
        pMemoryBlock = (PMHW_STATE_HEAP_MEMORY_BLOCK)MOS_AllocAndZeroMemory(
                        sizeof(MHW_STATE_HEAP_MEMORY_BLOCK));
        MHW_CHK_NULL(pMemoryBlock);

        FrameTrackerTokenFlat_Invalidate(&pMemoryBlock->trackerToken);
        pMemoryBlock->dwBlockSize = dwRequestedSize;
        pMemoryBlock->pStateHeap = pStateHeap;
        pMemoryBlock->bStatic = bStatic;

        *ppMemoryBlock = pMemoryBlock;
    }

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::InsertMemoryBlock(
        PMHW_STATE_HEAP_MEMORY_BLOCK    pMemoryBlockFree,
        PMHW_STATE_HEAP_MEMORY_BLOCK    pMemoryBlockToAdd)
{
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    MHW_CHK_NULL(pMemoryBlockFree);
    MHW_CHK_NULL(pMemoryBlockToAdd);

    if (pMemoryBlockFree->dwBlockSize < pMemoryBlockToAdd->dwBlockSize)
    {
        MHW_ASSERTMESSAGE("Free block does not have enough space to contain new block.");
        eStatus = MOS_STATUS_NO_SPACE;
        goto finish;
    }

    pMemoryBlockFree->dwBlockSize -= pMemoryBlockToAdd->dwBlockSize;
    pMemoryBlockToAdd->dwOffsetInStateHeap =
        pMemoryBlockFree->dwOffsetInStateHeap + pMemoryBlockFree->dwBlockSize;

    MHW_CHK_STATUS(InsertLinkedList(
        pMemoryBlockFree,
        pMemoryBlockToAdd));

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::InsertLinkedList(
        PMHW_STATE_HEAP_MEMORY_BLOCK    pStartNode,
        PMHW_STATE_HEAP_MEMORY_BLOCK    pNodeToAdd)
{
    PMHW_STATE_HEAP_MEMORY_BLOCK    pStartNext;
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    MHW_CHK_NULL(pStartNode);
    MHW_CHK_NULL(pNodeToAdd);

    pStartNext = pStartNode->pNext;

    pStartNode->pNext = pNodeToAdd;
    pNodeToAdd->pPrev = pStartNode;
    pNodeToAdd->pNext = pStartNext;
    if (pStartNext)
    {
        pStartNext->pPrev = pNodeToAdd;
    }

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::ReturnSpaceMemoryBlock(
    PMHW_STATE_HEAP_MEMORY_BLOCK    pMemoryBlock)
{
    PMHW_STATE_HEAP_MEMORY_BLOCK    pPrevBlock, pNextBlock;
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    MHW_CHK_NULL(pMemoryBlock);

    if (pMemoryBlock->bStatic)
    {
        MHW_VERBOSEMESSAGE("Static blocks do not need to be cleaned up.");
        goto finish;
    }

    pPrevBlock = pMemoryBlock->pPrev;
    pNextBlock = pMemoryBlock->pNext;

    FrameTrackerTokenFlat_Invalidate(&pMemoryBlock->trackerToken);

    if (pPrevBlock && !pPrevBlock->bStatic)
    {
        if (!FrameTrackerTokenFlat_IsValid(&pPrevBlock->trackerToken))
        {
            pPrevBlock->dwBlockSize += pMemoryBlock->dwBlockSize;
            pPrevBlock->pNext = pNextBlock;
            if (pNextBlock)
            {
                pNextBlock->pPrev = pPrevBlock;
            }
            MOS_FreeMemory(pMemoryBlock);
            pMemoryBlock = pPrevBlock;
        }
    }

    if (pNextBlock && !pNextBlock->bStatic)
    {
        if (!FrameTrackerTokenFlat_IsValid(&pNextBlock->trackerToken))
        {
            pMemoryBlock->dwBlockSize += pNextBlock->dwBlockSize;
            pMemoryBlock->pNext = pNextBlock->pNext;
            if (pNextBlock->pNext)
            {
                pNextBlock->pNext->pPrev = pMemoryBlock;
            }
            MOS_FreeMemory(pNextBlock);
        }
    }

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::AssignSpaceInStateHeap(
    MHW_STATE_HEAP_TYPE         StateHeapType,
    PMHW_KERNEL_STATE           pKernelState,
    uint32_t                    dwSpaceRequested,
    bool                        bStatic,
    bool                        bZeroAssignedMem)
{
    MHW_FUNCTION_ENTER;

    MHW_MI_CHK_NULL(pKernelState);

    HeapManager *heapManager = nullptr;
    MemoryBlock *requestedBlock = nullptr;
    if (StateHeapType == MHW_ISH_TYPE)
    {
        heapManager = &m_ishManager;
        requestedBlock = &pKernelState->m_ishRegion;
    }
    else if (StateHeapType == MHW_DSH_TYPE)
    {
        heapManager = &m_dshManager;
        requestedBlock = &pKernelState->m_dshRegion;
    }
    else if (StateHeapType == MHW_SSH_TYPE)
    {
        pKernelState->dwSshOffset = m_SurfaceStateHeap.dwCurrOffset;
        m_SurfaceStateHeap.dwCurrOffset += pKernelState->dwSshSize;
        if (m_SurfaceStateHeap.dwCurrOffset > m_SurfaceStateHeap.dwSize)
        {
            MHW_ASSERTMESSAGE("Insufficient space requested for SSH");
            return MOS_STATUS_NO_SPACE;
        }
        return MOS_STATUS_SUCCESS;
    }
    else
    {
        MHW_ASSERTMESSAGE("Unsupported state heap type.");
        return MOS_STATUS_INVALID_PARAMETER;
    }
    MHW_MI_CHK_NULL(heapManager);

    uint32_t spaceNeeded = 0;
    MemoryBlockManager::AcquireParams acquireParams =
        MemoryBlockManager::AcquireParams(pKernelState->m_currTrackerId, m_blockSizes);
    acquireParams.m_staticBlock = bStatic ? true : false;
    if (m_blockSizes.empty())
    {
        m_blockSizes.emplace_back(dwSpaceRequested);
    }
    else
    {
        m_blockSizes[0] = dwSpaceRequested;
    }

    MHW_MI_CHK_STATUS(heapManager->AcquireSpace(
        acquireParams,
        m_blocks,
        spaceNeeded));

    if (m_blocks.empty())
    {
        MHW_ASSERTMESSAGE("No blocks were acquired");
        return MOS_STATUS_UNKNOWN;
    }
    if (!m_blocks[0].IsValid())
    {
        MHW_ASSERTMESSAGE("No blocks were acquired");
        return MOS_STATUS_UNKNOWN;
    }

    *requestedBlock = m_blocks[0];

    if (bZeroAssignedMem)
    {
        requestedBlock->AddData(nullptr, 0, 0, true);
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::SubmitBlocks(PMHW_KERNEL_STATE pKernelState)
{
    MHW_MI_CHK_NULL(pKernelState);
    if (!pKernelState->m_ishRegion.IsStatic())
    {
        std::vector<MemoryBlock> block;
        block.push_back(pKernelState->m_ishRegion);
        MHW_MI_CHK_STATUS(m_ishManager.SubmitBlocks(block));
    }
    if (!pKernelState->m_dshRegion.IsStatic())
    {
        std::vector<MemoryBlock> block;
        block.push_back(pKernelState->m_dshRegion);
        MHW_MI_CHK_STATUS(m_dshManager.SubmitBlocks(block));
    }

    pKernelState->m_currTrackerId = MemoryBlock::m_invalidTrackerId;

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::LockStateHeap(
    PMHW_STATE_HEAP             pStateHeap)
{
    PMOS_INTERFACE  pOsInterface = nullptr;
    MOS_LOCK_PARAMS LockParams;
    MOS_STATUS      eStatus = MOS_STATUS_SUCCESS;

    MHW_CHK_NULL(pStateHeap);

    if (pStateHeap->bKeepLocked)
    {
        MHW_CHK_NULL(pStateHeap->pvLockedHeap);
        goto finish;
    }

    pOsInterface = m_pOsInterface;

    MOS_ZeroMemory(&LockParams, sizeof(LockParams));
    LockParams.WriteOnly = 1;
    LockParams.NoOverWrite = 1;
    LockParams.Uncached = 1;
    pStateHeap->pvLockedHeap =
        pOsInterface->pfnLockResource(pOsInterface, &pStateHeap->resHeap, &LockParams);
    MHW_CHK_NULL(pStateHeap->pvLockedHeap);

finish:
    return eStatus;
}

MOS_STATUS  XMHW_STATE_HEAP_INTERFACE::UnLockStateHeap(
    PMHW_STATE_HEAP             pStateHeap)
{
    MOS_STATUS      eStatus = MOS_STATUS_SUCCESS;

    MHW_CHK_NULL(pStateHeap);

    if (pStateHeap->bKeepLocked)
    {
        MHW_CHK_NULL(pStateHeap->pvLockedHeap);
        goto finish;
    }

    MHW_CHK_STATUS(m_pOsInterface->pfnUnlockResource(m_pOsInterface, &pStateHeap->resHeap));

    pStateHeap->pvLockedHeap = nullptr;

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::ExtendStateHeap(
    MHW_STATE_HEAP_TYPE         StateHeapType,
    uint32_t                    dwSizeRequested)
{
    if (m_bDynamicMode == MHW_DSH_MODE)
    {
        return ExtendStateHeapDyn(StateHeapType,dwSizeRequested);
    }
    else if (m_bDynamicMode == MHW_RENDER_HAL_MODE)
    {
        return ExtendStateHeapSta(StateHeapType,dwSizeRequested);
    }
    else
    {
        return MOS_STATUS_UNKNOWN;
    }
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::UpdateGlobalCmdBufId()
{
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    m_SurfaceStateHeap.dwCurrOffset = 0;

    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::SetCmdBufStatusPtr(void *pvCmdBufStatus)
{
    MHW_FUNCTION_ENTER;
    MHW_MI_CHK_NULL(pvCmdBufStatus);
    m_pdwCmdBufIdGlobal = (uint32_t*)pvCmdBufStatus;
    MHW_MI_CHK_STATUS(m_ishManager.RegisterTrackerResource((uint32_t*)m_pdwCmdBufIdGlobal));
    MHW_MI_CHK_STATUS(m_dshManager.RegisterTrackerResource((uint32_t*)m_pdwCmdBufIdGlobal));
    return MOS_STATUS_SUCCESS;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::RequestSshSpaceForCmdBuf(
    uint32_t                    dwBtEntriesRequested)
{
    PMOS_INTERFACE      pOsInterface;
    PMHW_STATE_HEAP     pStateHeap;
    MOS_COMMAND_BUFFER  CmdBuffer;
    uint32_t            dwRequestedSshSize = 0, dwBtSize = 0;
    uint32_t            uiExistingSshSize = 0, uiExistingSshOffset = 0;
    MOS_STATUS          eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    pOsInterface    = m_pOsInterface;
    pStateHeap      = &m_SurfaceStateHeap;
    MHW_CHK_NULL(pOsInterface);
    MHW_CHK_NULL(pStateHeap);

    MHW_CHK_STATUS(pOsInterface->pfnGetIndirectState(
        pOsInterface,
        &uiExistingSshOffset,
        &uiExistingSshSize));
    pStateHeap->dwSize = (uint32_t)uiExistingSshSize;

    dwBtSize =
        MOS_ALIGN_CEIL(dwBtEntriesRequested, m_wBtIdxAlignment);
    MHW_CHK_STATUS(CalculateSshAndBtSizesRequested(
        dwBtEntriesRequested,
        &dwRequestedSshSize,
        &dwBtSize));
    dwRequestedSshSize = MOS_ALIGN_CEIL(dwRequestedSshSize, (1 << MHW_SSH_BASE_SHIFT));

    if (dwRequestedSshSize > pStateHeap->dwSize)
    {
        MHW_CHK_STATUS(pOsInterface->pfnSetIndirectStateSize(
            pOsInterface,
            (uint32_t)dwRequestedSshSize));
        MOS_ZeroMemory(&CmdBuffer, sizeof(CmdBuffer));
        MHW_CHK_STATUS(pOsInterface->pfnGetCommandBuffer(pOsInterface, &CmdBuffer, 0));
        MHW_CHK_STATUS(pOsInterface->pfnResetCommandBuffer(pOsInterface, &CmdBuffer));
        pOsInterface->pfnReturnCommandBuffer(pOsInterface, &CmdBuffer, 0);
        pOsInterface->pfnResetOsStates(pOsInterface);

        m_SurfaceStateHeap.dwSize = dwRequestedSshSize;
    }

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::ExtendStateHeapDyn(
        MHW_STATE_HEAP_TYPE         StateHeapType,
        uint32_t                    dwSizeRequested)
{
    PMHW_STATE_HEAP             pNewStateHeap = nullptr;
    PMHW_STATE_HEAP            *ppStateHeapPtr;
    MOS_ALLOC_GFXRES_PARAMS     AllocParams;
    uint32_t                    dwNumHeaps;
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
    PMHW_BLOCK_MANAGER          pBlockManager = nullptr;
    MEDIA_FEATURE_TABLE        *skuTable = nullptr;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(m_pOsInterface);
    MHW_CHK_NULL(m_pOsInterface->pfnGetSkuTable);

    skuTable = m_pOsInterface->pfnGetSkuTable(m_pOsInterface);
    MHW_CHK_NULL(skuTable);

    pNewStateHeap = (PMHW_STATE_HEAP)MOS_AllocAndZeroMemory(sizeof(MHW_STATE_HEAP));
    MHW_CHK_NULL(pNewStateHeap);

    pNewStateHeap->dwSize = MOS_ALIGN_CEIL(dwSizeRequested, MHW_CACHELINE_SIZE);
    pNewStateHeap->dwUsed = 0;
    pNewStateHeap->dwFree = pNewStateHeap->dwSize;

    pNewStateHeap->pMhwStateHeapInterface = this;

    MOS_ZeroMemory(&AllocParams, sizeof(AllocParams));
    AllocParams.Type      = MOS_GFXRES_BUFFER;
    AllocParams.TileType  = MOS_TILE_LINEAR;
    AllocParams.Format    = Format_Buffer;
    AllocParams.dwBytes   = pNewStateHeap->dwSize;
    AllocParams.pBufName  = "DynamicStateHeap";
    if (MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar))
    {
        AllocParams.dwMemType = MOS_MEMPOOL_SYSTEMMEMORY;
    }

    MHW_CHK_STATUS(m_pOsInterface->pfnAllocateResource(
        m_pOsInterface,
        &AllocParams,
        &pNewStateHeap->resHeap));

    // RegisterResource will be called in AddResourceToHWCmd. It is not allowed to be called by hal explicitly for Async mode
    if (MosInterface::IsAsyncDevice(m_pOsInterface->osStreamState) == false)
    {
        MHW_CHK_STATUS(m_pOsInterface->pfnRegisterResource(m_pOsInterface, &pNewStateHeap->resHeap, true, true));
    }

    if (StateHeapType == MHW_ISH_TYPE)
    {
        if (m_StateHeapSettings.m_keepIshLocked)
        {
            MHW_CHK_STATUS(LockStateHeap(pNewStateHeap));
            pNewStateHeap->bKeepLocked = true;
        }

        ppStateHeapPtr = &m_pInstructionStateHeaps;
        dwNumHeaps     = m_dwNumIsh++;
        pBlockManager  = m_pIshBlockManager;
    }
    else
    {
        if (m_StateHeapSettings.m_keepDshLocked)
        {
            MHW_CHK_STATUS(LockStateHeap(pNewStateHeap));
            pNewStateHeap->bKeepLocked = true;
        }

        ppStateHeapPtr = &m_pDynamicStateHeaps;
        dwNumHeaps     = m_dwNumDsh++;
        pBlockManager  = m_pDshBlockManager;
    }

    pNewStateHeap->pNext = *ppStateHeapPtr;
    *ppStateHeapPtr = pNewStateHeap;
    if (pNewStateHeap->pNext) pNewStateHeap->pNext->pPrev = pNewStateHeap;

    pBlockManager->SetStateHeap(pNewStateHeap);

    // Register new state heap with block manager
    pBlockManager->RegisterStateHeap(pNewStateHeap);

finish:
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        if (pNewStateHeap)
        {
            if (m_pOsInterface)
            {
                m_pOsInterface->pfnFreeResource(m_pOsInterface, &pNewStateHeap->resHeap);
            }

            MOS_FreeMemory(pNewStateHeap);
        }
    }

    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::ExtendStateHeapSta(
        MHW_STATE_HEAP_TYPE         StateHeapType,
        uint32_t                    dwSizeRequested)
{
    PMOS_INTERFACE              pOsInterface = nullptr;
    PMHW_STATE_HEAP             pNewStateHeap = nullptr, pPrevStateHeap, *ppStateHeapPtr;
    MOS_ALLOC_GFXRES_PARAMS     AllocParams;
    uint32_t                    i, dwNumHeaps;
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
    MEDIA_FEATURE_TABLE         *skuTable = nullptr;

    MHW_FUNCTION_ENTER;

    pOsInterface = m_pOsInterface;
    MHW_CHK_NULL(pOsInterface);
    MHW_CHK_NULL(pOsInterface->pfnGetSkuTable);

    skuTable = pOsInterface->pfnGetSkuTable(pOsInterface);
    MHW_CHK_NULL(skuTable);

    pNewStateHeap = (PMHW_STATE_HEAP)MOS_AllocAndZeroMemory(sizeof(MHW_STATE_HEAP));
    MHW_CHK_NULL(pNewStateHeap);

    pNewStateHeap->dwSize = MOS_ALIGN_CEIL(dwSizeRequested, MHW_CACHELINE_SIZE);
    MOS_ZeroMemory(&AllocParams, sizeof(AllocParams));
    AllocParams.Type = MOS_GFXRES_BUFFER;
    AllocParams.TileType = MOS_TILE_LINEAR;
    AllocParams.Format = Format_Buffer;
    AllocParams.dwBytes = pNewStateHeap->dwSize;
    AllocParams.pBufName = "StateHeap";

    if (MEDIA_IS_SKU(skuTable, FtrLimitedLMemBar))
    {
        AllocParams.dwMemType = MOS_MEMPOOL_SYSTEMMEMORY;
    }

    MHW_CHK_STATUS(pOsInterface->pfnAllocateResource(
        pOsInterface,
        &AllocParams,
        &pNewStateHeap->resHeap));

    MHW_CHK_STATUS(InitMemoryBlock(
        pNewStateHeap,
        &pNewStateHeap->pMemoryHead,
        pNewStateHeap->dwSize,
        false));

    if (StateHeapType == MHW_ISH_TYPE)
    {
        ppStateHeapPtr = &m_pInstructionStateHeaps;
        dwNumHeaps = m_dwNumIsh++;
    }
    else
    {
        ppStateHeapPtr = &m_pDynamicStateHeaps;
        dwNumHeaps = m_dwNumDsh++;
    }
    MHW_CHK_NULL(ppStateHeapPtr);
    pPrevStateHeap = nullptr;
    for (i = 0; i < dwNumHeaps; i++)
    {
        pPrevStateHeap = *ppStateHeapPtr;
        ppStateHeapPtr = &(*ppStateHeapPtr)->pNext;
    }

    *ppStateHeapPtr = pNewStateHeap;
    pNewStateHeap->pPrev = pPrevStateHeap;

finish:
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        if (pNewStateHeap)
        {
            MOS_FreeMemAndSetNull(pNewStateHeap->pMemoryHead);
            if (pOsInterface)
            {
                pOsInterface->pfnFreeResource(pOsInterface, &pNewStateHeap->resHeap);
            }
            MOS_FreeMemory(pNewStateHeap);
        }
    }

    return eStatus;
}

uint32_t XMHW_STATE_HEAP_INTERFACE::CalculateSpaceNeededDyn(
    MHW_STATE_HEAP_TYPE                  StateHeapType,
    PMHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS pParams)
{

    PMHW_STATE_HEAP                 pStateHeap;
    PMHW_BLOCK_MANAGER              pBlockManager = nullptr;
    uint32_t                        dwNeeded = 0;
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pParams);
    MHW_CHK_NULL(pParams->piSizes);

    if (pParams->iCount <= 0)
    {
        goto finish;
    }

    if (StateHeapType == MHW_ISH_TYPE)
    {
        MHW_CHK_NULL(m_pInstructionStateHeaps);
        pStateHeap = m_pInstructionStateHeaps;
        pBlockManager = m_pIshBlockManager;
    }
    else if (StateHeapType == MHW_DSH_TYPE)
    {
        MHW_CHK_NULL(m_pDynamicStateHeaps);
        pStateHeap = m_pDynamicStateHeaps;
        pBlockManager = m_pDshBlockManager;
    }
    else
    {
        MHW_ASSERTMESSAGE("Unsupported state heap type.");
        eStatus = MOS_STATUS_INVALID_PARAMETER;
        goto finish;
    }

    // Allocate simple block
    MHW_CHK_NULL(pBlockManager);
    dwNeeded = pBlockManager->CalculateSpaceNeeded((uint32_t*)pParams->piSizes, pParams->iCount,
                                                   pParams->dwAlignment, pParams->bHeapAffinity, pParams->pHeapAffinity);

finish:
    return dwNeeded;

}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::CalculateSshAndBtSizesRequested(
        uint32_t                    dwBtEntriesRequested,
        uint32_t                    *pdwSshSize,
        uint32_t                    *pdwBtSize)
{
    MOS_STATUS  eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pdwSshSize);
    MHW_CHK_NULL(pdwBtSize);

    dwBtEntriesRequested =
        MOS_ALIGN_CEIL(dwBtEntriesRequested, m_wBtIdxAlignment);
    *pdwBtSize  = dwBtEntriesRequested * m_HwSizes.dwSizeBindingTableState;
    *pdwSshSize =
        (*pdwBtSize) + (dwBtEntriesRequested * m_dwMaxSurfaceStateSize);

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::ReleaseStateHeapDyn(
    PMHW_STATE_HEAP pStateHeap)
{
    PMHW_STATE_HEAP pFirstHeap;
    MOS_STATUS      eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pStateHeap);
    MHW_CHK_NULL(pStateHeap->pBlockManager);

    // Mark state heap for deletion (so size is not accounted for)
    pStateHeap->bDeleted = true;

    // Mark blocks for deletion, release heap when all blocks are released
    eStatus = pStateHeap->pBlockManager->UnregisterStateHeap(pStateHeap);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        // The only reason for this condition is in case some blocks are still in submitted state
        // The block manager will call this function from within when the last block is released
        // In the meantime, this heap will not contain any free blocks for allocation
        eStatus = MOS_STATUS_SUCCESS;
        goto finish;
    }

    // Find first heap of the chain (so we can figure out if its DSH or ISH!)
    for (pFirstHeap = pStateHeap; pFirstHeap->pPrev != nullptr; pFirstHeap = pFirstHeap->pPrev) ;

    // Detach heap from chain
    if (pStateHeap->pPrev)
    {
        pStateHeap->pPrev->pNext = pStateHeap->pNext;
    }

    if (pStateHeap->pNext)
    {
        pStateHeap->pNext->pPrev = pStateHeap->pPrev;
    }

    // Update heaps
    if (pFirstHeap == m_pDynamicStateHeaps)
    {
        m_dwNumDsh--;
        if (pStateHeap == m_pDynamicStateHeaps)
        {
            m_pDynamicStateHeaps           = pStateHeap->pNext;
            m_pDshBlockManager->SetStateHeap(pStateHeap->pNext);
        }
    }
    else if (pFirstHeap == m_pInstructionStateHeaps)
    {
        m_dwNumIsh--;
        if (pStateHeap == m_pInstructionStateHeaps)
        {
            m_pInstructionStateHeaps       = pStateHeap->pNext;
            m_pIshBlockManager->SetStateHeap(pStateHeap->pNext);
        }
    }

    // Unlock heap
    if (pStateHeap->bKeepLocked)
    {
        pStateHeap->bKeepLocked = false;
        UnLockStateHeap(pStateHeap);
    }

    // Free OS resource
    MHW_CHK_NULL(m_pOsInterface);
    m_pOsInterface->pfnFreeResource(m_pOsInterface, &pStateHeap->resHeap);

    // Free MHW State Heap structure
    MOS_FreeMemory(pStateHeap);

finish:
    return eStatus;
}

PMHW_STATE_HEAP_MEMORY_BLOCK  XMHW_STATE_HEAP_INTERFACE::AllocateDynamicBlockDyn(
        MHW_STATE_HEAP_TYPE                  StateHeapType,
        PMHW_STATE_HEAP_DYNAMIC_ALLOC_PARAMS pParams)
{
    PMHW_STATE_HEAP                *ppStateHeap;
    PMHW_BLOCK_MANAGER              pBlockManager = nullptr;
    PMHW_STATE_HEAP_MEMORY_BLOCK    pMemoryBlock = nullptr;
    PMHW_STATE_HEAP_MEMORY_BLOCK    pAuxBlock;
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;
    uint32_t                        dwMinSize, dwIncrement, dwMaxSize;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pParams);
    MHW_CHK_NULL(pParams->piSizes);
    MHW_ASSERT(pParams->iCount > 0);

    if (StateHeapType == MHW_ISH_TYPE)
    {
        ppStateHeap   = &m_pInstructionStateHeaps;
        pBlockManager = m_pIshBlockManager;
        dwMinSize     = m_StateHeapSettings.dwIshSize;
        dwIncrement   = m_StateHeapSettings.dwIshIncrement;
        dwMaxSize     = m_StateHeapSettings.dwIshMaxSize;
    }
    else if (StateHeapType == MHW_DSH_TYPE)
    {
        ppStateHeap   = &m_pDynamicStateHeaps;
        pBlockManager = m_pDshBlockManager;
        dwMinSize     = m_StateHeapSettings.dwDshSize;
        dwIncrement   = m_StateHeapSettings.dwDshIncrement;
        dwMaxSize     = m_StateHeapSettings.dwDshMaxSize;
    }
    else
    {
        MHW_ASSERTMESSAGE("Unsupported state heap type.");
        eStatus = MOS_STATUS_INVALID_PARAMETER;
        goto finish;
    }

    do
    {
        // Allocate simple block
        MHW_CHK_NULL(pBlockManager);
        if (pParams->iCount == 1)
        {
            if (pParams->dwScratchSpace == 0 )
            {
                pMemoryBlock = pBlockManager->AllocateBlock((uint32_t)pParams->piSizes[0],
                                                         pParams->dwAlignment,
                                                         pParams->pHeapAffinity);
            }
            else
            {
                pMemoryBlock = pBlockManager->AllocateWithScratchSpace(
                                                         (uint32_t)pParams->piSizes[0],
                                                         pParams->dwAlignment,
                                                         pParams->dwScratchSpace);
            }

            if (pMemoryBlock)
            {
                pParams->pScratchSpace  = pMemoryBlock->pStateHeap->pScratchSpace;
                pParams->dwScratchSpace = pMemoryBlock->pStateHeap->dwScratchSpace;
            }
        }
        else
        {
            pMemoryBlock = pBlockManager->AllocateMultiple( (uint32_t*)pParams->piSizes,
                                                             pParams->iCount,
                                                             pParams->dwAlignment,
                                                             pParams->bHeapAffinity,
                                                             pParams->pHeapAffinity);
        }

        // Allocation failed
        if (!pMemoryBlock)
        {
            uint32_t dwTotalSize = 0;

            // Do not allow heap to grow automatically
            // Note: Caller may try to clean up the heap, wait or implement a different heap expansion logic
            if (!pParams->bGrow)
            {
                break;
            }

            // Calculate size of all heaps (do not account heaps already being removed)
            for (PMHW_STATE_HEAP pStateHeap = *ppStateHeap; pStateHeap; pStateHeap = pStateHeap->pNext)
            {
                if (!pStateHeap->bDeleted)
                {
                    dwTotalSize += pStateHeap->dwSize;
                }
            }

            // Did not reach heap size limit - calculate increment to fit all allocations + scratch space (if GSH)
            uint32_t dwExtendSize = 0;
            if (dwTotalSize < dwMaxSize)
            {
                for (int32_t i = 0; i < pParams->iCount; i++)
                {
                    dwExtendSize += MOS_ALIGN_CEIL(pParams->piSizes[i], pParams->dwAlignment);
                }
                dwExtendSize = MOS_ALIGN_CEIL(dwExtendSize, dwIncrement);
                dwExtendSize = MOS_ALIGN_CEIL(dwExtendSize + pParams->dwScratchSpace, dwIncrement);
                dwExtendSize = MOS_MAX(dwExtendSize, dwMinSize);

                ExtendStateHeap(StateHeapType, dwExtendSize);
            }
            else
            {
                break;
            }
        }
    } while (pMemoryBlock == nullptr);

    // Zero memory blocks
    pAuxBlock = pMemoryBlock;
    for (int32_t i = pParams->iCount; (pAuxBlock != nullptr) && (i > 0);  i--, pAuxBlock = pAuxBlock->pNext)
    {
        // Set block static flag
        pAuxBlock->bStatic = pParams->bStatic;

        // Erase block contents
        if (pParams->bZeroAssignedMem)
        {
            MHW_CHK_STATUS(LockStateHeap(pAuxBlock->pStateHeap));
            MOS_ZeroMemory(pAuxBlock->pDataPtr - pAuxBlock->dwAlignment, pAuxBlock->dwBlockSize);
            MHW_CHK_STATUS(UnLockStateHeap(pAuxBlock->pStateHeap));
        }
    }

finish:
    // Failed - release memory blocks back to "Free" queue
    if (eStatus != MOS_STATUS_SUCCESS && pBlockManager != nullptr)
    {
        // Something went wrong - release blocks if already allocated
        for (; pMemoryBlock != nullptr; pMemoryBlock = pAuxBlock)
        {
            pAuxBlock = pMemoryBlock->pNext;            // Get next block (must be done before Mhw_BlockManager_Free)
            pBlockManager->FreeBlock(pMemoryBlock);  // Release block back to "Free" queue
        }
    }

    return pMemoryBlock;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::SubmitDynamicBlockDyn(
        MHW_STATE_HEAP_TYPE                  StateHeapType,
        PMHW_STATE_HEAP_MEMORY_BLOCK         pBlock,
        const FrameTrackerTokenFlat          *trakcerToken)
{
    PMHW_BLOCK_MANAGER  pBlockManager = nullptr;
    MOS_STATUS          eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pBlock);

    if (StateHeapType == MHW_ISH_TYPE)
    {
        pBlockManager = m_pIshBlockManager;
    }
    else if (StateHeapType == MHW_DSH_TYPE)
    {
        pBlockManager = m_pDshBlockManager;
    }
    else
    {
        MHW_ASSERTMESSAGE("Unsupported state heap type.");
        eStatus = MOS_STATUS_INVALID_PARAMETER;
        goto finish;
    }

    // Submit block
    MHW_CHK_NULL(pBlockManager);
    MHW_CHK_STATUS(pBlockManager->SubmitBlock(pBlock, trakcerToken));

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::FreeDynamicBlockDyn(
        MHW_STATE_HEAP_TYPE                  StateHeapType,
        PMHW_STATE_HEAP_MEMORY_BLOCK         pBlock)
{
    PMHW_BLOCK_MANAGER  pBlockManager = nullptr;
    MOS_STATUS          eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    MHW_CHK_NULL(pBlock);

    if (StateHeapType == MHW_ISH_TYPE)
    {
        pBlockManager = m_pIshBlockManager;
    }
    else if (StateHeapType == MHW_DSH_TYPE)
    {
        pBlockManager = m_pDshBlockManager;
    }
    else
    {
        MHW_ASSERTMESSAGE("Unsupported state heap type.");
        eStatus = MOS_STATUS_INVALID_PARAMETER;
        goto finish;
    }

    // Free block
    MHW_CHK_STATUS(pBlockManager->FreeBlock(pBlock));

finish:
    return eStatus;
}

MOS_STATUS XMHW_STATE_HEAP_INTERFACE::RefreshDynamicHeapDyn (
    MHW_STATE_HEAP_TYPE         StateHeapType)
{
    PMHW_BLOCK_MANAGER  pBlockManager = nullptr;
    MOS_STATUS          eStatus = MOS_STATUS_SUCCESS;

    MHW_FUNCTION_ENTER;

    if (StateHeapType == MHW_ISH_TYPE)
    {
        pBlockManager = m_pIshBlockManager;
    }
    else if (StateHeapType == MHW_DSH_TYPE)
    {
        pBlockManager = m_pDshBlockManager;
    }
    else
    {
        MHW_ASSERTMESSAGE("Unsupported state heap type.");
        eStatus = MOS_STATUS_INVALID_PARAMETER;
        goto finish;
    }

    // Free block
    MHW_CHK_NULL(pBlockManager)
    MHW_CHK_STATUS(pBlockManager->Refresh());

finish:
    return eStatus;
}

