/* * Copyright (C) 2017-2018 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "runtime/command_stream/linear_stream.h" #include "hw_cmds.h" #include "runtime/execution_environment/execution_environment.h" #include "runtime/gmm_helper/gmm_helper.h" #include "runtime/helpers/aligned_memory.h" #include "runtime/helpers/preamble.h" #include "runtime/mem_obj/buffer.h" #include "runtime/os_interface/linux/drm_buffer_object.h" #include "runtime/os_interface/linux/drm_command_stream.h" #include "runtime/os_interface/linux/drm_engine_mapper.h" #include "runtime/os_interface/linux/drm_memory_manager.h" #include "runtime/os_interface/linux/drm_neo.h" #include "runtime/os_interface/linux/os_interface.h" #include "runtime/platform/platform.h" #include #include namespace OCLRT { template DrmCommandStreamReceiver::DrmCommandStreamReceiver(const HardwareInfo &hwInfoIn, ExecutionEnvironment &executionEnvironment, gemCloseWorkerMode mode) : BaseClass(hwInfoIn, executionEnvironment), gemCloseWorkerOperationMode(mode) { if (!executionEnvironment.osInterface) { executionEnvironment.osInterface = std::make_unique(); this->drm = Drm::get(0); } else { this->drm = executionEnvironment.osInterface->get()->getDrm() ? executionEnvironment.osInterface->get()->getDrm() : Drm::get(0); } residency.reserve(512); execObjectsStorage.reserve(512); executionEnvironment.osInterface->get()->setDrm(this->drm); CommandStreamReceiver::osInterface = executionEnvironment.osInterface.get(); auto gmmHelper = platform()->peekExecutionEnvironment()->getGmmHelper(); gmmHelper->setSimplifiedMocsTableUsage(this->drm->getSimplifiedMocsTableUsage()); } template FlushStamp DrmCommandStreamReceiver::flush(BatchBuffer &batchBuffer, EngineType engineType, ResidencyContainer &allocationsForResidency, OsContext &osContext) { unsigned int engineFlag = 0xFF; bool ret = DrmEngineMapper::engineNodeMap(engineType, engineFlag); UNRECOVERABLE_IF(!(ret)); DrmAllocation *alloc = static_cast(batchBuffer.commandBufferAllocation); DEBUG_BREAK_IF(!alloc); size_t alignedStart = (reinterpret_cast(batchBuffer.commandBufferAllocation->getUnderlyingBuffer()) & (MemoryConstants::allocationAlignment - 1)) + batchBuffer.startOffset; BufferObject *bb = alloc->getBO(); FlushStamp flushStamp = 0; if (bb) { flushStamp = bb->peekHandle(); this->processResidency(allocationsForResidency, osContext); // Residency hold all allocation except command buffer, hence + 1 auto requiredSize = this->residency.size() + 1; if (requiredSize > this->execObjectsStorage.size()) { this->execObjectsStorage.resize(requiredSize); } bb->swapResidencyVector(&this->residency); bb->setExecObjectsStorage(this->execObjectsStorage.data()); this->residency.reserve(512); bb->exec(static_cast(alignUp(batchBuffer.usedSize - batchBuffer.startOffset, 8)), alignedStart, engineFlag | I915_EXEC_NO_RELOC, batchBuffer.requiresCoherency, batchBuffer.low_priority); for (auto &surface : *(bb->getResidency())) { surface->setIsResident(false); } bb->getResidency()->clear(); if (this->gemCloseWorkerOperationMode == gemCloseWorkerActive) { bb->reference(); this->getMemoryManager()->peekGemCloseWorker()->push(bb); } } return flushStamp; } template void DrmCommandStreamReceiver::makeResident(GraphicsAllocation &gfxAllocation) { if (gfxAllocation.getUnderlyingBufferSize() == 0) return; CommandStreamReceiver::makeResident(gfxAllocation); } template void DrmCommandStreamReceiver::makeResident(BufferObject *bo) { if (bo && !bo->peekIsResident()) { bo->setIsResident(true); residency.push_back(bo); } } template void DrmCommandStreamReceiver::processResidency(ResidencyContainer &inputAllocationsForResidency, OsContext &osContext) { for (auto &alloc : inputAllocationsForResidency) { auto drmAlloc = reinterpret_cast(alloc); if (drmAlloc->fragmentsStorage.fragmentCount) { for (unsigned int f = 0; f < drmAlloc->fragmentsStorage.fragmentCount; f++) { makeResident(drmAlloc->fragmentsStorage.fragmentStorageData[f].osHandleStorage->bo); drmAlloc->fragmentsStorage.fragmentStorageData[f].residency->resident = true; } } else { BufferObject *bo = drmAlloc->getBO(); makeResident(bo); } } } template void DrmCommandStreamReceiver::makeNonResident(GraphicsAllocation &gfxAllocation) { // Vector is moved to command buffer inside flush. // If flush wasn't called we need to make all objects non-resident. // If makeNonResident is called before flush, vector will be cleared. if (gfxAllocation.residencyTaskCount[this->deviceIndex] != ObjectNotResident) { for (auto &surface : residency) { surface->setIsResident(false); } if (this->residency.size() != 0) { this->residency.clear(); } if (gfxAllocation.fragmentsStorage.fragmentCount) { for (auto fragmentId = 0u; fragmentId < gfxAllocation.fragmentsStorage.fragmentCount; fragmentId++) { gfxAllocation.fragmentsStorage.fragmentStorageData[fragmentId].osHandleStorage->bo->setIsResident(false); gfxAllocation.fragmentsStorage.fragmentStorageData[fragmentId].residency->resident = false; } } } gfxAllocation.residencyTaskCount[this->deviceIndex] = ObjectNotResident; } template DrmMemoryManager *DrmCommandStreamReceiver::getMemoryManager() { return (DrmMemoryManager *)CommandStreamReceiver::getMemoryManager(); } template MemoryManager *DrmCommandStreamReceiver::createMemoryManager(bool enable64kbPages, bool enableLocalMemory) { return new DrmMemoryManager(this->drm, this->gemCloseWorkerOperationMode, DebugManager.flags.EnableForcePin.get(), true, this->executionEnvironment); } template bool DrmCommandStreamReceiver::waitForFlushStamp(FlushStamp &flushStamp, OsContext &osContext) { drm_i915_gem_wait wait = {}; wait.bo_handle = static_cast(flushStamp); wait.timeout_ns = -1; drm->ioctl(DRM_IOCTL_I915_GEM_WAIT, &wait); return true; } template inline void DrmCommandStreamReceiver::overrideMediaVFEStateDirty(bool dirty) { this->mediaVfeStateDirty = dirty; this->mediaVfeStateLowPriorityDirty = dirty; } template inline void DrmCommandStreamReceiver::programVFEState(LinearStream &csr, DispatchFlags &dispatchFlags) { bool ¤tContextDirtyFlag = dispatchFlags.lowPriority ? mediaVfeStateLowPriorityDirty : mediaVfeStateDirty; if (currentContextDirtyFlag) { PreambleHelper::programVFEState(&csr, hwInfo, requiredScratchSize, getScratchPatchAddress()); currentContextDirtyFlag = false; } } } // namespace OCLRT