blob: 074f0dcf37de6ebe5a337f95c7a8c9697b643ea6 [file] [log] [blame]
/*
* Copyright (c) 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file mos_gpucontext_specific.cpp
//! \brief Container class for the Linux specific gpu context
//!
#include "mos_context_specific.h"
#include "mos_gpucontext_specific.h"
#include "mos_graphicsresource_specific.h"
#include "mos_commandbuffer_specific.h"
#include "mos_util_devult_specific.h"
#include "mos_cmdbufmgr.h"
#define MI_BATCHBUFFER_END 0x05000000
static pthread_mutex_t command_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
GpuContextSpecific::GpuContextSpecific(
const MOS_GPU_NODE gpuNode,
MOS_GPU_CONTEXT mosGpuCtx,
CmdBufMgr *cmdBufMgr,
GpuContext *reusedContext)
{
MOS_OS_FUNCTION_ENTER;
m_nodeOrdinal = gpuNode;
m_cmdBufMgr = cmdBufMgr;
m_gpuContext = mosGpuCtx;
m_statusBufferResource = nullptr;
if (reusedContext)
{
MOS_OS_NORMALMESSAGE("gpucontex reusing not enabled on Linux");
}
}
GpuContextSpecific::~GpuContextSpecific()
{
MOS_OS_FUNCTION_ENTER;
Clear();
}
MOS_STATUS GpuContextSpecific::Init(OsContext *osContext)
{
MOS_OS_FUNCTION_ENTER;
m_cmdBufPool.clear();
m_commandBufferSize = COMMAND_BUFFER_SIZE;
m_nextFetchIndex = 0;
m_cmdBufFlushed = true;
m_osContext = osContext;
MOS_OS_CHK_STATUS_RETURN(AllocateGPUStatusBuf());
m_commandBuffer = (PMOS_COMMAND_BUFFER)MOS_AllocAndZeroMemory(sizeof(MOS_COMMAND_BUFFER));
m_IndirectHeapSize = 0;
// each thread has its own GPU context, so do not need any lock as guarder here
m_allocationList = (ALLOCATION_LIST *)MOS_AllocAndZeroMemory(sizeof(ALLOCATION_LIST) * ALLOCATIONLIST_SIZE);
MOS_OS_CHK_NULL_RETURN(m_allocationList);
m_maxNumAllocations = ALLOCATIONLIST_SIZE;
m_patchLocationList = (PATCHLOCATIONLIST *)MOS_AllocAndZeroMemory(sizeof(PATCHLOCATIONLIST) * PATCHLOCATIONLIST_SIZE);
MOS_OS_CHK_NULL_RETURN(m_patchLocationList);
m_maxPatchLocationsize = PATCHLOCATIONLIST_SIZE;
m_attachedResources = (PMOS_RESOURCE)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE) * ALLOCATIONLIST_SIZE);
MOS_OS_CHK_NULL_RETURN(m_attachedResources);
m_writeModeList = (bool *)MOS_AllocAndZeroMemory(sizeof(bool) * ALLOCATIONLIST_SIZE);
MOS_OS_CHK_NULL_RETURN(m_writeModeList);
m_GPUStatusTag = 1;
return MOS_STATUS_SUCCESS;
}
void GpuContextSpecific::Clear()
{
MOS_OS_FUNCTION_ENTER;
// hanlde the status buf bundled w/ the specified gpucontext
if (m_statusBufferResource)
{
if (m_statusBufferResource->Unlock(m_osContext) != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("failed to unlock the status buf bundled w/ the specified gpucontext");
}
m_statusBufferResource->Free(m_osContext, 0);
MOS_Delete(m_statusBufferResource);
}
for (auto& curCommandBuffer : m_cmdBufPool)
{
auto curCommandBufferSpecific = static_cast<CommandBufferSpecific *>(curCommandBuffer);
curCommandBufferSpecific->waitReady(); // wait ready and return to comamnd buffer manager.
m_cmdBufMgr->ReleaseCmdBuf(curCommandBuffer);
}
m_cmdBufPool.clear();
MOS_SafeFreeMemory(m_commandBuffer);
MOS_SafeFreeMemory(m_allocationList);
MOS_SafeFreeMemory(m_patchLocationList);
MOS_SafeFreeMemory(m_attachedResources);
MOS_SafeFreeMemory(m_writeModeList);
}
MOS_STATUS GpuContextSpecific::RegisterResource(
PMOS_RESOURCE osResource,
bool writeFlag)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(osResource);
MOS_OS_CHK_NULL_RETURN(m_attachedResources);
PMOS_RESOURCE registeredResources = m_attachedResources;
uint32_t allocationIndex = 0;
for ( allocationIndex = 0; allocationIndex < m_resCount; allocationIndex++, registeredResources++)
{
if (osResource->bo == registeredResources->bo)
{
break;
}
}
// Allocation list to be updated
if (allocationIndex < m_maxNumAllocations)
{
// New buffer
if (allocationIndex == m_resCount)
{
m_resCount++;
}
// Set allocation
osResource->iAllocationIndex[m_gpuContext] = (allocationIndex);
m_attachedResources[allocationIndex] = *osResource;
m_writeModeList[allocationIndex] |= writeFlag;
m_allocationList[allocationIndex].hAllocation = &m_attachedResources[allocationIndex];
m_allocationList[allocationIndex].WriteOperation |= writeFlag;
m_numAllocations = m_resCount;
}
else
{
MOS_OS_ASSERTMESSAGE("Reached max # registrations.");
return MOS_STATUS_UNKNOWN;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS GpuContextSpecific::SetPatchEntry(
PMOS_INTERFACE osInterface,
PMOS_PATCH_ENTRY_PARAMS params)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(m_patchLocationList);
MOS_OS_CHK_NULL_RETURN(osInterface);
MOS_OS_CHK_NULL_RETURN(params);
m_patchLocationList[m_currentNumPatchLocations].AllocationIndex = params->uiAllocationIndex;
m_patchLocationList[m_currentNumPatchLocations].AllocationOffset = params->uiResourceOffset;
m_patchLocationList[m_currentNumPatchLocations].PatchOffset = params->uiPatchOffset;
m_patchLocationList[m_currentNumPatchLocations].uiWriteOperation = params->bWrite;
if (osInterface->osCpInterface &&
osInterface->osCpInterface->IsHMEnabled())
{
osInterface->osCpInterface->RegisterPatchForHM(
(uint32_t *)(params->cmdBufBase + params->uiPatchOffset),
params->bWrite,
params->HwCommandType,
params->forceDwordOffset,
params->presResource,
&m_patchLocationList[m_currentNumPatchLocations]);
}
m_currentNumPatchLocations++;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS GpuContextSpecific::GetCommandBuffer(
PMOS_COMMAND_BUFFER comamndBuffer,
uint32_t flags)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(comamndBuffer);
CommandBuffer* cmdBuf = nullptr;
if (m_cmdBufFlushed)
{
if (m_cmdBufPool.size() < MAX_CMD_BUF_NUM)
{
cmdBuf = m_cmdBufMgr->PickupOneCmdBuf(m_commandBufferSize);
MOS_OS_CHK_STATUS_RETURN(cmdBuf->BindToGpuContext(this));
m_cmdBufPool.push_back(cmdBuf);
}
else if (m_cmdBufPool.size() == MAX_CMD_BUF_NUM)
{
auto cmdBufOld = m_cmdBufPool[m_nextFetchIndex];
auto cmdBufSpecificOld = static_cast<CommandBufferSpecific *>(cmdBufOld);
cmdBufSpecificOld->waitReady();
cmdBufSpecificOld->UnBindToGpuContext();
m_cmdBufMgr->ReleaseCmdBuf(cmdBufOld); // here just return old command buffer to available pool
//pick up new comamnd buffer
cmdBuf = m_cmdBufMgr->PickupOneCmdBuf(m_commandBufferSize);
MOS_OS_CHK_STATUS_RETURN(cmdBuf->BindToGpuContext(this));
m_cmdBufPool[m_nextFetchIndex] = cmdBuf;
}
// util now, we got new command buffer from CmdBufMgr, next step to fill in the input command buffer
MOS_OS_CHK_STATUS_RETURN(cmdBuf->GetResource()->ConvertToMosResource(&comamndBuffer->OsResource));
comamndBuffer->pCmdBase = (uint32_t *)cmdBuf->GetLockAddr();
comamndBuffer->pCmdPtr = (uint32_t *)cmdBuf->GetLockAddr();
comamndBuffer->iOffset = 0;
comamndBuffer->iRemaining = cmdBuf->GetCmdBufSize();
comamndBuffer->iCmdIndex = m_nextFetchIndex;
comamndBuffer->iVdboxNodeIndex = MOS_VDBOX_NODE_INVALID;
// zero comamnd buffer
MOS_ZeroMemory(comamndBuffer->pCmdBase, comamndBuffer->iRemaining);
// update command buffer relared filed in GPU context
m_cmdBufFlushed = false;
// keep a copy in GPU context
MOS_SecureMemcpy(m_commandBuffer, sizeof(MOS_COMMAND_BUFFER), comamndBuffer, sizeof(MOS_COMMAND_BUFFER));
// Command buffers are treated as cyclical buffers, the CB after the just submitted one
// has the minimal fence value that we should wait
m_nextFetchIndex++;
if (m_nextFetchIndex >= MAX_CMD_BUF_NUM)
{
m_nextFetchIndex = 0;
}
}
else
{
// current command buffer still active, directly copy to comamndBuffer
MOS_SecureMemcpy(comamndBuffer, sizeof(MOS_COMMAND_BUFFER), m_commandBuffer, sizeof(MOS_COMMAND_BUFFER));
}
MOS_OS_CHK_STATUS_RETURN(RegisterResource(&m_commandBuffer->OsResource, false));
return MOS_STATUS_SUCCESS;
}
void GpuContextSpecific::ReturnCommandBuffer(
PMOS_COMMAND_BUFFER cmdBuffer,
uint32_t flags)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_ASSERT(cmdBuffer);
m_commandBuffer->iOffset = cmdBuffer->iOffset;
m_commandBuffer->iRemaining = cmdBuffer->iRemaining;
m_commandBuffer->pCmdPtr = cmdBuffer->pCmdPtr;
m_commandBuffer->iVdboxNodeIndex = cmdBuffer->iVdboxNodeIndex;
}
MOS_STATUS GpuContextSpecific::ResetCommandBuffer()
{
m_cmdBufFlushed = true;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS GpuContextSpecific::SetIndirectStateSize(const uint32_t size)
{
if(size < m_commandBufferSize)
{
m_IndirectHeapSize = size;
return MOS_STATUS_SUCCESS;
}
else
{
MOS_OS_ASSERTMESSAGE("Indirect State Size if out of boundry!");
return MOS_STATUS_UNKNOWN;
}
}
MOS_STATUS GpuContextSpecific::GetIndirectState(
uint32_t *offset,
uint32_t *size)
{
MOS_OS_FUNCTION_ENTER;
if (offset)
{
*offset = m_commandBufferSize - m_IndirectHeapSize;
}
if (size)
{
*size = m_IndirectHeapSize;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS GpuContextSpecific::GetIndirectStatePointer(
uint8_t **indirectState)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(indirectState);
*indirectState = (uint8_t *)m_commandBuffer->pCmdBase + m_commandBufferSize - m_IndirectHeapSize;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS GpuContextSpecific::ResizeCommandBufferAndPatchList(
uint32_t requestedCommandBufferSize,
uint32_t requestedPatchListSize,
uint32_t flags)
{
MOS_OS_FUNCTION_ENTER;
// m_commandBufferSize is used for allocate command buffer and submit command buffer, in this moment, command buffer has not allocated yet.
// Linux KMD requires command buffer size align to 8 bytes, or it will not execute the commands.
m_commandBufferSize = MOS_ALIGN_CEIL(requestedCommandBufferSize, 8);
if (requestedPatchListSize > m_maxPatchLocationsize)
{
PPATCHLOCATIONLIST newPatchList = (PPATCHLOCATIONLIST)realloc(m_patchLocationList, sizeof(PATCHLOCATIONLIST) * requestedPatchListSize);
MOS_OS_CHK_NULL_RETURN(newPatchList);
m_patchLocationList = newPatchList;
// now zero the extended portion
MOS_ZeroMemory((m_patchLocationList + m_maxPatchLocationsize), sizeof(PATCHLOCATIONLIST) * (requestedPatchListSize - m_maxPatchLocationsize));
m_maxPatchLocationsize = requestedPatchListSize;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS GpuContextSpecific::ResizeCommandBuffer(uint32_t requestedSize)
{
MOS_OS_FUNCTION_ENTER;
m_commandBufferSize = requestedSize;
return MOS_STATUS_SUCCESS;
}
uint32_t GetVcsExecFlag(PMOS_INTERFACE osInterface,
PMOS_COMMAND_BUFFER cmdBuffer,
MOS_GPU_NODE gpuNode)
{
uint32_t vcsExecFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
if (MOS_VDBOX_NODE_INVALID == cmdBuffer->iVdboxNodeIndex)
{
// That's those case when BB did not have any VDBOX# specific commands.
// Thus, we need to select VDBOX# here. Alternatively we can rely on KMD
// to make balancing for us, i.e. rely on Virtual Engine support.
cmdBuffer->iVdboxNodeIndex = osInterface->pfnGetVdboxNodeId(osInterface, cmdBuffer);
if (MOS_VDBOX_NODE_INVALID == cmdBuffer->iVdboxNodeIndex)
{
cmdBuffer->iVdboxNodeIndex = (gpuNode == MOS_GPU_NODE_VIDEO)?
MOS_VDBOX_NODE_1: MOS_VDBOX_NODE_2;
}
}
if (MOS_VDBOX_NODE_1 == cmdBuffer->iVdboxNodeIndex)
{
vcsExecFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
}
else if (MOS_VDBOX_NODE_2 == cmdBuffer->iVdboxNodeIndex)
{
vcsExecFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING2;
}
return vcsExecFlag;
}
MOS_STATUS GpuContextSpecific::SubmitCommandBuffer(
PMOS_INTERFACE osInterface,
PMOS_COMMAND_BUFFER cmdBuffer,
bool nullRendering)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(osInterface);
PMOS_CONTEXT osContext = osInterface->pOsContext;
MOS_OS_CHK_NULL_RETURN(osContext);
MOS_OS_CHK_NULL_RETURN(cmdBuffer);
MOS_OS_CHK_NULL_RETURN(m_patchLocationList);
MOS_GPU_NODE gpuNode = OSKMGetGpuNode(m_gpuContext);
uint32_t execFlag = gpuNode;
uint32_t addCb2 = 0xffffffff;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int32_t ret = 0;
PLATFORM platform;
// Command buffer object DRM pointer
m_cmdBufFlushed = true;
auto cmd_bo = cmdBuffer->OsResource.bo;
// Now, the patching will be done, based on the patch list.
for (uint32_t patchIndex = 0; patchIndex < m_currentNumPatchLocations; patchIndex++)
{
auto currentPatch = &m_patchLocationList[patchIndex];
if (nullptr == currentPatch)
{
MOS_OS_ASSERTMESSAGE("Unexpected, found null entry in patch list!");
}
auto allocationIndex = currentPatch->AllocationIndex;
auto resourceOffset = currentPatch->AllocationOffset;
auto patchOffset = currentPatch->PatchOffset;
// This is the resource for which patching will be done
auto resource = (PMOS_RESOURCE)m_allocationList[allocationIndex].hAllocation;
MOS_OS_CHK_NULL_RETURN(resource);
// For now, we'll assume the system memory's DRM bo pointer
// is NULL. If nullptr is detected, then the resource has been
// placed inside the command buffer's indirect state area.
// We'll simply set alloc_bo to the command buffer's bo pointer.
MOS_OS_ASSERT(resource->bo);
auto alloc_bo = (resource->bo) ? resource->bo : cmd_bo;
MOS_OS_CHK_STATUS_RETURN(osInterface->osCpInterface->PermeatePatchForHM(
cmd_bo->virt,
currentPatch,
resource));
#ifndef ANDROID
uint64_t boOffset = alloc_bo->offset64;
if (alloc_bo != cmd_bo)
{
auto item_ctx = osContext->contextOffsetList.begin();
for (; item_ctx != osContext->contextOffsetList.end(); item_ctx++)
{
if (item_ctx->intel_context == osContext->intel_context && item_ctx->target_bo == alloc_bo)
{
boOffset = item_ctx->offset64;
break;
}
}
}
if (osContext->bUse64BitRelocs)
{
*((uint64_t *)((uint8_t *)cmd_bo->virt + patchOffset)) = boOffset + resourceOffset;
}
else
{
*((uint32_t *)((uint8_t *)cmd_bo->virt + patchOffset)) = boOffset + resourceOffset;
}
// This call will patch the command buffer with the offsets of the indirect state region of the command buffer
ret = mos_bo_emit_reloc2(
cmd_bo, // Command buffer
patchOffset, // Offset in the command buffer
alloc_bo, // Allocation object for which the patch will be made.
resourceOffset, // Offset to the indirect state
I915_GEM_DOMAIN_RENDER, // Read domain
(currentPatch->uiWriteOperation) ? I915_GEM_DOMAIN_RENDER : 0x0, // Write domain
boOffset);
#else
if (osContext->bUse64BitRelocs)
{
*((uint64_t*)((uint8_t*)cmd_bo->virt + patchOffset)) = alloc_bo->offset64 + resourceOffset;
}
else
{
*((uint32_t*)((uint8_t*)cmd_bo->virt + patchOffset)) = alloc_bo->offset64 + resourceOffset;
}
// This call will patch the command buffer with the offsets of the indirect state region of the command buffer
ret = mos_bo_emit_reloc(
cmd_bo, // Command buffer
patchOffset, // Offset in the command buffer
alloc_bo, // Allocation object for which the patch will be made.
resourceOffset, // Offset to the indirect state
I915_GEM_DOMAIN_RENDER, // Read domain
(currentPatch->uiWriteOperation) ? I915_GEM_DOMAIN_RENDER : 0x0); // Write domain
#endif
if (ret != 0)
{
MOS_OS_ASSERTMESSAGE("Error patching alloc_bo = 0x%x, cmd_bo = 0x%x.",
(uintptr_t)alloc_bo,
(uintptr_t)cmd_bo);
return MOS_STATUS_UNKNOWN;
}
}
//Add Batch buffer End Command
uint32_t batchBufferEndCmd = MI_BATCHBUFFER_END;
if (MOS_FAILED(Mos_AddCommand(
cmdBuffer,
&batchBufferEndCmd,
sizeof(uint32_t))))
{
MOS_OS_ASSERTMESSAGE("Inserting BB_END failed!");
return MOS_STATUS_UNKNOWN;
}
// Now, we can unmap the video command buffer, since we don't need CPU access anymore.
MOS_OS_CHK_NULL_RETURN(cmdBuffer->OsResource.pGfxResource);
cmdBuffer->OsResource.pGfxResource->Unlock(m_osContext);
int32_t perfData;
if (osContext->pPerfData != nullptr)
{
perfData = *(int32_t *)(osContext->pPerfData);
}
else
{
perfData = 0;
}
drm_clip_rect_t *cliprects = nullptr;
int32_t num_cliprects = 0;
int32_t DR4 = osContext->uEnablePerfTag ? perfData : 0;
if (gpuNode == I915_EXEC_RENDER)
{
if (true == osInterface->osCpInterface->IsHMEnabled())
{
osInterface->pfnGetPlatform(osInterface,&platform);
if (platform.eProductFamily < IGFX_BROXTON)
{
cliprects = (drm_clip_rect *)(&addCb2);
num_cliprects = sizeof(addCb2);
}
}
}
else
{
if (osContext->bKMDHasVCS2)
{
if (osContext->bPerCmdBufferBalancing && osInterface->pfnGetVdboxNodeId)
{
execFlag = GetVcsExecFlag(osInterface, cmdBuffer, gpuNode);
}
else if (gpuNode == MOS_GPU_NODE_VIDEO)
{
execFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING1;
}
else if (gpuNode == MOS_GPU_NODE_VIDEO2)
{
execFlag = I915_EXEC_BSD | I915_EXEC_BSD_RING2;
}
}
}
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_LINUX_BO *bad_cmd_bo;
MOS_LINUX_BO *nop_cmd_bo;
uint32_t dwComponentTag;
uint32_t dwCallType;
// trigger GPU HANG if bTriggerCodecHang is set
bad_cmd_bo = nullptr;
//dwComponentTag 3: decode,5: vpp,6: encode
//dwCallType 8: PAK(CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE)
// 34: PREENC
// 5: VPP
dwComponentTag = (perfData & 0xF000) >> 12;
dwCallType = (perfData & 0xFC) >> 2;
if (osInterface->bTriggerCodecHang &&
(dwComponentTag == 3 || (dwComponentTag == 6 && dwCallType == 8) ||
(dwComponentTag == 6 && dwCallType == 34) ||
(dwComponentTag == 5 && dwCallType == 5)))
{
bad_cmd_bo = Mos_GetBadCommandBuffer_Linux(osInterface);
if (bad_cmd_bo)
{
ret = mos_bo_mrb_exec(bad_cmd_bo,
4096,
nullptr,
0,
0,
execFlag);
}
}
else if (osInterface->bTriggerVPHang == true)
{
bad_cmd_bo = Mos_GetBadCommandBuffer_Linux(osInterface);
if (bad_cmd_bo)
{
ret = mos_bo_mrb_exec(bad_cmd_bo,
4096,
nullptr,
0,
0,
execFlag);
}
osInterface->bTriggerVPHang = false;
}
nop_cmd_bo = nullptr;
if (nullRendering == true)
{
nop_cmd_bo = Mos_GetNopCommandBuffer_Linux(osInterface);
if (nop_cmd_bo)
{
ret = mos_bo_mrb_exec(nop_cmd_bo,
4096,
nullptr,
0,
0,
execFlag);
}
}
#endif //(_DEBUG || _RELEASE_INTERNAL)
if (gpuNode != I915_EXEC_RENDER &&
osInterface->osCpInterface->IsTearDownHappen())
{
// skip PAK command when CP tear down happen to avoid of GPU hang
// conditonal batch buffer start PoC is in progress
}
else if (nullRendering == false)
{
#ifdef ANDROID
if (osContext->uEnablePerfTag == 2)
{
ret = mos_gem_bo_tag_exec(cmd_bo,
m_commandBufferSize,
osContext->intel_context,
cliprects,
num_cliprects,
0,
execFlag,
perfData);
}
else
{
ret = mos_bo_mrb_exec(cmd_bo,
m_commandBufferSize,
cliprects,
num_cliprects,
DR4,
execFlag);
}
#else
ret = mos_gem_bo_context_exec2(cmd_bo,
m_commandBufferSize,
osContext->intel_context,
cliprects,
num_cliprects,
DR4,
execFlag);
#endif
if (ret != 0)
{
eStatus = MOS_STATUS_UNKNOWN;
}
}
if (eStatus != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("Command buffer submission failed!");
}
MOS_DEVULT_FuncCall(pfnUltGetCmdBuf, cmdBuffer);
#if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
pthread_mutex_lock(&command_dump_mutex);
if (osInterface->bDumpCommandBuffer)
{
mos_bo_map(cmd_bo, 0);
osInterface->pfnDumpCommandBuffer(osInterface, cmdBuffer);
mos_bo_unmap(cmd_bo);
}
pthread_mutex_unlock(&command_dump_mutex);
#endif // MOS_COMMAND_BUFFER_DUMP_SUPPORTED
#if (_DEBUG || _RELEASE_INTERNAL)
if (bad_cmd_bo)
{
mos_bo_wait_rendering(bad_cmd_bo);
mos_bo_unreference(bad_cmd_bo);
}
if (nop_cmd_bo)
{
mos_bo_unreference(nop_cmd_bo);
}
#endif //(_DEBUG || _RELEASE_INTERNAL)
//clear command buffer relocations to fix memory leak issue
mos_gem_bo_clear_relocs(cmd_bo, 0);
// Reset resource allocation
m_numAllocations = 0;
MOS_ZeroMemory(m_allocationList, sizeof(ALLOCATION_LIST) * m_maxNumAllocations);
m_currentNumPatchLocations = 0;
MOS_ZeroMemory(m_patchLocationList, sizeof(PATCHLOCATIONLIST) * m_maxNumAllocations);
m_resCount = 0;
MOS_ZeroMemory(m_writeModeList, sizeof(bool) * m_maxNumAllocations);
finish:
return eStatus;
}
void GpuContextSpecific::IncrementGpuStatusTag()
{
m_GPUStatusTag = m_GPUStatusTag % UINT_MAX + 1;
if (m_GPUStatusTag == 0)
{
m_GPUStatusTag = 1;
}
}
void GpuContextSpecific::ResetGpuContextStatus()
{
MOS_ZeroMemory(m_allocationList, sizeof(ALLOCATION_LIST) * ALLOCATIONLIST_SIZE);
m_numAllocations = 0;
MOS_ZeroMemory(m_patchLocationList, sizeof(PATCHLOCATIONLIST) * PATCHLOCATIONLIST_SIZE);
m_currentNumPatchLocations = 0;
MOS_ZeroMemory(m_attachedResources, sizeof(MOS_RESOURCE) * ALLOCATIONLIST_SIZE);
m_resCount = 0;
MOS_ZeroMemory(m_writeModeList, sizeof(bool) * ALLOCATIONLIST_SIZE);
if ((m_cmdBufFlushed == true) && m_commandBuffer->OsResource.bo)
{
m_commandBuffer->OsResource.bo = nullptr;
}
}
MOS_STATUS GpuContextSpecific::AllocateGPUStatusBuf()
{
MOS_OS_FUNCTION_ENTER;
GraphicsResource::CreateParams params;
params.m_tileType = MOS_TILE_LINEAR;
params.m_type = MOS_GFXRES_BUFFER;
params.m_format = Format_Buffer;
params.m_width = sizeof(MOS_GPU_STATUS_DATA);
params.m_height = 1;
params.m_depth = 1;
params.m_arraySize = 1;
params.m_name = "GPU Status Buffer";
GraphicsResource *graphicsResource = GraphicsResource::CreateGraphicResource(GraphicsResource::osSpecificResource);
MOS_OS_CHK_NULL_RETURN(graphicsResource);
MOS_OS_CHK_STATUS_RETURN(graphicsResource->Allocate(m_osContext, params));
GraphicsResource::LockParams lockParams;
lockParams.m_writeRequest = true;
auto gpuStatusData = (MOS_GPU_STATUS_DATA *)graphicsResource->Lock(m_osContext, lockParams);
if (gpuStatusData == nullptr)
{
MOS_OS_ASSERTMESSAGE("Unable to lock gpu eStatus buffer for read.");
graphicsResource->Free(m_osContext);
MOS_Delete(graphicsResource);
return MOS_STATUS_UNKNOWN;
}
m_statusBufferResource = graphicsResource;
return MOS_STATUS_SUCCESS;
}