Pause for Dx11 bugcheck

This commit is contained in:
cdozdil
2025-08-08 22:24:24 +03:00
parent 04fc5e62b4
commit 52cde9cff0
8 changed files with 530 additions and 387 deletions
+9 -22
View File
@@ -11,11 +11,7 @@ UINT64 IFGFeature::StartNewFrame()
_frameCount++;
auto fIndex = GetIndex();
_hudlessReady[fIndex] = false;
_depthReady[fIndex] = false;
_mvsReady[fIndex] = false;
_uiReady[fIndex] = false;
_distortionFieldReady[fIndex] = false;
_resourceReady[fIndex].clear();
_waitingExecute[fIndex] = false;
@@ -23,29 +19,20 @@ UINT64 IFGFeature::StartNewFrame()
_noDistortionField[fIndex] = true;
_noHudless[fIndex] = true;
NewFrame();
return _frameCount;
}
void IFGFeature::SetResourceReady(FG_ResourceType type) { _resourceReady[GetIndex()][type] = true; }
bool IFGFeature::IsResourceReady(FG_ResourceType type) { return _resourceReady->contains(type); }
bool IFGFeature::WaitingExecution() { return _waitingExecute[GetIndex()]; }
void IFGFeature::SetExecuted() { _waitingExecute[GetIndex()] = false; }
bool IFGFeature::DepthReady() { return _depthReady[GetIndex()]; }
void IFGFeature::SetDepthReady() { _depthReady[GetIndex()] = true; }
bool IFGFeature::MVsReady() { return _mvsReady[GetIndex()]; }
void IFGFeature::SetMVsReady() { _mvsReady[GetIndex()] = true; }
bool IFGFeature::UIReady() { return _uiReady[GetIndex()]; }
void IFGFeature::SetUIReady() { _uiReady[GetIndex()] = true; }
bool IFGFeature::UsingUI() { return !_noUi[GetIndex()]; }
bool IFGFeature::DistortionFieldReady() { return _distortionFieldReady[GetIndex()]; }
void IFGFeature::SetDistortionFieldReady() { _distortionFieldReady[GetIndex()] = true; }
bool IFGFeature::UsingDistortionField() { return !_noDistortionField[GetIndex()]; }
bool IFGFeature::HudlessReady() { return _hudlessReady[GetIndex()]; }
void IFGFeature::SetHudlessReady() { _hudlessReady[GetIndex()] = true; }
bool IFGFeature::UsingHudless() { return !_noHudless[GetIndex()]; }
bool IFGFeature::IsUsingUI() { return !_noUi[GetIndex()]; }
bool IFGFeature::IsUsingDistortionField() { return !_noDistortionField[GetIndex()]; }
bool IFGFeature::IsUsingHudless() { return !_noHudless[GetIndex()]; }
bool IFGFeature::CheckForRealObject(std::string functionName, IUnknown* pObject, IUnknown** ppRealObject)
{
+26 -25
View File
@@ -26,6 +26,21 @@ struct FG_Constants
// uint32_t maxRenderHeight;
};
typedef enum FG_ResourceType
{
Depth = 0,
Velocity,
HudlessColor,
UIColor,
Distortion
};
typedef enum FG_ResourceValidity
{
ValidNow = 0,
UntilPresent
};
class IFGFeature
{
protected:
@@ -52,11 +67,7 @@ class IFGFeature
bool _isActive = false;
UINT64 _targetFrame = 0;
bool _hudlessReady[BUFFER_COUNT] {};
bool _depthReady[BUFFER_COUNT] {};
bool _mvsReady[BUFFER_COUNT] {};
bool _uiReady[BUFFER_COUNT] {};
bool _distortionFieldReady[BUFFER_COUNT] {};
std::map<FG_ResourceType, bool> _resourceReady[BUFFER_COUNT] {};
bool _noHudless[BUFFER_COUNT] = { true, true, true, true };
bool _noUi[BUFFER_COUNT] = { true, true, true, true };
@@ -66,40 +77,30 @@ class IFGFeature
IID streamlineRiid {};
bool CheckForRealObject(std::string functionName, IUnknown* pObject, IUnknown** ppRealObject);
virtual void NewFrame() = 0;
public:
OwnedMutex Mutex;
virtual feature_version Version() = 0;
virtual const char* Name() = 0;
virtual bool NeedsCommandlistExecution() = 0;
virtual bool ManualPipeline() = 0;
virtual void ReleaseObjects() = 0;
virtual void StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex) = 0;
virtual bool Dispatch() = 0;
virtual void StopAndDestroyContext(bool destroy, bool shutDown) = 0;
int GetIndex();
UINT64 StartNewFrame();
bool DepthReady();
void SetDepthReady();
void SetResourceReady(FG_ResourceType type);
bool IsResourceReady(FG_ResourceType type);
bool MVsReady();
void SetMVsReady();
bool IsUsingUI();
bool IsUsingDistortionField();
bool IsUsingHudless();
bool UIReady();
void SetUIReady();
bool UsingUI();
bool DistortionFieldReady();
void SetDistortionFieldReady();
bool UsingDistortionField();
void SetHudlessReady();
bool HudlessReady();
bool UsingHudless();
bool WaitingExecution();
void SetExecuted();
bool WaitingExecution();
bool IsActive();
bool IsPaused();
+8 -226
View File
@@ -3,148 +3,6 @@
#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 initialState, ID3D12Resource** target, 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 != inDesc.Width || bufDesc.Height != inDesc.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;
}
hr = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &inDesc, initialState, 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;
}
void IFGFeature_Dx12::ResourceBarrier(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* resource,
D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState)
{
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = resource;
barrier.Transition.StateBefore = beforeState;
barrier.Transition.StateAfter = afterState;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
cmdList->ResourceBarrier(1, &barrier);
}
bool IFGFeature_Dx12::CopyResource(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* source, ID3D12Resource** target,
D3D12_RESOURCE_STATES sourceState)
{
auto result = true;
ResourceBarrier(cmdList, source, sourceState, D3D12_RESOURCE_STATE_COPY_SOURCE);
if (CreateBufferResource(State::Instance().currentD3D12Device, source, D3D12_RESOURCE_STATE_COPY_DEST, target))
cmdList->CopyResource(*target, source);
else
result = false;
ResourceBarrier(cmdList, source, D3D12_RESOURCE_STATE_COPY_SOURCE, sourceState);
return result;
}
void IFGFeature_Dx12::SetVelocity(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* velocity,
D3D12_RESOURCE_STATES state)
{
@@ -386,95 +244,19 @@ void IFGFeature_Dx12::GetHudless(ID3D12Resource* buffer, D3D12_RESOURCE_STATES b
_gameCommandQueue->ExecuteCommandLists(1, &commandList);
}
void IFGFeature_Dx12::CreateObjects(ID3D12Device* InDevice)
Dx12Resource* IFGFeature_Dx12::GetResource(FG_ResourceType type)
{
_device = InDevice;
auto fIndex = GetIndex();
if (_commandAllocators[0] != nullptr)
ReleaseObjects();
if (_frameResources[fIndex].contains(type))
return &_frameResources[fIndex][type];
LOG_DEBUG("");
do
{
HRESULT result;
// One extra to copy things
for (size_t i = 0; i < BUFFER_COUNT + 1; i++)
{
ID3D12CommandAllocator* allocator = nullptr;
result = InDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&allocator));
if (result != S_OK)
{
LOG_ERROR("CreateCommandAllocators _commandAllocators[{}]: {:X}", i, (unsigned long) result);
break;
}
allocator->SetName(std::format(L"_commandAllocator_{}", i).c_str());
if (!CheckForRealObject(__FUNCTION__, allocator, (IUnknown**) &_commandAllocators[i]))
_commandAllocators[i] = allocator;
ID3D12GraphicsCommandList* cmdList = nullptr;
result = InDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocators[i], NULL,
IID_PPV_ARGS(&cmdList));
if (result != S_OK)
{
LOG_ERROR("CreateCommandList _hudlessCommandList[{}]: {:X}", i, (unsigned long) result);
break;
}
cmdList->SetName(std::format(L"_hudlessCommandList_{}", i).c_str());
if (!CheckForRealObject(__FUNCTION__, cmdList, (IUnknown**) &_commandList[i]))
_commandList[i] = cmdList;
result = _commandList[i]->Close();
if (result != S_OK)
{
LOG_ERROR("_hudlessCommandList[{}]->Close: {:X}", i, (unsigned long) result);
break;
}
}
} while (false);
return nullptr;
}
void IFGFeature_Dx12::ReleaseObjects()
void IFGFeature_Dx12::NewFrame()
{
LOG_DEBUG("");
auto fIndex = GetIndex();
for (size_t i = 0; i < BUFFER_COUNT; i++)
{
if (_commandAllocators[i] != nullptr)
{
_commandAllocators[i]->Release();
_commandAllocators[i] = nullptr;
}
if (_commandList[i] != nullptr)
{
_commandList[i]->Release();
_commandList[i] = nullptr;
}
}
_mvFlip.reset();
_depthFlip.reset();
}
ID3D12CommandList* IFGFeature_Dx12::GetCommandList() { return _commandList[GetIndex()]; }
bool IFGFeature_Dx12::ExecuteCommandList(ID3D12CommandQueue* queue)
{
LOG_DEBUG();
if (!NeedsCommandlistExecution())
return true;
if (WaitingExecution())
{
auto cmdList = GetCommandList();
queue->ExecuteCommandLists(1, &cmdList);
SetExecuted();
return true;
}
return false;
_frameResources[fIndex].clear();
}
+20 -81
View File
@@ -10,81 +10,31 @@
#include <d3d12.h>
#include <ffx_api_types.h>
struct Dx12Resource
typedef struct Dx12Resource
{
private:
D3D12_RESOURCE_STATES state {};
public:
ID3D12Resource* resource {};
void setState(D3D12_RESOURCE_STATES state) { this->state = state; }
D3D12_RESOURCE_STATES getState() { return state; }
FfxApiResourceState getFfxApiState()
{
switch (state)
{
case D3D12_RESOURCE_STATE_COMMON:
return FFX_API_RESOURCE_STATE_COMMON;
case D3D12_RESOURCE_STATE_UNORDERED_ACCESS:
return FFX_API_RESOURCE_STATE_UNORDERED_ACCESS;
case D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE:
return FFX_API_RESOURCE_STATE_COMPUTE_READ;
case D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE:
return FFX_API_RESOURCE_STATE_PIXEL_READ;
case (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE):
return FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ;
case D3D12_RESOURCE_STATE_COPY_SOURCE:
return FFX_API_RESOURCE_STATE_COPY_SRC;
case D3D12_RESOURCE_STATE_COPY_DEST:
return FFX_API_RESOURCE_STATE_COPY_DEST;
case D3D12_RESOURCE_STATE_GENERIC_READ:
return FFX_API_RESOURCE_STATE_GENERIC_READ;
case D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT:
return FFX_API_RESOURCE_STATE_INDIRECT_ARGUMENT;
case D3D12_RESOURCE_STATE_RENDER_TARGET:
return FFX_API_RESOURCE_STATE_RENDER_TARGET;
default:
return FFX_API_RESOURCE_STATE_COMMON;
}
}
FG_ResourceType type = FG_ResourceType::Undefined;
ID3D12Resource* resource = nullptr;
ID3D12Resource* copy = nullptr;
ID3D12CommandList* cmdList = nullptr;
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COMMON;
FG_ResourceValidity validity = FG_ResourceValidity::ValidNow;
};
class IFGFeature_Dx12 : public virtual IFGFeature
{
private:
std::unique_ptr<RF_Dx12> _mvFlip;
std::unique_ptr<RF_Dx12> _depthFlip;
ID3D12Device* _device = nullptr;
protected:
ID3D12Device* _device = nullptr;
IDXGISwapChain* _swapChain = nullptr;
ID3D12CommandQueue* _gameCommandQueue = nullptr;
HWND _hwnd = NULL;
Dx12Resource _paramVelocity[BUFFER_COUNT] {};
Dx12Resource _paramVelocityCopy[BUFFER_COUNT] {};
Dx12Resource _paramDepth[BUFFER_COUNT] {};
Dx12Resource _paramDepthCopy[BUFFER_COUNT] {};
Dx12Resource _paramHudless[BUFFER_COUNT] {};
Dx12Resource _paramHudlessCopy[BUFFER_COUNT] {};
Dx12Resource _paramUi[BUFFER_COUNT] {};
Dx12Resource _paramUiCopy[BUFFER_COUNT] {};
Dx12Resource _paramDistortionField[BUFFER_COUNT] {};
Dx12Resource _paramDistortionFieldCopy[BUFFER_COUNT] {};
std::map<FG_ResourceType, Dx12Resource> _frameResources[BUFFER_COUNT] {};
// One extra to copy things
ID3D12GraphicsCommandList* _commandList[BUFFER_COUNT + 1] {};
ID3D12CommandAllocator* _commandAllocators[BUFFER_COUNT + 1] {};
std::unique_ptr<RF_Dx12> _mvFlip;
std::unique_ptr<RF_Dx12> _depthFlip;
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,
D3D12_RESOURCE_STATES sourceState);
void NewFrame() override final;
public:
virtual bool CreateSwapchain(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, DXGI_SWAP_CHAIN_DESC* desc,
@@ -95,31 +45,20 @@ class IFGFeature_Dx12 : public virtual IFGFeature
virtual bool ReleaseSwapchain(HWND hwnd) = 0;
virtual void CreateContext(ID3D12Device* device, FG_Constants& fgConstants) = 0;
virtual void EvaluateState(ID3D12Device* device, FG_Constants& fgConstants) = 0;
virtual bool Dispatch() = 0;
virtual void* FrameGenerationContext() = 0;
virtual void* SwapchainContext() = 0;
// IFGFeature
void ReleaseObjects() override final;
void CreateObjects(ID3D12Device* InDevice);
virtual void ReleaseObjects() = 0;
virtual void CreateObjects(ID3D12Device* InDevice) = 0;
void SetVelocity(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* velocity, D3D12_RESOURCE_STATES state);
void SetDepth(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* depth, D3D12_RESOURCE_STATES state);
void SetHudless(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* hudless, D3D12_RESOURCE_STATES state,
bool makeCopy = false);
void SetUI(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* ui, D3D12_RESOURCE_STATES state,
bool makeCopy = false);
void SetDistortionField(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* ui, D3D12_RESOURCE_STATES state,
bool makeCopy = false);
Dx12Resource* GetResource(FG_ResourceType type);
virtual void SetResource(FG_ResourceType type, ID3D12GraphicsCommandList* cmdList, ID3D12Resource* resource,
D3D12_RESOURCE_STATES state, FG_ResourceValidity validity) = 0;
void GetHudless(ID3D12Resource* buffer, D3D12_RESOURCE_STATES bufferState);
bool ExecuteCommandList(ID3D12CommandQueue* queue);
ID3D12CommandList* GetCommandList();
virtual bool ExecuteCommandList(ID3D12CommandQueue* queue) = 0;
virtual ID3D12CommandList* GetCommandList() = 0;
IFGFeature_Dx12() = default;
};
+402 -27
View File
@@ -226,7 +226,7 @@ bool FSRFG_Dx12::Dispatch()
dfgPrepare.header.pNext = &dfgCameraData.header;
// Prepare command list
auto allocator = _commandAllocators[fIndex];
auto allocator = _fgCommandAllocator;
auto result = allocator->Reset();
if (result != S_OK)
{
@@ -234,14 +234,14 @@ bool FSRFG_Dx12::Dispatch()
return false;
}
result = _commandList[fIndex]->Reset(allocator, nullptr);
result = _fgCommandList->Reset(allocator, nullptr);
if (result != S_OK)
{
LOG_ERROR("_hudlessCommandList[fIndex]->Reset error: {:X}", (UINT) result);
return false;
}
dfgPrepare.commandList = _commandList[fIndex];
dfgPrepare.commandList = _fgCommandList;
dfgPrepare.frameID = _frameCount;
dfgPrepare.flags = m_FrameGenerationConfig.flags;
@@ -280,7 +280,7 @@ bool FSRFG_Dx12::Dispatch()
fIndex, (size_t) dfgPrepare.commandList);
if (retCode == FFX_API_RETURN_OK)
_commandList[fIndex]->Close();
_fgCommandList->Close();
}
if (Config::Instance()->FGUseMutexForSwapchain.value_or_default() && Mutex.getOwner() == 1)
@@ -289,11 +289,8 @@ bool FSRFG_Dx12::Dispatch()
Mutex.unlockThis(1);
};
_mvsReady[fIndex] = false;
_depthReady[fIndex] = false;
_hudlessReady[fIndex] = false;
_uiReady[fIndex] = false;
_distortionFieldReady[fIndex] = false;
_resourceReady[fIndex].clear();
_isCopyCmdListReset[fIndex] = false;
_waitingExecute[fIndex] = true;
return retCode == FFX_API_RETURN_OK;
@@ -363,21 +360,12 @@ void* FSRFG_Dx12::SwapchainContext()
return _swapChainContext;
}
void FSRFG_Dx12::StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex)
void FSRFG_Dx12::StopAndDestroyContext(bool destroy, bool shutDown)
{
_frameCount = 0;
LOG_DEBUG("");
bool mutexTaken = false;
if (Config::Instance()->FGUseMutexForSwapchain.value_or_default() && useMutex)
{
LOG_TRACE("Waiting Mutex 1, current: {}", Mutex.getOwner());
Mutex.lock(1);
mutexTaken = true;
LOG_TRACE("Accuired Mutex: {}", Mutex.getOwner());
}
if (!(shutDown || State::Instance().isShuttingDown) && _fgContext != nullptr)
{
ffxConfigureDescFrameGeneration m_FrameGenerationConfig = {};
@@ -408,12 +396,6 @@ void FSRFG_Dx12::StopAndDestroyContext(bool destroy, bool shutDown, bool useMute
if (shutDown || State::Instance().isShuttingDown)
ReleaseObjects();
if (mutexTaken)
{
LOG_TRACE("Releasing Mutex: {}", Mutex.getOwner());
Mutex.unlockThis(1);
}
}
bool FSRFG_Dx12::CreateSwapchain(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, DXGI_SWAP_CHAIN_DESC* desc,
@@ -506,7 +488,7 @@ bool FSRFG_Dx12::ReleaseSwapchain(HWND hwnd)
MenuOverlayDx::CleanupRenderTarget(true, NULL);
if (_fgContext != nullptr)
StopAndDestroyContext(true, true, false);
StopAndDestroyContext(true, true);
if (_swapChainContext != nullptr)
{
@@ -657,7 +639,7 @@ void FSRFG_Dx12::EvaluateState(ID3D12Device* device, FG_Constants& fgConstants)
}
else if ((!Config::Instance()->FGEnabled.value_or_default() || State::Instance().FGchanged) && IsActive())
{
StopAndDestroyContext(State::Instance().SCchanged, false, false);
StopAndDestroyContext(State::Instance().SCchanged, false);
if (State::Instance().activeFgInput == FGInput::Upscaler)
{
@@ -684,3 +666,396 @@ void FSRFG_Dx12::EvaluateState(ID3D12Device* device, FG_Constants& fgConstants)
State::Instance().SCchanged = false;
}
bool FSRFG_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 FSRFG_Dx12::CreateBufferResource(ID3D12Device* device, ID3D12Resource* source, D3D12_RESOURCE_STATES initialState,
ID3D12Resource** target, 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 != inDesc.Width || bufDesc.Height != inDesc.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;
}
hr = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &inDesc, initialState, 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;
}
void FSRFG_Dx12::ResourceBarrier(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* resource,
D3D12_RESOURCE_STATES beforeState, D3D12_RESOURCE_STATES afterState)
{
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = resource;
barrier.Transition.StateBefore = beforeState;
barrier.Transition.StateAfter = afterState;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
cmdList->ResourceBarrier(1, &barrier);
}
bool FSRFG_Dx12::CopyResource(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* source, ID3D12Resource** target,
D3D12_RESOURCE_STATES sourceState)
{
auto result = true;
ResourceBarrier(cmdList, source, sourceState, D3D12_RESOURCE_STATE_COPY_SOURCE);
if (CreateBufferResource(State::Instance().currentD3D12Device, source, D3D12_RESOURCE_STATE_COPY_DEST, target))
cmdList->CopyResource(*target, source);
else
result = false;
ResourceBarrier(cmdList, source, D3D12_RESOURCE_STATE_COPY_SOURCE, sourceState);
return result;
}
void FSRFG_Dx12::ReleaseObjects()
{
LOG_DEBUG("");
if (_fgCommandAllocator != nullptr)
{
_fgCommandAllocator->Release();
_fgCommandAllocator = nullptr;
}
if (_fgCommandList != nullptr)
{
_fgCommandList->Release();
_fgCommandList = nullptr;
}
magic_enum::enum_for_each<FG_ResourceType>(
[](auto val)
{
if (_copyCommandAllocator.contains(val))
_copyCommandAllocator[val]->Release();
if (_copyCommandList.contains(val))
_copyCommandList[val]->Release();
});
_copyCommandAllocator.clear();
_copyCommandList.clear();
_mvFlip.reset();
_depthFlip.reset();
}
ID3D12CommandList* FSRFG_Dx12::GetCommandList() { return _fgCommandList; }
bool FSRFG_Dx12::ExecuteCommandList(ID3D12CommandQueue* queue)
{
LOG_DEBUG();
if (!ManualPipeline())
return true;
if (WaitingExecution())
{
queue->ExecuteCommandLists(1, (ID3D12CommandList**) &_fgCommandList);
SetExecuted();
return true;
}
return false;
}
void FSRFG_Dx12::SetResource(FG_ResourceType type, ID3D12GraphicsCommandList* cmdList, ID3D12Resource* resource,
D3D12_RESOURCE_STATES state, FG_ResourceValidity validity)
{
if (resource == nullptr)
return;
if (validity == FG_ResourceValidity::ValidNow && State::Instance().currentCommandQueue == nullptr)
{
LOG_ERROR("{}, validity == ValidNow but State::Instance().currentCommandQueue is nullptr!",
magic_enum::enum_name(type));
return;
}
if (cmdList == nullptr && validity == FG_ResourceValidity::ValidNow)
{
if (!_copyCommandAllocator.contains(type) || !_copyCommandList.contains(type))
{
LOG_ERROR("{}, _copyCommandAllocator or _copyCommandList is nullptr!", magic_enum::enum_name(type));
return;
}
auto allocator = _copyCommandAllocator[type];
cmdList = _copyCommandList[type];
allocator->Reset();
cmdList->Reset(allocator, nullptr);
}
auto fIndex = GetIndex();
_frameResources[fIndex][type] = {};
auto fResource = &_frameResources[fIndex][type];
fResource->cmdList = cmdList;
fResource->state = state;
fResource->validity = validity;
fResource->resource = resource;
if (type == FG_ResourceType::Velocity && State::Instance().activeFgInput == FGInput::Upscaler &&
Config::Instance()->FGResourceFlip.value_or_default() && _device != nullptr)
{
if (_mvFlip.get() == nullptr)
{
_mvFlip = std::make_unique<RF_Dx12>("VelocityFlip", _device);
return;
}
ID3D12Resource* flipOutput = nullptr;
if (validity == FG_ResourceValidity::UntilPresent)
{
flipOutput = resource;
}
else
{
flipOutput = _resourceCopy[fIndex][type];
if (!CreateBufferResource(_device, resource, state, &flipOutput, true, false))
{
LOG_ERROR("{}, CreateBufferResource for flip is failed!", magic_enum::enum_name(type));
return;
}
_resourceCopy[fIndex][type] = flipOutput;
flipOutput->SetName(std::format(L"VelocityCopyResource_{}", fIndex).c_str());
}
if (_mvFlip->IsInit())
{
auto feature = State::Instance().currentFeature;
UINT width = feature->LowResMV() ? feature->RenderWidth() : feature->DisplayWidth();
UINT height = feature->LowResMV() ? feature->RenderHeight() : feature->DisplayHeight();
ResourceBarrier(cmdList, flipOutput, state, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
auto result = _mvFlip->Dispatch(_device, cmdList, resource, flipOutput, width, height, true);
ResourceBarrier(cmdList, flipOutput, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, state);
if (result)
{
LOG_TRACE("Setting velocity from flip, index: {}", fIndex);
fResource->copy = flipOutput;
}
}
}
if (validity == FG_ResourceValidity::ValidNow &&
(!Config::Instance()->FGResourceFlip.value_or_default() || (type != FG_ResourceType::Depth &&
type != FG_ResourceType::Velocity))
{
ID3D12Resource* copyOutput = nullptr;
copyOutput = _resourceCopy[fIndex][type];
if (!CopyResource(cmdList, resource, &copyOutput, state))
{
LOG_ERROR("{}, CopyResource error!", magic_enum::enum_name(type));
return;
}
_resourceCopy[fIndex][type] = copyOutput;
copyOutput->SetName(std::format(L"VelocityCopyResource_{}", fIndex).c_str());
fResource->copy = copyOutput;
}
if (validity == FG_ResourceValidity::ValidNow)
{
cmdList->Close();
State::Instance().currentCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList**) &cmdList);
}
}
void FSRFG_Dx12::CreateObjects(ID3D12Device* InDevice)
{
_device = InDevice;
if (_fgCommandAllocator != nullptr)
ReleaseObjects();
LOG_DEBUG("");
do
{
HRESULT result;
ID3D12CommandAllocator* allocator = nullptr;
ID3D12GraphicsCommandList* cmdList = nullptr;
// FG
result = InDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&_fgCommandAllocator));
if (result != S_OK)
{
LOG_ERROR("CreateCommandAllocators _fgCommandAllocator: {:X}", (unsigned long) result);
break;
}
_fgCommandAllocator->SetName(L"_fgCommandAllocator");
if (!CheckForRealObject(__FUNCTION__, _fgCommandAllocator, (IUnknown**) &allocator))
_fgCommandAllocator = allocator;
result = InDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, _fgCommandAllocator, NULL,
IID_PPV_ARGS(&_fgCommandList));
if (result != S_OK)
{
LOG_ERROR("CreateCommandList _hudlessCommandList: {:X}", (unsigned long) result);
break;
}
_fgCommandList->SetName(L"_fgCommandList");
if (!CheckForRealObject(__FUNCTION__, _fgCommandList, (IUnknown**) &cmdList))
_fgCommandList = cmdList;
result = _fgCommandList->Close();
if (result != S_OK)
{
LOG_ERROR("_fgCommandList->Close: {:X}", (unsigned long) result);
break;
}
magic_enum::enum_for_each<FG_ResourceType>(
[](auto val)
{
ID3D12CommandAllocator* enumAllocator = nullptr;
ID3D12GraphicsCommandList* enumCmdList = nullptr;
// Copy
result = InDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&enumAllocator));
if (result != S_OK)
{
LOG_ERROR("CreateCommandAllocators _copyCommandAllocator[]: {:X}", magic_enum::enum_name(val),
(unsigned long) result);
break;
}
enumAllocator->SetName(std::format(L"_copyCommandAllocator[{}]", magic_enum::enum_name(val)).c_str());
if (!CheckForRealObject(__FUNCTION__, enumAllocator, (IUnknown**) &allocator))
enumAllocator = allocator;
result = InDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, enumAllocator, NULL,
IID_PPV_ARGS(&enumCommandList));
if (result != S_OK)
{
LOG_ERROR("CreateCommandList _copyCommandList[{}]: {:X}", magic_enum::enum_name(val),
(unsigned long) result);
break;
}
enumCommandList->SetName(std::format(L"_copyCommandAllocator[{}]", magic_enum::enum_name(val)).c_str());
if (!CheckForRealObject(__FUNCTION__, enumCommandList, (IUnknown**) &cmdList))
enumCommandList = cmdList;
result = enumCommandList->Close();
if (result != S_OK)
{
LOG_ERROR("_copyCommandList[{}]->Close: {:X}", magic_enum::enum_name(val)).c_str(), (unsigned long) result);
break;
}
_copyCommandAllocator[val] = _copyCommandAllocator;
_copyCommandList[val] = _copyCommandList;
});
} while (false);
}
+63 -5
View File
@@ -7,21 +7,73 @@
#include <dx12/ffx_api_dx12.h>
#include <ffx_framegeneration.h>
#include <magic_enum.hpp>
#include <magic_enum_utility.hpp>
class FSRFG_Dx12 : public virtual IFGFeature_Dx12
{
private:
ffxContext _swapChainContext = nullptr;
ffxContext _fgContext = nullptr;
uint32_t _lastHudlessFormat = FFX_API_SURFACE_FORMAT_UNKNOWN;
uint32_t _usingHudlessFormat = FFX_API_SURFACE_FORMAT_UNKNOWN;
// One extra to copy things
ID3D12GraphicsCommandList* _fgCommandList {};
ID3D12CommandAllocator* _fgCommandAllocator {};
std::map<FG_ResourceType, ID3D12Resource*> _resourceCopy[BUFFER_COUNT] {};
std::map<FG_ResourceType, ID3D12CommandAllocator*> _copyCommandAllocator {};
std::map<FG_ResourceType, ID3D12GraphicsCommandList*> _copyCommandList {};
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,
D3D12_RESOURCE_STATES sourceState);
static FfxApiResourceState GetFfxApiState(D3D12_RESOURCE_STATES state)
{
switch (state)
{
case D3D12_RESOURCE_STATE_COMMON:
return FFX_API_RESOURCE_STATE_COMMON;
case D3D12_RESOURCE_STATE_UNORDERED_ACCESS:
return FFX_API_RESOURCE_STATE_UNORDERED_ACCESS;
case D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE:
return FFX_API_RESOURCE_STATE_COMPUTE_READ;
case D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE:
return FFX_API_RESOURCE_STATE_PIXEL_READ;
case (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE):
return FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ;
case D3D12_RESOURCE_STATE_COPY_SOURCE:
return FFX_API_RESOURCE_STATE_COPY_SRC;
case D3D12_RESOURCE_STATE_COPY_DEST:
return FFX_API_RESOURCE_STATE_COPY_DEST;
case D3D12_RESOURCE_STATE_GENERIC_READ:
return FFX_API_RESOURCE_STATE_GENERIC_READ;
case D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT:
return FFX_API_RESOURCE_STATE_INDIRECT_ARGUMENT;
case D3D12_RESOURCE_STATE_RENDER_TARGET:
return FFX_API_RESOURCE_STATE_RENDER_TARGET;
default:
return FFX_API_RESOURCE_STATE_COMMON;
}
}
public:
// IFGFeature
const char* Name() override final;
feature_version Version() override final;
bool NeedsCommandlistExecution() override final { return true; }
bool ManualPipeline() override final { return true; }
void* FrameGenerationContext() override final;
void* SwapchainContext() override final;
// IFGFeature_Dx12
bool CreateSwapchain(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, DXGI_SWAP_CHAIN_DESC* desc,
IDXGISwapChain** swapChain) override final;
bool CreateSwapchain1(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, HWND hwnd, DXGI_SWAP_CHAIN_DESC1* desc,
@@ -29,14 +81,20 @@ class FSRFG_Dx12 : public virtual IFGFeature_Dx12
bool ReleaseSwapchain(HWND hwnd) override final;
void CreateContext(ID3D12Device* device, FG_Constants& fgConstants) override final;
void StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex) override final;
void StopAndDestroyContext(bool destroy, bool shutDown) override final;
void EvaluateState(ID3D12Device* device, FG_Constants& fgConstants) override final;
void ReleaseObjects() override final;
void CreateObjects(ID3D12Device* InDevice) override final;
bool Dispatch() override final;
void* FrameGenerationContext() override final;
void* SwapchainContext() override final;
ID3D12CommandList* GetCommandList() override final;
bool ExecuteCommandList(ID3D12CommandQueue* queue) override final;
void SetResource(FG_ResourceType type, ID3D12GraphicsCommandList* cmdList, ID3D12Resource* resource,
D3D12_RESOURCE_STATES state, FG_ResourceValidity validity);
// Methods
void ConfigureFramePaceTuning();
+1 -1
View File
@@ -32,7 +32,7 @@ class XeFG_Dx12 : public virtual IFGFeature_Dx12
// IFGFeature
const char* Name() override final;
feature_version Version() override final;
bool NeedsCommandlistExecution() override final { return false; }
bool ManualPipeline() override final { return false; }
// IFGFeature_Dx12
bool CreateSwapchain(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, DXGI_SWAP_CHAIN_DESC* desc,
+1
View File
@@ -122,5 +122,6 @@ class IFeature
IFeature(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) { SetHandle(InHandleId); }
virtual void Shutdown() = 0;
virtual ~IFeature() {}
};