Skip to content

Commit c3e3d59

Browse files
committed
update wiki
1 parent d49e214 commit c3e3d59

File tree

1 file changed

+92
-65
lines changed

1 file changed

+92
-65
lines changed

source/pageableBuffer/README.md

Lines changed: 92 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ Note that the paging system is expected to be applicable in different workflows
2424
### Key Concepts
2525

2626
1. **Buffer States**: UnKnown, System (Scene), Hardware (Renderer), Disk
27-
2. **Buffer Usage**: Static, Dynamic
27+
2. **Buffer Usage**: Static (paged if possible), Dynamic (paged if necessary)
2828
3. **Core Operations**: Buffer Creation, Data Copy, Buffer Disposal
2929
4. **Paging Operations**:
3030
1. Page: Create new buffer and fill data. Keep the source buffer (e.g. `PageToDisk`).
3131
2. Swap: Create new buffer and fill data. Release the source buffer (e.g. `SwapSceneToDisk`).
32-
5. **Free Crawling**: Periodic cleanup of resources
32+
5. **Free Crawling**: Periodic cleanup of resources using configurable strategies
3333

3434
### Usages
3535

@@ -38,25 +38,26 @@ Ideally, users should use PageBufferManager as the entry point.
3838
Usage1: Paging On-demand (asynchronously):
3939
```cpp
4040
// Create a Buffer Manager when initializing
41-
HdPageableBufferManager<..., ...> bufferManager;
41+
PageableBufferManager<..., ...> bufferManager;
4242

4343
// Create a buffer
4444
constexpr size_t MB = 1024 * 1024;
45-
auto buffer1 = bufferManager.CreateBuffer("AsyncBuffer1", 50 * MB);
46-
45+
auto buffer = bufferManager.CreateBuffer(bufferPath, 50 * MB, BufferUsage::Static);
46+
4747
// Start some async operations
48-
auto swapFuture1 = bufferManager.SwapSystemToDiskAsync(buffer1);
49-
48+
auto swapFuture = bufferManager.SwapSceneToDiskAsync(buffer);
49+
auto pageFuture = bufferManager.PageToSceneMemoryAsync(buffer);
50+
5051
// Wait for operations (if needed)
51-
swapFuture1.wait();
52+
swapFuture.wait();
5253
// or, wait for all operations to complete
5354
// bufferManager.WaitForAllOperations();
5455
```
5556

5657
Usage2: Moniter & Automatic Freecrawl (recommend in background thread):
5758
```cpp
5859
// Create a Buffer Manager when initializing
59-
HdPageableBufferManager<..., ...> bufferManager;
60+
PageableBufferManager<..., ...> bufferManager;
6061

6162
// Create some buffers with different characteristics using factory
6263
constexpr size_t MB = 1024 * 1024;
@@ -65,11 +66,16 @@ auto buffer2 = bufferManager.CreateBuffer("MediumBuffer", 50 * MB, BufferUsage::
6566
auto buffer3 = bufferManager.CreateBuffer("LargeBuffer", 100 * MB, BufferUsage::Static);
6667

6768
// ...advance frames when doing the rendering
68-
cacheManager.AdvanceFrame();
69+
bufferManager.AdvanceFrame();
6970

7071
// In a background thread, at a certain time interval
7172
// check 50% of buffers to see if they get chance to page out
72-
cacheManager.FreeCrawl(50.0f);
73+
bufferManager.FreeCrawl(50.0f);
74+
// or, use async free crawl
75+
// auto futures = bufferManager.FreeCrawlAsync(20.0f);
76+
// for (auto& future : futures) {
77+
// future.wait();
78+
// }
7379
```
7480

7581
Note that for disposable intermediate data, users should directly control by themselves or using `std::move`.
@@ -106,6 +112,7 @@ stateDiagram-v2
106112
EvictHardwareBuffer --> [*]: MakeResident
107113
}
108114
115+
note right of SystemBuffer : Buffer in RAM (in Hydra, it means buffer in the scene side)
109116
note right of HardwareBuffer : Buffer in VRAM (in Hydra, it means buffer has been transferred to Renderer)
110117
note right of HardwareMappedBuffer : Buffer is mapped for GPU access via Graphics API (not used)
111118
note right of EvictHardwareBuffer : Buffer is evicted for saving VRAM via Graphics API (not used)
@@ -115,27 +122,25 @@ The ER diagram shows the key classes and their relationships in the memory pagin
115122

