mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-10-07 20:42:35 +00:00
Added delayed removal of captured resources
This commit is contained in:
1 parent
3bae8a59b7
commit
53050eeb4a
2 files changed
+159
-9
No files matched your search
@@ -92,6 +92,140 @@ inline static bool CompareResourceFormats(DXGI_FORMAT sc, DXGI_FORMAT hudless)
|
||||
return scGroup >= 0 && scGroup == hudlessGroup;
|
||||
}
|
||||
|
||||
void Hudfix_Dx12::RemoveCaptureBuffer(ID3D12Resource** resource)
|
||||
{
|
||||
if (resource == nullptr || *resource == nullptr)
|
||||
return;
|
||||
|
||||
auto* removedResource = *resource;
|
||||
*resource = nullptr;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_captureRemoveMutex);
|
||||
_pendingCaptureRemovals.push_back(removedResource);
|
||||
_captureRemovalActive.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
LOG_DEBUG("Capture buffer removed: {:X}", (size_t) removedResource);
|
||||
}
|
||||
|
||||
void Hudfix_Dx12::ProcessPendingCaptureRemovals()
|
||||
{
|
||||
if (!_captureRemovalActive.load(std::memory_order_acquire))
|
||||
return;
|
||||
|
||||
std::vector<ID3D12Resource*> completedResources;
|
||||
std::vector<ID3D12Fence*> completedFences;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_captureRemoveMutex);
|
||||
|
||||
for (auto it = _captureRemoveInfos.begin(); it != _captureRemoveInfos.end();)
|
||||
{
|
||||
if (it->fence != nullptr && it->fence->GetCompletedValue() >= it->fenceValue)
|
||||
{
|
||||
completedResources.insert(completedResources.end(), it->resources.begin(), it->resources.end());
|
||||
completedFences.push_back(it->fence);
|
||||
it = _captureRemoveInfos.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (_captureRemoveInfos.empty() && _pendingCaptureRemovals.empty())
|
||||
_captureRemovalActive.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
// Release outside _captureRemoveMutex
|
||||
for (auto* resource : completedResources)
|
||||
{
|
||||
if (resource != nullptr)
|
||||
resource->Release();
|
||||
}
|
||||
|
||||
for (auto* fence : completedFences)
|
||||
{
|
||||
if (fence != nullptr)
|
||||
fence->Release();
|
||||
}
|
||||
|
||||
if (!_captureRemovalActive.load(std::memory_order_acquire))
|
||||
return;
|
||||
|
||||
if (State::Instance().isShuttingDown)
|
||||
return;
|
||||
|
||||
std::vector<ID3D12Resource*> pendingResources;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_captureRemoveMutex);
|
||||
if (_pendingCaptureRemovals.empty())
|
||||
return;
|
||||
|
||||
pendingResources.swap(_pendingCaptureRemovals);
|
||||
}
|
||||
|
||||
auto* fg = State::Instance().currentFG;
|
||||
ID3D12CommandQueue* queue = fg != nullptr ? fg->GetCommandQueue() : nullptr;
|
||||
if (queue == nullptr)
|
||||
queue = State::Instance().currentCommandQueue;
|
||||
|
||||
auto requeuePending = [&pendingResources]()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_captureRemoveMutex);
|
||||
_pendingCaptureRemovals.insert(_pendingCaptureRemovals.end(), pendingResources.begin(), pendingResources.end());
|
||||
_captureRemovalActive.store(true, std::memory_order_release);
|
||||
};
|
||||
|
||||
if (queue == nullptr)
|
||||
{
|
||||
requeuePending();
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D12Device* device = nullptr;
|
||||
auto result = queue->GetDevice(IID_PPV_ARGS(&device));
|
||||
if (FAILED(result) || device == nullptr)
|
||||
{
|
||||
LOG_WARN("Can't get capture remove queue device: {:X}", (UINT) result);
|
||||
requeuePending();
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D12Fence* fence = nullptr;
|
||||
result = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
|
||||
device->Release();
|
||||
|
||||
if (FAILED(result) || fence == nullptr)
|
||||
{
|
||||
LOG_WARN("Can't create capture remove fence: {:X}", (UINT) result);
|
||||
requeuePending();
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr UINT64 fenceValue = 1;
|
||||
result = queue->Signal(fence, fenceValue);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_WARN("Can't signal capture remove fence: {:X}", (UINT) result);
|
||||
fence->Release();
|
||||
requeuePending();
|
||||
return;
|
||||
}
|
||||
|
||||
CaptureRemoveInfo batch {};
|
||||
batch.fence = fence;
|
||||
batch.fenceValue = fenceValue;
|
||||
batch.resources = std::move(pendingResources);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_captureRemoveMutex);
|
||||
_captureRemoveInfos.push_back(std::move(batch));
|
||||
_captureRemovalActive.store(true, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
bool Hudfix_Dx12::CreateBufferResource(ID3D12Device* InDevice, ResourceInfo* InSource, D3D12_RESOURCE_STATES InState,
|
||||
ID3D12Resource** OutResource)
|
||||
{
|
||||
@@ -105,11 +239,8 @@ bool Hudfix_Dx12::CreateBufferResource(ID3D12Device* InDevice, ResourceInfo* InS
|
||||
if (bufDesc.Width != (UINT64) (InSource->width) || bufDesc.Height != (UINT) (InSource->height) ||
|
||||
bufDesc.Format != InSource->format)
|
||||
{
|
||||
// Maybe need to add a fence here
|
||||
// To be sure it's not used anymore
|
||||
(*OutResource)->Release();
|
||||
(*OutResource) = nullptr;
|
||||
LOG_WARN("Release {}x{}, new one: {}x{}", bufDesc.Width, bufDesc.Height, InSource->width, InSource->height);
|
||||
RemoveCaptureBuffer(OutResource);
|
||||
LOG_WARN("Remove {}x{}, new one: {}x{}", bufDesc.Width, bufDesc.Height, InSource->width, InSource->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -156,9 +287,8 @@ bool Hudfix_Dx12::CreateBufferResourceWithSize(ID3D12Device* InDevice, ResourceI
|
||||
|
||||
if (bufDesc.Width != (UINT64) InWidth || bufDesc.Height != InHeight || bufDesc.Format != InSource->format)
|
||||
{
|
||||
(*OutResource)->Release();
|
||||
(*OutResource) = nullptr;
|
||||
LOG_WARN("Release {}x{}, new one: {}x{}", bufDesc.Width, bufDesc.Height, InWidth, InHeight);
|
||||
RemoveCaptureBuffer(OutResource);
|
||||
LOG_WARN("Remove {}x{}, new one: {}x{}", bufDesc.Width, bufDesc.Height, InWidth, InHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -443,7 +573,11 @@ void Hudfix_Dx12::PresentStart()
|
||||
_fgCounter.store(_upscaleCounter.load(std::memory_order_acquire), std::memory_order_release);
|
||||
}
|
||||
|
||||
void Hudfix_Dx12::PresentEnd() { LOG_DEBUG(""); }
|
||||
void Hudfix_Dx12::PresentEnd()
|
||||
{
|
||||
ProcessPendingCaptureRemovals();
|
||||
LOG_DEBUG("");
|
||||
}
|
||||
|
||||
UINT64 Hudfix_Dx12::ActiveUpscaleFrame() { return _upscaleCounter.load(std::memory_order_acquire); }
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <atomic>
|
||||
#include <d3d12.h>
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
|
||||
enum ResourceType
|
||||
{
|
||||
@@ -78,6 +79,18 @@ class Hudfix_Dx12
|
||||
// Buffer for Format Transfer
|
||||
inline static ID3D12Resource* _captureBuffer[BUFFER_COUNT] = { nullptr, nullptr, nullptr, nullptr };
|
||||
|
||||
struct CaptureRemoveInfo
|
||||
{
|
||||
ID3D12Fence* fence = nullptr;
|
||||
UINT64 fenceValue = 0;
|
||||
std::vector<ID3D12Resource*> resources;
|
||||
};
|
||||
|
||||
inline static std::atomic<bool> _captureRemovalActive { false };
|
||||
inline static std::mutex _captureRemoveMutex;
|
||||
inline static std::vector<ID3D12Resource*> _pendingCaptureRemovals;
|
||||
inline static std::vector<CaptureRemoveInfo> _captureRemoveInfos;
|
||||
|
||||
// used hudless list
|
||||
inline static ankerl::unordered_dense::map<ID3D12Resource*, HudlessInfo> _hudlessList;
|
||||
|
||||
@@ -93,6 +106,9 @@ class Hudfix_Dx12
|
||||
|
||||
inline static std::atomic<bool> _skipHudlessChecks { false };
|
||||
|
||||
static void RemoveCaptureBuffer(ID3D12Resource** resource);
|
||||
static void ProcessPendingCaptureRemovals();
|
||||
|
||||
static bool CreateBufferResource(ID3D12Device* InDevice, ResourceInfo* InSource, D3D12_RESOURCE_STATES InState,
|
||||
ID3D12Resource** OutResource);
|
||||
static bool CreateBufferResourceWithSize(ID3D12Device* InDevice, ResourceInfo* InSource,
|
||||
|
||||
Reference in new issue
Block a user