UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
MultiBufferResource.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "CoreMinimal.h"
5
6namespace Chaos
7{
9 {
10 Undefined = 0,
11 Single,
12 Double,
13 Triple,
15 };
16
17 template<typename ResourceType>
19 {
20 public:
21
22 virtual ~IBufferResource() {}
23
25 virtual ResourceType* AccessProducerBuffer() = 0;
26
27 //NOTE: these changes may not make it to producer side, it is meant for resource management not to pass information back
28 virtual ResourceType* GetConsumerBufferMutable() = 0;
29
30 virtual const ResourceType* GetProducerBuffer() const = 0;
31 virtual const ResourceType* GetConsumerBuffer() const = 0;
32 virtual void FlipProducer() = 0;
33 };
34
36
39 template<typename ResourceType>
40 class FSingleBuffer final : public IBufferResource<ResourceType>
41 {
42 public:
43
45 virtual ~FSingleBuffer() {}
46
48 virtual ResourceType* AccessProducerBuffer() override { return &Data; }
49 virtual ResourceType* GetConsumerBufferMutable() override {return &Data;}
50 virtual const ResourceType* GetProducerBuffer() const override { return &Data; }
51 virtual const ResourceType* GetConsumerBuffer() const override { return &Data; }
52
53 void FlipProducer() override { /* NOP */ }
54
55 private:
56
57 ResourceType Data;
58 };
60 /*
61 * Double Buffer Implementation - Not thread-safe requires external locks
62 */
63 template<typename ResourceType>
64 class FDoubleBuffer final : public IBufferResource<ResourceType>
65 {
66 public:
67
69 : Data_Producer(&Data1)
70 , Data_Consumer(&Data2)
71 {}
72 virtual ~FDoubleBuffer() {}
73
75 virtual ResourceType* AccessProducerBuffer() override { return Data_Producer; }
76 virtual ResourceType* GetConsumerBufferMutable() override {return Data_Consumer;}
77 virtual const ResourceType* GetProducerBuffer() const override { return Data_Producer; }
78 virtual const ResourceType* GetConsumerBuffer() const override { return Data_Consumer; }
79
81 {
82 if (Data_Producer == &Data1)
83 {
84 Data_Producer = &Data2;
85 Data_Consumer = &Data1;
86 }
87 else
88 {
89 Data_Producer = &Data1;
90 Data_Consumer = &Data2;
91 }
92 }
93
94 private:
95
96 ResourceType Data1;
97 ResourceType Data2;
98 ResourceType* Data_Producer;
99 ResourceType* Data_Consumer;
100 };
102 /*
103 * Triple Buffer Implementation - Not thread-safe requires external locks
104 */
105 template<typename ResourceType>
106 class FTripleBuffer final : public IBufferResource<ResourceType>
107 {
108 public:
109
111 : WriteIndex(1)
112 , ReadIndex(0)
113 {
114 }
115 virtual ~FTripleBuffer() {}
116
118 virtual ResourceType* AccessProducerBuffer() override { return &Data[GetWriteIndex()]; }
119 virtual ResourceType* GetConsumerBufferMutable() override {return &Data[GetReadIndex()];}
120
121 virtual const ResourceType* GetProducerBuffer() const override { return &Data[GetWriteIndex()]; }
122 virtual const ResourceType* GetConsumerBuffer() const override { return &Data[GetReadIndex()]; }
123
124 virtual void FlipProducer() override
125 {
126 int32 CurrentReadIdx = GetReadIndex();
127 int32 CurrentWriteIdx = GetWriteIndex();
129
130 ReadIndex.Store(CurrentWriteIdx);
131 WriteIndex.Store(FreeIdx);
132
133 checkSlow(GetReadIndex() != GetWriteIndex());
134 }
135
136 private:
137 int32 GetWriteIndex() const { return WriteIndex.Load(); }
138 int32 GetReadIndex() const { return ReadIndex.Load(); }
139
140 ResourceType Data[3];
141 TAtomic<int32> WriteIndex;
142 TAtomic<int32> ReadIndex;
143 };
145
151 template<typename ResourceType>
152 class FGuardedTripleBuffer final : public IBufferResource<ResourceType>
153 {
154 public:
201 : ProducerThreadBuffer(&Buffers[0])
202 , ConsumerThreadBuffer(&Buffers[1])
203 , Interchange(&Buffers[2])
204 {}
205
207
215 virtual ResourceType* AccessProducerBuffer() override
216 {
217 return ProducerThreadBuffer->Value.Get();
218 }
219
220 virtual ResourceType* GetConsumerBufferMutable() override
221 {
222 check(false);
223 return nullptr;
224 }
225
233 virtual const ResourceType* GetProducerBuffer() const override
234 {
235 return ProducerThreadBuffer->Value.Get();
236 }
237
246 virtual const ResourceType* GetConsumerBuffer() const override
247 {
248 ConsumerThreadBuffer = Interchange.Exchange(ConsumerThreadBuffer);
249 // Return null if the value hasn't changed.
250 if (!ConsumerThreadBuffer->bValid)
251 {
252 return nullptr;
253 }
254 // Mark the buffer as invalid so we don't use this value again.
255 ConsumerThreadBuffer->bValid = false;
256 return ConsumerThreadBuffer->Value.Get();
257 }
258
263 const ResourceType* PeekConsumerBuffer() const
264 {
265 return ConsumerThreadBuffer->Value.Get();
266 }
267
273 virtual void FlipProducer()
274 {
275 ProducerThreadBuffer->bValid = true; // In with the new...
276 ProducerThreadBuffer = Interchange.Exchange(ProducerThreadBuffer);
277 ProducerThreadBuffer->bValid = false; // Out with the old.
278 }
279
280 private:
281 struct ResourceTypeWrapper
282 {
283 ResourceTypeWrapper()
284 : Value(new ResourceType())
285 , bValid(false)
286 {}
287 ResourceTypeWrapper(const ResourceTypeWrapper&) = delete;
288 ResourceTypeWrapper(ResourceTypeWrapper&& Other)
289 : Value(MoveTemp(Other.Value))
290 , bValid(MoveTemp(Other.bValid))
291 {}
292
293 void operator=(const ResourceTypeWrapper& Other) = delete;
294
296 bool bValid;
297 };
298
299 ResourceTypeWrapper Buffers[3] = {ResourceTypeWrapper(), ResourceTypeWrapper(), ResourceTypeWrapper()};
300 ResourceTypeWrapper* ProducerThreadBuffer;
301 mutable ResourceTypeWrapper* ConsumerThreadBuffer;
302 mutable TAtomic<ResourceTypeWrapper*> Interchange;
303 };
304
306
307 template<typename ResourceType>
309 {
310 public:
312 {
313 switch (BufferMode)
314 {
316 {
318 }
319 break;
320
322 {
324 }
325 break;
326
328 {
330 }
331 break;
332
334 {
336 }
337 break;
338
339 default:
340 checkf(false, TEXT("FMultiBufferFactory Unexpected buffer mode"));
341 break;
342
343 }
344
345 return nullptr;
346 }
347 };
348
349} // namespace Chaos
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition MultiBufferResource.h:65
void FlipProducer()
Definition MultiBufferResource.h:80
virtual ~FDoubleBuffer()
Definition MultiBufferResource.h:72
virtual ResourceType * GetConsumerBufferMutable() override
Definition MultiBufferResource.h:76
virtual ResourceType * AccessProducerBuffer() override
Definition MultiBufferResource.h:75
virtual const ResourceType * GetProducerBuffer() const override
Definition MultiBufferResource.h:77
FDoubleBuffer()
Definition MultiBufferResource.h:68
virtual EMultiBufferMode GetBufferMode() override
Definition MultiBufferResource.h:74
virtual const ResourceType * GetConsumerBuffer() const override
Definition MultiBufferResource.h:78
Definition MultiBufferResource.h:153
virtual EMultiBufferMode GetBufferMode() override
Definition MultiBufferResource.h:206
virtual ResourceType * GetConsumerBufferMutable() override
Definition MultiBufferResource.h:220
const ResourceType * PeekConsumerBuffer() const
Definition MultiBufferResource.h:263
virtual const ResourceType * GetConsumerBuffer() const override
Definition MultiBufferResource.h:246
virtual ResourceType * AccessProducerBuffer() override
Definition MultiBufferResource.h:215
virtual const ResourceType * GetProducerBuffer() const override
Definition MultiBufferResource.h:233
FGuardedTripleBuffer()
Definition MultiBufferResource.h:200
virtual void FlipProducer()
Definition MultiBufferResource.h:273
Definition MultiBufferResource.h:309
static TUniquePtr< IBufferResource< ResourceType > > CreateBuffer(const EMultiBufferMode BufferMode)
Definition MultiBufferResource.h:311
Definition MultiBufferResource.h:41
FSingleBuffer()
Definition MultiBufferResource.h:44
virtual ~FSingleBuffer()
Definition MultiBufferResource.h:45
virtual ResourceType * GetConsumerBufferMutable() override
Definition MultiBufferResource.h:49
void FlipProducer() override
Definition MultiBufferResource.h:53
virtual const ResourceType * GetConsumerBuffer() const override
Definition MultiBufferResource.h:51
virtual const ResourceType * GetProducerBuffer() const override
Definition MultiBufferResource.h:50
virtual ResourceType * AccessProducerBuffer() override
Definition MultiBufferResource.h:48
virtual EMultiBufferMode GetBufferMode() override
Definition MultiBufferResource.h:47
Definition MultiBufferResource.h:107
virtual ~FTripleBuffer()
Definition MultiBufferResource.h:115
virtual const ResourceType * GetProducerBuffer() const override
Definition MultiBufferResource.h:121
virtual ResourceType * AccessProducerBuffer() override
Definition MultiBufferResource.h:118
virtual EMultiBufferMode GetBufferMode() override
Definition MultiBufferResource.h:117
virtual ResourceType * GetConsumerBufferMutable() override
Definition MultiBufferResource.h:119
virtual const ResourceType * GetConsumerBuffer() const override
Definition MultiBufferResource.h:122
virtual void FlipProducer() override
Definition MultiBufferResource.h:124
FTripleBuffer()
Definition MultiBufferResource.h:110
Definition MultiBufferResource.h:19
virtual const ResourceType * GetConsumerBuffer() const =0
virtual EMultiBufferMode GetBufferMode()=0
virtual ResourceType * AccessProducerBuffer()=0
virtual ~IBufferResource()
Definition MultiBufferResource.h:22
virtual const ResourceType * GetProducerBuffer() const =0
virtual ResourceType * GetConsumerBufferMutable()=0
virtual void FlipProducer()=0
Definition Atomic.h:538
Definition UniquePtr.h:107
Definition SkeletalMeshComponent.h:307
EMultiBufferMode
Definition MultiBufferResource.h:9
@ false
Definition radaudio_common.h:23