116123
```mermaid
117124
erDiagram
118-
Buffer {
119-
string mName
125+
PageableBuffer {
126+
key mKey
120127
size_t mSize
121128
BufferUsage mUsage
122129
BufferState mBufferState
123-
unique_ptr_byte_array mSystemBuffer
124-
unique_ptr_byte_array mHardwareBuffer
125-
unique_ptr_PageHandle mPageHandle
126-
void_ptr mMappedData
127-
atomic_int mLockCount
130+
unique_ptr_BufferPageHandle mPageHandle
128131
int mFrameStamp
129-
shared_mutex mMapMutex
132+
DestructionCallback mDestructionCallback
130133
}
131134
132-
CacheManager {
133-
vector_shared_ptr_Buffer mBuffers
134-
mutex mBuffersMutex
135-
atomic_int mCurrentFrame
135+
PageableBufferManager {
136+
associative_container mBuffers
137+
atomic_uint mCurrentFrame
136138
int mAgeLimit
137-
thread mBackgroundThread
138-
atomic_bool mStopBackgroundCrawl
139+
PagingStrategyType mPagingStrategy
140+
BufferSelectionStrategyType mBufferSelectionStrategy
141+
unique_ptr_PageFileManager mPageFileManager
142+
unique_ptr_MemoryMonitor mMemoryMonitor
143+
ThreadPool mThreadPool
139144
}
140145
141146
MemoryMonitor {
@@ -148,13 +153,14 @@ erDiagram
148153
float CPU_PAGING_THRESHOLD
149154
}
150155
151-
PageManager {
156+
PageFileManager {
152157
vector_unique_ptr_PageFileEntry mPageFileEntries
153158
mutex mSyncMutex
159+
filesystem_path mPageFileDirectory
154160
size_t MAX_PAGE_FILE_SIZE
155161
}
156162
157-
PageHandle {
163+
BufferPageHandle {
158164
size_t mPageId
159165
size_t mSize
160166
ptrdiff_t mOffset
@@ -175,65 +181,70 @@ erDiagram
175181
size_t size
176182
}
177183
178-
Buffer ||--o| PageHandle : "has"
179-
Buffer }o--|| PageManager : "uses for disk operations"
180-
Buffer }o--|| MemoryMonitor : "tracks memory usage"
181184
182-
CacheManager ||--o{ Buffer : "manages collection of"
183-
CacheManager }o--|| MemoryMonitor : "monitors pressure"
185+
PageableBuffer ||--o| BufferPageHandle : "has"
186+
PageableBuffer }o--|| PageFileManager : "uses for disk operations"
187+
PageableBuffer }o--|| MemoryMonitor : "tracks memory usage"
184188
185-
PageManager ||--o{ PageFileEntry : "contains"
186-
PageManager ||--o{ PageHandle : "creates"
189+
PageableBufferManager ||--o{ PageableBuffer : "manages collection of"
190+
PageableBufferManager }o--|| MemoryMonitor : "monitors pressure"
191+
PageableBufferManager }o--|| PageFileManager : "manages disk storage"
192+
193+
PageFileManager ||--o{ PageFileEntry : "contains"
194+
PageFileManager ||--o{ BufferPageHandle : "creates"
187195
188196
PageFileEntry ||--o{ FreeListEntry : "contains free list"
189197
```
190198

191199
Core Classes:
192200

193-
1. **Buffer** - The central entity that manages memory buffers across different storage locations (scene/RAM, renderer/VRAM, disk storage)
194-
2. **CacheManager** - Manages the lifecycle and aging of multiple buffers with background processing
195-
3. **MemoryMonitor** - Tracks memory usage and calculates memory pressure for both system and hardware memory
196-
4. **PageManager** - Handles disk paging operations and file management
201+
1. **PageableBuffer** - The central entity that manages memory buffers across different storage locations (scene/RAM, renderer/VRAM, disk storage).
202+
2. **PageableBufferManager** - Template-based buffer manager with configurable paging and selection strategies. Manages the lifecycle and aging of multiple buffers with background processing.
203+
3. **MemoryMonitor** - Tracks memory usage and calculates memory pressure for both system/scene and hardware/renderer memory.
204+
4. **PageFileManager** - Handles disk paging operations and file management.
197205

