diff --git a/Source/Engine/Core/Collections/RingBuffer.h b/Source/Engine/Core/Collections/RingBuffer.h
new file mode 100644
index 000000000..bffc70e40
--- /dev/null
+++ b/Source/Engine/Core/Collections/RingBuffer.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Platform/Platform.h"
+#include "Engine/Core/Memory/Memory.h"
+#include "Engine/Core/Memory/Allocation.h"
+
+///
+/// Template for ring buffer with variable capacity.
+///
+template
+class RingBuffer
+{
+public:
+
+ typedef T ItemType;
+ typedef typename AllocationType::template Data AllocationData;
+
+private:
+
+ int32 _front = 0, _back = 0, _count = 0, _capacity = 0;
+ AllocationData _allocation;
+
+public:
+
+ ~RingBuffer()
+ {
+ Memory::DestructItems(Get() + Math::Min(_front, _back), _count);
+ }
+
+ FORCE_INLINE T* Get()
+ {
+ return _allocation.Get();
+ }
+
+ FORCE_INLINE int32 Count() const
+ {
+ return _count;
+ }
+
+ FORCE_INLINE int32 Capacity() const
+ {
+ return _capacity;
+ }
+
+ void PushBack(const T& data)
+ {
+ if (_capacity == 0 || _capacity == _count)
+ {
+ const int32 capacity = _allocation.CalculateCapacityGrow(_capacity, 0);
+ AllocationData alloc;
+ alloc.Allocate(capacity);
+ const int32 frontCount = Math::Min(_capacity - _front, _count);
+ Memory::MoveItems(alloc.Get(), _allocation.Get() + _front, frontCount);
+ Memory::DestructItems(_allocation.Get() + _front, frontCount);
+ const int32 backCount = _count - frontCount;
+ Memory::MoveItems(alloc.Get() + frontCount, _allocation.Get(), backCount);
+ Memory::DestructItems(_allocation.Get(), backCount);
+ _allocation.Swap(alloc);
+ _front = 0;
+ _back = _count;
+ _capacity = capacity;
+ }
+ Memory::ConstructItems(_allocation.Get() + _back, &data, 1);
+ _back = (_back + 1) % _capacity;
+ _count++;
+ }
+
+ FORCE_INLINE T& PeekFront()
+ {
+ ASSERT(_front != _back);
+ return _allocation.Get()[_front];
+ }
+
+ FORCE_INLINE const T& PeekFront() const
+ {
+ ASSERT(_front != _back);
+ return _allocation.Get()[_front];
+ }
+
+ void PopFront()
+ {
+ ASSERT(_front != _back);
+ Memory::DestructItems(_allocation.Get() + _front, 1);
+ _front = (_front + 1) % _capacity;
+ _count--;
+ }
+
+ void Clear()
+ {
+ Memory::DestructItems(Get() + Math::Min(_front, _back), _count);
+ _front = _back = _count = 0;
+ }
+};