Hash :
7aba3bc5
Author :
Date :
2021-10-14T23:14:37
Vulkan: Use a CircularBuffer helper class in SurfaceVk There are two instances of circular buffer in SurfaceVk. A common helper class is introduced by this change to consolidate the implementation. This is in preparation for a follow up change that introduces yet another circular buffer in this class. Bug: angleproject:6401 Change-Id: Id01b585567310a2528888114239a5c80ff93f1ee Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3225084 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Ian Elliott <ianelliott@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CircularBuffer.h:
// An array class with an index that loops through the elements.
//
#ifndef COMMON_CIRCULARBUFFER_H_
#define COMMON_CIRCULARBUFFER_H_
#include "common/debug.h"
#include <algorithm>
#include <array>
namespace angle
{
template <class T, size_t N, class Storage = std::array<T, N>>
class CircularBuffer final
{
public:
using value_type = typename Storage::value_type;
using size_type = typename Storage::size_type;
using reference = typename Storage::reference;
using const_reference = typename Storage::const_reference;
using pointer = typename Storage::pointer;
using const_pointer = typename Storage::const_pointer;
using iterator = typename Storage::iterator;
using const_iterator = typename Storage::const_iterator;
CircularBuffer();
CircularBuffer(const value_type &value);
CircularBuffer(const CircularBuffer<T, N, Storage> &other);
CircularBuffer(CircularBuffer<T, N, Storage> &&other);
CircularBuffer<T, N, Storage> &operator=(const CircularBuffer<T, N, Storage> &other);
CircularBuffer<T, N, Storage> &operator=(CircularBuffer<T, N, Storage> &&other);
~CircularBuffer();
// begin() and end() are used to iterate over all elements regardless of the current position of
// the front of the buffer. Useful for initialization and clean up, as otherwise only the front
// element is expected to be accessed.
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
size_type size() const;
reference front();
const_reference front() const;
void swap(CircularBuffer<T, N, Storage> &other);
// Move the front forward to the next index, looping back to the beginning if the end of the
// array is reached.
void next();
private:
Storage mData;
size_type mFrontIndex;
};
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage>::CircularBuffer() : mFrontIndex(0)
{}
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage>::CircularBuffer(const value_type &value) : CircularBuffer()
{
std::fill(begin(), end(), value);
}
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage>::CircularBuffer(const CircularBuffer<T, N, Storage> &other)
{
*this = other;
}
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage>::CircularBuffer(CircularBuffer<T, N, Storage> &&other)
: CircularBuffer()
{
swap(other);
}
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage> &CircularBuffer<T, N, Storage>::operator=(
const CircularBuffer<T, N, Storage> &other)
{
std::copy(other.begin(), other.end(), begin());
mFrontIndex = other.mFrontIndex;
return *this;
}
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage> &CircularBuffer<T, N, Storage>::operator=(
CircularBuffer<T, N, Storage> &&other)
{
swap(other);
return *this;
}
template <class T, size_t N, class Storage>
CircularBuffer<T, N, Storage>::~CircularBuffer() = default;
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::iterator CircularBuffer<T, N, Storage>::begin()
{
return mData.begin();
}
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_iterator
CircularBuffer<T, N, Storage>::begin() const
{
return mData.begin();
}
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::iterator CircularBuffer<T, N, Storage>::end()
{
return mData.end();
}
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_iterator
CircularBuffer<T, N, Storage>::end() const
{
return mData.end();
}
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::size_type CircularBuffer<T, N, Storage>::size()
const
{
return N;
}
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::reference
CircularBuffer<T, N, Storage>::front()
{
ASSERT(mFrontIndex < size());
return mData[mFrontIndex];
}
template <class T, size_t N, class Storage>
ANGLE_INLINE typename CircularBuffer<T, N, Storage>::const_reference
CircularBuffer<T, N, Storage>::front() const
{
ASSERT(mFrontIndex < size());
return mData[mFrontIndex];
}
template <class T, size_t N, class Storage>
void CircularBuffer<T, N, Storage>::swap(CircularBuffer<T, N, Storage> &other)
{
std::swap(mData, other.mData);
std::swap(mFrontIndex, other.mFrontIndex);
}
template <class T, size_t N, class Storage>
void CircularBuffer<T, N, Storage>::next()
{
mFrontIndex = (mFrontIndex + 1) % size();
}
} // namespace angle
#endif // COMMON_CIRCULARBUFFER_H_