2018-10-04 00:52:51 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2018 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2018-10-09 17:03:07 +02:00
|
|
|
#include "runtime/os_interface/windows/wddm_residency_controller.h"
|
2018-10-04 00:52:51 +02:00
|
|
|
#include "runtime/os_interface/windows/wddm_allocation.h"
|
|
|
|
|
#include "runtime/os_interface/debug_settings_manager.h"
|
2018-10-15 17:12:55 +02:00
|
|
|
#include "runtime/utilities/spinlock.h"
|
2018-10-04 00:52:51 +02:00
|
|
|
|
|
|
|
|
namespace OCLRT {
|
|
|
|
|
|
2018-10-09 17:03:07 +02:00
|
|
|
WddmResidencyController::WddmResidencyController(uint32_t osContextId) : osContextId(osContextId) {}
|
2018-10-04 00:52:51 +02:00
|
|
|
|
|
|
|
|
void WddmResidencyController::acquireLock() {
|
|
|
|
|
bool previousLockValue = false;
|
|
|
|
|
while (!lock.compare_exchange_weak(previousLockValue, true))
|
|
|
|
|
previousLockValue = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmResidencyController::releaseLock() {
|
|
|
|
|
lock = false;
|
|
|
|
|
}
|
2018-10-04 00:52:51 +02:00
|
|
|
|
2018-10-15 17:12:55 +02:00
|
|
|
void WddmResidencyController::acquireTrimCallbackLock() {
|
|
|
|
|
SpinLock spinLock;
|
|
|
|
|
spinLock.enter(this->trimCallbackLock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmResidencyController::releaseTrimCallbackLock() {
|
|
|
|
|
SpinLock spinLock;
|
|
|
|
|
spinLock.leave(this->trimCallbackLock);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-04 00:52:51 +02:00
|
|
|
WddmAllocation *WddmResidencyController::getTrimCandidateHead() {
|
|
|
|
|
uint32_t i = 0;
|
|
|
|
|
const size_t size = trimCandidateList.size();
|
|
|
|
|
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
while ((trimCandidateList[i] == nullptr) && (i < size))
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
return reinterpret_cast<WddmAllocation *>(trimCandidateList[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmResidencyController::addToTrimCandidateList(GraphicsAllocation *allocation) {
|
|
|
|
|
WddmAllocation *wddmAllocation = (WddmAllocation *)allocation;
|
|
|
|
|
size_t position = trimCandidateList.size();
|
|
|
|
|
|
|
|
|
|
DEBUG_BREAK_IF(trimCandidatesCount > trimCandidateList.size());
|
|
|
|
|
|
2018-10-09 17:03:07 +02:00
|
|
|
if (wddmAllocation->getTrimCandidateListPosition(this->osContextId) == trimListUnusedPosition) {
|
2018-10-04 00:52:51 +02:00
|
|
|
trimCandidatesCount++;
|
|
|
|
|
trimCandidateList.push_back(allocation);
|
2018-10-09 17:03:07 +02:00
|
|
|
wddmAllocation->setTrimCandidateListPosition(this->osContextId, position);
|
2018-10-04 00:52:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkTrimCandidateCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmResidencyController::removeFromTrimCandidateList(GraphicsAllocation *allocation, bool compactList) {
|
|
|
|
|
WddmAllocation *wddmAllocation = (WddmAllocation *)allocation;
|
2018-10-09 17:03:07 +02:00
|
|
|
size_t position = wddmAllocation->getTrimCandidateListPosition(this->osContextId);
|
2018-10-04 00:52:51 +02:00
|
|
|
|
|
|
|
|
DEBUG_BREAK_IF(!(trimCandidatesCount > (trimCandidatesCount - 1)));
|
|
|
|
|
DEBUG_BREAK_IF(trimCandidatesCount > trimCandidateList.size());
|
|
|
|
|
|
|
|
|
|
trimCandidatesCount--;
|
|
|
|
|
|
|
|
|
|
trimCandidateList[position] = nullptr;
|
|
|
|
|
|
|
|
|
|
checkTrimCandidateCount();
|
|
|
|
|
|
|
|
|
|
if (position == trimCandidateList.size() - 1) {
|
|
|
|
|
size_t erasePosition = position;
|
|
|
|
|
|
|
|
|
|
if (position == 0) {
|
|
|
|
|
trimCandidateList.resize(0);
|
|
|
|
|
} else {
|
|
|
|
|
while (trimCandidateList[erasePosition] == nullptr && erasePosition > 0) {
|
|
|
|
|
erasePosition--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t sizeRemaining = erasePosition + 1;
|
|
|
|
|
if (erasePosition == 0 && trimCandidateList[erasePosition] == nullptr) {
|
|
|
|
|
sizeRemaining = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trimCandidateList.resize(sizeRemaining);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-09 17:03:07 +02:00
|
|
|
wddmAllocation->setTrimCandidateListPosition(this->osContextId, trimListUnusedPosition);
|
2018-10-04 00:52:51 +02:00
|
|
|
|
|
|
|
|
if (compactList && checkTrimCandidateListCompaction()) {
|
|
|
|
|
compactTrimCandidateList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkTrimCandidateCount();
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-09 17:03:07 +02:00
|
|
|
void WddmResidencyController::removeFromTrimCandidateListIfUsed(WddmAllocation *allocation, bool compactList) {
|
|
|
|
|
if (allocation->getTrimCandidateListPosition(this->osContextId) != trimListUnusedPosition) {
|
|
|
|
|
this->removeFromTrimCandidateList(allocation, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-04 00:52:51 +02:00
|
|
|
void WddmResidencyController::checkTrimCandidateCount() {
|
|
|
|
|
if (DebugManager.flags.ResidencyDebugEnable.get()) {
|
|
|
|
|
uint32_t sum = 0;
|
|
|
|
|
for (size_t i = 0; i < trimCandidateList.size(); i++) {
|
|
|
|
|
if (trimCandidateList[i] != nullptr) {
|
|
|
|
|
sum++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DEBUG_BREAK_IF(sum != trimCandidatesCount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WddmResidencyController::checkTrimCandidateListCompaction() {
|
|
|
|
|
if (2 * trimCandidatesCount <= trimCandidateList.size()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmResidencyController::compactTrimCandidateList() {
|
|
|
|
|
size_t size = trimCandidateList.size();
|
|
|
|
|
size_t freePosition = 0;
|
|
|
|
|
|
|
|
|
|
if (size == 0 || size == trimCandidatesCount) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEBUG_BREAK_IF(!(trimCandidateList[size - 1] != nullptr));
|
|
|
|
|
|
|
|
|
|
uint32_t previousCount = trimCandidatesCount;
|
|
|
|
|
DEBUG_BREAK_IF(trimCandidatesCount > trimCandidateList.size());
|
|
|
|
|
|
|
|
|
|
while (freePosition < trimCandidatesCount && trimCandidateList[freePosition] != nullptr)
|
|
|
|
|
freePosition++;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 1; i < size; i++) {
|
|
|
|
|
|
|
|
|
|
if (trimCandidateList[i] != nullptr && freePosition < i) {
|
|
|
|
|
trimCandidateList[freePosition] = trimCandidateList[i];
|
|
|
|
|
trimCandidateList[i] = nullptr;
|
2018-10-09 17:03:07 +02:00
|
|
|
static_cast<WddmAllocation *>(trimCandidateList[freePosition])->setTrimCandidateListPosition(this->osContextId, freePosition);
|
2018-10-04 00:52:51 +02:00
|
|
|
freePosition++;
|
|
|
|
|
|
|
|
|
|
// Last element was moved, erase elements from freePosition
|
|
|
|
|
if (i == size - 1) {
|
|
|
|
|
trimCandidateList.resize(freePosition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DEBUG_BREAK_IF(trimCandidatesCount > trimCandidateList.size());
|
|
|
|
|
DEBUG_BREAK_IF(trimCandidatesCount != previousCount);
|
|
|
|
|
|
|
|
|
|
checkTrimCandidateCount();
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-04 00:52:51 +02:00
|
|
|
} // namespace OCLRT
|