@@ -80,14 +80,24 @@ GPUUploadManagerImpl::Page::Writer::~Writer()
8080 }
8181}
8282
83- GPUUploadManagerImpl::Page::Page (Uint32 Size) noexcept :
84- m_Size{Size}
83+ GPUUploadManagerImpl::Page::Page (Uint32 Size, bool PersistentMapped) noexcept :
84+ m_Size{Size},
85+ m_PersistentMapped{PersistentMapped}
8586{}
8687
88+ inline bool PersistentMapSupported (IRenderDevice* pDevice)
89+ {
90+ RENDER_DEVICE_TYPE DeviceType = pDevice->GetDeviceInfo ().Type ;
91+ return DeviceType == RENDER_DEVICE_TYPE_D3D12 || DeviceType == RENDER_DEVICE_TYPE_VULKAN;
92+ }
93+
8794GPUUploadManagerImpl::Page::Page (IRenderDevice* pDevice,
8895 IDeviceContext* pContext,
8996 Uint32 Size) :
90- Page{Size}
97+ Page{
98+ Size,
99+ PersistentMapSupported (pDevice),
100+ }
91101{
92102 static std::atomic<int > PageCounter{0 };
93103 const std::string Name = " GPUUploadManagerImpl page " + std::to_string (PageCounter.fetch_add (1 ));
@@ -221,7 +231,7 @@ void GPUUploadManagerImpl::Page::ExecutePendingOps(IDeviceContext* pContext, Uin
221231 VERIFY (DbgIsSealed (), " Page must be sealed before executing pending operations" );
222232 VERIFY (DbgGetWriterCount () == 0 , " All writers must finish before executing pending operations" );
223233
224- if (m_pData != nullptr )
234+ if (m_pData != nullptr && !m_PersistentMapped )
225235 {
226236 VERIFY_EXPR (pContext != nullptr );
227237 pContext->UnmapBuffer (m_pStagingBuffer, MAP_WRITE);
@@ -258,7 +268,10 @@ void GPUUploadManagerImpl::Page::Reset(IDeviceContext* pContext)
258268
259269 if (pContext != nullptr )
260270 {
261- pContext->MapBuffer (m_pStagingBuffer, MAP_WRITE, MAP_FLAG_NONE, m_pData);
271+ if (!m_PersistentMapped)
272+ {
273+ pContext->MapBuffer (m_pStagingBuffer, MAP_WRITE, MAP_FLAG_NONE, m_pData);
274+ }
262275 VERIFY_EXPR (m_pData != nullptr );
263276 }
264277}
@@ -272,11 +285,23 @@ bool GPUUploadManagerImpl::Page::TryEnqueue()
272285 return m_Enqueued.compare_exchange_strong (Expected, true , std::memory_order_acq_rel);
273286}
274287
288+ void GPUUploadManagerImpl::Page::ReleaseStagingBuffer (IDeviceContext* pContext)
289+ {
290+ if (m_pData != nullptr )
291+ {
292+ VERIFY_EXPR (pContext != nullptr );
293+ pContext->UnmapBuffer (m_pStagingBuffer, MAP_WRITE);
294+ m_pData = nullptr ;
295+ }
296+ m_pStagingBuffer.Release ();
297+ }
298+
275299
276300GPUUploadManagerImpl::GPUUploadManagerImpl (IReferenceCounters* pRefCounters, const GPUUploadManagerCreateInfo& CI) :
277301 TBase{pRefCounters},
278302 m_PageSize{AlignUpToPowerOfTwo (CI.PageSize )},
279- m_pDevice{CI.pDevice }
303+ m_pDevice{CI.pDevice },
304+ m_pContext{CI.pContext }
280305{
281306 FenceDesc Desc;
282307 Desc.Name = " GPU upload manager fence" ;
@@ -289,11 +314,17 @@ GPUUploadManagerImpl::GPUUploadManagerImpl(IReferenceCounters* pRefCounters, con
289314
290315GPUUploadManagerImpl::~GPUUploadManagerImpl ()
291316{
317+ for (std::unique_ptr<Page>& P : m_Pages)
318+ {
319+ P->ReleaseStagingBuffer (m_pContext);
320+ }
292321}
293322
294323void GPUUploadManagerImpl::RenderThreadUpdate (IDeviceContext* pContext)
295324{
325+ DEV_CHECK_ERR (pContext == m_pContext, " The context passed to RenderThreadUpdate must be the same as the one used to create the GPUUploadManagerImpl" );
296326 (void )m_NextFenceValue;
327+ (void )m_FreePagesMtx;
297328}
298329
299330void GPUUploadManagerImpl::ScheduleBufferUpdate (IBuffer* pDstBuffer,
0 commit comments