198206
Supporting Classes:
199207

200-
1. **PageHandle** - Value object containing page metadata (ID, size, offset) for disk operations
208+
1. **BufferPageHandle** - Value object containing page metadata (ID, size, offset) for disk operations
201209
2. **PageFileEntry** - Manages individual page files on disk with free space tracking
202210
3. **FreeListEntry** - Simple data structure for tracking available free space in page files
203211

212+
Hydra Integration Classes:
213+
214+
1. **HdPageableContainerDataSource** - Memory-managed container data source
215+
2. **HdPageableVectorDataSource** - Memory-managed vector data source
216+
3. **HdPageableSampledDataSource** - Memory-managed sampled data source for time-sampled values
217+
4. **HdPageableBlockDataSource** - Memory-managed block data source
218+
204219
Design Patterns:
205220
- **RAII**: Buffer uses RAII for automatic memory management
206221
- **Three-tier Architecture**: System RAM → Hardware/GPU Memory → Disk storage hierarchy
207222
- **Free List Management**: Efficient disk space reuse through gap tracking
208223

209224
#### Paging Control
210225

211-
Abstract the strategy and decouple it from buffer management. Make the 1) paging, and 2) buffer selection strategies configurable. For safety and simplicity, they should be determined at the compiling time:
226+
The system abstracts paging strategy and buffer selection strategy, decoupling them from buffer management. Both strategies are configurable but should be determined at compile time for simplicity and optimal performance:
212227

213-
Configurable Strategies
228+
Configurable Strategies:
214229
```cpp
215230
// Concept for paging strategies
216231
// Use traits alternatively if C++20 is not supported
217232
template<typename T>
218-
concept PagingStrategyLike = requires(T t, const OGSDemo::Buffer& buffer, const OGSDemo::PagingContext& context) {
219-
{ t(buffer, context) } -> std::convertible_to<OGSDemo::PagingDecision>;
220-
} || requires(T t, const OGSDemo::Buffer& buffer, const OGSDemo::PagingContext& context) {
221-
{ t.operator()(buffer, context) } -> std::convertible_to<OGSDemo::PagingDecision>;
233+
concept PagingStrategyLike = requires(T t, const PageableBufferBase& buffer, const PagingContext& context) {
234+
{ t(buffer, context) } -> std::convertible_to<PagingDecision>;
222235
};
223236

224237
// Concept for buffer selection strategies
225-
// Use traits alternatively if C++20 is not supported
226-
template<typename T>
227-
concept BufferSelectionStrategyLike = requires(T t, const std::vector<std::shared_ptr<OGSDemo::Buffer>>& buffers, const OGSDemo::SelectionContext& context) {
228-
{ t(buffers, context) } -> std::convertible_to<std::vector<std::shared_ptr<OGSDemo::Buffer>>>;
229-
} || requires(T t, const std::vector<std::shared_ptr<OGSDemo::Buffer>>& buffers, const OGSDemo::SelectionContext& context) {
230-
{ t.operator()(buffers, context) } -> std::convertible_to<std::vector<std::shared_ptr<OGSDemo::Buffer>>>;
238+
// Use traits alternatively if C++20 is not supported
239+
template<typename T, typename InputIterator>
240+
concept BufferSelectionStrategyLike = requires(T t, InputIterator first, InputIterator last, const SelectionContext& context) {
241+
{ t(first, last, context) } -> std::convertible_to<std::vector<std::shared_ptr<PageableBufferBase>>>;
231242
};
232-
233-
// Encapsulate in CacheManager
234-
template<HdPagingConcepts::PagingStrategyLike PagingStrategyType,
235-
HdPagingConcepts::BufferSelectionStrategyLike BufferSelectionStrategyType>
236-
class HdPageableBufferManager {
243+
244+
// Template-based buffer manager
245+
template<PagingConcepts::PagingStrategyLike PagingStrategyType,
246+
PagingConcepts::BufferSelectionStrategyLike BufferSelectionStrategyType>
247+
class PageableBufferManager {
237248
// ......
238249
private:
239250
// Compile-time strategy instances (no runtime changing)
@@ -242,15 +253,31 @@ private:
242253
};
243254
```
244255
256+
Set configuration options:
257+
```cpp
258+
// Configure during BufferManager creation
259+
PageableBufferManager::InitializeDesc desc;
260+
desc.numThreads = 4; // Number of worker threads
261+
desc.pageFileDirectory = std::filesystem::temp_directory_path() / "temp_pages"; // Temp page file dest.
262+
desc.ageLimit= 20; // Frame count before resource is considered old.
263+
desc.sceneMemoryLimit = 2ULL * 1024 * 1024 * 1024; // Byte.
264+
desc.rendererMemoryLimit = 1ULL * 1024 * 1024 * 1024; // Byte.
265+
266+
// Configure background cleanup for MemoryManager
267+
memoryManager.SetFreeCrawlInterval(100); // Check every 100ms
268+
memoryManager.SetFreeCrawlPercentage(10.0f); // Check 10% of buffer
269+
```
270+
245271
Simplified implementation details:
246272
1. Use selection strategy to pick buffer candidates
247273
```cpp
248-
std::vector<std::shared_ptr<HdPageableBufferBase>> selectedBuffers = mBufferSelectionStrategy(mBuffers, selectionContext);
274+
std::vector<std::shared_ptr<PageableBufferBase>> selectedBuffers =
275+
mBufferSelectionStrategy(mBuffers.begin(), mBuffers.end(), selectionContext);
249276
```
250277
2. For each buffer, execute paging according to paging configs
251278
```cpp
252-
PagingDecision decision = mPagingStrategy(buffer, context);
253-
bool isDisposed = ExecutePagingDecision(buffer, decision);
279+
PagingDecision decision = mPagingStrategy(*buffer, context);
280+
bool isDisposed = ExecutePagingDecision(*buffer, decision);
254281
```
255282

