/* * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/command_stream/linear_stream.h" #include "shared/source/direct_submission/linux/drm_direct_submission.h" #include "shared/source/os_interface/linux/drm_allocation.h" #include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/os_context_linux.h" #include namespace NEO { template inline std::unique_ptr> DirectSubmissionHw::create(Device &device, OsContext &osContext) { return std::make_unique>(device, osContext); } template DrmDirectSubmission::DrmDirectSubmission(Device &device, OsContext &osContext) : DirectSubmissionHw(device, osContext) { this->disableMonitorFence = true; if (DebugManager.flags.DirectSubmissionDisableMonitorFence.get() != -1) { this->disableMonitorFence = DebugManager.flags.DirectSubmissionDisableMonitorFence.get(); } auto osContextLinux = static_cast(&this->osContext); osContextLinux->getDrm().setDirectSubmissionActive(true); }; template inline DrmDirectSubmission::~DrmDirectSubmission() { if (this->ringStart) { this->stopRingBuffer(); if (this->disableMonitorFence) { this->currentTagData.tagValue++; } this->wait(static_cast(this->currentTagData.tagValue)); auto bb = static_cast(this->ringBuffer)->getBO(); bb->wait(-1); } this->deallocateResources(); } template bool DrmDirectSubmission::allocateOsResources() { this->currentTagData.tagAddress = this->semaphoreGpuVa + MemoryConstants::cacheLineSize; this->currentTagData.tagValue = 0u; this->tagAddress = reinterpret_cast(reinterpret_cast(this->semaphorePtr) + MemoryConstants::cacheLineSize); return true; } template bool DrmDirectSubmission::submit(uint64_t gpuAddress, size_t size) { auto bb = static_cast(this->ringCommandStream.getGraphicsAllocation())->getBO(); auto osContextLinux = static_cast(&this->osContext); auto execFlags = osContextLinux->getEngineFlag() | I915_EXEC_NO_RELOC; auto &drmContextIds = osContextLinux->getDrmContextIds(); drm_i915_gem_exec_object2 execObject{}; this->handleResidency(); bool ret = false; uint32_t drmContextId = 0u; for (auto drmIterator = 0u; drmIterator < osContextLinux->getDeviceBitfield().size(); drmIterator++) { if (osContextLinux->getDeviceBitfield().test(drmIterator)) { ret |= !!bb->exec(static_cast(size), 0, execFlags, false, &this->osContext, drmIterator, drmContextIds[drmContextId], nullptr, 0, &execObject); drmContextId++; } } return !ret; } template bool DrmDirectSubmission::handleResidency() { auto osContextLinux = static_cast(&this->osContext); osContextLinux->waitForPagingFence(); return true; } template bool DrmDirectSubmission::isNewResourceHandleNeeded() { auto osContextLinux = static_cast(&this->osContext); auto newResourcesBound = osContextLinux->getDrm().getNewResourceBound(); if (DebugManager.flags.DirectSubmissionNewResourceTlbFlush.get() != -1) { newResourcesBound = DebugManager.flags.DirectSubmissionNewResourceTlbFlush.get(); } return newResourcesBound; } template void DrmDirectSubmission::handleNewResourcesSubmission() { if (isNewResourceHandleNeeded()) { Dispatcher::dispatchTlbFlush(this->ringCommandStream); } auto osContextLinux = static_cast(&this->osContext); if (!EngineHelpers::isBcs(osContextLinux->getEngineType())) { osContextLinux->getDrm().setNewResourceBound(false); } } template size_t DrmDirectSubmission::getSizeNewResourceHandler() { size_t size = 0u; if (isNewResourceHandleNeeded()) { size += Dispatcher::getSizeTlbFlush(); } return size; } template void DrmDirectSubmission::handleSwitchRingBuffers() { if (this->disableMonitorFence) { auto previousRingBuffer = this->currentRingBuffer == DirectSubmissionHw::RingBufferUse::FirstBuffer ? DirectSubmissionHw::RingBufferUse::SecondBuffer : DirectSubmissionHw::RingBufferUse::FirstBuffer; this->currentTagData.tagValue++; this->completionRingBuffers[previousRingBuffer] = this->currentTagData.tagValue; } if (this->ringStart) { if (this->completionRingBuffers[this->currentRingBuffer] != 0) { this->wait(static_cast(this->completionRingBuffers[this->currentRingBuffer])); } } } template uint64_t DrmDirectSubmission::updateTagValue() { if (!this->disableMonitorFence) { this->currentTagData.tagValue++; this->completionRingBuffers[this->currentRingBuffer] = this->currentTagData.tagValue; } return 0ull; } template void DrmDirectSubmission::getTagAddressValue(TagData &tagData) { tagData.tagAddress = this->currentTagData.tagAddress; tagData.tagValue = this->currentTagData.tagValue + 1; } template void DrmDirectSubmission::wait(uint32_t taskCountToWait) { while (taskCountToWait > *this->tagAddress) { } } } // namespace NEO