2020-01-16 00:02:47 +08:00
|
|
|
/*
|
2023-01-04 23:00:09 +08:00
|
|
|
* Copyright (C) 2020-2023 Intel Corporation
|
2020-01-16 00:02:47 +08:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2021-06-08 03:47:12 +08:00
|
|
|
#include "shared/source/device/device.h"
|
2020-02-24 05:44:01 +08:00
|
|
|
#include "shared/source/direct_submission/windows/wddm_direct_submission.h"
|
|
|
|
#include "shared/source/execution_environment/root_device_environment.h"
|
|
|
|
#include "shared/source/gmm_helper/gmm_helper.h"
|
|
|
|
#include "shared/source/os_interface/windows/os_context_win.h"
|
|
|
|
#include "shared/source/os_interface/windows/wddm/wddm.h"
|
|
|
|
#include "shared/source/os_interface/windows/wddm/wddm_interface.h"
|
2020-04-03 02:15:04 +08:00
|
|
|
#include "shared/source/os_interface/windows/wddm/wddm_residency_logger.h"
|
2020-02-24 05:44:01 +08:00
|
|
|
#include "shared/source/os_interface/windows/wddm_allocation.h"
|
|
|
|
#include "shared/source/os_interface/windows/wddm_memory_operations_handler.h"
|
|
|
|
#include "shared/source/utilities/arrayref.h"
|
2020-01-16 00:02:47 +08:00
|
|
|
|
|
|
|
namespace NEO {
|
|
|
|
|
|
|
|
// Initialize COMMAND_BUFFER_HEADER Type PatchList Streamer Perf Tag
|
|
|
|
DECLARE_COMMAND_BUFFER(CommandBufferHeader, UMD_OCL, FALSE, FALSE, PERFTAG_OCL);
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
2022-04-20 21:55:31 +08:00
|
|
|
WddmDirectSubmission<GfxFamily, Dispatcher>::WddmDirectSubmission(const DirectSubmissionInputParams &inputParams)
|
|
|
|
: DirectSubmissionHw<GfxFamily, Dispatcher>(inputParams) {
|
2022-04-19 22:44:06 +08:00
|
|
|
osContextWin = reinterpret_cast<OsContextWin *>(&this->osContext);
|
2020-01-16 00:02:47 +08:00
|
|
|
wddm = osContextWin->getWddm();
|
|
|
|
commandBufferHeader = std::make_unique<COMMAND_BUFFER_HEADER_REC>();
|
|
|
|
*(commandBufferHeader.get()) = CommandBufferHeader;
|
2022-04-19 22:44:06 +08:00
|
|
|
if (osContextWin->getPreemptionMode() != PreemptionMode::Disabled) {
|
2020-01-16 00:02:47 +08:00
|
|
|
commandBufferHeader->NeedsMidBatchPreEmptionSupport = true;
|
|
|
|
}
|
2020-04-03 20:43:13 +08:00
|
|
|
perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "Starting Wddm ULLS. Placement ring buffer: %d semaphore %d\n",
|
|
|
|
DebugManager.flags.DirectSubmissionBufferPlacement.get(),
|
|
|
|
DebugManager.flags.DirectSubmissionSemaphorePlacement.get());
|
2023-07-31 19:57:53 +08:00
|
|
|
|
|
|
|
this->completionFenceAllocation = inputParams.completionFenceAllocation;
|
|
|
|
UNRECOVERABLE_IF(!this->completionFenceAllocation);
|
|
|
|
if (this->miMemFenceRequired) {
|
|
|
|
this->gpuVaForAdditionalSynchronizationWA = this->completionFenceAllocation->getGpuAddress() + 8u;
|
|
|
|
}
|
2020-01-16 00:02:47 +08:00
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
WddmDirectSubmission<GfxFamily, Dispatcher>::~WddmDirectSubmission() {
|
2020-04-03 02:15:04 +08:00
|
|
|
perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "Stopping Wddm ULLS\n");
|
2021-05-20 04:12:09 +08:00
|
|
|
if (this->ringStart) {
|
2023-07-05 16:55:12 +08:00
|
|
|
this->stopRingBuffer(true);
|
2020-01-16 00:02:47 +08:00
|
|
|
}
|
2021-05-20 04:12:09 +08:00
|
|
|
this->deallocateResources();
|
2020-01-16 00:02:47 +08:00
|
|
|
wddm->getWddmInterface()->destroyMonitorFence(ringFence);
|
|
|
|
}
|
|
|
|
|
2023-08-07 21:33:24 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
inline void WddmDirectSubmission<GfxFamily, Dispatcher>::flushMonitorFence() {
|
|
|
|
this->startRingBuffer();
|
|
|
|
|
|
|
|
size_t requiredMinimalSize = this->getSizeSemaphoreSection(false) +
|
|
|
|
Dispatcher::getSizeMonitorFence(this->rootDeviceEnvironment) +
|
|
|
|
this->getSizeNewResourceHandler() +
|
|
|
|
this->getSizeSwitchRingBufferSection() +
|
|
|
|
this->getSizeEnd(false);
|
|
|
|
this->switchRingBuffersNeeded(requiredMinimalSize);
|
|
|
|
|
|
|
|
this->handleNewResourcesSubmission();
|
|
|
|
|
|
|
|
TagData currentTagData = {};
|
|
|
|
this->getTagAddressValue(currentTagData);
|
|
|
|
Dispatcher::dispatchMonitorFence(this->ringCommandStream, currentTagData.tagAddress, currentTagData.tagValue, this->rootDeviceEnvironment, this->useNotifyForPostSync, this->partitionedMode, this->dcFlushRequired);
|
|
|
|
|
|
|
|
this->dispatchSemaphoreSection(this->currentQueueWorkCount + 1);
|
|
|
|
this->handleResidency();
|
|
|
|
this->unblockGpu();
|
|
|
|
this->currentQueueWorkCount++;
|
|
|
|
|
2023-08-30 18:05:58 +08:00
|
|
|
this->updateTagValueImpl();
|
2023-08-07 21:33:24 +08:00
|
|
|
}
|
|
|
|
|
2023-07-05 16:55:12 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
void WddmDirectSubmission<GfxFamily, Dispatcher>::ensureRingCompletion() {
|
|
|
|
WddmDirectSubmission<GfxFamily, Dispatcher>::handleCompletionFence(ringFence.lastSubmittedFence, ringFence);
|
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
2020-07-17 17:28:59 +08:00
|
|
|
bool WddmDirectSubmission<GfxFamily, Dispatcher>::allocateOsResources() {
|
2023-01-04 23:00:09 +08:00
|
|
|
// for now only WDDM2.0
|
2020-01-16 00:02:47 +08:00
|
|
|
UNRECOVERABLE_IF(wddm->getWddmVersion() != WddmVersion::WDDM_2_0);
|
|
|
|
|
|
|
|
bool ret = wddm->getWddmInterface()->createMonitoredFence(ringFence);
|
|
|
|
ringFence.currentFenceValue = 1;
|
2020-04-03 02:15:04 +08:00
|
|
|
perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "ULLS resource allocation finished with: %d\n", ret);
|
2020-01-16 00:02:47 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
bool WddmDirectSubmission<GfxFamily, Dispatcher>::submit(uint64_t gpuAddress, size_t size) {
|
2020-04-03 02:15:04 +08:00
|
|
|
perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "ULLS Submit to GPU\n");
|
2020-01-16 00:02:47 +08:00
|
|
|
COMMAND_BUFFER_HEADER *pHeader = reinterpret_cast<COMMAND_BUFFER_HEADER *>(commandBufferHeader.get());
|
|
|
|
pHeader->RequiresCoherency = false;
|
|
|
|
|
|
|
|
pHeader->UmdRequestedSliceState = 0;
|
2020-03-23 20:26:56 +08:00
|
|
|
pHeader->UmdRequestedEUCount = wddm->getRequestedEUCount();
|
2020-01-16 00:02:47 +08:00
|
|
|
|
|
|
|
pHeader->UmdRequestedSubsliceCount = 0;
|
|
|
|
pHeader->NeedsMidBatchPreEmptionSupport = true;
|
|
|
|
|
|
|
|
WddmSubmitArguments submitArgs = {};
|
|
|
|
submitArgs.contextHandle = osContextWin->getWddmContextHandle();
|
|
|
|
submitArgs.hwQueueHandle = osContextWin->getHwQueue().handle;
|
|
|
|
submitArgs.monitorFence = &ringFence;
|
|
|
|
|
|
|
|
return wddm->submit(gpuAddress, size, pHeader, submitArgs);
|
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
bool WddmDirectSubmission<GfxFamily, Dispatcher>::handleResidency() {
|
2020-01-16 00:02:47 +08:00
|
|
|
wddm->waitOnPagingFenceFromCpu();
|
2020-04-03 20:43:13 +08:00
|
|
|
perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "ULLS residency wait exit\n");
|
2020-01-16 00:02:47 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-08-07 21:33:24 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
void WddmDirectSubmission<GfxFamily, Dispatcher>::handleStopRingBuffer() {
|
|
|
|
if (this->disableMonitorFence) {
|
|
|
|
MonitoredFence ¤tFence = osContextWin->getResidencyController().getMonitoredFence();
|
|
|
|
currentFence.lastSubmittedFence = currentFence.currentFenceValue;
|
|
|
|
currentFence.currentFenceValue++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
2020-07-17 17:28:59 +08:00
|
|
|
void WddmDirectSubmission<GfxFamily, Dispatcher>::handleSwitchRingBuffers() {
|
2023-08-07 21:33:24 +08:00
|
|
|
if (this->disableMonitorFence) {
|
|
|
|
MonitoredFence ¤tFence = osContextWin->getResidencyController().getMonitoredFence();
|
|
|
|
currentFence.lastSubmittedFence = currentFence.currentFenceValue;
|
|
|
|
currentFence.currentFenceValue++;
|
|
|
|
|
|
|
|
this->ringBuffers[this->currentRingBuffer].completionFence = currentFence.lastSubmittedFence;
|
|
|
|
}
|
2020-01-16 00:02:47 +08:00
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
2023-09-20 20:54:50 +08:00
|
|
|
uint64_t WddmDirectSubmission<GfxFamily, Dispatcher>::updateTagValue(bool requireMonitorFence) {
|
2023-11-03 00:30:57 +08:00
|
|
|
if (this->detectGpuHang) {
|
|
|
|
bool osHang = wddm->isGpuHangDetected(*osContextWin);
|
|
|
|
bool ringHang = *ringFence.cpuAddress == Wddm::gpuHangIndication;
|
|
|
|
|
|
|
|
if (osHang || ringHang) {
|
|
|
|
wddm->getDeviceState();
|
|
|
|
return DirectSubmissionHw<GfxFamily, Dispatcher>::updateTagValueFail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-20 20:54:50 +08:00
|
|
|
if (!this->disableMonitorFence || requireMonitorFence) {
|
2023-08-30 18:05:58 +08:00
|
|
|
return this->updateTagValueImpl();
|
2023-08-07 21:33:24 +08:00
|
|
|
}
|
|
|
|
return 0ull;
|
2020-01-16 00:02:47 +08:00
|
|
|
}
|
|
|
|
|
2023-08-30 18:05:58 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
2023-09-20 20:54:50 +08:00
|
|
|
bool WddmDirectSubmission<GfxFamily, Dispatcher>::dispatchMonitorFenceRequired(bool requireMonitorFence) {
|
|
|
|
return !this->disableMonitorFence || requireMonitorFence;
|
2023-08-30 18:05:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
uint64_t WddmDirectSubmission<GfxFamily, Dispatcher>::updateTagValueImpl() {
|
|
|
|
MonitoredFence ¤tFence = osContextWin->getResidencyController().getMonitoredFence();
|
|
|
|
|
|
|
|
currentFence.lastSubmittedFence = currentFence.currentFenceValue;
|
|
|
|
currentFence.currentFenceValue++;
|
|
|
|
this->ringBuffers[this->currentRingBuffer].completionFence = currentFence.lastSubmittedFence;
|
|
|
|
|
|
|
|
return currentFence.lastSubmittedFence;
|
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
2022-06-01 18:05:07 +08:00
|
|
|
void WddmDirectSubmission<GfxFamily, Dispatcher>::handleCompletionFence(uint64_t completionValue, MonitoredFence &fence) {
|
2023-09-08 20:08:28 +08:00
|
|
|
wddm->waitFromCpu(completionValue, fence, false);
|
2020-01-16 00:02:47 +08:00
|
|
|
}
|
|
|
|
|
2020-03-27 03:13:10 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
void WddmDirectSubmission<GfxFamily, Dispatcher>::getTagAddressValue(TagData &tagData) {
|
2020-01-16 00:02:47 +08:00
|
|
|
MonitoredFence ¤tFence = osContextWin->getResidencyController().getMonitoredFence();
|
2022-04-29 21:28:15 +08:00
|
|
|
auto gmmHelper = wddm->getRootDeviceEnvironment().getGmmHelper();
|
2020-01-16 00:02:47 +08:00
|
|
|
|
2022-04-29 21:28:15 +08:00
|
|
|
tagData.tagAddress = gmmHelper->canonize(currentFence.gpuAddress);
|
2020-01-16 00:02:47 +08:00
|
|
|
tagData.tagValue = currentFence.currentFenceValue;
|
|
|
|
}
|
|
|
|
|
2022-06-01 18:05:07 +08:00
|
|
|
template <typename GfxFamily, typename Dispatcher>
|
|
|
|
inline bool WddmDirectSubmission<GfxFamily, Dispatcher>::isCompleted(uint32_t ringBufferIndex) {
|
|
|
|
MonitoredFence ¤tFence = osContextWin->getResidencyController().getMonitoredFence();
|
|
|
|
auto lastSubmittedFence = this->ringBuffers[ringBufferIndex].completionFence;
|
|
|
|
if (lastSubmittedFence > *currentFence.cpuAddress) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-16 00:02:47 +08:00
|
|
|
} // namespace NEO
|