@@ -167,6 +167,18 @@ static HRESULT runOnUIThread(const ComPtr<ICoreDispatcher>& dispatcher, _Fty&& f
167167}
168168#endif
169169
170+ uint64_t GPUFence::wait () const
171+ {
172+ const auto completeFenceValue = this ->handle ->GetCompletedValue ();
173+ if (completeFenceValue < this ->value )
174+ {
175+ this ->handle ->SetEventOnCompletion (this ->value , this ->event );
176+ WaitForSingleObject (this ->event , INFINITE);
177+ return this ->value ;
178+ }
179+ return completeFenceValue;
180+ }
181+
170182RenderContextImpl::RenderContextImpl (DriverImpl* driver, void * surfaceContext) : _driver(driver)
171183{
172184 _device = driver->getDevice ();
@@ -342,17 +354,22 @@ RenderContextImpl::RenderContextImpl(DriverImpl* driver, void* surfaceContext) :
342354
343355RenderContextImpl::~RenderContextImpl ()
344356{
345- _driver->waitDeviceIdle ();
357+ _driver->waitForGPU ();
346358
347359 AX_SAFE_RELEASE_NULL (_screenRT);
348360 AX_SAFE_RELEASE_NULL (_renderPipeline);
349361
350362 for (int i = 0 ; i < MAX_FRAMES_IN_FLIGHT; ++i)
351363 {
352- if (_fenceEvents[i])
364+ if (_inflightFences[i].event )
365+ {
366+ CloseHandle (_inflightFences[i].event );
367+ _inflightFences[i].event = nullptr ;
368+ }
369+
370+ if (_inflightFences[i].handle )
353371 {
354- CloseHandle (_fenceEvents[i]);
355- _fenceEvents[i] = nullptr ;
372+ SafeRelease (_inflightFences[i].handle );
356373 }
357374
358375 if (_srvHeaps[i])
@@ -380,11 +397,10 @@ void RenderContextImpl::createCommandObjects()
380397 _commandLists[i]->Close ();
381398
382399 // Fence + event
383- hr = _device->CreateFence (0 , D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS (&_fences [i]));
400+ hr = _device->CreateFence (0 , D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS (&_inflightFences [i]. handle ));
384401 AXASSERT (SUCCEEDED (hr), " CreateFence failed" );
385- _fenceValues[i] = 0 ;
386- _fenceEvents[i] = CreateEvent (nullptr , FALSE , FALSE , nullptr );
387- AXASSERT (_fenceEvents[i] != nullptr , " CreateEvent failed" );
402+ _inflightFences[i].event = CreateEvent (nullptr , FALSE , FALSE , nullptr );
403+ AXASSERT (!!_inflightFences[i], " CreateEvent failed" );
388404 }
389405}
390406
@@ -428,32 +444,24 @@ void RenderContextImpl::setRenderPipeline(RenderPipeline* renderPipeline)
428444
429445uint64_t RenderContextImpl::getCompletedFenceValue () const
430446{
431- return _fenceValues[_currentFrame] ;
447+ return _completedFenceValue ;
432448}
433449
434450bool RenderContextImpl::beginFrame ()
435451{
436452 // Wait fence of current frame
437- auto fence = _fences[_currentFrame];
438-
439- const auto completeFenceValue = fence->GetCompletedValue ();
440- const auto frameFenceValue = _fenceValues[_currentFrame];
441- if (completeFenceValue < frameFenceValue)
442- {
443- fence->SetEventOnCompletion (frameFenceValue, _fenceEvents[_currentFrame]);
444- WaitForSingleObject (_fenceEvents[_currentFrame], INFINITE);
445- }
446-
447- _advanceFenceValues[_currentFrame] = frameFenceValue + 1 ;
453+ auto & currentFence = _inflightFences[_currentFrame];
454+ _completedFenceValue = currentFence.wait ();
455+ _driver->processDisposalQueue (_completedFenceValue);
448456
449- if (!_fenceCompletionOps .empty ())
457+ if (!_frameCompletionOps .empty ())
450458 {
451- for (auto & op : _fenceCompletionOps )
452- op (completeFenceValue );
453- _fenceCompletionOps .clear ();
459+ for (auto && op : _frameCompletionOps )
460+ op (_completedFenceValue );
461+ _frameCompletionOps .clear ();
454462 }
455463
456- _driver-> processDisposalQueue (completeFenceValue) ;
464+ currentFence. value = ++_frameFenceValue ;
457465
458466 if (_swapchainDirty)
459467 {
@@ -520,7 +528,7 @@ void RenderContextImpl::beginRenderPass(RenderTarget* renderTarget, const Render
520528 // Bind RTV/DSV and clear according to flags
521529 rtImpl->beginRenderPass (_currentCmdList, descriptor, _renderTargetWidth, _renderTargetHeight, _currentImageIndex);
522530
523- rtImpl->setLastFenceValue (_advanceFenceValues[_currentFrame] );
531+ rtImpl->setLastFenceValue (_frameFenceValue );
524532}
525533
526534void RenderContextImpl::endRenderPass ()
@@ -563,8 +571,8 @@ void RenderContextImpl::endFrame()
563571#endif
564572
565573 // Signal fence for this frame
566- _graphicsQueue-> Signal (_fences[_currentFrame]. Get (), _advanceFenceValues [_currentFrame]) ;
567- _fenceValues[_currentFrame] = _advanceFenceValues[_currentFrame] ;
574+ auto & currentFence = _inflightFences [_currentFrame];
575+ _graphicsQueue-> Signal (currentFence. handle , currentFence. value ) ;
568576
569577 // Next frame index
570578 _currentFrame = (_currentFrame + 1 ) % MAX_FRAMES_IN_FLIGHT;
@@ -849,8 +857,7 @@ void RenderContextImpl::prepareDrawing(ID3D12GraphicsCommandList* cmd)
849857
850858 applyPendingDynamicStates ();
851859
852- const auto advanceFenceValue = _advanceFenceValues[_currentFrame];
853- _vertexBuffer->setLastFenceValue (advanceFenceValue);
860+ _vertexBuffer->setLastFenceValue (_frameFenceValue);
854861
855862 // bind vertex buffers
856863 if (!_instanceBuffer)
@@ -863,7 +870,7 @@ void RenderContextImpl::prepareDrawing(ID3D12GraphicsCommandList* cmd)
863870 }
864871 else
865872 {
866- _instanceBuffer->setLastFenceValue (advanceFenceValue );
873+ _instanceBuffer->setLastFenceValue (_frameFenceValue );
867874 D3D12_VERTEX_BUFFER_VIEW views[2 ]{};
868875 views[0 ].BufferLocation = _vertexBuffer->internalResource ()->GetGPUVirtualAddress ();
869876 views[0 ].SizeInBytes = static_cast <UINT>(_vertexBuffer->getSize ());
@@ -919,7 +926,7 @@ void RenderContextImpl::prepareDrawing(ID3D12GraphicsCommandList* cmd)
919926 maxSlot = slot;
920927
921928 auto textureImpl = static_cast <TextureImpl*>(bindingSet.texs [i]);
922- textureImpl->setLastFenceValue (advanceFenceValue );
929+ textureImpl->setLastFenceValue (_frameFenceValue );
923930 auto srvHandle = textureImpl->internalHandle ().srv ;
924931 assert (!!srvHandle);
925932
@@ -1057,7 +1064,7 @@ void RenderContextImpl::readPixels(RenderTarget* rt,
10571064 }
10581065 rt->retain ();
10591066
1060- _fenceCompletionOps .emplace_back ([this , rt, preserveAxisHint, callback = std::move (callback)](uint64_t ) mutable {
1067+ _frameCompletionOps .emplace_back ([this , rt, preserveAxisHint, callback = std::move (callback)](uint64_t ) mutable {
10611068 readPixelsInternal (rt, preserveAxisHint, callback);
10621069
10631070 rt->release ();
0 commit comments