xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/serial_utils.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // serial_utils:
7*8975f5c5SAndroid Build Coastguard Worker //   Utilities for generating unique IDs for resources in ANGLE.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #ifndef LIBANGLE_RENDERER_SERIAL_UTILS_H_
11*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_RENDERER_SERIAL_UTILS_H_
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include <array>
14*8975f5c5SAndroid Build Coastguard Worker #include <atomic>
15*8975f5c5SAndroid Build Coastguard Worker #include <limits>
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker #include "common/angleutils.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
19*8975f5c5SAndroid Build Coastguard Worker 
20*8975f5c5SAndroid Build Coastguard Worker namespace rx
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker class ResourceSerial
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker   public:
ResourceSerial()25*8975f5c5SAndroid Build Coastguard Worker     constexpr ResourceSerial() : mValue(kDirty) {}
ResourceSerial(uintptr_t value)26*8975f5c5SAndroid Build Coastguard Worker     explicit constexpr ResourceSerial(uintptr_t value) : mValue(value) {}
27*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator==(ResourceSerial other) const { return mValue == other.mValue; }
28*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator!=(ResourceSerial other) const { return mValue != other.mValue; }
29*8975f5c5SAndroid Build Coastguard Worker 
dirty()30*8975f5c5SAndroid Build Coastguard Worker     void dirty() { mValue = kDirty; }
clear()31*8975f5c5SAndroid Build Coastguard Worker     void clear() { mValue = kEmpty; }
32*8975f5c5SAndroid Build Coastguard Worker 
valid()33*8975f5c5SAndroid Build Coastguard Worker     constexpr bool valid() const { return mValue != kEmpty && mValue != kDirty; }
empty()34*8975f5c5SAndroid Build Coastguard Worker     constexpr bool empty() const { return mValue == kEmpty; }
35*8975f5c5SAndroid Build Coastguard Worker 
36*8975f5c5SAndroid Build Coastguard Worker   private:
37*8975f5c5SAndroid Build Coastguard Worker     constexpr static uintptr_t kDirty = std::numeric_limits<uintptr_t>::max();
38*8975f5c5SAndroid Build Coastguard Worker     constexpr static uintptr_t kEmpty = 0;
39*8975f5c5SAndroid Build Coastguard Worker 
40*8975f5c5SAndroid Build Coastguard Worker     uintptr_t mValue;
41*8975f5c5SAndroid Build Coastguard Worker };
42*8975f5c5SAndroid Build Coastguard Worker 
43*8975f5c5SAndroid Build Coastguard Worker // Class UniqueSerial defines unique serial number for object identification. It has only
44*8975f5c5SAndroid Build Coastguard Worker // equal/unequal comparison but no greater/smaller comparison. The default constructor creates an
45*8975f5c5SAndroid Build Coastguard Worker // invalid value.
46*8975f5c5SAndroid Build Coastguard Worker class UniqueSerial final
47*8975f5c5SAndroid Build Coastguard Worker {
48*8975f5c5SAndroid Build Coastguard Worker   public:
UniqueSerial()49*8975f5c5SAndroid Build Coastguard Worker     constexpr UniqueSerial() : mValue(kInvalid) {}
50*8975f5c5SAndroid Build Coastguard Worker     constexpr UniqueSerial(const UniqueSerial &other)  = default;
51*8975f5c5SAndroid Build Coastguard Worker     UniqueSerial &operator=(const UniqueSerial &other) = default;
52*8975f5c5SAndroid Build Coastguard Worker 
53*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator==(const UniqueSerial &other) const
54*8975f5c5SAndroid Build Coastguard Worker     {
55*8975f5c5SAndroid Build Coastguard Worker         return mValue != kInvalid && mValue == other.mValue;
56*8975f5c5SAndroid Build Coastguard Worker     }
57*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator!=(const UniqueSerial &other) const
58*8975f5c5SAndroid Build Coastguard Worker     {
59*8975f5c5SAndroid Build Coastguard Worker         return mValue == kInvalid || mValue != other.mValue;
60*8975f5c5SAndroid Build Coastguard Worker     }
61*8975f5c5SAndroid Build Coastguard Worker 
62*8975f5c5SAndroid Build Coastguard Worker     // Useful for serialization.
getValue()63*8975f5c5SAndroid Build Coastguard Worker     constexpr uint64_t getValue() const { return mValue; }
valid()64*8975f5c5SAndroid Build Coastguard Worker     constexpr bool valid() const { return mValue != kInvalid; }
65*8975f5c5SAndroid Build Coastguard Worker 
66*8975f5c5SAndroid Build Coastguard Worker   private:
67*8975f5c5SAndroid Build Coastguard Worker     friend class UniqueSerialFactory;
UniqueSerial(uint64_t value)68*8975f5c5SAndroid Build Coastguard Worker     constexpr explicit UniqueSerial(uint64_t value) : mValue(value) {}
69*8975f5c5SAndroid Build Coastguard Worker     uint64_t mValue;
70*8975f5c5SAndroid Build Coastguard Worker     static constexpr uint64_t kInvalid = 0;
71*8975f5c5SAndroid Build Coastguard Worker };
72*8975f5c5SAndroid Build Coastguard Worker 
73*8975f5c5SAndroid Build Coastguard Worker class UniqueSerialFactory final : angle::NonCopyable
74*8975f5c5SAndroid Build Coastguard Worker {
75*8975f5c5SAndroid Build Coastguard Worker   public:
UniqueSerialFactory()76*8975f5c5SAndroid Build Coastguard Worker     UniqueSerialFactory() : mSerial(1) {}
77*8975f5c5SAndroid Build Coastguard Worker 
generate()78*8975f5c5SAndroid Build Coastguard Worker     UniqueSerial generate()
79*8975f5c5SAndroid Build Coastguard Worker     {
80*8975f5c5SAndroid Build Coastguard Worker         uint64_t current = mSerial++;
81*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mSerial > current);  // Integer overflow
82*8975f5c5SAndroid Build Coastguard Worker         return UniqueSerial(current);
83*8975f5c5SAndroid Build Coastguard Worker     }
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker   private:
86*8975f5c5SAndroid Build Coastguard Worker     uint64_t mSerial;
87*8975f5c5SAndroid Build Coastguard Worker };
88*8975f5c5SAndroid Build Coastguard Worker 
89*8975f5c5SAndroid Build Coastguard Worker // Class Serial defines a monotonically increasing serial number that indicates the timeline of
90*8975f5c5SAndroid Build Coastguard Worker // execution.
91*8975f5c5SAndroid Build Coastguard Worker class Serial final
92*8975f5c5SAndroid Build Coastguard Worker {
93*8975f5c5SAndroid Build Coastguard Worker   public:
Serial()94*8975f5c5SAndroid Build Coastguard Worker     constexpr Serial() : mValue(0) {}
95*8975f5c5SAndroid Build Coastguard Worker     constexpr Serial(const Serial &other)  = default;
96*8975f5c5SAndroid Build Coastguard Worker     Serial &operator=(const Serial &other) = default;
97*8975f5c5SAndroid Build Coastguard Worker 
Infinite()98*8975f5c5SAndroid Build Coastguard Worker     static constexpr Serial Infinite() { return Serial(std::numeric_limits<uint64_t>::max()); }
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator==(const Serial &other) const { return mValue == other.mValue; }
101*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator!=(const Serial &other) const { return mValue != other.mValue; }
102*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator>(const Serial &other) const { return mValue > other.mValue; }
103*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator>=(const Serial &other) const { return mValue >= other.mValue; }
104*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; }
105*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator<=(const Serial &other) const { return mValue <= other.mValue; }
106*8975f5c5SAndroid Build Coastguard Worker 
107*8975f5c5SAndroid Build Coastguard Worker     // Useful for serialization.
getValue()108*8975f5c5SAndroid Build Coastguard Worker     constexpr uint64_t getValue() const { return mValue; }
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker   private:
111*8975f5c5SAndroid Build Coastguard Worker     friend class AtomicSerialFactory;
112*8975f5c5SAndroid Build Coastguard Worker     friend class RangedSerialFactory;
113*8975f5c5SAndroid Build Coastguard Worker     friend class AtomicQueueSerial;
Serial(uint64_t value)114*8975f5c5SAndroid Build Coastguard Worker     constexpr explicit Serial(uint64_t value) : mValue(value) {}
115*8975f5c5SAndroid Build Coastguard Worker     uint64_t mValue;
116*8975f5c5SAndroid Build Coastguard Worker };
117*8975f5c5SAndroid Build Coastguard Worker 
118*8975f5c5SAndroid Build Coastguard Worker // Defines class to track the queue serial that can be load/store from multiple threads atomically.
119*8975f5c5SAndroid Build Coastguard Worker class alignas(8) AtomicQueueSerial final
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker   public:
122*8975f5c5SAndroid Build Coastguard Worker     AtomicQueueSerial &operator=(const Serial &other)
123*8975f5c5SAndroid Build Coastguard Worker     {
124*8975f5c5SAndroid Build Coastguard Worker         mValue.store(other.mValue, std::memory_order_release);
125*8975f5c5SAndroid Build Coastguard Worker         return *this;
126*8975f5c5SAndroid Build Coastguard Worker     }
getSerial()127*8975f5c5SAndroid Build Coastguard Worker     Serial getSerial() const { return Serial(mValue.load(std::memory_order_consume)); }
128*8975f5c5SAndroid Build Coastguard Worker 
129*8975f5c5SAndroid Build Coastguard Worker   private:
130*8975f5c5SAndroid Build Coastguard Worker     static constexpr uint64_t kInvalid = 0;
131*8975f5c5SAndroid Build Coastguard Worker     std::atomic<uint64_t> mValue       = kInvalid;
132*8975f5c5SAndroid Build Coastguard Worker };
133*8975f5c5SAndroid Build Coastguard Worker 
134*8975f5c5SAndroid Build Coastguard Worker // Used as default/initial serial
135*8975f5c5SAndroid Build Coastguard Worker static constexpr Serial kZeroSerial = Serial();
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker // The factory to generate a serial number within the range [mSerial, mSerial+mCount}
138*8975f5c5SAndroid Build Coastguard Worker class RangedSerialFactory final : angle::NonCopyable
139*8975f5c5SAndroid Build Coastguard Worker {
140*8975f5c5SAndroid Build Coastguard Worker   public:
RangedSerialFactory()141*8975f5c5SAndroid Build Coastguard Worker     RangedSerialFactory() : mSerial(0), mCount(0) {}
142*8975f5c5SAndroid Build Coastguard Worker 
reset()143*8975f5c5SAndroid Build Coastguard Worker     void reset() { mCount = 0; }
empty()144*8975f5c5SAndroid Build Coastguard Worker     bool empty() const { return mCount == 0; }
generate(Serial * serialOut)145*8975f5c5SAndroid Build Coastguard Worker     bool generate(Serial *serialOut)
146*8975f5c5SAndroid Build Coastguard Worker     {
147*8975f5c5SAndroid Build Coastguard Worker         if (mCount > 0)
148*8975f5c5SAndroid Build Coastguard Worker         {
149*8975f5c5SAndroid Build Coastguard Worker             uint64_t current = mSerial++;
150*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mSerial > current);  // Integer overflow
151*8975f5c5SAndroid Build Coastguard Worker             *serialOut = Serial(current);
152*8975f5c5SAndroid Build Coastguard Worker             mCount--;
153*8975f5c5SAndroid Build Coastguard Worker             return true;
154*8975f5c5SAndroid Build Coastguard Worker         }
155*8975f5c5SAndroid Build Coastguard Worker         return false;
156*8975f5c5SAndroid Build Coastguard Worker     }
157*8975f5c5SAndroid Build Coastguard Worker 
158*8975f5c5SAndroid Build Coastguard Worker   private:
159*8975f5c5SAndroid Build Coastguard Worker     friend class AtomicSerialFactory;
initialize(uint64_t initialSerial,size_t count)160*8975f5c5SAndroid Build Coastguard Worker     void initialize(uint64_t initialSerial, size_t count)
161*8975f5c5SAndroid Build Coastguard Worker     {
162*8975f5c5SAndroid Build Coastguard Worker         mSerial = initialSerial;
163*8975f5c5SAndroid Build Coastguard Worker         mCount  = count;
164*8975f5c5SAndroid Build Coastguard Worker     }
165*8975f5c5SAndroid Build Coastguard Worker     uint64_t mSerial;
166*8975f5c5SAndroid Build Coastguard Worker     size_t mCount;
167*8975f5c5SAndroid Build Coastguard Worker };
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker class AtomicSerialFactory final : angle::NonCopyable
170*8975f5c5SAndroid Build Coastguard Worker {
171*8975f5c5SAndroid Build Coastguard Worker   public:
AtomicSerialFactory()172*8975f5c5SAndroid Build Coastguard Worker     AtomicSerialFactory() : mSerial(1) {}
173*8975f5c5SAndroid Build Coastguard Worker 
generate()174*8975f5c5SAndroid Build Coastguard Worker     Serial generate()
175*8975f5c5SAndroid Build Coastguard Worker     {
176*8975f5c5SAndroid Build Coastguard Worker         uint64_t current = mSerial++;
177*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mSerial > current);  // Integer overflow
178*8975f5c5SAndroid Build Coastguard Worker         return Serial(current);
179*8975f5c5SAndroid Build Coastguard Worker     }
180*8975f5c5SAndroid Build Coastguard Worker 
reserve(RangedSerialFactory * rangeFactory,size_t count)181*8975f5c5SAndroid Build Coastguard Worker     void reserve(RangedSerialFactory *rangeFactory, size_t count)
182*8975f5c5SAndroid Build Coastguard Worker     {
183*8975f5c5SAndroid Build Coastguard Worker         uint64_t current = mSerial;
184*8975f5c5SAndroid Build Coastguard Worker         mSerial += count;
185*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mSerial > current);  // Integer overflow
186*8975f5c5SAndroid Build Coastguard Worker         rangeFactory->initialize(current, count);
187*8975f5c5SAndroid Build Coastguard Worker     }
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker   private:
190*8975f5c5SAndroid Build Coastguard Worker     std::atomic<uint64_t> mSerial;
191*8975f5c5SAndroid Build Coastguard Worker };
192*8975f5c5SAndroid Build Coastguard Worker 
193*8975f5c5SAndroid Build Coastguard Worker // For backend that supports multiple queue serials, QueueSerial includes a Serial and an index.
194*8975f5c5SAndroid Build Coastguard Worker using SerialIndex                                     = uint32_t;
195*8975f5c5SAndroid Build Coastguard Worker static constexpr SerialIndex kInvalidQueueSerialIndex = SerialIndex(-1);
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker class QueueSerial;
198*8975f5c5SAndroid Build Coastguard Worker // Because we release queue index when context becomes non-current, in order to use up all index
199*8975f5c5SAndroid Build Coastguard Worker // count, you will need to have 256 threads each has a context current. This is not a reasonable
200*8975f5c5SAndroid Build Coastguard Worker // usage case.
201*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kMaxQueueSerialIndexCount = 256;
202*8975f5c5SAndroid Build Coastguard Worker // Fixed array of queue serials
203*8975f5c5SAndroid Build Coastguard Worker class AtomicQueueSerialFixedArray final
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker   public:
206*8975f5c5SAndroid Build Coastguard Worker     AtomicQueueSerialFixedArray()  = default;
207*8975f5c5SAndroid Build Coastguard Worker     ~AtomicQueueSerialFixedArray() = default;
208*8975f5c5SAndroid Build Coastguard Worker 
209*8975f5c5SAndroid Build Coastguard Worker     void setQueueSerial(SerialIndex index, Serial serial);
210*8975f5c5SAndroid Build Coastguard Worker     void setQueueSerial(const QueueSerial &queueSerial);
fill(Serial serial)211*8975f5c5SAndroid Build Coastguard Worker     void fill(Serial serial) { std::fill(mSerials.begin(), mSerials.end(), serial); }
212*8975f5c5SAndroid Build Coastguard Worker     Serial operator[](SerialIndex index) const { return mSerials[index].getSerial(); }
size()213*8975f5c5SAndroid Build Coastguard Worker     size_t size() const { return mSerials.size(); }
214*8975f5c5SAndroid Build Coastguard Worker 
215*8975f5c5SAndroid Build Coastguard Worker   private:
216*8975f5c5SAndroid Build Coastguard Worker     std::array<AtomicQueueSerial, kMaxQueueSerialIndexCount> mSerials;
217*8975f5c5SAndroid Build Coastguard Worker };
218*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const AtomicQueueSerialFixedArray &serials);
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker class QueueSerial final
221*8975f5c5SAndroid Build Coastguard Worker {
222*8975f5c5SAndroid Build Coastguard Worker   public:
QueueSerial()223*8975f5c5SAndroid Build Coastguard Worker     QueueSerial() : mIndex(kInvalidQueueSerialIndex) {}
QueueSerial(SerialIndex index,Serial serial)224*8975f5c5SAndroid Build Coastguard Worker     QueueSerial(SerialIndex index, Serial serial) : mIndex(index), mSerial(serial)
225*8975f5c5SAndroid Build Coastguard Worker     {
226*8975f5c5SAndroid Build Coastguard Worker         ASSERT(index != kInvalidQueueSerialIndex);
227*8975f5c5SAndroid Build Coastguard Worker     }
228*8975f5c5SAndroid Build Coastguard Worker     constexpr QueueSerial(const QueueSerial &other)  = default;
229*8975f5c5SAndroid Build Coastguard Worker     QueueSerial &operator=(const QueueSerial &other) = default;
230*8975f5c5SAndroid Build Coastguard Worker 
231*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator==(const QueueSerial &other) const
232*8975f5c5SAndroid Build Coastguard Worker     {
233*8975f5c5SAndroid Build Coastguard Worker         return mIndex == other.mIndex && mSerial == other.mSerial;
234*8975f5c5SAndroid Build Coastguard Worker     }
235*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator!=(const QueueSerial &other) const
236*8975f5c5SAndroid Build Coastguard Worker     {
237*8975f5c5SAndroid Build Coastguard Worker         return mIndex != other.mIndex || mSerial != other.mSerial;
238*8975f5c5SAndroid Build Coastguard Worker     }
239*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator<(const QueueSerial &other) const
240*8975f5c5SAndroid Build Coastguard Worker     {
241*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex != kInvalidQueueSerialIndex);
242*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex == other.mIndex);
243*8975f5c5SAndroid Build Coastguard Worker         return mSerial < other.mSerial;
244*8975f5c5SAndroid Build Coastguard Worker     }
245*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator<=(const QueueSerial &other) const
246*8975f5c5SAndroid Build Coastguard Worker     {
247*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex != kInvalidQueueSerialIndex);
248*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex == other.mIndex);
249*8975f5c5SAndroid Build Coastguard Worker         return mSerial <= other.mSerial;
250*8975f5c5SAndroid Build Coastguard Worker     }
251*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator>(const QueueSerial &other) const
252*8975f5c5SAndroid Build Coastguard Worker     {
253*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex != kInvalidQueueSerialIndex);
254*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex == other.mIndex);
255*8975f5c5SAndroid Build Coastguard Worker         return mSerial > other.mSerial;
256*8975f5c5SAndroid Build Coastguard Worker     }
257*8975f5c5SAndroid Build Coastguard Worker     constexpr bool operator>=(const QueueSerial &other) const
258*8975f5c5SAndroid Build Coastguard Worker     {
259*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex != kInvalidQueueSerialIndex);
260*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex == other.mIndex);
261*8975f5c5SAndroid Build Coastguard Worker         return mSerial >= other.mSerial;
262*8975f5c5SAndroid Build Coastguard Worker     }
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     bool operator>(const AtomicQueueSerialFixedArray &serials) const
265*8975f5c5SAndroid Build Coastguard Worker     {
266*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex != kInvalidQueueSerialIndex);
267*8975f5c5SAndroid Build Coastguard Worker         return mSerial > serials[mIndex];
268*8975f5c5SAndroid Build Coastguard Worker     }
269*8975f5c5SAndroid Build Coastguard Worker     bool operator<=(const AtomicQueueSerialFixedArray &serials) const
270*8975f5c5SAndroid Build Coastguard Worker     {
271*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mIndex != kInvalidQueueSerialIndex);
272*8975f5c5SAndroid Build Coastguard Worker         return mSerial <= serials[mIndex];
273*8975f5c5SAndroid Build Coastguard Worker     }
274*8975f5c5SAndroid Build Coastguard Worker 
valid()275*8975f5c5SAndroid Build Coastguard Worker     constexpr bool valid() const { return mIndex != kInvalidQueueSerialIndex; }
276*8975f5c5SAndroid Build Coastguard Worker 
getIndex()277*8975f5c5SAndroid Build Coastguard Worker     SerialIndex getIndex() const { return mIndex; }
getSerial()278*8975f5c5SAndroid Build Coastguard Worker     Serial getSerial() const { return mSerial; }
279*8975f5c5SAndroid Build Coastguard Worker 
280*8975f5c5SAndroid Build Coastguard Worker   private:
281*8975f5c5SAndroid Build Coastguard Worker     SerialIndex mIndex;
282*8975f5c5SAndroid Build Coastguard Worker     Serial mSerial;
283*8975f5c5SAndroid Build Coastguard Worker };
284*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const QueueSerial &queueSerial);
285*8975f5c5SAndroid Build Coastguard Worker 
setQueueSerial(SerialIndex index,Serial serial)286*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void AtomicQueueSerialFixedArray::setQueueSerial(SerialIndex index, Serial serial)
287*8975f5c5SAndroid Build Coastguard Worker {
288*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index != kInvalidQueueSerialIndex);
289*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index < mSerials.size());
290*8975f5c5SAndroid Build Coastguard Worker     // Serial can only increase
291*8975f5c5SAndroid Build Coastguard Worker     ASSERT(serial > mSerials[index].getSerial());
292*8975f5c5SAndroid Build Coastguard Worker     mSerials[index] = serial;
293*8975f5c5SAndroid Build Coastguard Worker }
294*8975f5c5SAndroid Build Coastguard Worker 
setQueueSerial(const QueueSerial & queueSerial)295*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void AtomicQueueSerialFixedArray::setQueueSerial(const QueueSerial &queueSerial)
296*8975f5c5SAndroid Build Coastguard Worker {
297*8975f5c5SAndroid Build Coastguard Worker     setQueueSerial(queueSerial.getIndex(), queueSerial.getSerial());
298*8975f5c5SAndroid Build Coastguard Worker }
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE std::ostream &operator<<(std::ostream &os, const AtomicQueueSerialFixedArray &serials)
301*8975f5c5SAndroid Build Coastguard Worker {
302*8975f5c5SAndroid Build Coastguard Worker     // Search for last non-zero index (or 0 if all zeros).
303*8975f5c5SAndroid Build Coastguard Worker     SerialIndex lastIndex = serials.size() == 0 ? 0 : static_cast<SerialIndex>(serials.size() - 1);
304*8975f5c5SAndroid Build Coastguard Worker     while (lastIndex > 0 && serials[lastIndex].getValue() == 0)
305*8975f5c5SAndroid Build Coastguard Worker     {
306*8975f5c5SAndroid Build Coastguard Worker         lastIndex--;
307*8975f5c5SAndroid Build Coastguard Worker     }
308*8975f5c5SAndroid Build Coastguard Worker     os << '{';
309*8975f5c5SAndroid Build Coastguard Worker     for (SerialIndex i = 0; i < lastIndex; i++)
310*8975f5c5SAndroid Build Coastguard Worker     {
311*8975f5c5SAndroid Build Coastguard Worker         os << serials[i].getValue() << ',';
312*8975f5c5SAndroid Build Coastguard Worker     }
313*8975f5c5SAndroid Build Coastguard Worker     os << serials[lastIndex].getValue() << '}';
314*8975f5c5SAndroid Build Coastguard Worker     return os;
315*8975f5c5SAndroid Build Coastguard Worker }
316*8975f5c5SAndroid Build Coastguard Worker 
317*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE std::ostream &operator<<(std::ostream &os, const QueueSerial &queueSerial)
318*8975f5c5SAndroid Build Coastguard Worker {
319*8975f5c5SAndroid Build Coastguard Worker     os << '{' << queueSerial.getIndex() << ':' << queueSerial.getSerial().getValue() << '}';
320*8975f5c5SAndroid Build Coastguard Worker     return os;
321*8975f5c5SAndroid Build Coastguard Worker }
322*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
323*8975f5c5SAndroid Build Coastguard Worker 
324*8975f5c5SAndroid Build Coastguard Worker #endif  // LIBANGLE_RENDERER_SERIAL_UTILS_H_
325