[MOS] Destroy compute gpu context in cmd queue destroy

Destroy cm queue gpu compute context to avoid memory growth.
diff --git a/media_driver/agnostic/common/cm/cm_queue_rt.cpp b/media_driver/agnostic/common/cm/cm_queue_rt.cpp
index 843d1cd..47da4da 100644
--- a/media_driver/agnostic/common/cm/cm_queue_rt.cpp
+++ b/media_driver/agnostic/common/cm/cm_queue_rt.cpp
@@ -118,6 +118,9 @@
     }
 
     uint32_t result = queue->CleanQueue();
+
+    queue->DestroyComputeGpuContext();
+
     CmSafeDelete( queue );
 
     return result;
@@ -4074,6 +4077,30 @@
     return status;
 }
 
+MOS_STATUS  CmQueueRT::DestroyComputeGpuContext()
+{
+    MOS_STATUS          status      = MOS_STATUS_SUCCESS;
+    PCM_CONTEXT_DATA    cmCtxData   = nullptr;
+    PCM_HAL_STATE       cmHalState  = nullptr;
+
+    if (MOS_GPU_CONTEXT_INVALID_HANDLE == m_gpuContextHandle)
+    {
+        return MOS_STATUS_SUCCESS;
+    }
+
+    cmCtxData   = (PCM_CONTEXT_DATA)m_device->GetAccelData();
+    if(!cmCtxData || !cmCtxData->cmHalState || !cmCtxData->cmHalState->osInterface)
+    {
+        return MOS_STATUS_INVALID_PARAMETER;
+    }
+
+    cmHalState = cmCtxData->cmHalState;
+
+    status =  cmHalState->osInterface->pfnDestroyGpuComputeContext(cmHalState->osInterface, m_gpuContextHandle);
+
+    return status;
+}
+
 MOS_STATUS CmQueueRT::ExecuteGroupTask(CM_HAL_STATE *halState,
                                        CM_HAL_EXEC_TASK_GROUP_PARAM *taskParam,
                                        MOS_GPU_CONTEXT gpuContextName)
diff --git a/media_driver/agnostic/common/cm/cm_queue_rt.h b/media_driver/agnostic/common/cm/cm_queue_rt.h
index 6066319..e56e3d2 100644
--- a/media_driver/agnostic/common/cm/cm_queue_rt.h
+++ b/media_driver/agnostic/common/cm/cm_queue_rt.h
@@ -376,6 +376,11 @@
                                 MOS_GPUCTX_CREATOPTIONS *createOptions);
 
     //--------------------------------------------------------------------------------
+    // Destroy compute GPU context
+    //--------------------------------------------------------------------------------
+    MOS_STATUS DestroyComputeGpuContext();
+
+    //--------------------------------------------------------------------------------
     // Calls CM HAL API to submit a group task to command buffer.
     //--------------------------------------------------------------------------------
     MOS_STATUS ExecuteGroupTask(CM_HAL_STATE *halState,
diff --git a/media_driver/agnostic/common/os/mos_interface.h b/media_driver/agnostic/common/os/mos_interface.h
index bf5a15d..9aa8020 100644
--- a/media_driver/agnostic/common/os/mos_interface.h
+++ b/media_driver/agnostic/common/os/mos_interface.h
@@ -410,6 +410,20 @@
         GPU_CONTEXT_HANDLE gpuContextHandle);
 
     //!
+    //! \brief   Get GpuContext
+    //! \details MOS internal toolset func to get GPU context instance
+    //!
+    //! \param    [in] streamState
+    //!           Handle of Os Stream State
+    //! \param    [in] gpuContext
+    //!           MOS GPU Context handle
+    //!
+    //! \return   GpuContextSpecificNext
+    //!           GPU Context instance got by GPU context handle, nullptr if get failed
+    //!
+    static GpuContextSpecificNext *GetGpuContext(MOS_STREAM_HANDLE streamState, GPU_CONTEXT_HANDLE handle);
+
+    //!
     //! \brief    Add Command
     //! \details  [Cmd Buffer Interface] Add gpu commands into cmd buffer
     //! \details  Caller: MHW only
@@ -1860,20 +1874,6 @@
         MOS_STREAM_HANDLE streamState,
         COMMAND_BUFFER_HANDLE cmdBuffer);
 
-    //!
-    //! \brief   Get GpuContext
-    //! \details MOS internal toolset func to get GPU context instance
-    //!
-    //! \param    [in] streamState
-    //!           Handle of Os Stream State
-    //! \param    [in] gpuContext
-    //!           MOS GPU Context handle
-    //!
-    //! \return   GpuContextSpecificNext
-    //!           GPU Context instance got by GPU context handle, nullptr if get failed
-    //!
-    static GpuContextSpecificNext *GetGpuContext(MOS_STREAM_HANDLE streamState, GPU_CONTEXT_HANDLE handle);
-
 #if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
     //! \brief    Unified dump command buffer initialization
     //! \details  check if dump command buffer was enabled and create the output directory
diff --git a/media_driver/agnostic/common/os/mos_os.h b/media_driver/agnostic/common/os/mos_os.h
index 1951806..04692d6 100644
--- a/media_driver/agnostic/common/os/mos_os.h
+++ b/media_driver/agnostic/common/os/mos_os.h
@@ -786,6 +786,10 @@
         PMOS_INTERFACE              pOsInterface,
         MOS_GPU_CONTEXT             GpuContext);
 
