blob: 9ba3f92f981ea9a84de4abb436573fcd39071c48 [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 media_cmd_task.cpp
//! \brief Defines the interface for media cmd task
//! \details The media cmd task is dedicated for command buffer submission
//!
#include "media_cmd_task.h"
#include "media_packet.h"
#include "media_utils.h"
CmdTask::CmdTask(PMOS_INTERFACE osInterface)
: m_osInterface(osInterface)
{
}
MOS_STATUS CmdTask::CalculateCmdBufferSizeFromActivePackets()
{
uint32_t curCommandBufferSize = 0;
uint32_t curRequestedPatchListSize = 0;
m_cmdBufSize = 0;
m_patchListSize = 0;
for (auto prop : m_packets)
{
// Calculate total size based on pipe 0
if (prop.stateProperty.currentPipe == 0)
{
auto packetId = prop.packetId;
auto packet = prop.packet;
MEDIA_CHK_NULL_RETURN(packet);
curCommandBufferSize = 0;
curRequestedPatchListSize = 0;
packet->CalculateCommandSize(curCommandBufferSize, curRequestedPatchListSize);
m_cmdBufSize += curCommandBufferSize;
m_patchListSize += curRequestedPatchListSize;
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CmdTask::Submit(bool immediateSubmit, MediaScalability *scalability, CodechalDebugInterface *debugInterface)
{
MEDIA_CHK_NULL_RETURN(scalability);
// Algin this variable in pipeline, packet and scalability.
bool singleTaskPhaseSupportedInPak = false;
MEDIA_CHK_STATUS_RETURN(CalculateCmdBufferSizeFromActivePackets());
// prepare cmd buffer
MOS_COMMAND_BUFFER cmdBuffer;
// initialize the command buffer struct
MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
if (m_packets.size() > 0)
{
MEDIA_CHK_STATUS_RETURN(scalability->UpdateState(&m_packets[0].stateProperty));
// VerifyCmdBuffer could be called for duplicated times for singleTaskPhase mult-pass cases
// Each task submit verify only once
MEDIA_CHK_STATUS_RETURN(scalability->VerifyCmdBuffer(m_cmdBufSize, m_patchListSize, singleTaskPhaseSupportedInPak));
}
else
{
SCALABILITY_ASSERTMESSAGE("No packets to execute in the task!");
return MOS_STATUS_INVALID_PARAMETER;
}
int8_t curPipe = -1;
for (auto& prop : m_packets)
{
MEDIA_CHK_STATUS_RETURN(scalability->UpdateState(&prop.stateProperty));
auto packet = prop.packet;
uint8_t packetPhase = MediaPacket::otherPacket;
MEDIA_CHK_NULL_RETURN(packet);
MEDIA_CHK_STATUS_RETURN(packet->Prepare());
MEDIA_CHK_STATUS_RETURN(scalability->GetCmdBuffer(&cmdBuffer, prop.frameTrackingRequested));
//Set first packet for each pipe in the first pass, used for prolog & forcewakeup insertion
if (scalability->GetCurrentPass() == 0 && curPipe < scalability->GetCurrentPipe())
{
packetPhase = MediaPacket::firstPacket;
}
curPipe = scalability->GetCurrentPipe();
MEDIA_CHK_STATUS_RETURN(packet->Submit(&cmdBuffer, packetPhase));
MEDIA_CHK_STATUS_RETURN(scalability->ReturnCmdBuffer(&cmdBuffer));
}
#if (_DEBUG || _RELEASE_INTERNAL)
MEDIA_CHK_STATUS_RETURN(DumpCmdBufferAllPipes(&cmdBuffer, debugInterface, scalability));
#endif // _DEBUG || _RELEASE_INTERNAL
// submit cmd buffer
MEDIA_CHK_STATUS_RETURN(scalability->SubmitCmdBuffer(&cmdBuffer));
#if (_DEBUG || _RELEASE_INTERNAL)
for (auto prop : m_packets)
{
MEDIA_CHK_STATUS_RETURN(scalability->UpdateState(&prop.stateProperty));
auto packet = prop.packet;
MEDIA_CHK_NULL_RETURN(packet);
MEDIA_CHK_STATUS_RETURN(packet->DumpOutput());
}
#endif // _DEBUG || _RELEASE_INTERNAL
// clear the packet lists since all commands are composed into command buffer
m_packets.clear();
return MOS_STATUS_SUCCESS;
}
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_STATUS CmdTask::DumpCmdBuffer(PMOS_COMMAND_BUFFER cmdBuffer, CodechalDebugInterface *debugInterface, uint8_t pipeIdx)
{
MEDIA_CHK_NULL_RETURN(cmdBuffer);
if (debugInterface)
{
std::string packetName = "";
for (auto prop : m_packets)
{
// Construct cmd buffer dump name only from packets in pipe 0
if (prop.stateProperty.currentPipe == 0)
{
packetName += prop.packet->GetPacketName();
break;
}
}
// Put pipe index to file name
std::stringstream pipeIdxStrStream;
pipeIdxStrStream << "_" << uint32_t(pipeIdx);
packetName += pipeIdxStrStream.str();
MEDIA_CHK_STATUS_RETURN(debugInterface->DumpCmdBuffer(
cmdBuffer,
CODECHAL_NUM_MEDIA_STATES,
packetName.data()));
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CmdTask::DumpCmdBufferAllPipes(PMOS_COMMAND_BUFFER cmdBuffer, CodechalDebugInterface *debugInterface, MediaScalability *scalability)
{
MEDIA_CHK_NULL_RETURN(cmdBuffer);
MEDIA_CHK_NULL_RETURN(scalability);
if (debugInterface)
{
auto pipeNum = scalability->GetPipeNumber();
auto lastPipeIndex = scalability->GetCurrentPipe();
for (uint8_t pipeIdx = 0; pipeIdx < pipeNum; pipeIdx++)
{
scalability->SetCurrentPipeIndex(pipeIdx);
MEDIA_CHK_STATUS_RETURN(scalability->GetCmdBuffer(cmdBuffer));
MEDIA_CHK_STATUS_RETURN(DumpCmdBuffer(cmdBuffer, debugInterface, pipeIdx));
MEDIA_CHK_STATUS_RETURN(scalability->ReturnCmdBuffer(cmdBuffer));
}
// Recover scalability current pipe index after dump
scalability->SetCurrentPipeIndex(lastPipeIndex);
}
return MOS_STATUS_SUCCESS;
}
#endif // _DEBUG || _RELEASE_INTERNAL