/* * 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 #include #include #include "media_scalability.h" #include "media_scalability_defs.h" #include "mos_utilities.h" #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 bool isFirstPacket = scalability->GetCurrentPass() == 0 && curPipe < scalability->GetCurrentPipe(); if (isFirstPacket) { packetPhase = MediaPacket::firstPacket; } if (isFirstPacket || !prop.stateProperty.singleTaskPhaseSupported) { scalability->Oca1stLevelBBStart(cmdBuffer); } curPipe = scalability->GetCurrentPipe(); MEDIA_CHK_STATUS_RETURN(packet->Submit(&cmdBuffer, packetPhase)); MEDIA_CHK_STATUS_RETURN(scalability->ReturnCmdBuffer(&cmdBuffer)); } #if (_DEBUG || _RELEASE_INTERNAL) && !EMUL 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) && !EMUL) 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