blob: 0c49ae6a7f65d3f210078d157468ba8dfa3f06f4 [file] [log] [blame]
/*
* Copyright (c) 2020-2021, 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_mi_xe_xpm_base_impl.h
//! \brief MHW MI interface common base for Xe_XPM_BASE
//! \details
//!
#ifndef __MHW_MI_XE_XPM_BASE_IMPL_H__
#define __MHW_MI_XE_XPM_BASE_IMPL_H__
#include "mhw_mi_impl.h"
#include "mhw_mi_hwcmd_xe_xpm_base.h"
#include "mhw_mi_itf.h"
#include "mhw_impl.h"
namespace mhw
{
namespace mi
{
namespace xe_xpm_base
{
class Impl : public mi::Impl<Cmd>
{
protected:
using base_t = mi::Impl<Cmd>;
static constexpr uint32_t m_mmioMaxRelativeOffset = M_MMIO_MAX_RELATIVE_OFFSET; //!< Max reg relative offset in an engine
static constexpr uint32_t m_mmioMediaLowOffset = M_MMIO_MEDIA_LOW_OFFSET; //!< Low bound of VDBox and VEBox MMIO offset
static constexpr uint32_t m_mmioMediaHighOffset = M_MMIO_MEDIA_HIGH_OFFSET; //!< High bound of VDBox and VEBox MMIO offset
//! \brief Indicates the MediaReset Parameter.
struct
{
uint32_t watchdogCountThreshold = 0;
uint32_t watchdogCountCtrlOffset = 0;
uint32_t watchdogCountThresholdOffset = 0;
} MediaResetParam;
public:
Impl(PMOS_INTERFACE osItf) : base_t(osItf)
{
MHW_FUNCTION_ENTER;
InitMhwMiInterface();
InitMmioRegisters();
};
void GetWatchdogThreshold(PMOS_INTERFACE osInterface)
{
MOS_USER_FEATURE_VALUE_DATA userFeatureData = {};
#if (_DEBUG || _RELEASE_INTERNAL)
// User feature config of watchdog timer threshold
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_MEDIA_RESET_TH_ID,
&userFeatureData,
osInterface->pOsContext);
if (userFeatureData.u32Data != 0)
{
MediaResetParam.watchdogCountThreshold = userFeatureData.u32Data;
}
#endif
}
void InitMhwMiInterface()
{
MHW_FUNCTION_ENTER;
UseGlobalGtt = {};
MediaResetParam = {};
if (this->m_osItf == nullptr)
{
MHW_ASSERTMESSAGE("Invalid input pointers provided");
return;
}
if (!this->m_osItf->bUsesGfxAddress && !this->m_osItf->bUsesPatchList)
{
MHW_ASSERTMESSAGE("No valid addressing mode indicated");
return;
}
UseGlobalGtt.m_cs =
UseGlobalGtt.m_vcs =
UseGlobalGtt.m_vecs = MEDIA_IS_WA(this->m_osItf->pfnGetWaTable(this->m_osItf), WaForceGlobalGTT) ||
!MEDIA_IS_SKU(this->m_osItf->pfnGetSkuTable(this->m_osItf), FtrPPGTT);
MediaResetParam.watchdogCountThreshold = MHW_MI_DEFAULT_WATCHDOG_THRESHOLD_IN_MS;
GetWatchdogThreshold(this->m_osItf);
if (this->m_osItf->bUsesGfxAddress)
{
AddResourceToCmd = Mhw_AddResourceToCmd_GfxAddress;
}
else // if (pOsInterface->bUsesPatchList)
{
AddResourceToCmd = Mhw_AddResourceToCmd_PatchList;
}
}
void InitMmioRegisters()
{
MHW_FUNCTION_ENTER;
MHW_MI_MMIOREGISTERS* mmioRegisters = &m_mmioRegisters;
mmioRegisters->generalPurposeRegister0LoOffset = GP_REGISTER0_LO_OFFSET;
mmioRegisters->generalPurposeRegister0HiOffset = GP_REGISTER0_HI_OFFSET;
mmioRegisters->generalPurposeRegister4LoOffset = GP_REGISTER4_LO_OFFSET;
mmioRegisters->generalPurposeRegister4HiOffset = GP_REGISTER4_HI_OFFSET;
mmioRegisters->generalPurposeRegister11LoOffset = GP_REGISTER11_LO_OFFSET;
mmioRegisters->generalPurposeRegister11HiOffset = GP_REGISTER11_HI_OFFSET;
mmioRegisters->generalPurposeRegister12LoOffset = GP_REGISTER12_LO_OFFSET;
mmioRegisters->generalPurposeRegister12HiOffset = GP_REGISTER12_HI_OFFSET;
}
//!
//! \brief Check RCS and CCS remap offset
//! \details Check if a RCS register offset is set and remap it to RCS/CCS register offset if so.
//! \param [in] reg
//! Register to be checked and converted
//! \return bool
//! Return true if it is RCS register
//!
bool IsRemappingMMIO(uint32_t reg)
{
if (nullptr == this->m_osItf)
{
MHW_ASSERTMESSAGE("invalid m_osInterface for RemappingMMIO");
return false;
}
MOS_GPU_CONTEXT gpuContext = this->m_osItf->pfnGetGpuContext(this->m_osItf);
if (MOS_RCS_ENGINE_USED(gpuContext) &&
((M_MMIO_RCS_HW_FE_REMAP_RANGE_BEGIN <= reg && reg <= M_MMIO_RCS_HW_FE_REMAP_RANGE_END)
|| (M_MMIO_RCS_AUX_TBL_REMAP_RANGE_BEGIN <= reg && reg <= M_MMIO_RCS_AUX_TBL_REMAP_RANGE_END)
|| (M_MMIO_RCS_TRTT_REMAP_RANGE_BEGIN <= reg && reg <= M_MMIO_RCS_TRTT_REMAP_RANGE_END)
|| (M_MMIO_CCS0_HW_FRONT_END_BASE_BEGIN <= reg && reg <= M_MMIO_CCS0_HW_FRONT_END_BASE_END)
|| (M_MMIO_CCS1_HW_FRONT_END_BASE_BEGIN <= reg && reg <= M_MMIO_CCS1_HW_FRONT_END_BASE_END)
|| (M_MMIO_CCS2_HW_FRONT_END_BASE_BEGIN <= reg && reg <= M_MMIO_CCS2_HW_FRONT_END_BASE_END)
|| (M_MMIO_CCS3_HW_FRONT_END_BASE_BEGIN <= reg && reg <= M_MMIO_CCS3_HW_FRONT_END_BASE_END)))
{
return true;
}
else
{
return false;
}
}
bool IsRelativeMMIO(uint32_t &reg)
{
if (nullptr == this->m_osItf)
{
MHW_ASSERTMESSAGE("invalid m_osInterface for RelativeMMIO");
return false;
}
MOS_GPU_CONTEXT gpuContext = this->m_osItf->pfnGetGpuContext(this->m_osItf);
if ((MOS_VCS_ENGINE_USED(gpuContext) || MOS_VECS_ENGINE_USED(gpuContext)) &&
(reg >= m_mmioMediaLowOffset && reg < m_mmioMediaHighOffset))
{
reg &= m_mmioMaxRelativeOffset;
return true;
}
return false;
}
MOS_STATUS SetWatchdogTimerThreshold(uint32_t frameWidth, uint32_t frameHeight, bool isEncoder) override
{
MEDIA_WA_TABLE *waTable = nullptr;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(this->m_osItf);
if (this->m_osItf->bMediaReset == false ||
this->m_osItf->umdMediaResetEnable == false)
{
return MOS_STATUS_SUCCESS;
}
waTable = this->m_osItf->pfnGetWaTable(this->m_osItf);
MHW_CHK_NULL_RETURN(waTable);
if (isEncoder)
{
if ((frameWidth * frameHeight) >= (7680 * 4320))
{
MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_16K_WATCHDOG_THRESHOLD_IN_MS;
}
else if ((frameWidth * frameHeight) >= (3840 * 2160))
{
MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_8K_WATCHDOG_THRESHOLD_IN_MS;
}
else if ((frameWidth * frameHeight) >= (1920 * 1080))
{
MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_4K_WATCHDOG_THRESHOLD_IN_MS;
}
else
{
MediaResetParam.watchdogCountThreshold = MHW_MI_ENCODER_FHD_WATCHDOG_THRESHOLD_IN_MS;
}
}
else
{
if ((frameWidth * frameHeight) >= (16000 * 16000))
{
MediaResetParam.watchdogCountThreshold = MHW_MI_DECODER_16Kx16K_WATCHDOG_THRESHOLD_IN_MS;
}
else if ((frameWidth * frameHeight) >= (7680 * 4320))
{
MediaResetParam.watchdogCountThreshold = MHW_MI_DECODER_16K_WATCHDOG_THRESHOLD_IN_MS;
}
else if (((frameWidth * frameHeight) < (1280 * 720)) && MEDIA_IS_WA(waTable, WaSliceMissingMB))
{
MediaResetParam.watchdogCountThreshold = MHW_MI_DECODER_720P_WATCHDOG_THRESHOLD_IN_MS;
}
else
{
// 60ms should be enough for decoder with resolution smaller than 8k
MediaResetParam.watchdogCountThreshold = MHW_MI_DEFAULT_WATCHDOG_THRESHOLD_IN_MS;
}
}
GetWatchdogThreshold(this->m_osItf);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS SetWatchdogTimerRegisterOffset(MOS_GPU_CONTEXT gpuContext) override
{
MHW_FUNCTION_ENTER;
switch (gpuContext)
{
// RCS
case MOS_GPU_CONTEXT_RENDER:
case MOS_GPU_CONTEXT_RENDER2:
case MOS_GPU_CONTEXT_RENDER3:
case MOS_GPU_CONTEXT_RENDER4:
case MOS_GPU_CONTEXT_COMPUTE:
case MOS_GPU_CONTEXT_CM_COMPUTE:
case MOS_GPU_CONTEXT_RENDER_RA:
case MOS_GPU_CONTEXT_COMPUTE_RA:
MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_RCS;
MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_RCS;
break;
// VCS0
case MOS_GPU_CONTEXT_VIDEO:
case MOS_GPU_CONTEXT_VIDEO2:
case MOS_GPU_CONTEXT_VIDEO3:
case MOS_GPU_CONTEXT_VIDEO4:
case MOS_GPU_CONTEXT_VIDEO5:
case MOS_GPU_CONTEXT_VIDEO6:
case MOS_GPU_CONTEXT_VIDEO7:
MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_VCS0;
MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_VCS0;
break;
// VCS1
case MOS_GPU_CONTEXT_VDBOX2_VIDEO:
case MOS_GPU_CONTEXT_VDBOX2_VIDEO2:
case MOS_GPU_CONTEXT_VDBOX2_VIDEO3:
MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_VCS1;
MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_VCS1;
break;
// VECS
case MOS_GPU_CONTEXT_VEBOX:
MediaResetParam.watchdogCountCtrlOffset = WATCHDOG_COUNT_CTRL_OFFSET_VECS;
MediaResetParam.watchdogCountThresholdOffset = WATCHDOG_COUNT_THRESTHOLD_OFFSET_VECS;
break;
// Default
default:
break;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AddWatchdogTimerStartCmd(PMOS_COMMAND_BUFFER cmdBuffer) override
{
MOS_GPU_CONTEXT gpuContext;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(this->m_osItf);
if (this->m_osItf->bMediaReset == false ||
this->m_osItf->umdMediaResetEnable == false)
{
return MOS_STATUS_SUCCESS;
}
MHW_MI_CHK_NULL(cmdBuffer);
// Set Watchdog Timer Register Offset
gpuContext = this->m_osItf->pfnGetGpuContext(this->m_osItf);
MHW_MI_CHK_STATUS(SetWatchdogTimerRegisterOffset(gpuContext));
// Send Stop before Start is to help recover from incorrect wdt state if previous submission
// cause hang and not have a chance to execute the stop cmd in the end of batch buffer.
MHW_MI_CHK_STATUS(AddWatchdogTimerStopCmd(cmdBuffer));
//Configure Watchdog timer Threshold
auto& par = MHW_GETPAR_F(MI_LOAD_REGISTER_IMM)();
par = {};
par.dwData = MHW_MI_WATCHDOG_COUNTS_PER_MILLISECOND * MediaResetParam.watchdogCountThreshold *
(this->m_osItf->bSimIsActive ? 2 : 1);
par.dwRegister = MediaResetParam.watchdogCountThresholdOffset;
MHW_ADDCMD_F(MI_LOAD_REGISTER_IMM)(cmdBuffer);
MHW_VERBOSEMESSAGE("MediaReset Threshold is %d", MediaResetParam.watchdogCountThreshold * (this->m_osItf->bSimIsActive ? 2 : 1));
//Start Watchdog Timer
auto& par1 = MHW_GETPAR_F(MI_LOAD_REGISTER_IMM)();
par1 = {};
par1.dwData = MHW_MI_WATCHDOG_ENABLE_COUNTER;
par1.dwRegister = MediaResetParam.watchdogCountCtrlOffset;
MHW_ADDCMD_F(MI_LOAD_REGISTER_IMM)(cmdBuffer);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AddWatchdogTimerStopCmd(PMOS_COMMAND_BUFFER cmdBuffer) override
{
MOS_GPU_CONTEXT gpuContext;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(this->m_osItf);
if (this->m_osItf->bMediaReset == false ||
this->m_osItf->umdMediaResetEnable == false)
{
return MOS_STATUS_SUCCESS;
}
MHW_MI_CHK_NULL(cmdBuffer);
// Set Watchdog Timer Register Offset
gpuContext = this->m_osItf->pfnGetGpuContext(this->m_osItf);
MHW_MI_CHK_STATUS(SetWatchdogTimerRegisterOffset(gpuContext));
//Stop Watchdog Timer
auto& par = MHW_GETPAR_F(MI_LOAD_REGISTER_IMM)();
par = {};
par.dwData = MHW_MI_WATCHDOG_DISABLE_COUNTER;
par.dwRegister = MediaResetParam.watchdogCountCtrlOffset;
MHW_ADDCMD_F(MI_LOAD_REGISTER_IMM)(cmdBuffer);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AddMiBatchBufferEnd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer) override
{
MHW_FUNCTION_ENTER;
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
return MOS_STATUS_NULL_POINTER;
}
auto waTable = this->m_osItf->pfnGetWaTable(this->m_osItf);
MHW_MI_CHK_NULL(waTable);
// This WA does not apply for video or other engines, render requirement only
bool isRender =
MOS_RCS_ENGINE_USED(this->m_osItf->pfnGetGpuContext(this->m_osItf));
if (isRender &&
(MEDIA_IS_WA(waTable, WaMSFWithNoWatermarkTSGHang) ||
MEDIA_IS_WA(waTable, WaAddMediaStateFlushCmd)))
{
auto& params = MHW_GETPAR_F(MEDIA_STATE_FLUSH)();
params = {};
MHW_ADDCMD_F(MEDIA_STATE_FLUSH)(cmdBuffer, batchBuffer);
}
// Mhw_CommonMi_AddMiBatchBufferEnd() is designed to handle both 1st level
// and 2nd level BB. It inserts MI_BATCH_BUFFER_END in both cases.
// However, since the 2nd level BB always returens to the 1st level BB and
// no chained BB scenario in Media, Epilog is only needed in the 1st level BB.
// Therefre, here only the 1st level BB case needs an Epilog inserted.
if (cmdBuffer && cmdBuffer->is1stLvlBB)
{
MHW_MI_CHK_STATUS(m_cpInterface->AddEpilog(this->m_osItf, cmdBuffer));
}
auto& params = MHW_GETPAR_F(MI_BATCH_BUFFER_END)();
params = {};
MHW_ADDCMD_F(MI_BATCH_BUFFER_END)(cmdBuffer, batchBuffer);
if (!cmdBuffer) // Don't need BB not nullptr chk b/c if both are nullptr it won't get this far
{
#if (_DEBUG || _RELEASE_INTERNAL)
batchBuffer->iLastCurrent = batchBuffer->iCurrent;
#endif
}
// Send End Marker command
if (this->m_osItf->pfnIsSetMarkerEnabled(this->m_osItf) && cmdBuffer && cmdBuffer->is1stLvlBB)
{
PMOS_RESOURCE resMarker = nullptr;
resMarker = this->m_osItf->pfnGetMarkerResource(this->m_osItf);
MHW_MI_CHK_NULL(resMarker);
if (isRender)
{
// Send pipe_control to get the timestamp
auto& params = MHW_GETPAR_F(PIPE_CONTROL)();
params = {};
params.presDest = resMarker;
params.dwResourceOffset = sizeof(uint64_t);
params.dwPostSyncOp = MHW_FLUSH_WRITE_TIMESTAMP_REG;
params.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
MHW_ADDCMD_F(PIPE_CONTROL)(cmdBuffer, batchBuffer);
}
else
{
// Send flush_dw to get the timestamp
auto& params = MHW_GETPAR_F(MI_FLUSH_DW)();
params = {};
params.pOsResource = resMarker;
params.dwResourceOffset = sizeof(uint64_t);
params.postSyncOperation = MHW_FLUSH_WRITE_TIMESTAMP_REG;
params.bQWordEnable = 1;
MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer, batchBuffer);
}
if (!this->m_osItf->apoMosEnabled)
{
MOS_SafeFreeMemory(resMarker);
}
}
MHW_MI_CHK_STATUS(this->m_osItf->osCpInterface->PermeateBBPatchForHM());
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_SEMAPHORE_WAIT)
{
_MHW_SETCMD_CALLBASE(MI_SEMAPHORE_WAIT);
cmd.DW0.RegisterPollMode = params.bRegisterPollMode;
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(PIPE_CONTROL)
{
_MHW_SETCMD_CALLBASE(PIPE_CONTROL);
MEDIA_WA_TABLE *pWaTable = this->m_osItf->pfnGetWaTable(this->m_osItf);
MHW_MI_CHK_NULL(pWaTable);
if (this->m_currentCmdBuf == nullptr && this->m_currentBatchBuf == nullptr)
{
MHW_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
return MOS_STATUS_NULL_POINTER;
}
cmd.DW1.PipeControlFlushEnable = params.bKernelFenceEnabled ? false : true;
cmd.DW1.CommandStreamerStallEnable = !params.bDisableCSStall;
cmd.DW4_5.Value[0] = params.dwDataDW1;
cmd.DW4_5.Value[1] = params.dwDataDW2;
if (params.presDest)
{
cmd.DW1.PostSyncOperation = params.dwPostSyncOp;
cmd.DW1.DestinationAddressType = UseGlobalGtt.m_cs;
MHW_RESOURCE_PARAMS resourceParams = {};
resourceParams.presResource = params.presDest;
resourceParams.dwOffset = params.dwResourceOffset;
resourceParams.pdwCmd = &(cmd.DW2.Value);
resourceParams.dwLocationInCmd = _MHW_CMD_DW_LOCATION(DW2.Value);
resourceParams.dwLsbNum = MHW_COMMON_MI_PIPE_CONTROL_SHIFT;
resourceParams.bIsWritable = true;
resourceParams.HwCommandType = MOS_PIPE_CONTROL;
MHW_MI_CHK_STATUS(AddResourceToCmd(
this->m_osItf,
this->m_currentCmdBuf,
&resourceParams));
}
else
{
if (MEDIA_IS_WA(pWaTable, Wa_14010840176))
{
cmd.DW0.HdcPipelineFlush = true;
cmd.DW1.ConstantCacheInvalidationEnable = false;
}
else
{
cmd.DW1.ConstantCacheInvalidationEnable = true;
}
cmd.DW1.StateCacheInvalidationEnable = true;
cmd.DW1.VfCacheInvalidationEnable = true;
cmd.DW1.InstructionCacheInvalidateEnable = true;
cmd.DW1.RenderTargetCacheFlushEnable = true;
cmd.DW1.PostSyncOperation = cmd.POST_SYNC_OPERATION_NOWRITE;
}
// Cache flush mode
switch (params.dwFlushMode)
{
// Flush all Write caches
case MHW_FLUSH_WRITE_CACHE:
cmd.DW1.RenderTargetCacheFlushEnable = true;
cmd.DW1.DcFlushEnable = true;
break;
// Invalidate all Read-only caches
case MHW_FLUSH_READ_CACHE:
if (MEDIA_IS_WA(pWaTable, Wa_14010840176))
{
cmd.DW0.HdcPipelineFlush = true;
cmd.DW1.ConstantCacheInvalidationEnable = false;
}
else
{
cmd.DW1.ConstantCacheInvalidationEnable = true;
}
cmd.DW1.RenderTargetCacheFlushEnable = false;
cmd.DW1.StateCacheInvalidationEnable = true;
cmd.DW1.VfCacheInvalidationEnable = true;
cmd.DW1.InstructionCacheInvalidateEnable = true;
break;
// Custom flush parameters
case MHW_FLUSH_CUSTOM:
if (MEDIA_IS_WA(pWaTable, Wa_14010840176) && params.bInvalidateConstantCache)
{
cmd.DW0.HdcPipelineFlush = true;
cmd.DW1.StateCacheInvalidationEnable = true;
cmd.DW1.ConstantCacheInvalidationEnable = false;
}
else
{
cmd.DW1.StateCacheInvalidationEnable = params.bInvalidateStateCache;
cmd.DW1.ConstantCacheInvalidationEnable = params.bInvalidateConstantCache;
}
cmd.DW1.RenderTargetCacheFlushEnable = params.bFlushRenderTargetCache;
cmd.DW1.DcFlushEnable = params.bFlushRenderTargetCache; // same as above
cmd.DW1.VfCacheInvalidationEnable = params.bInvalidateVFECache;
cmd.DW1.InstructionCacheInvalidateEnable = params.bInvalidateInstructionCache;
cmd.DW1.TlbInvalidate = params.bTlbInvalidate;
cmd.DW1.TextureCacheInvalidationEnable = params.bInvalidateTextureCache;
break;
// No-flush operation requested
case MHW_FLUSH_NONE:
default:
cmd.DW1.RenderTargetCacheFlushEnable = false;
break;
}
// When PIPE_CONTROL stall bit is set, one of the following must also be set, otherwise set stall bit to 0
if (cmd.DW1.CommandStreamerStallEnable &&
(cmd.DW1.DcFlushEnable == 0 && cmd.DW1.NotifyEnable == 0 && cmd.DW1.PostSyncOperation == 0 &&
cmd.DW1.DepthStallEnable == 0 && cmd.DW1.StallAtPixelScoreboard == 0 && cmd.DW1.DepthCacheFlushEnable == 0 &&
cmd.DW1.RenderTargetCacheFlushEnable == 0) &&
!params.bKernelFenceEnabled)
{
cmd.DW1.CommandStreamerStallEnable = 0;
}
cmd.DW1.GenericMediaStateClear = params.bGenericMediaStateClear;
cmd.DW1.IndirectStatePointersDisable = params.bIndirectStatePointersDisable;
cmd.DW0.HdcPipelineFlush = params.bHdcPipelineFlush;
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_BATCH_BUFFER_START)
{
_MHW_SETCMD_CALLBASE(MI_BATCH_BUFFER_START);
MHW_MI_CHK_NULL(this->m_currentCmdBuf);
MHW_MI_CHK_NULL(this->m_currentBatchBuf);
MHW_MI_CHK_NULL(this->m_osItf);
bool vcsEngineUsed =
MOS_VCS_ENGINE_USED(this->m_osItf->pfnGetGpuContext(this->m_osItf));
MHW_RESOURCE_PARAMS resourceParams = {};
resourceParams.presResource = &this->m_currentBatchBuf->OsResource;
resourceParams.dwOffset = this->m_currentBatchBuf->dwOffset;
resourceParams.pdwCmd = cmd.DW1_2.Value;
resourceParams.dwLocationInCmd = _MHW_CMD_DW_LOCATION(DW1_2.Value);
resourceParams.dwLsbNum = MHW_COMMON_MI_GENERAL_SHIFT;
resourceParams.HwCommandType = vcsEngineUsed ? MOS_MI_BATCH_BUFFER_START : MOS_MI_BATCH_BUFFER_START_RCS;
MHW_MI_CHK_STATUS(AddResourceToCmd(
this->m_osItf,
this->m_currentCmdBuf,
&resourceParams));
// Set BB start
cmd.DW0.Obj3.SecondLevelBatchBuffer = true;
cmd.DW0.Obj0.AddressSpaceIndicator = !IsGlobalGttInUse();
return MOS_STATUS_SUCCESS;
}
__MHW_ADDCMD_DECL(MI_CONDITIONAL_BATCH_BUFFER_END) override
{
// Case 1 - Batch buffer condition matches - If this is not present then conditional
// batch buffer will exit to ring with terminating CP.
// Case 2 - Batch buffer condition DOES NOT match - Although this will disable CP
// but after end of conditional batch buffer CP will be re-enabled.
MHW_MI_CHK_STATUS(m_cpInterface->AddEpilog(this->m_osItf, cmdBuf));
base_t::MHW_ADDCMD_F(MI_CONDITIONAL_BATCH_BUFFER_END)(cmdBuf, batchBuf);
MHW_MI_CHK_STATUS(m_cpInterface->AddProlog(this->m_osItf, cmdBuf));
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_CONDITIONAL_BATCH_BUFFER_END)
{
_MHW_SETCMD_CALLBASE(MI_CONDITIONAL_BATCH_BUFFER_END);
MHW_MI_CHK_NULL(params.presSemaphoreBuffer);
cmd.DW0.UseGlobalGtt = IsGlobalGttInUse();
cmd.DW0.CompareSemaphore = 1; // CompareDataDword is always assumed to be set
cmd.DW0.CompareMaskMode = !params.bDisableCompareMask;
if (params.dwParamsType == MHW_MI_ENHANCED_CONDITIONAL_BATCH_BUFFER_END_PARAMS::ENHANCED_PARAMS)
{
cmd.DW0.EndCurrentBatchBufferLevel = params.enableEndCurrentBatchBuffLevel;
cmd.DW0.CompareOperation = params.compareOperation;
}
cmd.DW1.CompareDataDword = params.dwValue;
MHW_RESOURCE_PARAMS resourceParams = {};
resourceParams.presResource = params.presSemaphoreBuffer;
resourceParams.dwOffset = params.dwOffset;
resourceParams.pdwCmd = cmd.DW2_3.Value;
resourceParams.dwLocationInCmd = _MHW_CMD_DW_LOCATION(DW2_3.Value);
resourceParams.dwLsbNum = MHW_COMMON_MI_CONDITIONAL_BATCH_BUFFER_END_SHIFT;
resourceParams.HwCommandType = MOS_MI_CONDITIONAL_BATCH_BUFFER_END;
MHW_MI_CHK_STATUS(AddResourceToCmd(
this->m_osItf,
this->m_currentCmdBuf,
&resourceParams));
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_SET_PREDICATE)
{
_MHW_SETCMD_CALLBASE(MI_SET_PREDICATE);
cmd.DW0.PredicateEnable = params.PredicateEnable;
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_STORE_REGISTER_MEM)
{
_MHW_SETCMD_CALLBASE(MI_STORE_REGISTER_MEM);
uint32_t reg = params.dwRegister;
if (IsRelativeMMIO(reg))
{
cmd.DW0.AddCsMmioStartOffset = 1;
cmd.DW1.RegisterAddress = reg >> 2;
}
cmd.DW0.MmioRemapEnable = IsRemappingMMIO(reg);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_LOAD_REGISTER_MEM)
{
_MHW_SETCMD_CALLBASE(MI_LOAD_REGISTER_MEM);
uint32_t reg = params.dwRegister;
if (IsRelativeMMIO(reg))
{
cmd.DW0.AddCsMmioStartOffset = 1;
cmd.DW1.RegisterAddress = reg >> 2;
}
cmd.DW0.MmioRemapEnable = IsRemappingMMIO(reg);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_LOAD_REGISTER_IMM)
{
_MHW_SETCMD_CALLBASE(MI_LOAD_REGISTER_IMM);
uint32_t reg = params.dwRegister;
if (IsRelativeMMIO(reg))
{
cmd.DW0.AddCsMmioStartOffset = 1;
cmd.DW1.RegisterOffset = reg >> 2;
}
cmd.DW0.MmioRemapEnable = IsRemappingMMIO(reg);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_LOAD_REGISTER_REG)
{
_MHW_SETCMD_CALLBASE(MI_LOAD_REGISTER_REG);
uint32_t srcReg = params.dwSrcRegister;
if (IsRelativeMMIO(srcReg))
{
cmd.DW0.AddCsMmioStartOffsetSource = 1;
cmd.DW1.SourceRegisterAddress = srcReg >> 2;
}
uint32_t dstReg = params.dwDstRegister;
if (IsRelativeMMIO(dstReg))
{
cmd.DW0.AddCsMmioStartOffsetDestination = 1;
cmd.DW2.DestinationRegisterAddress = dstReg >> 2;
}
cmd.DW0.MmioRemapEnableSource = IsRemappingMMIO(srcReg);
cmd.DW0.MmioRemapEnableDestination = IsRemappingMMIO(dstReg);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_FORCE_WAKEUP)
{
_MHW_SETCMD_CALLBASE(MI_FORCE_WAKEUP);
cmd.DW1.ForceMediaSlice0Awake = params.bForceMediaSlice0Awake;
cmd.DW1.ForceRenderAwake = params.bForceRenderAwake;
cmd.DW1.ForceMediaSlice1Awake = params.bForceMediaSlice1Awake;
cmd.DW1.ForceMediaSlice2Awake = params.bForceMediaSlice2Awake;
cmd.DW1.ForceMediaSlice3Awake = params.bForceMediaSlice3Awake;
cmd.DW1.HevcPowerWellControl = params.bHEVCPowerWellControl;
cmd.DW1.MfxPowerWellControl = params.bMFXPowerWellControl;
cmd.DW1.MaskBits = params.bForceMediaSlice0AwakeMask;
cmd.DW1.MaskBits += (params.bForceRenderAwakeMask << 1);
cmd.DW1.MaskBits += (params.bForceMediaSlice1AwakeMask << 2);
cmd.DW1.MaskBits += (params.bForceMediaSlice2AwakeMask << 3);
cmd.DW1.MaskBits += (params.bForceMediaSlice3AwakeMask << 4);
cmd.DW1.MaskBits += (params.bHEVCPowerWellControlMask << 8);
cmd.DW1.MaskBits += (params.bMFXPowerWellControlMask << 9);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(VD_CONTROL_STATE)
{
_MHW_SETCMD_CALLBASE(VD_CONTROL_STATE);
if (params.vdencEnabled)
{
cmd.DW0.MediaInstructionCommand =
mhw::mi::xe_xpm_base::Cmd::VD_CONTROL_STATE_CMD::MEDIA_INSTRUCTION_COMMAND_VDCONTROLSTATEFORVDENC;
cmd.DW0.MediaInstructionOpcode =
mhw::mi::xe_xpm_base::Cmd::VD_CONTROL_STATE_CMD::MEDIA_INSTRUCTION_OPCODE_CODECENGINENAMEFORVDENC;
}
else
{
cmd.DW0.MediaInstructionCommand =
mhw::mi::xe_xpm_base::Cmd::VD_CONTROL_STATE_CMD::MEDIA_INSTRUCTION_COMMAND_VDCONTROLSTATEFORHCP;
if (params.avpEnabled)
{
cmd.DW0.MediaInstructionOpcode =
mhw::mi::xe_xpm_base::Cmd::VD_CONTROL_STATE_CMD::MEDIA_INSTRUCTION_OPCODE_CODECENGINENAMEFORAVP;
}
else
{
cmd.DW0.MediaInstructionOpcode =
mhw::mi::xe_xpm_base::Cmd::VD_CONTROL_STATE_CMD::MEDIA_INSTRUCTION_OPCODE_CODECENGINENAMEFORHCP;
}
cmd.DW1.PipelineInitialization = params.initialization;
cmd.DW2.MemoryImplicitFlush = params.memoryImplicitFlush;
cmd.DW2.ScalableModePipeLock = params.scalableModePipeLock;
cmd.DW2.ScalableModePipeUnlock = params.scalableModePipeUnlock;
}
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MEDIA_STATE_FLUSH)
{
_MHW_SETCMD_CALLBASE(MEDIA_STATE_FLUSH);
cmd.DW1.FlushToGo = params.bFlushToGo;
cmd.DW1.InterfaceDescriptorOffset = params.ui8InterfaceDescriptorOffset;
#if (_DEBUG || _RELEASE_INTERNAL)
if (this->m_currentBatchBuf)
{
this->m_currentBatchBuf->iLastCurrent = this->m_currentBatchBuf->iCurrent;
}
#endif
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_BATCH_BUFFER_END)
{
_MHW_SETCMD_CALLBASE(MI_BATCH_BUFFER_END);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_FLUSH_DW)
{
_MHW_SETCMD_CALLBASE(MI_FLUSH_DW);
MHW_MI_CHK_STATUS(m_cpInterface->SetProtectionSettingsForMiFlushDw(this->m_osItf, &cmd));
cmd.DW0.VideoPipelineCacheInvalidate = params.bVideoPipelineCacheInvalidate;
cmd.DW0.PostSyncOperation = cmd.POST_SYNC_OPERATION_NOWRITE;
cmd.DW3_4.Value[0] = params.dwDataDW1;
if (!Mos_ResourceIsNull(params.pOsResource))
{
cmd.DW0.PostSyncOperation = cmd.POST_SYNC_OPERATION_WRITEIMMEDIATEDATA;
cmd.DW1_2.DestinationAddressType = UseGlobalGtt.m_vcs;
MHW_RESOURCE_PARAMS resourceParams = {};
resourceParams.presResource = params.pOsResource;
resourceParams.dwOffset = params.dwResourceOffset;
resourceParams.pdwCmd = cmd.DW1_2.Value;
resourceParams.dwLocationInCmd = _MHW_CMD_DW_LOCATION(DW1_2.Value);
resourceParams.dwLsbNum = MHW_COMMON_MI_FLUSH_DW_SHIFT;
resourceParams.HwCommandType = MOS_MI_FLUSH_DW;
resourceParams.bIsWritable = true;
MHW_MI_CHK_STATUS(AddResourceToCmd(
this->m_osItf,
this->m_currentCmdBuf,
&resourceParams));
}
if (params.postSyncOperation)
{
cmd.DW0.PostSyncOperation = params.postSyncOperation;
}
if (params.dwDataDW2 || params.bQWordEnable)
{
cmd.DW3_4.Value[1] = params.dwDataDW2;
}
else
{
cmd.DW0.DwordLength--;
}
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_NOOP)
{
_MHW_SETCMD_CALLBASE(MI_NOOP);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_ATOMIC)
{
_MHW_SETCMD_CALLBASE(MI_ATOMIC);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_STORE_DATA_IMM)
{
_MHW_SETCMD_CALLBASE(MI_STORE_DATA_IMM);
return MOS_STATUS_SUCCESS;
}
_MHW_SETCMD_OVERRIDE_DECL(MI_MATH)
{
_MHW_SETCMD_CALLBASE(MI_MATH);
return MOS_STATUS_SUCCESS;
}
MEDIA_CLASS_DEFINE_END(mhw__mi__xe_xpm_base__Impl)
};
} // namespace xe_xpm_base
} // namespace mi
} // namespace mhw
#endif // __MHW_MI_XE_XPM_BASE_IMPL_H__