diff --git a/OptiScaler/framegen/IFGFeature.cpp b/OptiScaler/framegen/IFGFeature.cpp index 4a31a1f1..65fabab6 100644 --- a/OptiScaler/framegen/IFGFeature.cpp +++ b/OptiScaler/framegen/IFGFeature.cpp @@ -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) { diff --git a/OptiScaler/framegen/IFGFeature.h b/OptiScaler/framegen/IFGFeature.h index 35c7cf0f..c2fc9739 100644 --- a/OptiScaler/framegen/IFGFeature.h +++ b/OptiScaler/framegen/IFGFeature.h @@ -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 _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(); diff --git a/OptiScaler/framegen/IFGFeature_Dx12.cpp b/OptiScaler/framegen/IFGFeature_Dx12.cpp index 07a1fc18..1f7b2ce9 100644 --- a/OptiScaler/framegen/IFGFeature_Dx12.cpp +++ b/OptiScaler/framegen/IFGFeature_Dx12.cpp @@ -3,148 +3,6 @@ #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 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(); } diff --git a/OptiScaler/framegen/IFGFeature_Dx12.h b/OptiScaler/framegen/IFGFeature_Dx12.h index 6197950c..d1e11e89 100644 --- a/OptiScaler/framegen/IFGFeature_Dx12.h +++ b/OptiScaler/framegen/IFGFeature_Dx12.h @@ -10,81 +10,31 @@ #include #include -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 _mvFlip; - std::unique_ptr _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 _frameResources[BUFFER_COUNT] {}; - // One extra to copy things - ID3D12GraphicsCommandList* _commandList[BUFFER_COUNT + 1] {}; - ID3D12CommandAllocator* _commandAllocators[BUFFER_COUNT + 1] {}; + std::unique_ptr _mvFlip; + std::unique_ptr _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; }; diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp index 81594d81..4d9fcd78 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp @@ -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( + [](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("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, ©Output, 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( + [](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); +} diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.h b/OptiScaler/framegen/ffx/FSRFG_Dx12.h index 1303f4b1..f9a9c4f5 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.h +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.h @@ -7,21 +7,73 @@ #include #include +#include +#include + 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 _resourceCopy[BUFFER_COUNT] {}; + std::map _copyCommandAllocator {}; + std::map _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(); diff --git a/OptiScaler/framegen/xefg/XeFG_Dx12.h b/OptiScaler/framegen/xefg/XeFG_Dx12.h index 226b4aca..b0e6d0cd 100644 --- a/OptiScaler/framegen/xefg/XeFG_Dx12.h +++ b/OptiScaler/framegen/xefg/XeFG_Dx12.h @@ -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, diff --git a/OptiScaler/upscalers/IFeature.h b/OptiScaler/upscalers/IFeature.h index df06d781..8059c80a 100644 --- a/OptiScaler/upscalers/IFeature.h +++ b/OptiScaler/upscalers/IFeature.h @@ -122,5 +122,6 @@ class IFeature IFeature(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) { SetHandle(InHandleId); } virtual void Shutdown() = 0; + virtual ~IFeature() {} };