FG Extended not checks for texture size too and with 32 pixel tolerance uses these as hudless too

This commit is contained in:
cdozdil
2025-07-12 12:51:00 +03:00
parent de14d46755
commit 9f83423a96
8 changed files with 258 additions and 78 deletions
+58
View File
@@ -3,6 +3,64 @@
#include <State.h>
#include <Config.h>
bool IFGFeature_Dx12::CreateBufferResourceWithSize(ID3D12Device* device, ID3D12Resource* source,
D3D12_RESOURCE_STATES state, ID3D12Resource** target, UINT width,
UINT height, bool UAV, bool depth)
{
if (device == nullptr || source == nullptr)
return false;
auto inDesc = source->GetDesc();
if (UAV)
inDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
if (depth)
inDesc.Format = DXGI_FORMAT_R32_FLOAT;
if (*target != nullptr)
{
auto bufDesc = (*target)->GetDesc();
if (bufDesc.Width != width || bufDesc.Height != height || bufDesc.Format != inDesc.Format ||
bufDesc.Flags != inDesc.Flags)
{
(*target)->Release();
(*target) = nullptr;
}
else
{
return true;
}
}
D3D12_HEAP_PROPERTIES heapProperties;
D3D12_HEAP_FLAGS heapFlags;
HRESULT hr = source->GetHeapProperties(&heapProperties, &heapFlags);
if (hr != S_OK)
{
LOG_ERROR("GetHeapProperties result: {:X}", (UINT64) hr);
return false;
}
inDesc.Width = width;
inDesc.Height = height;
hr = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &inDesc, state, nullptr,
IID_PPV_ARGS(target));
if (hr != S_OK)
{
LOG_ERROR("CreateCommittedResource result: {:X}", (UINT64) hr);
return false;
}
LOG_DEBUG("Created new one: {}x{}", inDesc.Width, inDesc.Height);
return true;
}
bool IFGFeature_Dx12::CreateBufferResource(ID3D12Device* device, ID3D12Resource* source, D3D12_RESOURCE_STATES state,
ID3D12Resource** target, bool UAV, bool depth)
{
+2
View File
@@ -37,6 +37,8 @@ class IFGFeature_Dx12 : public virtual IFGFeature
bool CreateBufferResource(ID3D12Device* InDevice, ID3D12Resource* InSource, D3D12_RESOURCE_STATES InState,
ID3D12Resource** OutResource, bool UAV = false, bool depth = false);
bool CreateBufferResourceWithSize(ID3D12Device* device, ID3D12Resource* source, D3D12_RESOURCE_STATES state,
ID3D12Resource** target, UINT width, UINT height, bool UAV, bool depth);
void ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource,
D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState);
bool CopyResource(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* source, ID3D12Resource** target,
+46 -3
View File
@@ -116,10 +116,53 @@ bool FSRFG_Dx12::Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* ou
DXGI_SWAP_CHAIN_DESC scDesc {};
_swapChain->GetDesc(&scDesc);
auto desc = output->GetDesc();
if (desc.Format == scDesc.BufferDesc.Format)
if (Config::Instance()->FGHUDFixExtended.value_or_default() && desc.Format == scDesc.BufferDesc.Format)
{
LOG_DEBUG("(FG) desc.Format == HooksDx::swapchainFormat, using for hudless!");
m_FrameGenerationConfig.HUDLessColor = ffxApiGetResourceDX12(output, FFX_API_RESOURCE_STATE_UNORDERED_ACCESS);
if (desc.Width == scDesc.BufferDesc.Width && desc.Height == scDesc.BufferDesc.Height)
{
if (CreateBufferResource(State::Instance().currentD3D12Device, output, D3D12_RESOURCE_STATE_COPY_DEST,
&_paramHudless[frameIndex], true, false))
{
LOG_DEBUG("(FG) desc.Format == HooksDx::swapchainFormat, using for hudless!");
cmdList->CopyResource(_paramHudless[frameIndex], output);
m_FrameGenerationConfig.HUDLessColor =
ffxApiGetResourceDX12(_paramHudless[frameIndex], FFX_API_RESOURCE_STATE_UNORDERED_ACCESS);
}
}
else if ((desc.Width > scDesc.BufferDesc.Width || desc.Height > scDesc.BufferDesc.Height) &&
State::Instance().currentD3D12Device != nullptr)
{
if (CreateBufferResourceWithSize(State::Instance().currentD3D12Device, output,
D3D12_RESOURCE_STATE_COPY_DEST, &_paramHudless[frameIndex],
scDesc.BufferDesc.Width, scDesc.BufferDesc.Height, true, false))
{
D3D12_TEXTURE_COPY_LOCATION srcLocation;
ZeroMemory(&srcLocation, sizeof(srcLocation));
srcLocation.pResource = output;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
srcLocation.SubresourceIndex = 0; // copy from mip 0, array slice 0
D3D12_TEXTURE_COPY_LOCATION dstLocation;
ZeroMemory(&dstLocation, sizeof(dstLocation));
dstLocation.pResource = _paramHudless[frameIndex];
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dstLocation.SubresourceIndex = 0; // paste into mip 0, array slice 0
D3D12_BOX srcBox;
srcBox.left = 0;
srcBox.top = 0;
srcBox.front = 0;
srcBox.right = scDesc.BufferDesc.Width;
srcBox.bottom = scDesc.BufferDesc.Height;
srcBox.back = 1;
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, &srcBox);
m_FrameGenerationConfig.HUDLessColor =
ffxApiGetResourceDX12(_paramHudless[frameIndex], FFX_API_RESOURCE_STATE_COPY_DEST);
}
}
}
else
{
+132 -60
View File
@@ -127,6 +127,58 @@ bool Hudfix_Dx12::CreateBufferResource(ID3D12Device* InDevice, ResourceInfo* InS
return true;
}
bool Hudfix_Dx12::CreateBufferResourceWithSize(ID3D12Device* InDevice, ResourceInfo* InSource,
D3D12_RESOURCE_STATES InState, ID3D12Resource** OutResource,
UINT InWidth, UINT InHeight)
{
if (InDevice == nullptr || InSource == nullptr)
return false;
if (*OutResource != nullptr)
{
auto bufDesc = (*OutResource)->GetDesc();
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);
}
else
{
return true;
}
}
D3D12_HEAP_PROPERTIES heapProperties;
D3D12_HEAP_FLAGS heapFlags;
HRESULT hr = InSource->buffer->GetHeapProperties(&heapProperties, &heapFlags);
if (hr != S_OK)
{
LOG_ERROR("GetHeapProperties result: {:X}", (UINT64) hr);
return false;
}
D3D12_RESOURCE_DESC texDesc = InSource->buffer->GetDesc();
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
texDesc.Width = InWidth;
texDesc.Height = InHeight;
hr = InDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, InState, nullptr,
IID_PPV_ARGS(OutResource));
if (hr != S_OK)
{
LOG_ERROR("CreateCommittedResource result: {:X}", (UINT64) hr);
return false;
}
LOG_DEBUG("Created new one: {}x{}", InWidth, InHeight);
return true;
}
void Hudfix_Dx12::ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource,
D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState)
{
@@ -190,49 +242,21 @@ bool Hudfix_Dx12::CheckResource(ResourceInfo* resource)
if (resource->width == 0 || resource->height == 0 || resource->buffer == nullptr)
return false;
// LOG_DEBUG("Width: {}, Height: {}, Format: {}, Resource: {:X}", resource->width, resource->height,
// (UINT) resource->format, (size_t) resource->buffer);
/*
*
* Was breaking immediate capture, disabled for now
*
// Check if info is valid
auto currentMs = Util::MillisecondsNow();
if (!Config::Instance()->FGAlwaysTrackHeaps.value_or_default() && resource->lastUsedFrame != 0 &&
(currentMs - resource->lastUsedFrame) > 0.3)
{
LOG_DEBUG("Resource {:X}, last used frame ({}) is too small ({}) from current one ({}) skipping resource!",
(size_t) resource->buffer, currentMs - resource->lastUsedFrame, resource->lastUsedFrame, currentMs);
resource->lastUsedFrame = currentMs; // use it next time if timing is ok
return false;
}
*/
// Check if resource is valid
// LOG_TRACE("Check resource if resource is still valid, if crashes here ResTrack is missing something");
// ID3D12Resource* testRes;
// auto queryResult = resource->buffer->QueryInterface(IID_PPV_ARGS(&testRes));
// if (queryResult != S_OK)
//{
// // LOG_WARN("Resource is not valid anymore!");
// return false;
//}
// Get resource info
auto resDesc = resource->buffer->GetDesc();
// Release test resource
// testRes->Release();
// testRes = nullptr;
// dimensions not match
if (resDesc.Height != scDesc.BufferDesc.Height || resDesc.Width != scDesc.BufferDesc.Width)
{
return false;
// Extended size check
if (!(Config::Instance()->FGHUDFixExtended.value_or_default() && resDesc.Height >= scDesc.BufferDesc.Height &&
resDesc.Height <= scDesc.BufferDesc.Height + 32 && resDesc.Width >= scDesc.BufferDesc.Width &&
resDesc.Width <= scDesc.BufferDesc.Width + 32))
{
return false;
}
resource->extended = true;
}
// check for resource flags
@@ -252,19 +276,12 @@ bool Hudfix_Dx12::CheckResource(ResourceInfo* resource)
(UINT) resDesc.Format, (UINT) scDesc.BufferDesc.Format, (size_t) resource->buffer,
Config::Instance()->FGHUDFixExtended.value_or_default());
// resource->lastUsedFrame = currentMs;
return true;
}
// extended not active
if (!Config::Instance()->FGHUDFixExtended.value_or_default())
{
// LOG_TRACE("Width: {}/{}, Height: {}/{}, Format: {}/{}, Resource: {:X}, convertFormat: {} -> FALSE",
// resDesc.Width, scDesc.BufferDesc.Width, resDesc.Height, scDesc.BufferDesc.Height,
// (UINT) resDesc.Format, (UINT) scDesc.BufferDesc.Format, (size_t) resource->buffer,
// Config::Instance()->FGHUDFixExtended.value_or_default());
return false;
}
@@ -298,8 +315,6 @@ bool Hudfix_Dx12::CheckResource(ResourceInfo* resource)
(UINT) resDesc.Format, (UINT) scDesc.BufferDesc.Format, (size_t) resource->buffer,
Config::Instance()->FGHUDFixExtended.value_or_default());
// resource->lastUsedFrame = currentMs;
return true;
}
@@ -583,28 +598,85 @@ bool Hudfix_Dx12::CheckForHudless(std::string callerName, ID3D12GraphicsCommandL
}
// Make a copy of resource to capture current state
if (CreateBufferResource(State::Instance().currentD3D12Device, resource, D3D12_RESOURCE_STATE_COPY_DEST,
&_captureBuffer[fIndex]))
if (!resource->extended)
{
LOG_DEBUG("Create a copy of resource: {:X}", (size_t) resource->buffer);
if (CreateBufferResource(State::Instance().currentD3D12Device, resource, D3D12_RESOURCE_STATE_COPY_DEST,
&_captureBuffer[fIndex]))
{
LOG_DEBUG("Create a copy of resource: {:X}", (size_t) resource->buffer);
// Using state D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE as skip flag
if (state != D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE)
ResourceBarrier(cmdList, resource->buffer, state, D3D12_RESOURCE_STATE_COPY_SOURCE);
// Using state D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE as skip flag
if (state != D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE)
ResourceBarrier(cmdList, resource->buffer, state, D3D12_RESOURCE_STATE_COPY_SOURCE);
cmdList->CopyResource(_captureBuffer[fIndex], resource->buffer);
cmdList->CopyResource(_captureBuffer[fIndex], resource->buffer);
// Using state D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE as skip flag
if (state != D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE)
ResourceBarrier(cmdList, resource->buffer, D3D12_RESOURCE_STATE_COPY_SOURCE, state);
// Using state D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE as skip flag
if (state != D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE)
ResourceBarrier(cmdList, resource->buffer, D3D12_RESOURCE_STATE_COPY_SOURCE, state);
LOG_DEBUG("Copy created");
LOG_DEBUG("Copy created");
}
else
{
LOG_WARN("Can't create _captureBuffer!");
_captureCounter[fIndex]--;
break;
}
}
else
{
LOG_WARN("Can't create _captureBuffer!");
_captureCounter[fIndex]--;
break;
DXGI_SWAP_CHAIN_DESC scDesc {};
if (State::Instance().currentSwapchain->GetDesc(&scDesc) != S_OK)
{
LOG_WARN("Can't get swapchain desc!");
break;
}
if (CreateBufferResourceWithSize(State::Instance().currentD3D12Device, resource,
D3D12_RESOURCE_STATE_COPY_DEST, &_captureBuffer[fIndex],
scDesc.BufferDesc.Width, scDesc.BufferDesc.Height))
{
LOG_DEBUG("Create a copy of resource: {:X}", (size_t) resource->buffer);
// Using state D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE as skip flag
if (state != D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE)
ResourceBarrier(cmdList, resource->buffer, state, D3D12_RESOURCE_STATE_COPY_SOURCE);
D3D12_TEXTURE_COPY_LOCATION srcLocation;
ZeroMemory(&srcLocation, sizeof(srcLocation));
srcLocation.pResource = resource->buffer;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
srcLocation.SubresourceIndex = 0; // copy from mip 0, array slice 0
D3D12_TEXTURE_COPY_LOCATION dstLocation;
ZeroMemory(&dstLocation, sizeof(dstLocation));
dstLocation.pResource = _captureBuffer[fIndex];
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dstLocation.SubresourceIndex = 0; // paste into mip 0, array slice 0
D3D12_BOX srcBox;
srcBox.left = 0;
srcBox.top = 0;
srcBox.front = 0;
srcBox.right = scDesc.BufferDesc.Width;
srcBox.bottom = scDesc.BufferDesc.Height;
srcBox.back = 1;
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, &srcBox);
// Using state D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE as skip flag
if (state != D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE)
ResourceBarrier(cmdList, resource->buffer, D3D12_RESOURCE_STATE_COPY_SOURCE, state);
LOG_DEBUG("Copy created");
}
else
{
LOG_WARN("Can't create _captureBuffer!");
_captureCounter[fIndex]--;
break;
}
}
// needs conversion?
+4
View File
@@ -27,6 +27,7 @@ typedef struct ResourceInfo
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
ResourceType type = SRV;
double lastUsedFrame = 0;
bool extended = false;
} resource_info;
typedef struct HudlessInfo
@@ -81,6 +82,9 @@ class Hudfix_Dx12
static bool CreateObjects();
static bool CreateBufferResource(ID3D12Device* InDevice, ResourceInfo* InSource, D3D12_RESOURCE_STATES InState,
ID3D12Resource** OutResource);
static bool CreateBufferResourceWithSize(ID3D12Device* InDevice, ResourceInfo* InSource,
D3D12_RESOURCE_STATES InState, ID3D12Resource** OutResource, UINT InWidth,
UINT InHeight);
static void ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource,
D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState);
+13 -9
View File
@@ -2583,6 +2583,19 @@ bool MenuCommon::RenderMenu()
}
ShowHelpMarker("Delay HUDless capture, high values might cause crash!");
ImGui::EndDisabled();
auto hudExtended = Config::Instance()->FGHUDFixExtended.value_or_default();
if (ImGui::Checkbox("FG Extended", &hudExtended))
{
LOG_DEBUG("Enabled set FGHUDFixExtended: {}", hudExtended);
Config::Instance()->FGHUDFixExtended = hudExtended;
}
ShowHelpMarker("Extended format checks for possible hudless\nMight cause crash and slowdowns!");
ImGui::SameLine(0.0f, 16.0f);
ImGui::BeginDisabled(!Config::Instance()->FGHUDFix.value_or_default());
auto immediate = Config::Instance()->FGImmediateCapture.value_or_default();
if (ImGui::Checkbox("FG Immediate Capture", &immediate))
{
@@ -2592,15 +2605,6 @@ bool MenuCommon::RenderMenu()
ShowHelpMarker("Enables capturing of resources before shader execution.\nIncrease hudless "
"capture chances but might cause capturing of unnecessary resources.");
ImGui::SameLine(0.0f, 16.0f);
auto hudExtended = Config::Instance()->FGHUDFixExtended.value_or_default();
if (ImGui::Checkbox("FG Extended", &hudExtended))
{
LOG_DEBUG("Enabled set FGHUDFixExtended: {}", hudExtended);
Config::Instance()->FGHUDFixExtended = hudExtended;
}
ShowHelpMarker("Extended format checks for possible hudless\nMight cause crash and slowdowns!");
ImGui::PopItemWidth();
ImGui::EndDisabled();
@@ -138,12 +138,11 @@ bool ResTrack_Dx12::CheckResource(ID3D12Resource* resource)
auto resDesc = resource->GetDesc();
if (resDesc.Height != scDesc.BufferDesc.Height || resDesc.Width != scDesc.BufferDesc.Width)
{
return false;
return Config::Instance()->FGHUDFixExtended.value_or_default() && resDesc.Height >= scDesc.BufferDesc.Height &&
resDesc.Height <= scDesc.BufferDesc.Height + 32 && resDesc.Width >= scDesc.BufferDesc.Width &&
resDesc.Width <= scDesc.BufferDesc.Width + 32;
}
// LOG_TRACE("Resource: {:X} {}x{} == {}x{}", (size_t) resource, resDesc.Width, resDesc.Height,
// scDesc.BufferDesc.Width, scDesc.BufferDesc.Height);
return true;
}
-2
View File
@@ -24,8 +24,6 @@ IFeature_Dx12::~IFeature_Dx12()
if (State::Instance().isShuttingDown)
return;
LOG_DEBUG("");
if (Imgui != nullptr && Imgui.get() != nullptr)
Imgui.reset();