2018-10-04 00:52:51 +02:00
/*
2024-05-22 14:12:59 +00:00
* Copyright ( C ) 2018 - 2024 Intel Corporation
2018-10-04 00:52:51 +02:00
*
* SPDX - License - Identifier : MIT
*
*/
2020-02-23 22:44:01 +01:00
# include "shared/source/os_interface/windows/wddm_residency_controller.h"
2019-02-27 11:39:32 +01:00
2024-08-29 10:13:00 +00:00
# include "shared/source/command_stream/command_stream_receiver.h"
2020-02-23 22:44:01 +01:00
# include "shared/source/debug_settings/debug_settings_manager.h"
# include "shared/source/os_interface/windows/wddm/wddm.h"
# include "shared/source/os_interface/windows/wddm_allocation.h"
# include "shared/source/os_interface/windows/wddm_residency_allocations_container.h"
# include "shared/source/utilities/spinlock.h"
2018-10-04 00:52:51 +02:00
2019-03-26 11:59:46 +01:00
namespace NEO {
2018-10-04 00:52:51 +02:00
2018-10-30 14:40:02 +01:00
WddmResidencyController : : WddmResidencyController ( Wddm & wddm , uint32_t osContextId ) : wddm ( wddm ) , osContextId ( osContextId ) {
2018-11-14 14:35:45 +01:00
}
void WddmResidencyController : : registerCallback ( ) {
2018-11-15 11:44:37 +01:00
this - > trimCallbackHandle = wddm . registerTrimCallback ( WddmResidencyController : : trimCallback , * this ) ;
2018-10-30 14:40:02 +01:00
}
WddmResidencyController : : ~ WddmResidencyController ( ) {
auto lock = this - > acquireTrimCallbackLock ( ) ;
2018-11-15 11:44:37 +01:00
wddm . unregisterTrimCallback ( WddmResidencyController : : trimCallback , this - > trimCallbackHandle ) ;
2018-10-30 14:40:02 +01:00
lock . unlock ( ) ;
// Wait for lock to ensure trimCallback ended
lock . lock ( ) ;
}
2018-10-04 00:52:51 +02:00
2018-10-16 15:53:39 +02:00
std : : unique_lock < SpinLock > WddmResidencyController : : acquireLock ( ) {
return std : : unique_lock < SpinLock > { this - > lock } ;
2018-10-04 00:52:51 +02:00
}
2018-10-16 15:53:39 +02:00
std : : unique_lock < SpinLock > WddmResidencyController : : acquireTrimCallbackLock ( ) {
return std : : unique_lock < SpinLock > { this - > trimCallbackLock } ;
2018-10-15 17:12:55 +02:00
}
2018-10-22 15:59:26 +02:00
void WddmResidencyController : : resetMonitoredFenceParams ( D3DKMT_HANDLE & handle , uint64_t * cpuAddress , D3DGPU_VIRTUAL_ADDRESS & gpuAddress ) {
monitoredFence . lastSubmittedFence = 0 ;
monitoredFence . currentFenceValue = 1 ;
monitoredFence . fenceHandle = handle ;
monitoredFence . cpuAddress = cpuAddress ;
monitoredFence . gpuAddress = gpuAddress ;
}
2024-08-06 16:13:06 +00:00
/**
* @ brief Makes resident passed allocations on a device
*
* @ param [ in ] allocationsForResidency container of allocations which need to be resident .
* @ param [ out ] requiresBlockingResidencyHandling flag indicating whether wait for paging fence must be handled in user thread .
* Setting to false means that it can be handled in background thread , which will signal semaphore after paging fence reaches required value .
*
2024-08-22 10:25:49 +00:00
* @ note This method filters allocations which are already resident . After calling this method , passed allocationsForResidency will contain
* only allocations which were not resident before .
2024-08-06 16:13:06 +00:00
*
* @ return returns true if all allocations either succeeded or are pending to be resident
*/
2024-08-22 10:25:49 +00:00
bool WddmResidencyController : : makeResidentResidencyAllocations ( ResidencyContainer & allocationsForResidency , bool & requiresBlockingResidencyHandling ) {
2024-09-05 12:38:10 +00:00
const size_t residencyCount = allocationsForResidency . size ( ) ;
2024-08-07 09:31:59 +00:00
requiresBlockingResidencyHandling = false ;
2024-08-06 16:13:06 +00:00
if ( debugManager . flags . WaitForPagingFenceInController . get ( ) ! = - 1 ) {
requiresBlockingResidencyHandling = ! debugManager . flags . WaitForPagingFenceInController . get ( ) ;
}
2018-11-05 15:47:32 +01:00
auto lock = this - > acquireLock ( ) ;
2024-10-07 13:43:59 +00:00
backupResidencyContainer = allocationsForResidency ;
2024-09-05 12:38:10 +00:00
auto totalSize = fillHandlesContainer ( allocationsForResidency , requiresBlockingResidencyHandling ) ;
2018-11-05 15:47:32 +01:00
bool result = true ;
2024-09-05 12:38:10 +00:00
if ( ! handlesForResidency . empty ( ) ) {
2018-11-05 15:47:32 +01:00
uint64_t bytesToTrim = 0 ;
2024-09-05 12:38:10 +00:00
while ( ( result = wddm . makeResident ( handlesForResidency . data ( ) , static_cast < uint32_t > ( handlesForResidency . size ( ) ) , false , & bytesToTrim , totalSize ) ) = = false ) {
2018-11-05 15:47:32 +01:00
this - > setMemoryBudgetExhausted ( ) ;
2024-09-24 10:58:26 +00:00
const bool trimmingDone = this - > trimResidencyToBudget ( bytesToTrim ) ;
2024-10-07 13:43:59 +00:00
allocationsForResidency = backupResidencyContainer ;
2018-11-15 14:45:35 +01:00
if ( ! trimmingDone ) {
2019-07-12 16:50:14 +02:00
auto evictionStatus = wddm . getTemporaryResourcesContainer ( ) - > evictAllResources ( ) ;
2024-09-05 12:38:10 +00:00
totalSize = fillHandlesContainer ( allocationsForResidency , requiresBlockingResidencyHandling ) ;
2023-12-13 09:17:24 +00:00
if ( evictionStatus = = MemoryOperationsStatus : : success ) {
2019-01-16 15:09:33 +01:00
continue ;
}
2023-12-13 09:17:24 +00:00
DEBUG_BREAK_IF ( evictionStatus ! = MemoryOperationsStatus : : memoryNotFound ) ;
2023-05-31 13:55:08 +00:00
do {
2024-09-05 12:38:10 +00:00
result = wddm . makeResident ( handlesForResidency . data ( ) , static_cast < uint32_t > ( handlesForResidency . size ( ) ) , true , & bytesToTrim , totalSize ) ;
2023-11-30 08:32:25 +00:00
} while ( debugManager . flags . WaitForMemoryRelease . get ( ) & & result = = false ) ;
2018-11-05 15:47:32 +01:00
break ;
}
2024-09-05 12:38:10 +00:00
totalSize = fillHandlesContainer ( allocationsForResidency , requiresBlockingResidencyHandling ) ;
2018-11-05 15:47:32 +01:00
}
}
2024-09-05 12:38:10 +00:00
const auto currentFence = this - > getMonitoredFence ( ) . currentFenceValue ;
2018-11-05 15:47:32 +01:00
if ( result = = true ) {
2024-09-05 12:38:10 +00:00
for ( uint32_t i = 0 ; i < residencyCount ; i + + ) {
2024-10-07 13:43:59 +00:00
WddmAllocation * allocation = static_cast < WddmAllocation * > ( backupResidencyContainer [ i ] ) ;
2018-11-28 11:01:41 +01:00
allocation - > getResidencyData ( ) . resident [ osContextId ] = true ;
2024-09-05 12:38:10 +00:00
allocation - > getResidencyData ( ) . updateCompletionData ( currentFence , this - > osContextId ) ;
DBG_LOG ( ResidencyDebugEnable , " Residency: " , __FUNCTION__ , " allocation, gpu address = " , std : : hex , allocation - > getGpuAddress ( ) , " fence value to reach for eviction = " , currentFence ) ;
2018-11-05 15:47:32 +01:00
for ( uint32_t allocationId = 0 ; allocationId < allocation - > fragmentsStorage . fragmentCount ; allocationId + + ) {
auto residencyData = allocation - > fragmentsStorage . fragmentStorageData [ allocationId ] . residency ;
2018-11-28 11:01:41 +01:00
residencyData - > resident [ osContextId ] = true ;
2024-09-05 12:38:10 +00:00
residencyData - > updateCompletionData ( currentFence , this - > osContextId ) ;
2018-11-05 15:47:32 +01:00
}
}
}
return result ;
}
2024-09-05 12:38:10 +00:00
/**
* @ brief Fills containers related to residency handling based on passed allocations . For each allocation ,
* if it ' s not yet resident , this allocation and it ' s handle are added to associated containers .
*
* @ return returns total size in bytes of allocations which are not yet resident .
*/
2024-10-07 13:43:59 +00:00
size_t WddmResidencyController : : fillHandlesContainer ( ResidencyContainer & allocationsForResidency , bool & requiresBlockingResidencyHandling ) {
2024-09-05 12:38:10 +00:00
size_t totalSize = 0 ;
const size_t residencyCount = allocationsForResidency . size ( ) ;
handlesForResidency . clear ( ) ;
handlesForResidency . reserve ( residencyCount ) ;
DBG_LOG ( ResidencyDebugEnable , " Residency: " , __FUNCTION__ , " currentFenceValue = " , this - > getMonitoredFence ( ) . currentFenceValue ) ;
2024-10-07 13:43:59 +00:00
auto checkIfAlreadyResident = [ & ] ( GraphicsAllocation * alloc ) {
WddmAllocation * allocation = static_cast < WddmAllocation * > ( alloc ) ;
2024-09-05 12:38:10 +00:00
ResidencyData & residencyData = allocation - > getResidencyData ( ) ;
static constexpr int maxFragments = 3 ;
const auto fragmentCount = allocation - > fragmentsStorage . fragmentCount ;
UNRECOVERABLE_IF ( fragmentCount > maxFragments ) ;
DBG_LOG ( ResidencyDebugEnable , " Residency: " , __FUNCTION__ , " allocation, gpu address = " , std : : hex , allocation - > getGpuAddress ( ) , residencyData . resident [ osContextId ] ? " resident " : " not resident " ) ;
bool isAlreadyResident = true ;
if ( fragmentCount > 0 ) {
for ( uint32_t allocationId = 0 ; allocationId < fragmentCount ; allocationId + + ) {
2024-10-07 13:43:59 +00:00
handlesForResidency . push_back ( static_cast < OsHandleWin * > ( allocation - > fragmentsStorage . fragmentStorageData [ allocationId ] . osHandleStorage ) - > handle ) ;
requiresBlockingResidencyHandling | = ( allocation - > getAllocationType ( ) ! = AllocationType : : buffer & & allocation - > getAllocationType ( ) ! = AllocationType : : bufferHostMemory ) ;
isAlreadyResident = false ;
2024-09-05 12:38:10 +00:00
}
} else if ( ! residencyData . resident [ osContextId ] ) {
for ( uint32_t gmmId = 0 ; gmmId < allocation - > getNumGmms ( ) ; + + gmmId ) {
handlesForResidency . push_back ( allocation - > getHandle ( gmmId ) ) ;
requiresBlockingResidencyHandling | = ( allocation - > getAllocationType ( ) ! = AllocationType : : buffer & & allocation - > getAllocationType ( ) ! = AllocationType : : bufferHostMemory ) ;
isAlreadyResident = false ;
}
}
if ( ! isAlreadyResident ) {
totalSize + = allocation - > getAlignedSize ( ) ;
}
2024-10-07 13:43:59 +00:00
return isAlreadyResident ;
} ;
allocationsForResidency . erase ( std : : remove_if ( allocationsForResidency . begin ( ) , allocationsForResidency . end ( ) , checkIfAlreadyResident ) , allocationsForResidency . end ( ) ) ;
2024-09-05 12:38:10 +00:00
return totalSize ;
}
2019-12-19 14:02:05 +01:00
bool WddmResidencyController : : isInitialized ( ) const {
2021-05-21 01:17:57 +02:00
bool requiresTrimCallbacks = OSInterface : : requiresSupportForWddmTrimNotification ;
2023-11-30 08:32:25 +00:00
requiresTrimCallbacks = requiresTrimCallbacks & & ( false = = debugManager . flags . DoNotRegisterTrimCallback . get ( ) ) ;
2021-05-21 01:17:57 +02:00
if ( requiresTrimCallbacks ) {
2019-12-19 14:02:05 +01:00
return trimCallbackHandle ! = nullptr ;
}
return true ;
}
2024-08-22 10:25:49 +00:00
void WddmResidencyController : : setCommandStreamReceiver ( CommandStreamReceiver * csr ) {
this - > csr = csr ;
}
2024-08-29 10:13:00 +00:00
void WddmResidencyController : : removeAllocation ( ResidencyContainer & container , GraphicsAllocation * gfxAllocation ) {
std : : unique_lock < std : : mutex > lock1 ( this - > lock , std : : defer_lock ) ;
std : : unique_lock < std : : mutex > lock2 ( this - > trimCallbackLock , std : : defer_lock ) ;
std : : lock ( lock1 , lock2 ) ;
auto iter = std : : find ( container . begin ( ) , container . end ( ) , gfxAllocation ) ;
if ( iter ! = container . end ( ) ) {
container . erase ( iter ) ;
}
}
2019-03-26 11:59:46 +01:00
} // namespace NEO