From 5b56a4c3cf18be582da7e5df2120e475ce839e2c Mon Sep 17 00:00:00 2001 From: FakeMichau <49685661+FakeMichau@users.noreply.github.com> Date: Thu, 14 Aug 2025 14:17:50 +0200 Subject: [PATCH] Revert "Remove buckets and narrow down scope of _trMutex" This reverts commit 41aad239e713ea1839c5adb9ee4319544411990a. --- .../resource_tracking/ResTrack_dx12.cpp | 237 ++++++++++++++++-- OptiScaler/resource_tracking/ResTrack_dx12.h | 15 +- 2 files changed, 229 insertions(+), 23 deletions(-) diff --git a/OptiScaler/resource_tracking/ResTrack_dx12.cpp b/OptiScaler/resource_tracking/ResTrack_dx12.cpp index 140fc5eb..0ecac925 100644 --- a/OptiScaler/resource_tracking/ResTrack_dx12.cpp +++ b/OptiScaler/resource_tracking/ResTrack_dx12.cpp @@ -115,11 +115,21 @@ static std::vector _notFoundCmdLists; static std::map _resCmdList; static std::map _resCmdListFound; +#define USE_BUCKETS_FOR_HEAPS + +#ifdef USE_BUCKETS_FOR_HEAPS +struct HeapCacheTLS +{ + HeapInfo* heap = nullptr; + unsigned genSeen = 0; +}; +#else struct HeapCacheTLS { int index = -1; unsigned genSeen = 0; }; +#endif static thread_local HeapCacheTLS cache; static thread_local HeapCacheTLS cacheRTV; @@ -131,6 +141,59 @@ static std::atomic gHeapGeneration { 1 }; static thread_local HeapCacheTLS cacheGR; static thread_local HeapCacheTLS cacheCR; +#ifdef USE_BUCKETS_FOR_HEAPS +static constexpr uint32_t BUCKET_SHIFT = 16; // 64 KB buckets +static std::unordered_map gCpuBuckets; +static std::unordered_map gGpuBuckets; + +static uint64_t BucketOf(SIZE_T addr) { return addr >> BUCKET_SHIFT; } + +static void AddHeapBuckets(HeapInfo* h) +{ + uint64_t b0 = BucketOf(h->cpuStart); + uint64_t b1 = BucketOf(h->cpuEnd - 1); + for (uint64_t b = b0; b <= b1; ++b) + gCpuBuckets[b] = h; + + b0 = BucketOf(h->gpuStart); + b1 = BucketOf(h->gpuEnd - 1); + for (uint64_t b = b0; b <= b1; ++b) + gGpuBuckets[b] = h; +} + +inline bool InRangeCPU(SIZE_T addr, const HeapInfo* h) +{ + const SIZE_T s = h->cpuStart; + const SIZE_T e = h->cpuEnd; + return (addr - s) < (e - s); +} + +inline bool InRangeGPU(SIZE_T addr, const HeapInfo* h) +{ + const SIZE_T s = h->gpuStart; + const SIZE_T e = h->gpuEnd; + return (addr - s) < (e - s); +} + +HeapInfo* FindHeapByCPU_Bucketed(SIZE_T addr) +{ + auto it = gCpuBuckets.find(BucketOf(addr)); + if (it == gCpuBuckets.end()) + return nullptr; + HeapInfo* h = it->second; + return InRangeCPU(addr, h) ? h : nullptr; +} + +HeapInfo* FindHeapByGPU_Bucketed(SIZE_T addr) +{ + auto it = gGpuBuckets.find(BucketOf(addr)); + if (it == gGpuBuckets.end()) + return nullptr; + HeapInfo* h = it->second; + return InRangeGPU(addr, h) ? h : nullptr; +} +#endif + bool ResTrack_Dx12::CheckResource(ID3D12Resource* resource) { if (State::Instance().currentSwapchain == nullptr || State::Instance().isShuttingDown) @@ -253,10 +316,22 @@ SIZE_T ResTrack_Dx12::GetGPUHandle(ID3D12Device* This, SIZE_T cpuHandle, D3D12_D { std::shared_lock lock(heapMutex); +#ifdef USE_BUCKETS_FOR_HEAPS + auto val = FindHeapByCPU_Bucketed(cpuHandle); + if (val != nullptr) + { + auto incSize = This->GetDescriptorHandleIncrementSize(type); + auto addr = cpuHandle - val->cpuStart; + auto index = addr / incSize; + auto gpuAddr = val->gpuStart + (index * incSize); + + return gpuAddr; + } +#else for (UINT i = 0; i < fgHeapIndex; i++) { auto val = fgHeaps[i].get(); - if (cpuHandle - val->cpuStart < val->size && val->gpuStart != 0) + if (val->cpuStart <= cpuHandle && val->cpuEnd >= cpuHandle && val->gpuStart != 0) { auto incSize = This->GetDescriptorHandleIncrementSize(type); auto addr = cpuHandle - val->cpuStart; @@ -266,6 +341,7 @@ SIZE_T ResTrack_Dx12::GetGPUHandle(ID3D12Device* This, SIZE_T cpuHandle, D3D12_D return gpuAddr; } } +#endif return NULL; } @@ -274,10 +350,22 @@ SIZE_T ResTrack_Dx12::GetCPUHandle(ID3D12Device* This, SIZE_T gpuHandle, D3D12_D { std::shared_lock lock(heapMutex); +#ifdef USE_BUCKETS_FOR_HEAPS + auto val = FindHeapByGPU_Bucketed(gpuHandle); + if (val != nullptr) + { + auto incSize = This->GetDescriptorHandleIncrementSize(type); + auto addr = gpuHandle - val->gpuStart; + auto index = addr / incSize; + auto cpuAddr = val->cpuStart + (index * incSize); + + return cpuAddr; + } +#else for (UINT i = 0; i < fgHeapIndex; i++) { auto val = fgHeaps[i].get(); - if (gpuHandle - val->gpuStart < val->size && val->cpuStart != 0) + if (val->gpuStart <= gpuHandle && val->gpuEnd >= gpuHandle && val->cpuStart != 0) { auto incSize = This->GetDescriptorHandleIncrementSize(type); auto addr = gpuHandle - val->gpuStart; @@ -287,6 +375,7 @@ SIZE_T ResTrack_Dx12::GetCPUHandle(ID3D12Device* This, SIZE_T gpuHandle, D3D12_D return cpuAddr; } } +#endif return NULL; } @@ -295,17 +384,32 @@ HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleCBV(SIZE_T cpuHandle) { unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cacheCBV.genSeen == currentGen && cacheCBV.heap != nullptr) + { + if (cacheCBV.heap->cpuStart <= cpuHandle && cpuHandle < cacheCBV.heap->cpuEnd) + return cacheCBV.heap; + } + + auto heap = FindHeapByCPU_Bucketed(cpuHandle); + if (heap != nullptr) + { + cacheCBV.heap = heap; + cacheCBV.genSeen = currentGen; + } + return heap; +#else if (cacheCBV.genSeen == currentGen && cacheCBV.index != -1) { auto heapInfo = fgHeaps[cacheCBV.index].get(); - if (cpuHandle - heapInfo->cpuStart < heapInfo->size) + if (heapInfo->cpuStart <= cpuHandle && cpuHandle < heapInfo->cpuEnd) return heapInfo; } for (size_t i = 0; i < fgHeapIndex; i++) { - if (cpuHandle - fgHeaps[i]->cpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= cpuHandle && fgHeaps[i]->cpuEnd > cpuHandle) { cacheCBV.index = i; cacheCBV.genSeen = currentGen; @@ -314,23 +418,39 @@ HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleCBV(SIZE_T cpuHandle) } return nullptr; +#endif } HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleRTV(SIZE_T cpuHandle) { unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cacheRTV.genSeen == currentGen && cacheRTV.heap != nullptr) + { + if (cacheRTV.heap->cpuStart <= cpuHandle && cpuHandle < cacheRTV.heap->cpuEnd) + return cacheRTV.heap; + } + + auto heap = FindHeapByCPU_Bucketed(cpuHandle); + if (heap != nullptr) + { + cacheRTV.heap = heap; + cacheRTV.genSeen = currentGen; + } + return heap; +#else if (cacheRTV.genSeen == currentGen && cacheRTV.index != -1) { auto heapInfo = fgHeaps[cacheRTV.index].get(); - if (cpuHandle - heapInfo->cpuStart < heapInfo->size) + if (heapInfo->cpuStart <= cpuHandle && cpuHandle < heapInfo->cpuEnd) return heapInfo; } for (size_t i = 0; i < fgHeapIndex; i++) { - if (cpuHandle - fgHeaps[i]->cpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= cpuHandle && fgHeaps[i]->cpuEnd > cpuHandle) { cacheRTV.index = i; cacheRTV.genSeen = currentGen; @@ -339,23 +459,39 @@ HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleRTV(SIZE_T cpuHandle) } return nullptr; +#endif } HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleSRV(SIZE_T cpuHandle) { unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cacheSRV.genSeen == currentGen && cacheSRV.heap != nullptr) + { + if (cacheSRV.heap->cpuStart <= cpuHandle && cpuHandle < cacheSRV.heap->cpuEnd) + return cacheSRV.heap; + } + + auto heap = FindHeapByCPU_Bucketed(cpuHandle); + if (heap != nullptr) + { + cacheSRV.heap = heap; + cacheSRV.genSeen = currentGen; + } + return heap; +#else if (cacheSRV.genSeen == currentGen && cacheSRV.index != -1) { auto heapInfo = fgHeaps[cacheSRV.index].get(); - if (cpuHandle - heapInfo->cpuStart < heapInfo->size) + if (heapInfo->cpuStart <= cpuHandle && cpuHandle < heapInfo->cpuEnd) return heapInfo; } for (size_t i = 0; i < fgHeapIndex; i++) { - if (cpuHandle - fgHeaps[i]->cpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= cpuHandle && fgHeaps[i]->cpuEnd > cpuHandle) { cacheSRV.index = i; cacheSRV.genSeen = currentGen; @@ -364,23 +500,39 @@ HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleSRV(SIZE_T cpuHandle) } return nullptr; +#endif } HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleUAV(SIZE_T cpuHandle) { unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cacheUAV.genSeen == currentGen && cacheUAV.heap != nullptr) + { + if (cacheUAV.heap->cpuStart <= cpuHandle && cpuHandle < cacheUAV.heap->cpuEnd) + return cacheUAV.heap; + } + + auto heap = FindHeapByCPU_Bucketed(cpuHandle); + if (heap != nullptr) + { + cacheUAV.heap = heap; + cacheUAV.genSeen = currentGen; + } + return heap; +#else if (cacheUAV.genSeen == currentGen && cacheUAV.index != -1) { auto heapInfo = fgHeaps[cacheUAV.index].get(); - if (cpuHandle - heapInfo->cpuStart < heapInfo->size) + if (heapInfo->cpuStart <= cpuHandle && cpuHandle < heapInfo->cpuEnd) return heapInfo; } for (size_t i = 0; i < fgHeapIndex; i++) { - if (cpuHandle - fgHeaps[i]->cpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= cpuHandle && fgHeaps[i]->cpuEnd > cpuHandle) { cacheUAV.index = i; cacheUAV.genSeen = currentGen; @@ -389,25 +541,41 @@ HeapInfo* ResTrack_Dx12::GetHeapByCpuHandleUAV(SIZE_T cpuHandle) } return nullptr; +#endif } HeapInfo* ResTrack_Dx12::GetHeapByCpuHandle(SIZE_T cpuHandle) { unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cache.genSeen == currentGen && cache.heap != nullptr) + { + if (cache.heap->cpuStart <= cpuHandle && cpuHandle < cache.heap->cpuEnd) + return cache.heap; + } + + auto heap = FindHeapByCPU_Bucketed(cpuHandle); + if (heap != nullptr) + { + cache.heap = heap; + cache.genSeen = currentGen; + } + return heap; +#else { if (cache.genSeen == currentGen && cache.index != -1) { auto heapInfo = fgHeaps[cache.index].get(); - if (cpuHandle - heapInfo->cpuStart < heapInfo->size) + if (heapInfo->cpuStart <= cpuHandle && cpuHandle < heapInfo->cpuEnd) return heapInfo; } } for (size_t i = 0; i < fgHeapIndex; i++) { - if (cpuHandle - fgHeaps[i]->cpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= cpuHandle && fgHeaps[i]->cpuEnd > cpuHandle) { cache.index = i; cache.genSeen = currentGen; @@ -416,25 +584,41 @@ HeapInfo* ResTrack_Dx12::GetHeapByCpuHandle(SIZE_T cpuHandle) } return nullptr; +#endif } HeapInfo* ResTrack_Dx12::GetHeapByGpuHandleGR(SIZE_T gpuHandle) { unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cacheGR.genSeen == currentGen && cacheGR.heap != nullptr) + { + if (cacheGR.heap->cpuStart <= gpuHandle && gpuHandle < cacheGR.heap->cpuEnd) + return cacheGR.heap; + } + + auto heap = FindHeapByGPU_Bucketed(gpuHandle); + if (heap != nullptr) + { + cacheGR.heap = heap; + cacheGR.genSeen = currentGen; + } + return heap; +#else { if (cacheGR.genSeen == currentGen && cacheGR.index != -1) { auto heapInfo = fgHeaps[cacheGR.index].get(); - if (gpuHandle - heapInfo->gpuStart < heapInfo->size) + if (heapInfo->gpuStart <= gpuHandle && gpuHandle < heapInfo->gpuEnd) return heapInfo; } } for (size_t i = 0; i < fgHeapIndex; i++) { - if (gpuHandle - fgHeaps[i]->gpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= gpuHandle && fgHeaps[i]->gpuEnd > gpuHandle) { cacheGR.index = i; cacheGR.genSeen = currentGen; @@ -443,6 +627,7 @@ HeapInfo* ResTrack_Dx12::GetHeapByGpuHandleGR(SIZE_T gpuHandle) } return nullptr; +#endif } HeapInfo* ResTrack_Dx12::GetHeapByGpuHandleCR(SIZE_T gpuHandle) @@ -452,19 +637,34 @@ HeapInfo* ResTrack_Dx12::GetHeapByGpuHandleCR(SIZE_T gpuHandle) unsigned currentGen = gHeapGeneration.load(std::memory_order_relaxed); +#ifdef USE_BUCKETS_FOR_HEAPS + if (cacheCR.genSeen == currentGen && cacheCR.heap != nullptr) + { + if (cacheCR.heap->cpuStart <= gpuHandle && gpuHandle < cacheCR.heap->cpuEnd) + return cacheCR.heap; + } + + auto heap = FindHeapByGPU_Bucketed(gpuHandle); + if (heap != nullptr) + { + cacheCR.heap = heap; + cacheCR.genSeen = currentGen; + } + return heap; +#else { if (cacheCR.genSeen == currentGen && cacheCR.index != -1) { auto heapInfo = fgHeaps[cacheCR.index].get(); - if (gpuHandle - heapInfo->gpuStart < heapInfo->size) + if (heapInfo->gpuStart <= gpuHandle && gpuHandle < heapInfo->gpuEnd) return heapInfo; } } for (size_t i = 0; i < fgHeapIndex; i++) { - if (gpuHandle - fgHeaps[i]->gpuStart < fgHeaps[i]->size) + if (fgHeaps[i]->cpuStart <= gpuHandle && fgHeaps[i]->gpuEnd > gpuHandle) { cacheCR.index = i; cacheCR.genSeen = currentGen; @@ -473,6 +673,7 @@ HeapInfo* ResTrack_Dx12::GetHeapByGpuHandleCR(SIZE_T gpuHandle) } return nullptr; +#endif } #pragma endregion @@ -795,6 +996,10 @@ HRESULT ResTrack_Dx12::hkCreateDescriptorHeap(ID3D12Device* This, D3D12_DESCRIPT fgHeaps[fgHeapIndex] = std::make_unique(heap, cpuStart, cpuEnd, gpuStart, gpuEnd, numDescriptors, increment, type, fgHeapIndex); +#ifdef USE_BUCKETS_FOR_HEAPS + AddHeapBuckets(fgHeaps[fgHeapIndex].get()); +#endif + fgHeapIndex++; gHeapGeneration.fetch_add(1, std::memory_order_relaxed); } diff --git a/OptiScaler/resource_tracking/ResTrack_dx12.h b/OptiScaler/resource_tracking/ResTrack_dx12.h index 1a75b53d..a4a1e458 100644 --- a/OptiScaler/resource_tracking/ResTrack_dx12.h +++ b/OptiScaler/resource_tracking/ResTrack_dx12.h @@ -45,7 +45,6 @@ typedef struct HeapInfo SIZE_T cpuEnd = NULL; SIZE_T gpuStart = NULL; SIZE_T gpuEnd = NULL; - SIZE_T size = NULL; UINT numDescriptors = 0; UINT increment = 0; UINT type = 0; @@ -62,8 +61,6 @@ typedef struct HeapInfo { info[i].buffer = nullptr; } - - size = increment * numDescriptors; } ResourceInfo* GetByCpuHandle(SIZE_T cpuHandle) const @@ -167,6 +164,8 @@ typedef struct HeapInfo if (index >= numDescriptors) return; + _trMutex.lock(); + if (info[index].buffer != nullptr) { LOG_TRACK("Resource: {:X}, Res: {}x{}", (size_t) info[index].buffer, info[index].width, info[index].height); @@ -179,16 +178,16 @@ typedef struct HeapInfo { if (vector->at(i) == &info[index]) { - _trMutex.lock(); LOG_TRACK("Erase from _trackedResources info: {:X}", (size_t) vector->at(i)); vector->erase(vector->begin() + i); - _trMutex.unlock(); break; } } } } + _trMutex.unlock(); + info[index].buffer = nullptr; info[index].lastUsedFrame = 0; } @@ -200,6 +199,8 @@ typedef struct HeapInfo if (index >= numDescriptors) return; + _trMutex.lock(); + if (info[index].buffer != nullptr) { LOG_TRACK("Resource: {:X}, Res: {}x{}", (size_t) info[index].buffer, info[index].width, info[index].height); @@ -212,16 +213,16 @@ typedef struct HeapInfo { if (vector->at(i) == &info[index]) { - _trMutex.lock(); LOG_TRACK("Erase from _trackedResources info: {:X}", (size_t) vector->at(i)); vector->erase(vector->begin() + i); - _trMutex.unlock(); break; } } } } + _trMutex.unlock(); + info[index].buffer = nullptr; info[index].lastUsedFrame = 0; }