mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-08-26 08:06:33 +00:00
Made resource tracking optional
This commit is contained in:
@@ -306,6 +306,11 @@ HUDFixImmediate=auto
|
||||
; true or false - Default (auto) is false
|
||||
AlwaysTrackHeaps=auto
|
||||
|
||||
; Instead of single mutex use shards for tracking resources
|
||||
; Might improve performance on heavy multithreaded games
|
||||
; true or false - Default (auto) is false
|
||||
UseShards=auto
|
||||
|
||||
; Block rarely used resources from using as hudless
|
||||
; to prevent flickers and other issues
|
||||
; true or false - Default (auto) is false
|
||||
|
||||
@@ -142,6 +142,7 @@ bool Config::Reload(std::filesystem::path iniPath)
|
||||
FGHUDLimit.set_from_config(readInt("OptiFG", "HUDLimit"));
|
||||
FGHUDFixExtended.set_from_config(readBool("OptiFG", "HUDFixExtended"));
|
||||
FGImmediateCapture.set_from_config(readBool("OptiFG", "HUDFixImmediate"));
|
||||
FGUseShards.set_from_config(readBool("OptiFG", "UseShards"));
|
||||
FGAlwaysTrackHeaps.set_from_config(readBool("OptiFG", "AlwaysTrackHeaps"));
|
||||
FGResourceBlocking.set_from_config(readBool("OptiFG", "ResourceBlocking"));
|
||||
FGMakeDepthCopy.set_from_config(readBool("OptiFG", "MakeDepthCopy"));
|
||||
@@ -768,6 +769,7 @@ bool Config::SaveIni()
|
||||
ini.SetValue("OptiFG", "HUDFixExtended", GetBoolValue(Instance()->FGHUDFixExtended.value_for_config()).c_str());
|
||||
ini.SetValue("OptiFG", "HUDFixImmediate",
|
||||
GetBoolValue(Instance()->FGImmediateCapture.value_for_config()).c_str());
|
||||
ini.SetValue("OptiFG", "UseShards", GetBoolValue(Instance()->FGUseShards.value_for_config()).c_str());
|
||||
ini.SetValue("OptiFG", "AlwaysTrackHeaps",
|
||||
GetBoolValue(Instance()->FGAlwaysTrackHeaps.value_for_config()).c_str());
|
||||
ini.SetValue("OptiFG", "ResourceBlocking",
|
||||
|
||||
@@ -438,6 +438,7 @@ class Config
|
||||
// OptiFG - Resource Tracking
|
||||
CustomOptional<bool> FGAlwaysTrackHeaps { false };
|
||||
CustomOptional<bool> FGResourceBlocking { false };
|
||||
CustomOptional<bool> FGUseShards { false };
|
||||
|
||||
// OptiFG - DLSS-D Depth scale
|
||||
CustomOptional<bool> FGEnableDepthScale { false };
|
||||
|
||||
@@ -109,7 +109,12 @@ static PFN_OMSetRenderTargets o_OMSetRenderTargets = nullptr;
|
||||
static PFN_SetGraphicsRootDescriptorTable o_SetGraphicsRootDescriptorTable = nullptr;
|
||||
static PFN_SetComputeRootDescriptorTable o_SetComputeRootDescriptorTable = nullptr;
|
||||
|
||||
// heaps
|
||||
static std::mutex _hudlessTrackMutex;
|
||||
static ankerl::unordered_dense::map<ID3D12GraphicsCommandList*,
|
||||
ankerl::unordered_dense::map<ID3D12Resource*, ResourceInfo>>
|
||||
fgPossibleHudless[BUFFER_COUNT];
|
||||
|
||||
// heaps section
|
||||
|
||||
// #define USE_SPINLOCK_MUTEX_FOR_HEAP_CREATION
|
||||
|
||||
@@ -1190,10 +1195,26 @@ void ResTrack_Dx12::hkSetGraphicsRootDescriptorTable(ID3D12GraphicsCommandList*
|
||||
}
|
||||
|
||||
auto fIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (!_useShards)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
|
||||
if (!fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
ankerl::unordered_dense::map<ID3D12Resource*, ResourceInfo> newMap;
|
||||
newMap.reserve(32);
|
||||
fgPossibleHudless[fIndex].insert_or_assign(This, newMap);
|
||||
}
|
||||
|
||||
LOG_TRACK("AddRef Resource: {:X}, Desc: {:X}", (size_t) capturedBuffer->buffer, BaseDescriptor.ptr);
|
||||
fgPossibleHudless[fIndex][This].insert_or_assign(capturedBuffer->buffer, *capturedBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
@@ -1293,10 +1314,27 @@ void ResTrack_Dx12::hkOMSetRenderTargets(ID3D12GraphicsCommandList* This, UINT N
|
||||
}
|
||||
|
||||
auto fIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (!_useShards)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
|
||||
if (!fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
ankerl::unordered_dense::map<ID3D12Resource*, ResourceInfo> newMap;
|
||||
newMap.reserve(32);
|
||||
fgPossibleHudless[fIndex].insert_or_assign(This, newMap);
|
||||
}
|
||||
|
||||
// add found resource
|
||||
LOG_TRACK("AddRef Resource: {:X}, Desc: {:X}", (size_t) capturedBuffer->buffer, handle.ptr);
|
||||
fgPossibleHudless[fIndex][This].insert_or_assign(capturedBuffer->buffer, *capturedBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
@@ -1382,10 +1420,27 @@ void ResTrack_Dx12::hkSetComputeRootDescriptorTable(ID3D12GraphicsCommandList* T
|
||||
}
|
||||
|
||||
auto fIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (!_useShards)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
|
||||
if (!fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
ankerl::unordered_dense::map<ID3D12Resource*, ResourceInfo> newMap;
|
||||
newMap.reserve(32);
|
||||
fgPossibleHudless[fIndex].insert_or_assign(This, newMap);
|
||||
}
|
||||
|
||||
// add found resource
|
||||
LOG_TRACK("AddRef Resource: {:X}, Desc: {:X}", (size_t) capturedBuffer->buffer, handle.ptr);
|
||||
fgPossibleHudless[fIndex][This].insert_or_assign(capturedBuffer->buffer, *capturedBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
@@ -1429,18 +1484,61 @@ void ResTrack_Dx12::hkDrawInstanced(ID3D12GraphicsCommandList* This, UINT Vertex
|
||||
LOG_TRACK("CmdList: {:X}", (size_t) This);
|
||||
|
||||
auto fIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (!_useShards)
|
||||
{
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
if (This == MenuOverlayDx::MenuCommandList() && fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
fgPossibleHudless[fIndex][This].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fgPossibleHudless[fIndex].size() == 0 || !fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
LOG_DEBUG_ONLY("Early exit");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
auto val0 = fgPossibleHudless[fIndex][This];
|
||||
|
||||
do
|
||||
{
|
||||
// if this command list does not have entries skip
|
||||
if (val0.size() == 0)
|
||||
break;
|
||||
|
||||
if (Config::Instance()->FGHudfixDisableDI.value_or_default())
|
||||
break;
|
||||
|
||||
for (auto& [key, val] : val0)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_drawMutex);
|
||||
|
||||
val.captureInfo |= CaptureInfo::DrawInstanced;
|
||||
|
||||
if (Hudfix_Dx12::CheckForHudless(This, &val, val.state))
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
fgPossibleHudless[fIndex][This].clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (This == MenuOverlayDx::MenuCommandList() && shard.map.contains(This))
|
||||
{
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
shard.map[This].clear();
|
||||
return;
|
||||
}
|
||||
@@ -1452,6 +1550,12 @@ void ResTrack_Dx12::hkDrawInstanced(ID3D12GraphicsCommandList* This, UINT Vertex
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
auto val0 = shard.map[This];
|
||||
|
||||
do
|
||||
@@ -1495,18 +1599,63 @@ void ResTrack_Dx12::hkDrawIndexedInstanced(ID3D12GraphicsCommandList* This, UINT
|
||||
LOG_TRACK("CmdList: {:X}", (size_t) This);
|
||||
|
||||
auto fIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (!_useShards)
|
||||
{
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
if (This == MenuOverlayDx::MenuCommandList() && fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
fgPossibleHudless[fIndex][This].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// if can't find output skip
|
||||
if (fgPossibleHudless[fIndex].size() == 0 || !fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
LOG_DEBUG_ONLY("Early exit");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
auto val0 = fgPossibleHudless[fIndex][This];
|
||||
|
||||
do
|
||||
{
|
||||
// if this command list does not have entries skip
|
||||
if (val0.size() == 0)
|
||||
break;
|
||||
|
||||
if (Config::Instance()->FGHudfixDisableDII.value_or_default())
|
||||
break;
|
||||
|
||||
for (auto& [key, val] : val0)
|
||||
{
|
||||
// LOG_DEBUG("Waiting _drawMutex {:X}", (size_t)val.buffer);
|
||||
std::lock_guard<std::mutex> lock(_drawMutex);
|
||||
|
||||
val.captureInfo |= CaptureInfo::DrawIndexedInstanced;
|
||||
|
||||
if (Hudfix_Dx12::CheckForHudless(This, &val, val.state))
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
fgPossibleHudless[fIndex][This].clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (This == MenuOverlayDx::MenuCommandList() && shard.map.contains(This))
|
||||
{
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
shard.map[This].clear();
|
||||
return;
|
||||
}
|
||||
@@ -1518,6 +1667,12 @@ void ResTrack_Dx12::hkDrawIndexedInstanced(ID3D12GraphicsCommandList* This, UINT
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
auto val0 = shard.map[This];
|
||||
|
||||
do
|
||||
@@ -1633,18 +1788,63 @@ void ResTrack_Dx12::hkDispatch(ID3D12GraphicsCommandList* This, UINT ThreadGroup
|
||||
LOG_TRACK("CmdList: {:X}", (size_t) This);
|
||||
|
||||
auto fIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (!_useShards)
|
||||
{
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
if (This == MenuOverlayDx::MenuCommandList() && fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
fgPossibleHudless[fIndex][This].clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// if can't find output skip
|
||||
if (fgPossibleHudless[fIndex].size() == 0 || !fgPossibleHudless[fIndex].contains(This))
|
||||
{
|
||||
LOG_DEBUG_ONLY("Early exit");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
auto val0 = fgPossibleHudless[fIndex][This];
|
||||
|
||||
do
|
||||
{
|
||||
// if this command list does not have entries skip
|
||||
if (val0.size() == 0)
|
||||
break;
|
||||
|
||||
if (Config::Instance()->FGHudfixDisableDispatch.value_or_default())
|
||||
break;
|
||||
|
||||
for (auto& [key, val] : val0)
|
||||
{
|
||||
// LOG_DEBUG("Waiting _drawMutex {:X}", (size_t)val.buffer);
|
||||
std::lock_guard<std::mutex> lock(_drawMutex);
|
||||
|
||||
val.captureInfo |= CaptureInfo::Dispatch;
|
||||
if (Hudfix_Dx12::CheckForHudless(This, &val, val.state))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
|
||||
fgPossibleHudless[fIndex][This].clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t shardIdx = GetShardIndex(This);
|
||||
auto& shard = _hudlessShards[fIndex][shardIdx];
|
||||
|
||||
if (This == MenuOverlayDx::MenuCommandList() && shard.map.contains(This))
|
||||
{
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
shard.map[This].clear();
|
||||
return;
|
||||
}
|
||||
@@ -1656,6 +1856,12 @@ void ResTrack_Dx12::hkDispatch(ID3D12GraphicsCommandList* This, UINT ThreadGroup
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
auto val0 = shard.map[This];
|
||||
|
||||
do
|
||||
@@ -1844,6 +2050,7 @@ void ResTrack_Dx12::HookDevice(ID3D12Device* device)
|
||||
if (device == nullptr)
|
||||
return;
|
||||
|
||||
_useShards = Config::Instance()->FGUseShards.value_or_default();
|
||||
_trackedResources.reserve(1024);
|
||||
fgHeaps.reserve(65536);
|
||||
|
||||
@@ -1984,17 +2191,25 @@ void ResTrack_Dx12::ClearPossibleHudless()
|
||||
|
||||
auto hfIndex = Hudfix_Dx12::ActivePresentFrame() % BUFFER_COUNT;
|
||||
|
||||
for (size_t i = 0; i < SHARD_COUNT; i++)
|
||||
if (!_useShards)
|
||||
{
|
||||
auto& shard = _hudlessShards[hfIndex][i];
|
||||
std::lock_guard<std::mutex> lock(_hudlessTrackMutex);
|
||||
fgPossibleHudless[hfIndex].clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < SHARD_COUNT; i++)
|
||||
{
|
||||
auto& shard = _hudlessShards[hfIndex][i];
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
std::lock_guard<SpinLock> lock(shard.mutex);
|
||||
#else
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
std::lock_guard<std::mutex> lock(shard.mutex);
|
||||
#endif
|
||||
|
||||
shard.map.clear();
|
||||
shard.map.clear();
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock2(_resourceCommandListMutex);
|
||||
|
||||
@@ -36,7 +36,7 @@ static void TestResource(ResourceInfo* info)
|
||||
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
|
||||
#define USE_PERF_SPINLOCK
|
||||
// #define USE_PERF_SPINLOCK
|
||||
|
||||
#ifdef __cpp_lib_hardware_interference_size
|
||||
constexpr size_t CACHE_LINE_SIZE = std::hardware_destructive_interference_size;
|
||||
@@ -337,6 +337,7 @@ class ResTrack_Dx12
|
||||
private:
|
||||
inline static bool _presentDone = true;
|
||||
inline static std::mutex _drawMutex;
|
||||
inline static bool _useShards = false;
|
||||
|
||||
inline static std::mutex _resourceCommandListMutex;
|
||||
inline static std::unordered_map<FG_ResourceType, ID3D12GraphicsCommandList*> _resourceCommandList[BUFFER_COUNT];
|
||||
@@ -424,13 +425,8 @@ class ResTrack_Dx12
|
||||
|
||||
static void FillResourceInfo(ID3D12Resource* resource, ResourceInfo* info);
|
||||
|
||||
// Sharding
|
||||
#ifdef USE_SPINLOCK_MUTEX
|
||||
// Sharding
|
||||
inline static constexpr size_t SHARD_COUNT = 16;
|
||||
#else
|
||||
inline static constexpr size_t SHARD_COUNT = 16;
|
||||
#endif
|
||||
|
||||
inline static CommandListShard _hudlessShards[BUFFER_COUNT][SHARD_COUNT];
|
||||
|
||||
inline static size_t GetShardIndex(ID3D12GraphicsCommandList* ptr)
|
||||
|
||||
Reference in New Issue
Block a user