3838
3939#include < memory>
4040#include < vector>
41+ #include < array>
4142#include < mutex>
4243#include < map>
4344#include < unordered_map>
@@ -70,7 +71,7 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
7071 public:
7172 explicit Page (Uint32 Size, bool PersistentMapped = false ) noexcept ;
7273
73- Page (IRenderDevice* pDevice, Uint32 Size);
74+ Page (size_t StreamIndex, IRenderDevice* pDevice, Uint32 Size);
7475 ~Page ();
7576
7677 enum class WritingStatus
@@ -142,6 +143,8 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
142143 // Returns true if the page was not previously enqueued, false otherwise.
143144 bool TryEnqueue ();
144145
146+ size_t GetStreamIndex () const { return m_StreamIdx; }
147+
145148 Uint64 GetFenceValue () const { return m_FenceValue; }
146149 Uint32 GetSize () const { return m_Size; }
147150
@@ -179,6 +182,7 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
179182 private:
180183 const Uint32 m_Size = 0 ;
181184 const bool m_PersistentMapped = false ;
185+ const size_t m_StreamIdx = 0 ;
182186
183187 RefCntAutoPtr<IBuffer> m_pStagingBuffer;
184188
@@ -238,26 +242,14 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
238242 };
239243
240244private:
241- void ScheduleUpdate (IDeviceContext* pContext,
242- Uint32 UpdateSize,
243- const void * pUpdateInfo,
244- bool ScheduleUpdate (Page::Writer& Writer, const void * pUpdateInfo));
245-
246- void ReclaimCompletedPages (IDeviceContext* pContext);
247- bool SealAndSwapCurrentPage (IDeviceContext* pContext);
248- void AddFreePages (IDeviceContext* pContext);
249- void ProcessPendingPages (IDeviceContext* pContext);
250- bool TryRotatePage (IDeviceContext* pContext, Page* ExpectedCurrent, Uint32 RequiredSize);
251- bool TryEnqueuePage (Page* P);
252- Page* AcquireFreePage (IDeviceContext* pContext, Uint32 RequiredSize = 0 );
253- Page* CreatePage (IDeviceContext* pContext, Uint32 RequiredSize = 0 );
254- void ProcessPagesToRelease (IDeviceContext* pContext);
255- void UpdateBucketInfo ();
245+ class UploadStream ;
256246
257- private:
258- const Uint32 m_PageSize;
259- const Uint32 m_MaxPageCount;
247+ void ReclaimCompletedPages (IDeviceContext* pContext);
248+ void ProcessPendingPages (IDeviceContext* pContext);
249+
250+ UploadStream& GetStreamForUpdateSize (Uint32 UpdateSize);
260251
252+ private:
261253 RefCntAutoPtr<IRenderDevice> m_pDevice;
262254 RefCntAutoPtr<IDeviceContext> m_pContext;
263255
@@ -281,7 +273,6 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
281273 std::map<Uint32, std::vector<Page*>> m_PagesBySize;
282274 std::atomic<size_t > m_Size{0 };
283275 };
284- FreePages m_FreePages;
285276
286277 // Pages that have been submitted for execution and are being processed by the GPU.
287278 std::vector<Page*> m_InFlightPages;
@@ -290,24 +281,75 @@ class GPUUploadManagerImpl final : public ObjectBase<IGPUUploadManager>
290281 RefCntAutoPtr<IFence> m_pFence;
291282 Uint64 m_NextFenceValue = 1 ;
292283
293- std::atomic<Page*> m_pCurrentPage{nullptr };
294- Threading::TickSignal m_PageRotatedSignal;
284+ class UploadStream
285+ {
286+ public:
287+ UploadStream (GPUUploadManagerImpl& Mgr,
288+ size_t StreamIdx,
289+ Uint32 PageSize,
290+ Uint32 MaxPageCount,
291+ Uint32 InitialPageCount) noexcept ;
292+
293+ Page* CreatePage (IDeviceContext* pContext, Uint32 RequiredSize = 0 );
294+ Page* AcquireFreePage (IDeviceContext* pContext, Uint32 RequiredSize = 0 );
295+ bool SealAndSwapCurrentPage (IDeviceContext* pContext);
296+ bool TryRotatePage (IDeviceContext* pContext, Page* ExpectedCurrent, Uint32 RequiredSize);
297+ bool TryEnqueuePage (Page* P);
298+ void ProcessPagesToRelease (IDeviceContext* pContext);
299+ void AddFreePages (IDeviceContext* pContext);
300+ void AddFreePage (Page* pPage) { m_FreePages.Push (pPage); }
301+
302+ void ScheduleUpdate (IDeviceContext* pContext,
303+ Uint32 UpdateSize,
304+ const void * pUpdateInfo,
305+ bool ScheduleUpdate (Page::Writer& Writer, const void * pUpdateInfo));
306+ void ReleaseStagingBuffers ();
307+ void SignalPageRotated () { m_PageRotatedSignal.Tick (); }
308+ void SignalStop ();
309+
310+ Uint32 GetPageSize () const { return m_PageSize; }
311+
312+ void GetStats (GPUUploadManagerStreamStats& Stats) const ;
313+
314+ private:
315+ GPUUploadManagerImpl& m_Mgr;
316+ const size_t m_StreamIdx;
317+ const Uint32 m_PageSize;
318+ const Uint32 m_MaxPageCount;
319+
320+ std::atomic<Page*> m_pCurrentPage{nullptr };
295321
296- std::unordered_map<Page*, std::unique_ptr<Page>> m_Pages;
297- std::map<Uint32, Uint32> m_PageSizeToCount;
298- std::vector<GPUUploadManagerBucketInfo> m_BucketInfo;
322+ Threading::TickSignal m_PageRotatedSignal;
323+
324+ std::unordered_map<Page*, std::unique_ptr<Page>> m_Pages;
325+ std::map<Uint32, Uint32> m_PageSizeToCount;
326+ mutable std::vector<GPUUploadManagerBucketInfo> m_BucketInfo;
327+
328+ std::atomic<Uint32> m_NumRunningUpdates{0 };
329+ std::atomic<Uint32> m_MaxPendingUpdateSize{0 };
330+ std::atomic<Uint32> m_TotalPendingUpdateSize{0 };
331+
332+ FreePages m_FreePages;
333+
334+ std::atomic<Uint32> m_PeakUpdateSize{0 };
335+ Uint32 m_PeakTotalPendingUpdateSize = 0 ;
336+ Uint32 m_PeakPageCount = 0 ;
337+ };
338+
339+ enum class UploadStreamType : Uint32
340+ {
341+ Normal = 0 ,
342+ Large = 1 ,
343+ Count
344+ };
345+ std::array<UploadStream, static_cast <size_t >(UploadStreamType::Count)> m_Streams;
299346
300347 // The number of running ScheduleBufferUpdate operations.
301348 std::atomic<Uint32> m_NumRunningUpdates{0 };
302349 std::atomic<bool > m_Stopping{false };
303350 Threading::Signal m_LastRunningThreadFinishedSignal;
304351
305- std::atomic<Uint32> m_MaxPendingUpdateSize{0 };
306- std::atomic<Uint32> m_TotalPendingUpdateSize{0 };
307-
308- std::atomic<Uint32> m_PeakUpdateSize{0 };
309- Uint32 m_PeakTotalPendingUpdateSize = 0 ;
310- Uint32 m_PeakPageCount = 0 ;
352+ mutable std::array<GPUUploadManagerStreamStats, static_cast <size_t >(UploadStreamType::Count)> m_StreamStats;
311353};
312354
313355} // namespace Diligent
0 commit comments