2017-12-21 00:45:38 +01:00
|
|
|
/*
|
2018-09-18 09:11:08 +02:00
|
|
|
* Copyright (C) 2017-2018 Intel Corporation
|
2017-12-21 00:45:38 +01:00
|
|
|
*
|
2018-09-18 09:11:08 +02:00
|
|
|
* SPDX-License-Identifier: MIT
|
2017-12-21 00:45:38 +01:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2018-07-16 17:30:56 +02:00
|
|
|
#include "runtime/os_interface/windows/wddm_memory_manager.h"
|
2018-01-17 16:23:51 +01:00
|
|
|
#include "runtime/command_stream/command_stream_receiver_hw.h"
|
|
|
|
|
#include "runtime/device/device.h"
|
2018-06-21 11:36:47 +02:00
|
|
|
#include "runtime/gmm_helper/gmm.h"
|
2017-12-21 00:45:38 +01:00
|
|
|
#include "runtime/gmm_helper/gmm_helper.h"
|
|
|
|
|
#include "runtime/gmm_helper/resource_info.h"
|
2018-07-16 17:30:56 +02:00
|
|
|
#include "runtime/helpers/aligned_memory.h"
|
|
|
|
|
#include "runtime/helpers/ptr_math.h"
|
2017-12-21 00:45:38 +01:00
|
|
|
#include "runtime/helpers/surface_formats.h"
|
|
|
|
|
#include "runtime/memory_manager/deferrable_deletion.h"
|
2018-07-16 17:30:56 +02:00
|
|
|
#include "runtime/memory_manager/deferred_deleter.h"
|
2018-10-24 08:46:54 +02:00
|
|
|
#include "runtime/memory_manager/host_ptr_manager.h"
|
2018-05-10 11:42:41 +02:00
|
|
|
#include "runtime/os_interface/windows/wddm/wddm.h"
|
2018-07-16 17:30:56 +02:00
|
|
|
#include "runtime/os_interface/windows/wddm_allocation.h"
|
2018-10-04 00:52:51 +02:00
|
|
|
#include "runtime/os_interface/windows/wddm_residency_controller.h"
|
2018-08-27 15:48:29 +02:00
|
|
|
#include "runtime/os_interface/windows/os_context_win.h"
|
|
|
|
|
#include "runtime/platform/platform.h"
|
2017-12-21 00:45:38 +01:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
namespace OCLRT {
|
|
|
|
|
|
|
|
|
|
WddmMemoryManager::~WddmMemoryManager() {
|
|
|
|
|
applyCommonCleanup();
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-04 00:52:51 +02:00
|
|
|
WddmMemoryManager::WddmMemoryManager(bool enable64kbPages, bool enableLocalMemory, Wddm *wddm, ExecutionEnvironment &executionEnvironment) : MemoryManager(enable64kbPages, enableLocalMemory, executionEnvironment) {
|
2017-12-21 00:45:38 +01:00
|
|
|
DEBUG_BREAK_IF(wddm == nullptr);
|
|
|
|
|
this->wddm = wddm;
|
|
|
|
|
allocator32Bit = std::unique_ptr<Allocator32bit>(new Allocator32bit(wddm->getHeap32Base(), wddm->getHeap32Size()));
|
|
|
|
|
asyncDeleterEnabled = DebugManager.flags.EnableDeferredDeleter.get();
|
|
|
|
|
if (asyncDeleterEnabled)
|
|
|
|
|
deferredDeleter = createDeferredDeleter();
|
2018-01-22 16:43:26 +01:00
|
|
|
mallocRestrictions.minAddress = wddm->getWddmMinAddress();
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void APIENTRY WddmMemoryManager::trimCallback(_Inout_ D3DKMT_TRIMNOTIFICATION *trimNotification) {
|
2018-10-30 14:40:02 +01:00
|
|
|
auto residencyController = static_cast<WddmResidencyController *>(trimNotification->Context);
|
|
|
|
|
DEBUG_BREAK_IF(residencyController == nullptr);
|
2018-10-22 17:15:13 +02:00
|
|
|
|
2018-10-30 14:40:02 +01:00
|
|
|
auto lock = residencyController->acquireTrimCallbackLock();
|
|
|
|
|
residencyController->trimResidency(trimNotification->Flags, trimNotification->NumBytesToTrim);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GraphicsAllocation *WddmMemoryManager::allocateGraphicsMemoryForImage(ImageInfo &imgInfo, Gmm *gmm) {
|
2018-06-21 11:36:47 +02:00
|
|
|
if (!GmmHelper::allowTiling(*imgInfo.imgDesc) && imgInfo.mipCount == 0) {
|
2017-12-21 00:45:38 +01:00
|
|
|
delete gmm;
|
2018-07-09 14:12:32 +02:00
|
|
|
return allocateGraphicsMemory(imgInfo.size);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2018-10-31 10:05:34 +01:00
|
|
|
auto allocation = std::make_unique<WddmAllocation>(nullptr, imgInfo.size, nullptr, MemoryPool::SystemCpuInaccessible, getOsContextCount());
|
2018-03-01 10:08:20 +01:00
|
|
|
allocation->gmm = gmm;
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
if (!WddmMemoryManager::createWddmAllocation(allocation.get(), AllocationOrigin::EXTERNAL_ALLOCATION)) {
|
2018-02-06 22:43:38 +01:00
|
|
|
return nullptr;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2018-10-31 10:05:34 +01:00
|
|
|
return allocation.release();
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
2018-07-22 19:27:33 +02:00
|
|
|
GraphicsAllocation *WddmMemoryManager::allocateGraphicsMemory64kb(size_t size, size_t alignment, bool forcePin, bool preferRenderCompressed) {
|
2017-12-21 00:45:38 +01:00
|
|
|
size_t sizeAligned = alignUp(size, MemoryConstants::pageSize64k);
|
|
|
|
|
Gmm *gmm = nullptr;
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
auto wddmAllocation = std::make_unique<WddmAllocation>(nullptr, sizeAligned, nullptr, MemoryPool::System64KBPages, getOsContextCount());
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-08-02 18:24:59 +02:00
|
|
|
gmm = new Gmm(nullptr, sizeAligned, false, preferRenderCompressed, true);
|
2018-03-01 10:08:20 +01:00
|
|
|
wddmAllocation->gmm = gmm;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
if (!wddm->createAllocation64k(wddmAllocation.get())) {
|
2018-03-01 10:08:20 +01:00
|
|
|
delete gmm;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
auto cpuPtr = lockResource(wddmAllocation.get());
|
2018-03-01 10:08:20 +01:00
|
|
|
wddmAllocation->setLocked(true);
|
2018-10-31 10:05:34 +01:00
|
|
|
|
2018-03-01 10:08:20 +01:00
|
|
|
// 64kb map is not needed
|
2018-10-31 10:05:34 +01:00
|
|
|
auto status = wddm->mapGpuVirtualAddress(wddmAllocation.get(), cpuPtr, false, false, false);
|
2018-03-01 10:08:20 +01:00
|
|
|
DEBUG_BREAK_IF(!status);
|
|
|
|
|
wddmAllocation->setCpuPtrAndGpuAddress(cpuPtr, (uint64_t)wddmAllocation->gpuPtr);
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
return wddmAllocation.release();
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
2018-01-04 17:48:46 +01:00
|
|
|
GraphicsAllocation *WddmMemoryManager::allocateGraphicsMemory(size_t size, size_t alignment, bool forcePin, bool uncacheable) {
|
2017-12-21 00:45:38 +01:00
|
|
|
size_t newAlignment = alignment ? alignUp(alignment, MemoryConstants::pageSize) : MemoryConstants::pageSize;
|
|
|
|
|
size_t sizeAligned = size ? alignUp(size, MemoryConstants::pageSize) : MemoryConstants::pageSize;
|
|
|
|
|
void *pSysMem = allocateSystemMemory(sizeAligned, newAlignment);
|
|
|
|
|
Gmm *gmm = nullptr;
|
|
|
|
|
|
|
|
|
|
if (pSysMem == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
auto wddmAllocation = std::make_unique<WddmAllocation>(pSysMem, sizeAligned, nullptr, MemoryPool::System4KBPages, getOsContextCount());
|
2018-10-30 14:44:41 +01:00
|
|
|
wddmAllocation->driverAllocatedCpuPointer = pSysMem;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-06-29 11:48:19 +02:00
|
|
|
gmm = new Gmm(pSysMem, sizeAligned, uncacheable);
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-03-01 10:08:20 +01:00
|
|
|
wddmAllocation->gmm = gmm;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
if (!createWddmAllocation(wddmAllocation.get(), AllocationOrigin::EXTERNAL_ALLOCATION)) {
|
2018-03-01 10:08:20 +01:00
|
|
|
delete gmm;
|
|
|
|
|
freeSystemMemory(pSysMem);
|
|
|
|
|
return nullptr;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2018-10-31 10:05:34 +01:00
|
|
|
return wddmAllocation.release();
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
2018-08-24 15:23:45 +02:00
|
|
|
GraphicsAllocation *WddmMemoryManager::allocateGraphicsMemoryForNonSvmHostPtr(size_t size, void *cpuPtr) {
|
2018-09-10 12:50:45 +02:00
|
|
|
auto alignedPtr = alignDown(cpuPtr, MemoryConstants::pageSize);
|
|
|
|
|
auto offsetInPage = ptrDiff(cpuPtr, alignedPtr);
|
2018-08-24 15:23:45 +02:00
|
|
|
auto alignedSize = alignSizeWholePage(cpuPtr, size);
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
auto wddmAllocation = std::make_unique<WddmAllocation>(cpuPtr, size, nullptr, MemoryPool::System4KBPages, getOsContextCount());
|
2018-08-24 15:23:45 +02:00
|
|
|
wddmAllocation->allocationOffset = offsetInPage;
|
|
|
|
|
|
|
|
|
|
auto gmm = new Gmm(alignedPtr, alignedSize, false);
|
|
|
|
|
|
|
|
|
|
wddmAllocation->gmm = gmm;
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
if (!createWddmAllocation(wddmAllocation.get(), AllocationOrigin::EXTERNAL_ALLOCATION)) {
|
2018-08-24 15:23:45 +02:00
|
|
|
delete gmm;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2018-10-31 10:05:34 +01:00
|
|
|
return wddmAllocation.release();
|
2018-08-24 15:23:45 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
GraphicsAllocation *WddmMemoryManager::allocateGraphicsMemory(size_t size, const void *ptrArg) {
|
|
|
|
|
void *ptr = const_cast<void *>(ptrArg);
|
|
|
|
|
|
|
|
|
|
if (ptr == nullptr) {
|
|
|
|
|
DEBUG_BREAK_IF(true);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2018-01-30 15:07:58 +01:00
|
|
|
|
|
|
|
|
if (mallocRestrictions.minAddress > reinterpret_cast<uintptr_t>(ptrArg)) {
|
|
|
|
|
void *reserve = nullptr;
|
|
|
|
|
void *ptrAligned = alignDown(ptr, MemoryConstants::allocationAlignment);
|
|
|
|
|
size_t sizeAligned = alignSizeWholePage(ptr, size);
|
|
|
|
|
size_t offset = ptrDiff(ptr, ptrAligned);
|
|
|
|
|
|
|
|
|
|
if (!wddm->reserveValidAddressRange(sizeAligned, reserve)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
auto allocation = new WddmAllocation(ptr, size, reserve, MemoryPool::System4KBPages, getOsContextCount());
|
2018-01-30 15:07:58 +01:00
|
|
|
allocation->allocationOffset = offset;
|
|
|
|
|
|
2018-06-29 11:48:19 +02:00
|
|
|
Gmm *gmm = new Gmm(ptrAligned, sizeAligned, false);
|
2018-01-30 15:07:58 +01:00
|
|
|
allocation->gmm = gmm;
|
2018-05-11 17:24:00 +02:00
|
|
|
if (createWddmAllocation(allocation, AllocationOrigin::EXTERNAL_ALLOCATION)) {
|
2018-01-30 15:07:58 +01:00
|
|
|
return allocation;
|
|
|
|
|
}
|
|
|
|
|
freeGraphicsMemory(allocation);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
return MemoryManager::allocateGraphicsMemory(size, ptr);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-09 14:12:32 +02:00
|
|
|
GraphicsAllocation *WddmMemoryManager::allocate32BitGraphicsMemory(size_t size, const void *ptr, AllocationOrigin allocationOrigin) {
|
2017-12-21 00:45:38 +01:00
|
|
|
Gmm *gmm = nullptr;
|
|
|
|
|
const void *ptrAligned = nullptr;
|
|
|
|
|
size_t sizeAligned = size;
|
|
|
|
|
void *pSysMem = nullptr;
|
|
|
|
|
size_t offset = 0;
|
|
|
|
|
|
|
|
|
|
if (ptr) {
|
|
|
|
|
ptrAligned = alignDown(ptr, MemoryConstants::allocationAlignment);
|
|
|
|
|
sizeAligned = alignSizeWholePage(ptr, size);
|
|
|
|
|
offset = ptrDiff(ptr, ptrAligned);
|
|
|
|
|
} else {
|
|
|
|
|
sizeAligned = alignUp(size, MemoryConstants::allocationAlignment);
|
|
|
|
|
pSysMem = allocateSystemMemory(sizeAligned, MemoryConstants::allocationAlignment);
|
|
|
|
|
if (pSysMem == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
ptrAligned = pSysMem;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
auto wddmAllocation = std::make_unique<WddmAllocation>(const_cast<void *>(ptrAligned), sizeAligned, nullptr, MemoryPool::System4KBPagesWith32BitGpuAddressing, getOsContextCount());
|
2018-10-30 14:44:41 +01:00
|
|
|
wddmAllocation->driverAllocatedCpuPointer = pSysMem;
|
2018-03-01 10:08:20 +01:00
|
|
|
wddmAllocation->is32BitAllocation = true;
|
|
|
|
|
wddmAllocation->allocationOffset = offset;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-06-29 11:48:19 +02:00
|
|
|
gmm = new Gmm(ptrAligned, sizeAligned, false);
|
2018-03-01 10:08:20 +01:00
|
|
|
wddmAllocation->gmm = gmm;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
if (!createWddmAllocation(wddmAllocation.get(), allocationOrigin)) {
|
2018-03-01 10:08:20 +01:00
|
|
|
delete gmm;
|
|
|
|
|
freeSystemMemory(pSysMem);
|
|
|
|
|
return nullptr;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
2018-03-01 10:08:20 +01:00
|
|
|
wddmAllocation->is32BitAllocation = true;
|
2018-05-11 17:24:00 +02:00
|
|
|
auto baseAddress = allocationOrigin == AllocationOrigin::EXTERNAL_ALLOCATION ? allocator32Bit->getBase() : this->wddm->getGfxPartition().Heap32[1].Base;
|
2018-06-21 11:36:47 +02:00
|
|
|
wddmAllocation->gpuBaseAddress = GmmHelper::canonize(baseAddress);
|
2018-03-01 10:08:20 +01:00
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
return wddmAllocation.release();
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GraphicsAllocation *WddmMemoryManager::createAllocationFromHandle(osHandle handle, bool requireSpecificBitness, bool ntHandle) {
|
2018-10-31 10:05:34 +01:00
|
|
|
auto allocation = std::make_unique<WddmAllocation>(nullptr, 0, handle, MemoryPool::SystemCpuInaccessible, getOsContextCount());
|
2017-12-21 00:45:38 +01:00
|
|
|
bool is32BitAllocation = false;
|
|
|
|
|
|
2018-10-31 10:05:34 +01:00
|
|
|
bool status = ntHandle ? wddm->openNTHandle((HANDLE)((UINT_PTR)handle), allocation.get())
|
|
|
|
|
: wddm->openSharedHandle(handle, allocation.get());
|
2018-03-01 10:08:20 +01:00
|
|
|
|
|
|
|
|
if (!status) {
|
|
|
|
|
return nullptr;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shared objects are passed without size
|
2018-03-01 10:08:20 +01:00
|
|
|
size_t size = allocation->gmm->gmmResourceInfo->getSizeAllocation();
|
|
|
|
|
allocation->setSize(size);
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
void *ptr = nullptr;
|
|
|
|
|
if (is32bit) {
|
2018-01-30 15:07:58 +01:00
|
|
|
if (!wddm->reserveValidAddressRange(size, ptr)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2018-03-01 10:08:20 +01:00
|
|
|
allocation->setReservedAddress(ptr);
|
2017-12-21 00:45:38 +01:00
|
|
|
} else if (requireSpecificBitness && this->force32bitAllocations) {
|
|
|
|
|
is32BitAllocation = true;
|
2018-03-01 10:08:20 +01:00
|
|
|
allocation->is32BitAllocation = true;
|
2018-06-21 11:36:47 +02:00
|
|
|
allocation->gpuBaseAddress = GmmHelper::canonize(allocator32Bit->getBase());
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2018-10-31 10:05:34 +01:00
|
|
|
status = wddm->mapGpuVirtualAddress(allocation.get(), ptr, is32BitAllocation, false, false);
|
2018-02-06 22:43:38 +01:00
|
|
|
DEBUG_BREAK_IF(!status);
|
2018-03-01 10:08:20 +01:00
|
|
|
allocation->setGpuAddress(allocation->gpuPtr);
|
2018-10-31 10:05:34 +01:00
|
|
|
return allocation.release();
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
2018-08-29 14:50:36 +02:00
|
|
|
GraphicsAllocation *WddmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, bool requireSpecificBitness) {
|
2017-12-21 00:45:38 +01:00
|
|
|
return createAllocationFromHandle(handle, requireSpecificBitness, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GraphicsAllocation *WddmMemoryManager::createGraphicsAllocationFromNTHandle(void *handle) {
|
|
|
|
|
return createAllocationFromHandle((osHandle)((UINT_PTR)handle), false, true);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-08 10:00:23 +02:00
|
|
|
void WddmMemoryManager::addAllocationToHostPtrManager(GraphicsAllocation *gfxAllocation) {
|
|
|
|
|
WddmAllocation *wddmMemory = static_cast<WddmAllocation *>(gfxAllocation);
|
|
|
|
|
FragmentStorage fragment = {};
|
|
|
|
|
fragment.driverAllocation = true;
|
|
|
|
|
fragment.fragmentCpuPointer = gfxAllocation->getUnderlyingBuffer();
|
|
|
|
|
fragment.fragmentSize = alignUp(gfxAllocation->getUnderlyingBufferSize(), MemoryConstants::pageSize);
|
|
|
|
|
|
|
|
|
|
fragment.osInternalStorage = new OsHandle();
|
|
|
|
|
fragment.osInternalStorage->gpuPtr = gfxAllocation->getGpuAddress();
|
2018-06-15 15:44:28 +02:00
|
|
|
fragment.osInternalStorage->handle = wddmMemory->handle;
|
2018-05-08 10:00:23 +02:00
|
|
|
fragment.osInternalStorage->gmm = gfxAllocation->gmm;
|
|
|
|
|
fragment.residency = &wddmMemory->getResidencyData();
|
2018-10-24 08:46:54 +02:00
|
|
|
hostPtrManager->storeFragment(fragment);
|
2018-05-08 10:00:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmMemoryManager::removeAllocationFromHostPtrManager(GraphicsAllocation *gfxAllocation) {
|
|
|
|
|
auto buffer = gfxAllocation->getUnderlyingBuffer();
|
2018-10-24 08:46:54 +02:00
|
|
|
auto fragment = hostPtrManager->getFragment(buffer);
|
2018-05-08 10:00:23 +02:00
|
|
|
if (fragment && fragment->driverAllocation) {
|
|
|
|
|
OsHandle *osStorageToRelease = fragment->osInternalStorage;
|
2018-10-24 08:46:54 +02:00
|
|
|
if (hostPtrManager->releaseHostPtr(buffer)) {
|
2018-05-08 10:00:23 +02:00
|
|
|
delete osStorageToRelease;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
void *WddmMemoryManager::lockResource(GraphicsAllocation *graphicsAllocation) {
|
|
|
|
|
return wddm->lockResource(static_cast<WddmAllocation *>(graphicsAllocation));
|
|
|
|
|
};
|
|
|
|
|
void WddmMemoryManager::unlockResource(GraphicsAllocation *graphicsAllocation) {
|
|
|
|
|
wddm->unlockResource(static_cast<WddmAllocation *>(graphicsAllocation));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void WddmMemoryManager::freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation) {
|
|
|
|
|
WddmAllocation *input = static_cast<WddmAllocation *>(gfxAllocation);
|
2018-01-17 21:28:55 +01:00
|
|
|
DEBUG_BREAK_IF(!validateAllocation(input));
|
|
|
|
|
if (gfxAllocation == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-10-04 00:52:51 +02:00
|
|
|
|
2018-10-10 10:39:02 +02:00
|
|
|
for (auto &osContext : this->registeredOsContexts) {
|
|
|
|
|
if (osContext) {
|
|
|
|
|
auto &residencyController = osContext->get()->getResidencyController();
|
2018-10-16 15:53:39 +02:00
|
|
|
auto lock = residencyController.acquireLock();
|
2018-10-09 17:03:07 +02:00
|
|
|
residencyController.removeFromTrimCandidateListIfUsed(input, true);
|
2018-10-04 00:52:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-09-24 12:41:59 -07:00
|
|
|
UNRECOVERABLE_IF(DebugManager.flags.CreateMultipleDevices.get() == 0 &&
|
2018-11-02 10:01:56 +01:00
|
|
|
gfxAllocation->peekWasUsed() && this->executionEnvironment.commandStreamReceivers.size() > 0 &&
|
2018-10-01 16:10:54 +02:00
|
|
|
this->getCommandStreamReceiver(0) && this->getCommandStreamReceiver(0)->getTagAddress() &&
|
2018-11-02 10:01:56 +01:00
|
|
|
gfxAllocation->getTaskCount(0u) > *this->getCommandStreamReceiver(0)->getTagAddress());
|
2018-03-09 14:48:42 +01:00
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
if (input->gmm) {
|
2018-10-02 10:10:29 -07:00
|
|
|
if (input->gmm->isRenderCompressed && wddm->getPageTableManager()) {
|
2018-01-25 15:10:07 +01:00
|
|
|
auto status = wddm->updateAuxTable(input->gpuPtr, input->gmm, false);
|
2017-12-21 00:45:38 +01:00
|
|
|
DEBUG_BREAK_IF(!status);
|
|
|
|
|
}
|
|
|
|
|
delete input->gmm;
|
|
|
|
|
}
|
2018-05-08 10:00:23 +02:00
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
if (input->peekSharedHandle() == false &&
|
2018-10-30 14:44:41 +01:00
|
|
|
input->driverAllocatedCpuPointer == nullptr &&
|
2017-12-21 00:45:38 +01:00
|
|
|
input->fragmentsStorage.fragmentCount > 0) {
|
|
|
|
|
cleanGraphicsMemoryCreatedFromHostPtr(gfxAllocation);
|
|
|
|
|
} else {
|
|
|
|
|
D3DKMT_HANDLE *allocationHandles = nullptr;
|
|
|
|
|
uint32_t allocationCount = 0;
|
|
|
|
|
D3DKMT_HANDLE resourceHandle = 0;
|
|
|
|
|
if (input->peekSharedHandle()) {
|
|
|
|
|
resourceHandle = input->resourceHandle;
|
|
|
|
|
} else {
|
|
|
|
|
allocationHandles = &input->handle;
|
|
|
|
|
allocationCount = 1;
|
|
|
|
|
}
|
|
|
|
|
if (input->isLocked()) {
|
|
|
|
|
unlockResource(input);
|
|
|
|
|
input->setLocked(false);
|
|
|
|
|
}
|
2018-09-06 17:58:32 +02:00
|
|
|
auto status = tryDeferDeletions(allocationHandles, allocationCount, resourceHandle);
|
2017-12-21 00:45:38 +01:00
|
|
|
DEBUG_BREAK_IF(!status);
|
2018-10-30 14:44:41 +01:00
|
|
|
alignedFreeWrapper(input->driverAllocatedCpuPointer);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2018-01-30 15:07:58 +01:00
|
|
|
wddm->releaseReservedAddress(input->getReservedAddress());
|
2017-12-21 00:45:38 +01:00
|
|
|
delete gfxAllocation;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-06 17:58:32 +02:00
|
|
|
bool WddmMemoryManager::tryDeferDeletions(D3DKMT_HANDLE *handles, uint32_t allocationCount, D3DKMT_HANDLE resourceHandle) {
|
2017-12-21 00:45:38 +01:00
|
|
|
bool status = true;
|
|
|
|
|
if (deferredDeleter) {
|
2018-09-06 17:58:32 +02:00
|
|
|
deferredDeleter->deferDeletion(DeferrableDeletion::create(wddm, handles, allocationCount, resourceHandle));
|
2017-12-21 00:45:38 +01:00
|
|
|
} else {
|
2018-09-06 17:58:32 +02:00
|
|
|
status = wddm->destroyAllocations(handles, allocationCount, resourceHandle);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WddmMemoryManager::validateAllocation(WddmAllocation *alloc) {
|
|
|
|
|
if (alloc == nullptr)
|
|
|
|
|
return false;
|
|
|
|
|
auto size = alloc->getUnderlyingBufferSize();
|
|
|
|
|
if (alloc->getGpuAddress() == 0u || size == 0 || (alloc->handle == 0 && alloc->fragmentsStorage.fragmentCount == 0))
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-28 12:09:48 +01:00
|
|
|
MemoryManager::AllocationStatus WddmMemoryManager::populateOsHandles(OsHandleStorage &handleStorage) {
|
2018-10-22 14:20:05 +02:00
|
|
|
uint32_t allocatedFragmentIndexes[maxFragmentsCount];
|
2018-03-27 14:01:04 +02:00
|
|
|
uint32_t allocatedFragmentsCounter = 0;
|
|
|
|
|
|
2018-10-22 14:20:05 +02:00
|
|
|
for (unsigned int i = 0; i < maxFragmentsCount; i++) {
|
2017-12-21 00:45:38 +01:00
|
|
|
// If no fragment is present it means it already exists.
|
|
|
|
|
if (!handleStorage.fragmentStorageData[i].osHandleStorage && handleStorage.fragmentStorageData[i].cpuPtr) {
|
|
|
|
|
handleStorage.fragmentStorageData[i].osHandleStorage = new OsHandle();
|
|
|
|
|
handleStorage.fragmentStorageData[i].residency = new ResidencyData();
|
|
|
|
|
|
2018-06-29 11:48:19 +02:00
|
|
|
handleStorage.fragmentStorageData[i].osHandleStorage->gmm = new Gmm(handleStorage.fragmentStorageData[i].cpuPtr, handleStorage.fragmentStorageData[i].fragmentSize, false);
|
2018-03-27 14:01:04 +02:00
|
|
|
allocatedFragmentIndexes[allocatedFragmentsCounter] = i;
|
|
|
|
|
allocatedFragmentsCounter++;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
2018-03-23 10:07:31 +01:00
|
|
|
NTSTATUS result = wddm->createAllocationsAndMapGpuVa(handleStorage);
|
|
|
|
|
|
|
|
|
|
if (result == STATUS_GRAPHICS_NO_VIDEO_MEMORY) {
|
|
|
|
|
return AllocationStatus::InvalidHostPointer;
|
|
|
|
|
}
|
2018-03-27 14:01:04 +02:00
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < allocatedFragmentsCounter; i++) {
|
2018-10-24 08:46:54 +02:00
|
|
|
hostPtrManager->storeFragment(handleStorage.fragmentStorageData[allocatedFragmentIndexes[i]]);
|
2018-03-27 14:01:04 +02:00
|
|
|
}
|
|
|
|
|
|
2018-02-28 12:09:48 +01:00
|
|
|
return AllocationStatus::Success;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WddmMemoryManager::cleanOsHandles(OsHandleStorage &handleStorage) {
|
|
|
|
|
|
2018-10-22 14:20:05 +02:00
|
|
|
D3DKMT_HANDLE handles[maxFragmentsCount] = {0};
|
2017-12-21 00:45:38 +01:00
|
|
|
auto allocationCount = 0;
|
|
|
|
|
|
2018-10-22 14:20:05 +02:00
|
|
|
for (unsigned int i = 0; i < maxFragmentsCount; i++) {
|
2017-12-21 00:45:38 +01:00
|
|
|
if (handleStorage.fragmentStorageData[i].freeTheFragment) {
|
|
|
|
|
handles[allocationCount] = handleStorage.fragmentStorageData[i].osHandleStorage->handle;
|
|
|
|
|
handleStorage.fragmentStorageData[i].residency->resident = false;
|
|
|
|
|
allocationCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-06 17:58:32 +02:00
|
|
|
bool success = tryDeferDeletions(handles, allocationCount, 0);
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-22 14:20:05 +02:00
|
|
|
for (unsigned int i = 0; i < maxFragmentsCount; i++) {
|
2017-12-21 00:45:38 +01:00
|
|
|
if (handleStorage.fragmentStorageData[i].freeTheFragment) {
|
|
|
|
|
if (success) {
|
|
|
|
|
handleStorage.fragmentStorageData[i].osHandleStorage->handle = 0;
|
|
|
|
|
}
|
|
|
|
|
delete handleStorage.fragmentStorageData[i].osHandleStorage->gmm;
|
|
|
|
|
delete handleStorage.fragmentStorageData[i].osHandleStorage;
|
|
|
|
|
delete handleStorage.fragmentStorageData[i].residency;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-21 11:42:03 +02:00
|
|
|
void WddmMemoryManager::obtainGpuAddresFromFragments(WddmAllocation *allocation, OsHandleStorage &handleStorage) {
|
|
|
|
|
if (this->force32bitAllocations && (handleStorage.fragmentCount > 0)) {
|
|
|
|
|
auto hostPtr = allocation->getUnderlyingBuffer();
|
2018-10-24 08:46:54 +02:00
|
|
|
auto fragment = hostPtrManager->getFragment(hostPtr);
|
2018-06-21 11:42:03 +02:00
|
|
|
if (fragment && fragment->driverAllocation) {
|
|
|
|
|
auto gpuPtr = handleStorage.fragmentStorageData[0].osHandleStorage->gpuPtr;
|
|
|
|
|
for (uint32_t i = 1; i < handleStorage.fragmentCount; i++) {
|
|
|
|
|
if (handleStorage.fragmentStorageData[i].osHandleStorage->gpuPtr < gpuPtr) {
|
|
|
|
|
gpuPtr = handleStorage.fragmentStorageData[i].osHandleStorage->gpuPtr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
allocation->allocationOffset = reinterpret_cast<uint64_t>(hostPtr) & MemoryConstants::pageMask;
|
|
|
|
|
allocation->setGpuAddress(gpuPtr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
GraphicsAllocation *WddmMemoryManager::createGraphicsAllocation(OsHandleStorage &handleStorage, size_t hostPtrSize, const void *hostPtr) {
|
2018-10-31 10:05:34 +01:00
|
|
|
auto allocation = new WddmAllocation(const_cast<void *>(hostPtr), hostPtrSize, nullptr, MemoryPool::System4KBPages, getOsContextCount());
|
2017-12-21 00:45:38 +01:00
|
|
|
allocation->fragmentsStorage = handleStorage;
|
2018-06-21 11:42:03 +02:00
|
|
|
obtainGpuAddresFromFragments(allocation, handleStorage);
|
2017-12-21 00:45:38 +01:00
|
|
|
return allocation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t WddmMemoryManager::getSystemSharedMemory() {
|
|
|
|
|
return wddm->getSystemSharedMemory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t WddmMemoryManager::getMaxApplicationAddress() {
|
|
|
|
|
return wddm->getMaxApplicationAddress();
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-12 15:24:46 +01:00
|
|
|
uint64_t WddmMemoryManager::getInternalHeapBaseAddress() {
|
|
|
|
|
return this->wddm->getGfxPartition().Heap32[1].Base;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-25 11:34:16 +02:00
|
|
|
bool WddmMemoryManager::makeResidentResidencyAllocations(ResidencyContainer &allocationsForResidency, OsContext &osContext) {
|
|
|
|
|
size_t residencyCount = allocationsForResidency.size();
|
2018-10-22 14:20:05 +02:00
|
|
|
std::unique_ptr<D3DKMT_HANDLE[]> handlesForResidency(new D3DKMT_HANDLE[residencyCount * maxFragmentsCount]);
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
uint32_t totalHandlesCount = 0;
|
|
|
|
|
|
2018-10-16 15:53:39 +02:00
|
|
|
auto lock = osContext.get()->getResidencyController().acquireLock();
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2018-10-22 15:59:26 +02:00
|
|
|
DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "currentFenceValue =", osContext.get()->getResidencyController().getMonitoredFence().currentFenceValue);
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < residencyCount; i++) {
|
2018-09-25 11:34:16 +02:00
|
|
|
WddmAllocation *allocation = reinterpret_cast<WddmAllocation *>(allocationsForResidency[i]);
|
2017-12-21 00:45:38 +01:00
|
|
|
bool mainResidency = false;
|
|
|
|
|
bool fragmentResidency[3] = {false, false, false};
|
|
|
|
|
|
|
|
|
|
mainResidency = allocation->getResidencyData().resident;
|
|
|
|
|
|
|
|
|
|
DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "allocation =", allocation, mainResidency ? "resident" : "not resident");
|
|
|
|
|
|
2018-10-09 17:03:07 +02:00
|
|
|
if (allocation->getTrimCandidateListPosition(osContext.getContextId()) != trimListUnusedPosition) {
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "allocation =", allocation, "on trimCandidateList");
|
2018-10-10 10:39:02 +02:00
|
|
|
osContext.get()->getResidencyController().removeFromTrimCandidateList(allocation, false);
|
2017-12-21 00:45:38 +01:00
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
for (uint32_t allocationId = 0; allocationId < allocation->fragmentsStorage.fragmentCount; allocationId++) {
|
|
|
|
|
fragmentResidency[allocationId] = allocation->fragmentsStorage.fragmentStorageData[allocationId].residency->resident;
|
|
|
|
|
|
|
|
|
|
DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "fragment handle =",
|
|
|
|
|
allocation->fragmentsStorage.fragmentStorageData[allocationId].osHandleStorage->handle,
|
|
|
|
|
fragmentResidency[allocationId] ? "resident" : "not resident");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (allocation->fragmentsStorage.fragmentCount == 0) {
|
|
|
|
|
if (!mainResidency)
|
|
|
|
|
handlesForResidency[totalHandlesCount++] = allocation->handle;
|
|
|
|
|
} else {
|
|
|
|
|
for (uint32_t allocationId = 0; allocationId < allocation->fragmentsStorage.fragmentCount; allocationId++) {
|
|
|
|
|
if (!fragmentResidency[allocationId])
|
|
|
|
|
handlesForResidency[totalHandlesCount++] = allocation->fragmentsStorage.fragmentStorageData[allocationId].osHandleStorage->handle;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool result = true;
|
|
|
|
|
if (totalHandlesCount) {
|
|
|
|
|
uint64_t bytesToTrim = 0;
|
|
|
|
|
while ((result = wddm->makeResident(handlesForResidency.get(), totalHandlesCount, false, &bytesToTrim)) == false) {
|
|
|
|
|
this->memoryBudgetExhausted = true;
|
2018-10-26 12:22:47 +02:00
|
|
|
bool trimmingDone = this->getRegisteredOsContext(0u)->get()->getResidencyController().trimResidencyToBudget(bytesToTrim);
|
2017-12-21 00:45:38 +01:00
|
|
|
bool cantTrimFurther = !trimmingDone;
|
|
|
|
|
if (cantTrimFurther) {
|
|
|
|
|
result = wddm->makeResident(handlesForResidency.get(), totalHandlesCount, true, &bytesToTrim);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result == true) {
|
|
|
|
|
for (uint32_t i = 0; i < residencyCount; i++) {
|
2018-09-25 11:34:16 +02:00
|
|
|
WddmAllocation *allocation = reinterpret_cast<WddmAllocation *>(allocationsForResidency[i]);
|
2017-12-21 00:45:38 +01:00
|
|
|
// Update fence value not to early destroy / evict allocation
|
2018-10-22 15:59:26 +02:00
|
|
|
auto currentFence = osContext.get()->getResidencyController().getMonitoredFence().currentFenceValue;
|
2018-10-22 16:43:20 +02:00
|
|
|
allocation->getResidencyData().updateCompletionData(currentFence, osContext.getContextId());
|
2017-12-21 00:45:38 +01:00
|
|
|
allocation->getResidencyData().resident = true;
|
|
|
|
|
|
|
|
|
|
for (uint32_t allocationId = 0; allocationId < allocation->fragmentsStorage.fragmentCount; allocationId++) {
|
2018-08-27 15:48:29 +02:00
|
|
|
auto residencyData = allocation->fragmentsStorage.fragmentStorageData[allocationId].residency;
|
2017-12-21 00:45:38 +01:00
|
|
|
// Update fence value not to remove the fragment referenced by different GA in trimming callback
|
2018-10-22 16:43:20 +02:00
|
|
|
residencyData->updateCompletionData(currentFence, osContext.getContextId());
|
2018-09-07 07:18:38 +02:00
|
|
|
residencyData->resident = true;
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-03 17:48:59 +02:00
|
|
|
void WddmMemoryManager::makeNonResidentEvictionAllocations(ResidencyContainer &evictionAllocations, OsContext &osContext) {
|
2018-10-16 15:53:39 +02:00
|
|
|
auto lock = osContext.get()->getResidencyController().acquireLock();
|
|
|
|
|
const size_t residencyCount = evictionAllocations.size();
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < residencyCount; i++) {
|
|
|
|
|
WddmAllocation *allocation = reinterpret_cast<WddmAllocation *>(evictionAllocations[i]);
|
2018-10-10 10:39:02 +02:00
|
|
|
osContext.get()->getResidencyController().addToTrimCandidateList(allocation);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-25 15:10:07 +01:00
|
|
|
bool WddmMemoryManager::mapAuxGpuVA(GraphicsAllocation *graphicsAllocation) {
|
|
|
|
|
return wddm->updateAuxTable(graphicsAllocation->getGpuAddress(), graphicsAllocation->gmm, true);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2018-01-22 16:43:26 +01:00
|
|
|
|
|
|
|
|
AlignedMallocRestrictions *WddmMemoryManager::getAlignedMallocRestrictions() {
|
|
|
|
|
return &mallocRestrictions;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-11 17:24:00 +02:00
|
|
|
bool WddmMemoryManager::createWddmAllocation(WddmAllocation *allocation, AllocationOrigin allocationOrigin) {
|
|
|
|
|
bool useHeap1 = (allocationOrigin == AllocationOrigin::INTERNAL_ALLOCATION);
|
2018-02-06 22:43:38 +01:00
|
|
|
auto wddmSuccess = wddm->createAllocation(allocation);
|
|
|
|
|
if (wddmSuccess == STATUS_GRAPHICS_NO_VIDEO_MEMORY && deferredDeleter) {
|
|
|
|
|
deferredDeleter->drain(true);
|
|
|
|
|
wddmSuccess = wddm->createAllocation(allocation);
|
|
|
|
|
}
|
|
|
|
|
if (wddmSuccess == STATUS_SUCCESS) {
|
2018-07-12 15:42:46 +02:00
|
|
|
bool mapSuccess = wddm->mapGpuVirtualAddress(allocation, allocation->getAlignedCpuPtr(), allocation->is32BitAllocation, false, useHeap1);
|
2018-02-06 22:43:38 +01:00
|
|
|
if (!mapSuccess && deferredDeleter) {
|
|
|
|
|
deferredDeleter->drain(true);
|
2018-07-12 15:42:46 +02:00
|
|
|
mapSuccess = wddm->mapGpuVirtualAddress(allocation, allocation->getAlignedCpuPtr(), allocation->is32BitAllocation, false, useHeap1);
|
2018-02-06 22:43:38 +01:00
|
|
|
}
|
|
|
|
|
if (!mapSuccess) {
|
2018-09-06 17:58:32 +02:00
|
|
|
wddm->destroyAllocations(&allocation->handle, 1, allocation->resourceHandle);
|
2018-02-06 22:43:38 +01:00
|
|
|
wddmSuccess = STATUS_UNSUCCESSFUL;
|
|
|
|
|
}
|
|
|
|
|
allocation->setGpuAddress(allocation->gpuPtr);
|
|
|
|
|
}
|
|
|
|
|
return (wddmSuccess == STATUS_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
} // namespace OCLRT
|