2018-10-04 06:52:51 +08:00
/*
2024-05-22 22:12:59 +08:00
* Copyright ( C ) 2018 - 2024 Intel Corporation
2018-10-04 06:52:51 +08:00
*
* SPDX - License - Identifier : MIT
*
*/
2020-02-24 05:44:01 +08:00
# include "shared/source/os_interface/windows/wddm_residency_controller.h"
2019-02-27 18:39:32 +08:00
2024-08-29 18:13:00 +08:00
# include "shared/source/command_stream/command_stream_receiver.h"
2020-02-24 05:44:01 +08: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 06:52:51 +08:00
2019-03-26 18:59:46 +08:00
namespace NEO {
2018-10-04 06:52:51 +08:00
2018-10-30 21:40:02 +08:00
WddmResidencyController : : WddmResidencyController ( Wddm & wddm , uint32_t osContextId ) : wddm ( wddm ) , osContextId ( osContextId ) {
2018-11-14 21:35:45 +08:00
}
void WddmResidencyController : : registerCallback ( ) {
2018-11-15 18:44:37 +08:00
this - > trimCallbackHandle = wddm . registerTrimCallback ( WddmResidencyController : : trimCallback , * this ) ;
2018-10-30 21:40:02 +08:00
}
WddmResidencyController : : ~ WddmResidencyController ( ) {
auto lock = this - > acquireTrimCallbackLock ( ) ;
2018-11-15 18:44:37 +08:00
wddm . unregisterTrimCallback ( WddmResidencyController : : trimCallback , this - > trimCallbackHandle ) ;
2018-10-30 21:40:02 +08:00
lock . unlock ( ) ;
// Wait for lock to ensure trimCallback ended
lock . lock ( ) ;
}
2018-10-04 06:52:51 +08:00
2018-10-16 21:53:39 +08:00
std : : unique_lock < SpinLock > WddmResidencyController : : acquireLock ( ) {
return std : : unique_lock < SpinLock > { this - > lock } ;
2018-10-04 06:52:51 +08:00
}
2018-10-16 21:53:39 +08:00
std : : unique_lock < SpinLock > WddmResidencyController : : acquireTrimCallbackLock ( ) {
return std : : unique_lock < SpinLock > { this - > trimCallbackLock } ;
2018-10-15 23:12:55 +08:00
}
2018-10-22 21:59:26 +08: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-07 00:13:06 +08: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 18:25:49 +08: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-07 00:13:06 +08:00
*
* @ return returns true if all allocations either succeeded or are pending to be resident
*/
2024-08-22 18:25:49 +08:00
bool WddmResidencyController : : makeResidentResidencyAllocations ( ResidencyContainer & allocationsForResidency , bool & requiresBlockingResidencyHandling ) {
2020-04-21 19:16:45 +08:00
constexpr uint32_t stackAllocations = 64 ;
constexpr uint32_t stackHandlesCount = NEO : : maxFragmentsCount * EngineLimits : : maxHandleCount * stackAllocations ;
StackVec < D3DKMT_HANDLE , stackHandlesCount > handlesForResidency ;
2024-09-01 02:25:41 +08:00
uint32_t totalHandlesCount = 0 ;
2020-03-17 19:19:38 +08:00
size_t totalSize = 0 ;
2024-09-01 02:25:41 +08:00
const auto currentFence = this - > getMonitoredFence ( ) . currentFenceValue ;
2024-08-07 17:31:59 +08:00
requiresBlockingResidencyHandling = false ;
2024-08-07 00:13:06 +08:00
if ( debugManager . flags . WaitForPagingFenceInController . get ( ) ! = - 1 ) {
requiresBlockingResidencyHandling = ! debugManager . flags . WaitForPagingFenceInController . get ( ) ;
}
2018-11-05 22:47:32 +08:00
auto lock = this - > acquireLock ( ) ;
2024-09-01 02:25:41 +08:00
DBG_LOG ( ResidencyDebugEnable , " Residency: " , __FUNCTION__ , " currentFenceValue = " , this - > getMonitoredFence ( ) . currentFenceValue ) ;
auto iter = allocationsForResidency . begin ( ) ;
while ( iter ! = allocationsForResidency . end ( ) ) {
WddmAllocation * allocation = static_cast < WddmAllocation * > ( * iter ) ;
2018-11-15 21:45:35 +08:00
ResidencyData & residencyData = allocation - > getResidencyData ( ) ;
2021-06-09 21:53:41 +08:00
static constexpr int maxFragments = 3 ;
bool fragmentResidency [ maxFragments ] = { false , false , false } ;
2024-08-22 18:25:49 +08:00
const auto fragmentCount = allocation - > fragmentsStorage . fragmentCount ;
UNRECOVERABLE_IF ( fragmentCount > maxFragments ) ;
2020-03-17 19:19:38 +08:00
totalSize + = allocation - > getAlignedSize ( ) ;
2018-11-05 22:47:32 +08:00
2024-05-23 16:23:44 +08:00
DBG_LOG ( ResidencyDebugEnable , " Residency: " , __FUNCTION__ , " allocation, gpu address = " , std : : hex , allocation - > getGpuAddress ( ) , residencyData . resident [ osContextId ] ? " resident " : " not resident " ) ;
2024-08-22 18:25:49 +08:00
DBG_LOG ( ResidencyDebugEnable , " Residency: " , __FUNCTION__ , " allocation, gpu address = " , std : : hex , allocation - > getGpuAddress ( ) , " fence value to reach for eviction = " , currentFence ) ;
2018-11-05 22:47:32 +08:00
2024-09-01 02:25:41 +08:00
allocation - > getResidencyData ( ) . updateCompletionData ( currentFence , this - > osContextId ) ;
2024-08-22 18:25:49 +08:00
bool isAlreadyResident = true ;
2021-06-11 03:43:22 +08:00
if ( fragmentCount > 0 ) {
for ( uint32_t allocationId = 0 ; allocationId < fragmentCount ; allocationId + + ) {
2024-09-01 02:25:41 +08:00
auto residencyData = allocation - > fragmentsStorage . fragmentStorageData [ allocationId ] . residency ;
residencyData - > updateCompletionData ( currentFence , this - > osContextId ) ;
2020-04-21 19:16:45 +08:00
if ( ! fragmentResidency [ allocationId ] ) {
2021-04-03 01:01:51 +08:00
handlesForResidency . push_back ( static_cast < OsHandleWin * > ( allocation - > fragmentsStorage . fragmentStorageData [ allocationId ] . osHandleStorage ) - > handle ) ;
2024-09-01 02:25:41 +08:00
totalHandlesCount + + ;
2024-08-07 00:13:06 +08:00
requiresBlockingResidencyHandling | = ( allocation - > getAllocationType ( ) ! = AllocationType : : buffer & & allocation - > getAllocationType ( ) ! = AllocationType : : bufferHostMemory ) ;
2024-08-22 18:25:49 +08:00
isAlreadyResident = false ;
2020-04-21 19:16:45 +08:00
}
2018-11-05 22:47:32 +08:00
}
2018-11-28 18:01:41 +08:00
} else if ( ! residencyData . resident [ osContextId ] ) {
2020-04-21 19:16:45 +08:00
for ( uint32_t gmmId = 0 ; gmmId < allocation - > getNumGmms ( ) ; + + gmmId ) {
handlesForResidency . push_back ( allocation - > getHandle ( gmmId ) ) ;
2024-09-01 02:25:41 +08:00
totalHandlesCount + + ;
2024-08-07 00:13:06 +08:00
requiresBlockingResidencyHandling | = ( allocation - > getAllocationType ( ) ! = AllocationType : : buffer & & allocation - > getAllocationType ( ) ! = AllocationType : : bufferHostMemory ) ;
2024-08-22 18:25:49 +08:00
isAlreadyResident = false ;
2020-04-21 19:16:45 +08:00
}
2018-11-05 22:47:32 +08:00
}
2024-08-22 18:25:49 +08:00
2024-09-01 02:25:41 +08:00
if ( isAlreadyResident ) {
iter = allocationsForResidency . erase ( iter ) ;
} else {
iter + + ;
2024-08-22 18:25:49 +08:00
}
2018-11-05 22:47:32 +08:00
}
bool result = true ;
2024-09-01 02:25:41 +08:00
if ( totalHandlesCount ) {
2018-11-05 22:47:32 +08:00
uint64_t bytesToTrim = 0 ;
2024-09-01 02:25:41 +08:00
while ( ( result = wddm . makeResident ( & handlesForResidency [ 0 ] , totalHandlesCount , false , & bytesToTrim , totalSize ) ) = = false ) {
2018-11-05 22:47:32 +08:00
this - > setMemoryBudgetExhausted ( ) ;
2024-08-08 22:49:39 +08:00
const bool trimmingDone = this - > trimResidencyToBudget ( bytesToTrim , lock ) ;
2018-11-15 21:45:35 +08:00
if ( ! trimmingDone ) {
2019-07-12 22:50:14 +08:00
auto evictionStatus = wddm . getTemporaryResourcesContainer ( ) - > evictAllResources ( ) ;
2023-12-13 17:17:24 +08:00
if ( evictionStatus = = MemoryOperationsStatus : : success ) {
2019-01-16 22:09:33 +08:00
continue ;
}
2023-12-13 17:17:24 +08:00
DEBUG_BREAK_IF ( evictionStatus ! = MemoryOperationsStatus : : memoryNotFound ) ;
2023-05-31 21:55:08 +08:00
do {
2024-09-01 02:25:41 +08:00
result = wddm . makeResident ( & handlesForResidency [ 0 ] , totalHandlesCount , true , & bytesToTrim , totalSize ) ;
2023-11-30 16:32:25 +08:00
} while ( debugManager . flags . WaitForMemoryRelease . get ( ) & & result = = false ) ;
2018-11-05 22:47:32 +08:00
break ;
}
}
}
if ( result = = true ) {
2024-09-01 02:25:41 +08:00
iter = allocationsForResidency . begin ( ) ;
while ( iter ! = allocationsForResidency . end ( ) ) {
WddmAllocation * allocation = static_cast < WddmAllocation * > ( * iter ) ;
2018-11-28 18:01:41 +08:00
allocation - > getResidencyData ( ) . resident [ osContextId ] = true ;
2018-11-05 22:47:32 +08:00
for ( uint32_t allocationId = 0 ; allocationId < allocation - > fragmentsStorage . fragmentCount ; allocationId + + ) {
auto residencyData = allocation - > fragmentsStorage . fragmentStorageData [ allocationId ] . residency ;
2018-11-28 18:01:41 +08:00
residencyData - > resident [ osContextId ] = true ;
2018-11-05 22:47:32 +08:00
}
2024-09-01 02:25:41 +08:00
iter + + ;
2018-11-05 22:47:32 +08:00
}
}
return result ;
}
2019-12-19 21:02:05 +08:00
bool WddmResidencyController : : isInitialized ( ) const {
2021-05-21 07:17:57 +08:00
bool requiresTrimCallbacks = OSInterface : : requiresSupportForWddmTrimNotification ;
2023-11-30 16:32:25 +08:00
requiresTrimCallbacks = requiresTrimCallbacks & & ( false = = debugManager . flags . DoNotRegisterTrimCallback . get ( ) ) ;
2021-05-21 07:17:57 +08:00
if ( requiresTrimCallbacks ) {
2019-12-19 21:02:05 +08:00
return trimCallbackHandle ! = nullptr ;
}
return true ;
}
2024-08-22 18:25:49 +08:00
void WddmResidencyController : : setCommandStreamReceiver ( CommandStreamReceiver * csr ) {
this - > csr = csr ;
}
2024-08-29 18:13:00 +08: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 18:59:46 +08:00
} // namespace NEO