diff --git a/OptiScaler/framegen/IFGFeature_Dx12.cpp b/OptiScaler/framegen/IFGFeature_Dx12.cpp index 09a1183a..bacdc2f2 100644 --- a/OptiScaler/framegen/IFGFeature_Dx12.cpp +++ b/OptiScaler/framegen/IFGFeature_Dx12.cpp @@ -3,6 +3,64 @@ #include #include +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) { diff --git a/OptiScaler/framegen/IFGFeature_Dx12.h b/OptiScaler/framegen/IFGFeature_Dx12.h index 902016c1..6c3b618b 100644 --- a/OptiScaler/framegen/IFGFeature_Dx12.h +++ b/OptiScaler/framegen/IFGFeature_Dx12.h @@ -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, diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp index c29220dd..82c5b4b4 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp @@ -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 { diff --git a/OptiScaler/hudfix/Hudfix_Dx12.cpp b/OptiScaler/hudfix/Hudfix_Dx12.cpp index 64eb148a..844c5dcf 100644 --- a/OptiScaler/hudfix/Hudfix_Dx12.cpp +++ b/OptiScaler/hudfix/Hudfix_Dx12.cpp @@ -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? diff --git a/OptiScaler/hudfix/Hudfix_Dx12.h b/OptiScaler/hudfix/Hudfix_Dx12.h index 31e7cc67..57df22b0 100644 --- a/OptiScaler/hudfix/Hudfix_Dx12.h +++ b/OptiScaler/hudfix/Hudfix_Dx12.h @@ -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); diff --git a/OptiScaler/menu/menu_common.cpp b/OptiScaler/menu/menu_common.cpp index 3397a65e..9a4b7669 100644 --- a/OptiScaler/menu/menu_common.cpp +++ b/OptiScaler/menu/menu_common.cpp @@ -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(); diff --git a/OptiScaler/resource_tracking/ResTrack_dx12.cpp b/OptiScaler/resource_tracking/ResTrack_dx12.cpp index 8cb8e98f..54470c71 100644 --- a/OptiScaler/resource_tracking/ResTrack_dx12.cpp +++ b/OptiScaler/resource_tracking/ResTrack_dx12.cpp @@ -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; } diff --git a/OptiScaler/upscalers/IFeature_Dx12.cpp b/OptiScaler/upscalers/IFeature_Dx12.cpp index a9c6767e..b0505dd1 100644 --- a/OptiScaler/upscalers/IFeature_Dx12.cpp +++ b/OptiScaler/upscalers/IFeature_Dx12.cpp @@ -24,8 +24,6 @@ IFeature_Dx12::~IFeature_Dx12() if (State::Instance().isShuttingDown) return; - LOG_DEBUG(""); - if (Imgui != nullptr && Imgui.get() != nullptr) Imgui.reset();