256283
#### Thread Mode
@@ -263,11 +290,11 @@ graph LR
263290
A["Create Background Thread"] --> B["Create Buffers"]
264291
B --> G["Release Buffers"]
265292
G --> C["Stop & Join<br/>Background Thread"]
266-
F["CacheManager<br/>MemoryMonitor"]
293+
F["BufferManager<br/>MemoryMonitor"]
267294
end
268295

269296
subgraph H["Background Thread"]
270-
D["Monitor Memory<br/>Every 1000ms"] --> E["Auto Cleanup<br/>when needed"]
297+
D["Monitor Memory<br/>Every FreeCrawlInterval"] --> E["Auto Cleanup<br/>when needed"]
271298
E --> D
272299
end
273300

@@ -290,19 +317,19 @@ graph LR
290317
graph TD
291318
subgraph Caller ["Caller"]
292319
end
293-
subgraph CacheManager ["CacheManager"]
320+
subgraph BufferManager ["PageableBufferManager"]
294321
AsyncOps["Async Operations<br/>PageToSystemMemoryAsync()<br/>SwapSystemToDiskAsync()<br/>etc."]
295322
ReturnObj["std::future"]
296323
end
297324
298-
subgraph ThreadPool ["ThreadPool"]
325+
subgraph ThreadPool ["Internal ThreadPool"]
299326
Queue["Task Queue"]
300327
Worker1["Worker Thread 1"]
301328
Worker2["Worker Thread 2"]
302329
Worker3["Worker Thread ..."]
303330
end
304331
305-
subgraph BufferOps ["Buffer Operations"]
332+
subgraph Operations ["Buffer Operations"]
306333
BufferWork["Actual Memory Operations<br/>Page/Swap/etc."]
307334
end
308335
@@ -320,7 +347,7 @@ graph TD
320347
ReturnObj -.->|"Return"| Caller
321348
BufferWork -.-> ReturnObj
322349
323-
style CacheManager fill:#e1f5fe
350+
style BufferManager fill:#e1f5fe
324351
style ThreadPool fill:#f3e5f5
325352
style BufferOps fill:#e8f5e8
326353

0 commit comments

Comments
 (0)