1 #ifndef _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
2 #define _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
3 /*------------------------------------------------------------------------
4 * Vulkan Conformance Tests
5 * ------------------------
6 *
7 * Copyright (c) 2015 The Khronos Group Inc.
8 * Copyright (c) 2015 Imagination Technologies Ltd.
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Iterator over a unique sequence of items
25 *//*--------------------------------------------------------------------*/
26
27 #include "tcuDefs.hpp"
28 #include "deRandom.hpp"
29 #include <set>
30 #include <vector>
31
32 namespace vkt
33 {
34 namespace pipeline
35 {
36
37 template <typename T>
38 class UniqueRandomIterator
39 {
40 public:
41 UniqueRandomIterator(uint32_t numItems, uint32_t numValues, int seed);
~UniqueRandomIterator(void)42 virtual ~UniqueRandomIterator(void)
43 {
44 }
45 bool hasNext(void) const;
46 T next(void);
47 void reset(void);
48
49 protected:
50 virtual T getIndexedValue(uint32_t index) = 0;
51
52 private:
53 std::vector<uint32_t> m_indices;
54 size_t m_currentIndex;
55 };
56
57 template <typename T>
UniqueRandomIterator(uint32_t numItems,uint32_t numValues,int seed)58 UniqueRandomIterator<T>::UniqueRandomIterator(uint32_t numItems, uint32_t numValues, int seed)
59 {
60 de::Random rnd(seed);
61
62 DE_ASSERT(numItems <= numValues);
63
64 if (numItems == numValues)
65 {
66 // Fast way to populate the index sequence
67 m_indices = std::vector<uint32_t>(numItems);
68
69 for (uint32_t itemNdx = 0; itemNdx < numItems; itemNdx++)
70 m_indices[itemNdx] = itemNdx;
71 }
72 else
73 {
74 std::set<uint32_t> uniqueIndices;
75
76 // Populate set with "numItems" unique values between 0 and numValues - 1
77 while (uniqueIndices.size() < numItems)
78 uniqueIndices.insert(rnd.getUint32() % numValues);
79
80 // Copy set into index sequence
81 m_indices = std::vector<uint32_t>(uniqueIndices.begin(), uniqueIndices.end());
82 }
83
84 // Scramble the indices
85 rnd.shuffle(m_indices.begin(), m_indices.end());
86
87 reset();
88 }
89
90 template <typename T>
hasNext(void) const91 bool UniqueRandomIterator<T>::hasNext(void) const
92 {
93 return m_currentIndex < m_indices.size();
94 }
95
96 template <typename T>
next(void)97 T UniqueRandomIterator<T>::next(void)
98 {
99 DE_ASSERT(m_currentIndex < m_indices.size());
100
101 return getIndexedValue(m_indices[m_currentIndex++]);
102 }
103
104 template <typename T>
reset(void)105 void UniqueRandomIterator<T>::reset(void)
106 {
107 m_currentIndex = 0;
108 }
109
110 } // namespace pipeline
111 } // namespace vkt
112
113 #endif // _VKTPIPELINEUNIQUERANDOMITERATOR_HPP
114