mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-09-22 21:35:51 +00:00
Merge branch 'master' of https://github.com/cdozdil/OptiScaler
This commit is contained in:
@@ -31,27 +31,28 @@ protected:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
OwnedMutex Mutex;
|
||||
|
||||
bool IsActive();
|
||||
int GetIndex();
|
||||
virtual feature_version Version() = 0;
|
||||
virtual const char* Name() = 0;
|
||||
|
||||
virtual UINT64 UpscaleStart() = 0;
|
||||
virtual void UpscaleEnd() = 0;
|
||||
|
||||
virtual void FgDone() = 0;
|
||||
virtual void ReleaseObjects() = 0;
|
||||
virtual void StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex) = 0;
|
||||
|
||||
bool IsActive();
|
||||
int GetIndex();
|
||||
|
||||
void SetJitter(float x, float y);
|
||||
void SetMVScale(float x, float y);
|
||||
void SetCameraValues(float nearValue, float farValue, float vFov, float meterFactor = 0.0f);
|
||||
void SetFrameTimeDelta(float delta);
|
||||
void SetReset(UINT reset);
|
||||
|
||||
virtual feature_version Version() = 0;
|
||||
virtual const char* Name() = 0;
|
||||
|
||||
virtual void ReleaseObjects() = 0;
|
||||
virtual void StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex) = 0;
|
||||
virtual void FgDone() = 0;
|
||||
|
||||
void ResetCounters();
|
||||
void UpdateTarget();
|
||||
|
||||
|
||||
@@ -43,26 +43,32 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
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);
|
||||
|
||||
virtual bool CreateSwapchain(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, DXGI_SWAP_CHAIN_DESC* desc, IDXGISwapChain** swapChain) = 0;
|
||||
virtual bool CreateSwapchain1(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, HWND hwnd, DXGI_SWAP_CHAIN_DESC1* desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, IDXGISwapChain1** swapChain) = 0;
|
||||
virtual bool ReleaseSwapchain(HWND hwnd) = 0;
|
||||
|
||||
void CreateObjects(ID3D12Device* InDevice);
|
||||
|
||||
virtual void CreateContext(ID3D12Device* device, IFeature* upscalerContext) = 0;
|
||||
void ReleaseObjects() final;
|
||||
|
||||
virtual bool Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* output, double frameTime) = 0;
|
||||
virtual bool DispatchHudless(bool useHudless, double frameTime) = 0;
|
||||
|
||||
virtual void* FrameGenerationContext() = 0;
|
||||
virtual void* SwapchainContext() = 0;
|
||||
|
||||
// IFGFeature
|
||||
void ReleaseObjects() override final;
|
||||
|
||||
void CreateObjects(ID3D12Device* InDevice);
|
||||
|
||||
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);
|
||||
|
||||
ID3D12Fence* GetCopyFence();
|
||||
ID3D12Fence* GetHudlessFence();
|
||||
|
||||
void SetWaitOnGameQueue(UINT64 value);
|
||||
|
||||
virtual bool Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* output, double frameTime) = 0;
|
||||
virtual bool DispatchHudless(bool useHudless, double frameTime) = 0;
|
||||
|
||||
bool IsFGCommandList(void* cmdList);
|
||||
|
||||
IFGFeature_Dx12() = default;
|
||||
|
||||
@@ -19,7 +19,7 @@ typedef struct FfxSwapchainFramePacingTuning
|
||||
|
||||
void FSRFG_Dx12::ConfigureFramePaceTuning()
|
||||
{
|
||||
if (_swapChainContext == nullptr)
|
||||
if (_swapChainContext == nullptr || !isVersionOrBetter(Version(), { 3, 1, 3 }))
|
||||
return;
|
||||
|
||||
FfxSwapchainFramePacingTuning fpt{};
|
||||
@@ -30,15 +30,15 @@ void FSRFG_Dx12::ConfigureFramePaceTuning()
|
||||
fpt.hybridSpinTime = Config::Instance()->FGFPTHybridSpinTime.value_or_default();
|
||||
fpt.safetyMarginInMs = Config::Instance()->FGFPTSafetyMarginInMs.value_or_default();
|
||||
fpt.varianceFactor = Config::Instance()->FGFPTVarianceFactor.value_or_default();
|
||||
|
||||
ffxConfigureDescFrameGenerationSwapChainKeyValueDX12 cfgDesc{};
|
||||
cfgDesc.header.type = FFX_API_CONFIGURE_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_KEYVALUE_DX12;
|
||||
cfgDesc.key = 2; // FfxSwapchainFramePacingTuning
|
||||
cfgDesc.ptr = &fpt;
|
||||
|
||||
auto result = FfxApiProxy::D3D12_Configure()(&_swapChainContext, &cfgDesc.header);
|
||||
LOG_DEBUG("HybridSpin D3D12_Configure result: {}", FfxApiProxy::ReturnCodeToString(result));
|
||||
}
|
||||
|
||||
ffxConfigureDescFrameGenerationSwapChainKeyValueDX12 cfgDesc{};
|
||||
cfgDesc.header.type = FFX_API_CONFIGURE_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_KEYVALUE_DX12;
|
||||
cfgDesc.key = 2; // FfxSwapchainFramePacingTuning
|
||||
cfgDesc.ptr = &fpt;
|
||||
|
||||
auto result = FfxApiProxy::D3D12_Configure()(&_swapChainContext, &cfgDesc.header);
|
||||
LOG_DEBUG("HybridSpin D3D12_Configure result: {}", FfxApiProxy::ReturnCodeToString(result));
|
||||
}
|
||||
|
||||
void FSRFG_Dx12::GetDispatchCommandList()
|
||||
@@ -562,7 +562,19 @@ void FSRFG_Dx12::FgDone()
|
||||
LOG_TRACE("Releasing Mutex: {}", Mutex.getOwner());
|
||||
Mutex.unlockThis(1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void* FSRFG_Dx12::FrameGenerationContext()
|
||||
{
|
||||
LOG_DEBUG("");
|
||||
return (void*)_fgContext;
|
||||
}
|
||||
|
||||
void* FSRFG_Dx12::SwapchainContext()
|
||||
{
|
||||
LOG_DEBUG("");
|
||||
return _swapChainContext;
|
||||
}
|
||||
|
||||
void FSRFG_Dx12::StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex)
|
||||
{
|
||||
|
||||
@@ -17,35 +17,37 @@ private:
|
||||
void GetDispatchCommandList();
|
||||
|
||||
public:
|
||||
// Inherited via IFGFeature_Dx12
|
||||
UINT64 UpscaleStart() final;
|
||||
void UpscaleEnd() final;
|
||||
// IFGFeature
|
||||
const char* Name() override final;
|
||||
feature_version Version() override final;
|
||||
|
||||
feature_version Version() final;
|
||||
UINT64 UpscaleStart() override final;
|
||||
void UpscaleEnd() override final;
|
||||
|
||||
const char* Name() final;
|
||||
void FgDone() override final;
|
||||
void StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex) override final;
|
||||
|
||||
bool Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* output, double frameTime) 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, DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, IDXGISwapChain1** swapChain) override final;
|
||||
bool ReleaseSwapchain(HWND hwnd) override final;
|
||||
|
||||
bool DispatchHudless(bool useHudless, double frameTime) final;
|
||||
void CreateContext(ID3D12Device* device, IFeature* upscalerContext) override final;
|
||||
|
||||
void StopAndDestroyContext(bool destroy, bool shutDown, bool useMutex) final;
|
||||
bool Dispatch(ID3D12GraphicsCommandList* cmdList, ID3D12Resource* output, double frameTime) override final;
|
||||
bool DispatchHudless(bool useHudless, double frameTime) override final;
|
||||
|
||||
bool CreateSwapchain(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, DXGI_SWAP_CHAIN_DESC* desc, IDXGISwapChain** swapChain) final;
|
||||
|
||||
bool CreateSwapchain1(IDXGIFactory* factory, ID3D12CommandQueue* cmdQueue, HWND hwnd, DXGI_SWAP_CHAIN_DESC1* desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, IDXGISwapChain1** swapChain) final;
|
||||
|
||||
bool ReleaseSwapchain(HWND hwnd) final;
|
||||
|
||||
void CreateContext(ID3D12Device* device, IFeature* upscalerContext) final;
|
||||
void* FrameGenerationContext() override final;
|
||||
void* SwapchainContext() override final;
|
||||
|
||||
// Methods
|
||||
void ConfigureFramePaceTuning();
|
||||
|
||||
ffxReturnCode_t DispatchCallback(ffxDispatchDescFrameGeneration* params);
|
||||
ffxReturnCode_t HudlessDispatchCallback(ffxDispatchDescFrameGeneration* params);
|
||||
|
||||
FSRFG_Dx12() = default;
|
||||
|
||||
// Inherited via IFGFeature_Dx12
|
||||
void FgDone() override;
|
||||
FSRFG_Dx12() : IFGFeature_Dx12(), IFGFeature()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,23 +156,23 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags)
|
||||
fg = reinterpret_cast<IFGFeature_Dx12*>(State::Instance().currentFG);
|
||||
|
||||
auto lockAccuired = false;
|
||||
if (!(Flags & DXGI_PRESENT_TEST || Flags & DXGI_PRESENT_RESTART) && fg != nullptr && fg->IsActive() &&
|
||||
fg->TargetFrame() < fg->FrameCount() && Config::Instance()->FGUseMutexForSwaphain.value_or_default() && fg->Mutex.getOwner() != 2)
|
||||
{
|
||||
LOG_TRACE("Waiting FG->Mutex 2, current: {}", fg->Mutex.getOwner());
|
||||
fg->Mutex.lock(2);
|
||||
//if (!(Flags & DXGI_PRESENT_TEST || Flags & DXGI_PRESENT_RESTART) && fg != nullptr && fg->IsActive() &&
|
||||
// fg->TargetFrame() < fg->FrameCount() && Config::Instance()->FGUseMutexForSwaphain.value_or_default() && fg->Mutex.getOwner() != 2)
|
||||
//{
|
||||
// LOG_TRACE("Waiting FG->Mutex 2, current: {}", fg->Mutex.getOwner());
|
||||
// fg->Mutex.lock(2);
|
||||
|
||||
// If half or full sync is active, we need to release the mutex after 1 or 2 frames at Present
|
||||
lockAccuired = !Config::Instance()->FGHudfixHalfSync.value_or_default() && !Config::Instance()->FGHudfixFullSync.value_or_default();
|
||||
_lockAccuiredForHalfOrFull = !lockAccuired;
|
||||
// // If half or full sync is active, we need to release the mutex after 1 or 2 frames at Present
|
||||
// lockAccuired = !Config::Instance()->FGHudfixHalfSync.value_or_default() && !Config::Instance()->FGHudfixFullSync.value_or_default();
|
||||
// _lockAccuiredForHalfOrFull = !lockAccuired;
|
||||
|
||||
if (Config::Instance()->FGDebugView.value_or_default() || Config::Instance()->FGHudfixHalfSync.value_or_default())
|
||||
_releaseMutexTargetFrame = _frameCounter + 1; // For debug 1 frame
|
||||
else
|
||||
_releaseMutexTargetFrame = _frameCounter + 2; // For FG 2 frames
|
||||
// if (Config::Instance()->FGDebugView.value_or_default() || Config::Instance()->FGHudfixHalfSync.value_or_default())
|
||||
// _releaseMutexTargetFrame = _frameCounter + 1; // For debug 1 frame
|
||||
// else
|
||||
// _releaseMutexTargetFrame = _frameCounter + 2; // For FG 2 frames
|
||||
|
||||
LOG_TRACE("Accuired FG->Mutex: {}, fgMutexReleaseFrame: {}", fg->Mutex.getOwner(), _releaseMutexTargetFrame);
|
||||
}
|
||||
// LOG_TRACE("Accuired FG->Mutex: {}, fgMutexReleaseFrame: {}", fg->Mutex.getOwner(), _releaseMutexTargetFrame);
|
||||
//}
|
||||
|
||||
if (!(Flags & DXGI_PRESENT_TEST || Flags & DXGI_PRESENT_RESTART))
|
||||
{
|
||||
@@ -184,11 +184,11 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags)
|
||||
result = o_FGSCPresent(This, SyncInterval, Flags);
|
||||
LOG_DEBUG("Result: {:X}", result);
|
||||
|
||||
if (lockAccuired && Config::Instance()->FGUseMutexForSwaphain.value_or_default())
|
||||
{
|
||||
LOG_TRACE("Releasing FG->Mutex: {}", fg->Mutex.getOwner());
|
||||
fg->Mutex.unlockThis(2);
|
||||
}
|
||||
//if (lockAccuired && Config::Instance()->FGUseMutexForSwaphain.value_or_default())
|
||||
//{
|
||||
// LOG_TRACE("Releasing FG->Mutex: {}", fg->Mutex.getOwner());
|
||||
// fg->Mutex.unlockThis(2);
|
||||
//}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -399,20 +399,20 @@ static HRESULT Present(IDXGISwapChain * pSwapChain, UINT SyncInterval, UINT Flag
|
||||
ResTrack_Dx12::PresentDone();
|
||||
|
||||
// If Half of Full sync is active or was active (_releaseMutexTargetFrame != 0)
|
||||
if (_releaseMutexTargetFrame != 0 && Config::Instance()->FGUseMutexForSwaphain.value_or_default() && _frameCounter >= _releaseMutexTargetFrame && fg != nullptr)
|
||||
{
|
||||
if (_lockAccuiredForHalfOrFull)
|
||||
{
|
||||
LOG_TRACE("Releasing FG->Mutex: {}", fg->Mutex.getOwner());
|
||||
fg->Mutex.unlockThis(2);
|
||||
_lockAccuiredForHalfOrFull = false;
|
||||
}
|
||||
//if (_releaseMutexTargetFrame != 0 && Config::Instance()->FGUseMutexForSwaphain.value_or_default() && _frameCounter >= _releaseMutexTargetFrame && fg != nullptr)
|
||||
//{
|
||||
// if (_lockAccuiredForHalfOrFull)
|
||||
// {
|
||||
// LOG_TRACE("Releasing FG->Mutex: {}", fg->Mutex.getOwner());
|
||||
// fg->Mutex.unlockThis(2);
|
||||
// _lockAccuiredForHalfOrFull = false;
|
||||
// }
|
||||
|
||||
_releaseMutexTargetFrame = 0;
|
||||
// _releaseMutexTargetFrame = 0;
|
||||
|
||||
// Signal for pause
|
||||
fg->FgDone();
|
||||
}
|
||||
// // Signal for pause
|
||||
// fg->FgDone();
|
||||
//}
|
||||
|
||||
return presentResult;
|
||||
}
|
||||
@@ -1991,7 +1991,7 @@ void HooksDx::ReleaseDx12SwapChain(HWND hwnd)
|
||||
if (State::Instance().currentFG != nullptr)
|
||||
fg = reinterpret_cast<IFGFeature_Dx12*>(State::Instance().currentFG);
|
||||
|
||||
if (fg != nullptr)
|
||||
if (fg != nullptr && fg->SwapchainContext() != nullptr)
|
||||
fg->ReleaseSwapchain(hwnd);
|
||||
}
|
||||
|
||||
|
||||
@@ -254,6 +254,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGISwapChain4::SetFullscreenState(BOOL Fullsc
|
||||
else
|
||||
LOG_DEBUG("result: {:X}", result);
|
||||
|
||||
/*
|
||||
if (Config::Instance()->FGEnabled.value_or_default())
|
||||
{
|
||||
State::Instance().FGresetCapturedResources = true;
|
||||
|
||||
@@ -172,6 +172,67 @@ ffxReturnCode_t ffxCreateContext_Dx12(ffxContext* context, ffxCreateContextDescH
|
||||
auto backendDesc = (ffxCreateBackendDX12Desc*)header;
|
||||
_d3d12Device = backendDesc->device;
|
||||
}
|
||||
else if (State::Instance().activeFgType == OptiFG)
|
||||
{
|
||||
if (header->type == FFX_API_CREATE_CONTEXT_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_WRAP_DX12)
|
||||
{
|
||||
LOG_INFO("Using already wrapped swapchain");
|
||||
return FFX_API_RETURN_OK;
|
||||
}
|
||||
else if (header->type == FFX_API_CREATE_CONTEXT_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_NEW_DX12)
|
||||
{
|
||||
LOG_INFO("Creating OptiFG swapchain, new swapchain");
|
||||
auto fgDesc = (ffxCreateContextDescFrameGenerationSwapChainNewDX12*)header;
|
||||
auto scResult = fgDesc->dxgiFactory->CreateSwapChain(fgDesc->gameQueue, fgDesc->desc, (IDXGISwapChain**)fgDesc->swapchain);
|
||||
|
||||
if (scResult == S_OK)
|
||||
{
|
||||
if (State::Instance().currentFG == nullptr)
|
||||
{
|
||||
LOG_ERROR("State::Instance().currentFG is nullptr");
|
||||
return FFX_API_RETURN_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
void* scContext = State::Instance().currentFG->SwapchainContext();
|
||||
context = (ffxContext*)&scContext;
|
||||
return FFX_API_RETURN_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("CreateSwapChain error: {:X}", (UINT)scResult);
|
||||
return FFX_API_RETURN_ERROR_PARAMETER;
|
||||
}
|
||||
}
|
||||
else if (header->type == FFX_API_CREATE_CONTEXT_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_FOR_HWND_DX12)
|
||||
{
|
||||
LOG_INFO("Creating OptiFG swapchain, new swapchain for hwnd");
|
||||
auto fgDesc = (ffxCreateContextDescFrameGenerationSwapChainForHwndDX12*)header;
|
||||
|
||||
IDXGIFactory2* factory = nullptr;
|
||||
auto scResult = fgDesc->dxgiFactory->QueryInterface(IID_PPV_ARGS(&factory));
|
||||
if (scResult != S_OK)
|
||||
{
|
||||
LOG_ERROR("CreateSwapChain error: {:X}", (UINT)scResult);
|
||||
return FFX_API_RETURN_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
factory->Release();
|
||||
|
||||
scResult = factory->CreateSwapChainForHwnd(fgDesc->gameQueue, fgDesc->hwnd, fgDesc->desc, fgDesc->fullscreenDesc, nullptr, (IDXGISwapChain1**)fgDesc->swapchain);
|
||||
if (scResult == S_OK)
|
||||
{
|
||||
auto fg = reinterpret_cast<IFGFeature_Dx12*>(State::Instance().currentFG);
|
||||
auto scContext = fg->SwapchainContext();
|
||||
context = (ffxContext*)&scContext;
|
||||
return FFX_API_RETURN_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("CreateSwapChainForHwnd error: {:X}", (UINT)scResult);
|
||||
return FFX_API_RETURN_ERROR_PARAMETER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header = header->pNext;
|
||||
|
||||
|
||||
@@ -1619,6 +1619,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom
|
||||
|
||||
if (Config::Instance()->FGHUDFix.value_or_default())
|
||||
{
|
||||
// For signal after mv & depth copies
|
||||
ResTrack_Dx12::SetUpscalerCmdList(InCmdList);
|
||||
Hudfix_Dx12::UpscaleEnd(deviceContext->feature->FrameCount(), ftDelta);
|
||||
|
||||
@@ -1659,7 +1660,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom
|
||||
LOG_WARN("Can't restore ComputeRootSig!");
|
||||
}
|
||||
|
||||
if (Config::Instance()->RestoreGraphicSignature.value_or_default() && /*graphTime != 0 && graphTime > lastEvalTime && graphTime <= evaluateStart &&*/ graphicSignatures[InCmdList])
|
||||
if (Config::Instance()->RestoreGraphicSignature.value_or_default() && graphicSignatures[InCmdList])
|
||||
{
|
||||
auto signature = graphicSignatures[InCmdList];
|
||||
LOG_TRACE("restore orgGraphicRootSig: {0:X}", (UINT64)signature);
|
||||
|
||||
@@ -1627,11 +1627,11 @@ bool MenuCommon::RenderMenu()
|
||||
{
|
||||
Config::Instance()->FGDebugView = fgDV;
|
||||
|
||||
//if (Config::Instance()->FGEnabled.value_or_default())
|
||||
//{
|
||||
// State::Instance().FGchanged = true;
|
||||
// LOG_DEBUG("DebugView set FGChanged");
|
||||
//}
|
||||
if (Config::Instance()->FGEnabled.value_or_default())
|
||||
{
|
||||
State::Instance().FGchanged = true;
|
||||
LOG_DEBUG("DebugView set FGChanged");
|
||||
}
|
||||
}
|
||||
ShowHelpMarker("Enable FSR 3.1 frame generation debug view");
|
||||
|
||||
|
||||
@@ -2182,6 +2182,9 @@ void ResTrack_Dx12::ClearPossibleHudless()
|
||||
_skipHudless = false;
|
||||
_rcActive = false;
|
||||
_cmdList = false;
|
||||
//_upscalerCommandList = nullptr;
|
||||
//_commandList = nullptr;
|
||||
|
||||
}
|
||||
|
||||
void ResTrack_Dx12::PresentDone()
|
||||
|
||||
Reference in New Issue
Block a user