@@ -323,7 +323,12 @@ GPUUploadManagerImpl::~GPUUploadManagerImpl()
323323void GPUUploadManagerImpl::RenderThreadUpdate (IDeviceContext* pContext)
324324{
325325 DEV_CHECK_ERR (pContext == m_pContext, " The context passed to RenderThreadUpdate must be the same as the one used to create the GPUUploadManagerImpl" );
326- (void )m_NextFenceValue;
326+
327+ SealAndSwapCurrentPage (pContext);
328+
329+ ReclaimCompletedPages (pContext);
330+
331+ m_pFence->Signal (m_NextFenceValue++);
327332}
328333
329334void GPUUploadManagerImpl::ScheduleBufferUpdate (IBuffer* pDstBuffer,
@@ -349,6 +354,97 @@ GPUUploadManagerImpl::Page* GPUUploadManagerImpl::CreatePage(IDeviceContext* pCo
349354 return P;
350355}
351356
357+ bool GPUUploadManagerImpl::SealAndSwapCurrentPage (IDeviceContext* pContext)
358+ {
359+ VERIFY_EXPR (pContext != nullptr );
360+
361+ // Get a fresh page (from free-list or allocate)
362+ Page* pFreshPage = AcquireFreePage (pContext);
363+ VERIFY_EXPR (pFreshPage != nullptr );
364+
365+ // Swap it in
366+ Page* pOld = m_pCurrentPage.exchange (pFreshPage, std::memory_order_acq_rel);
367+
368+ // Seal old page and enqueue if no writers; otherwise last writer will enqueue it
369+ if (pOld->TrySeal () == Page::SealStatus::Ready)
370+ {
371+ TryEnqueuePage (pOld);
372+ }
373+
374+ return true ;
375+ }
376+
377+ bool GPUUploadManagerImpl::TryEnqueuePage (Page* P)
378+ {
379+ if (P->TryEnqueue ())
380+ {
381+ m_PendingPages.Enqueue (P);
382+ return true ;
383+ }
384+ return false ;
385+ }
386+
387+ void GPUUploadManagerImpl::ReclaimCompletedPages (IDeviceContext* pContext)
388+ {
389+ VERIFY_EXPR (pContext != nullptr );
390+
391+ Uint64 CompletedFenceValue = m_pFence->GetCompletedValue ();
392+
393+ m_TmpInFlightPages.clear ();
394+ m_NewFreePages.clear ();
395+ for (Page* P : m_InFlightPages)
396+ {
397+ if (P->GetFenceValue () <= CompletedFenceValue)
398+ {
399+ P->Reset (pContext);
400+ m_NewFreePages.push_back (P);
401+ }
402+ else
403+ {
404+ m_TmpInFlightPages.push_back (P);
405+ }
406+ }
407+ m_InFlightPages.swap (m_TmpInFlightPages);
408+ m_TmpInFlightPages.clear ();
409+
410+ {
411+ std::lock_guard<std::mutex> Guard{m_FreePagesMtx};
412+ m_FreePages.insert (m_FreePages.end (), m_NewFreePages.begin (), m_NewFreePages.end ());
413+ }
414+ m_NewFreePages.clear ();
415+ }
416+
417+ GPUUploadManagerImpl::Page* GPUUploadManagerImpl::AcquireFreePage (IDeviceContext* pContext)
418+ {
419+ Uint32 MaxPendingUpdateSize = m_MaxPendingUpdateSize.load (std::memory_order_relaxed);
420+
421+ Page* P = nullptr ;
422+ {
423+ std::lock_guard<std::mutex> Guard{m_FreePagesMtx};
424+ for (auto it = m_FreePages.begin (); it != m_FreePages.end (); ++it)
425+ {
426+ if ((*it)->GetSize () >= MaxPendingUpdateSize)
427+ {
428+ P = *it;
429+ m_FreePages.erase (it);
430+ break ;
431+ }
432+ }
433+ }
434+
435+ if (P == nullptr && pContext != nullptr )
436+ {
437+ P = CreatePage (pContext, MaxPendingUpdateSize);
438+ }
439+
440+ if (P != nullptr )
441+ {
442+ // Clear only if no one increased it since we read it
443+ m_MaxPendingUpdateSize.compare_exchange_strong (MaxPendingUpdateSize, 0u , std::memory_order_relaxed);
444+ }
445+
446+ return P;
447+ }
352448
353449void CreateGPUUploadManager (const GPUUploadManagerCreateInfo& CreateInfo,
354450 IGPUUploadManager** ppManager)
0 commit comments