+    MOS_STATUS (* pfnDestroyGpuComputeContext) (
+        PMOS_INTERFACE              osInterface,
+        GPU_CONTEXT_HANDLE          gpuContextHandle);
+
     MOS_STATUS (* pfnSetGpuContext) (
         PMOS_INTERFACE              pOsInterface,
         MOS_GPU_CONTEXT             GpuContext);
diff --git a/media_driver/linux/common/os/mos_os_specific.c b/media_driver/linux/common/os/mos_os_specific.c
index a0d0e88..6fda6f2 100644
--- a/media_driver/linux/common/os/mos_os_specific.c
+++ b/media_driver/linux/common/os/mos_os_specific.c
@@ -5032,6 +5032,79 @@
 }
 
 //!
+//! \brief    Destroy Compute GPU context
+//! \details  Destroy Compute GPU context
+//!           [in] Pointer to OS interface structure
+//! \param    GPU_CONTEXT_HANDLE gpuContextHandle
+//!           [in] GPU Context handle
+//! \return   MOS_STATUS
+//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
+//!
+MOS_STATUS Mos_Specific_DestroyGpuComputeContext(
+    PMOS_INTERFACE        osInterface,
+    GPU_CONTEXT_HANDLE    gpuContextHandle)
+{
+    MOS_OS_FUNCTION_ENTER;
+
+    MOS_OS_CHK_NULL_RETURN(osInterface);
+    if(MOS_GPU_CONTEXT_INVALID_HANDLE == gpuContextHandle)
+    {
+        MOS_OS_ASSERTMESSAGE("Invalid compute gpu context handle.");
+        return MOS_STATUS_INVALID_HANDLE;
+    }
+    if (!osInterface->modularizedGpuCtxEnabled || Mos_Solo_IsEnabled(nullptr))
+    {
+        return MOS_STATUS_SUCCESS;
+    }
+
+    OsContextSpecific *pOsContextSpecific = static_cast<OsContextSpecific *>(osInterface->osContextPtr);
+    MOS_OS_CHK_NULL_RETURN(pOsContextSpecific);
+
+    GPU_CONTEXT_HANDLE iGpuContextHandle = pOsContextSpecific->GetGpuContextHandle(MOS_GPU_CONTEXT_CM_COMPUTE);
+    if(iGpuContextHandle == gpuContextHandle)
+    {
+        MOS_OS_ASSERTMESSAGE("It will be destroyed in osInterface destroy.");
+        return MOS_STATUS_SUCCESS;
+    }
+
+    iGpuContextHandle = pOsContextSpecific->GetGpuContextHandle(MOS_GPU_CONTEXT_COMPUTE);
+    if(iGpuContextHandle == gpuContextHandle)
+    {
+        MOS_OS_ASSERTMESSAGE("It will be destroyed in osInterface destroy.");
+        return MOS_STATUS_SUCCESS;
+    }
+
+    if (osInterface->apoMosEnabled)
+    {
+        auto gpuContext = MosInterface::GetGpuContext(osInterface->osStreamState, gpuContextHandle);
+        MOS_OS_CHK_NULL_RETURN(gpuContext);
+
+        MOS_GPU_CONTEXT gpuContextName = gpuContext->GetCpuContextID();
+        if(gpuContextName != MOS_GPU_CONTEXT_CM_COMPUTE && gpuContextName != MOS_GPU_CONTEXT_COMPUTE)
+        {
+            MOS_OS_ASSERTMESSAGE("It is not compute gpu context and it will be destroyed in osInterface destroy.");
+            return MOS_STATUS_SUCCESS;
+        }
+        return MosInterface::DestroyGpuContext(osInterface->osStreamState, gpuContextHandle);
+    }
+
+    GpuContextMgr *gpuContextMgr = pOsContextSpecific->GetGpuContextMgr();
+    MOS_OS_CHK_NULL_RETURN(gpuContextMgr);
+    GpuContext *gpuContext = gpuContextMgr->GetGpuContext(gpuContextHandle);
+    MOS_OS_CHK_NULL_RETURN(gpuContext);
+
+    MOS_GPU_CONTEXT gpuContextName = gpuContext->GetCpuContextID();
+    if(gpuContextName != MOS_GPU_CONTEXT_CM_COMPUTE && gpuContextName != MOS_GPU_CONTEXT_COMPUTE)
+    {
+        MOS_OS_ASSERTMESSAGE("It is not compute gpu context and it will be destroyed in osInterface destroy.");
+        return MOS_STATUS_SUCCESS;
+    }
+
+    gpuContextMgr->DestroyGpuContext(gpuContext);
+    return MOS_STATUS_SUCCESS;
+ }
+
+//!
 //! \brief    Sets the perf tag
 //! \details  Sets the perf tag
 //! \param    PMOS_INTERFACE pOsInterface
@@ -7490,6 +7563,7 @@
     pOsInterface->pfnCreateGpuContext                       = Mos_Specific_CreateGpuContext;
     pOsInterface->pfnCreateGpuComputeContext                = Mos_Specific_CreateGpuComputeContext;
     pOsInterface->pfnDestroyGpuContext                      = Mos_Specific_DestroyGpuContext;
+    pOsInterface->pfnDestroyGpuComputeContext               = Mos_Specific_DestroyGpuComputeContext;
     pOsInterface->pfnIsGpuContextValid                      = Mos_Specific_IsGpuContextValid;
     pOsInterface->pfnSyncOnResource                         = Mos_Specific_SyncOnResource;
     pOsInterface->pfnSyncGpuContext                         = Mos_Specific_SyncGpuContext;