Skip to content

Commit 956d784

Browse files
committed
Add FastVec, start using it for InitSteps
1 parent 78eaa8c commit 956d784

File tree

9 files changed

+132
-8
lines changed

9 files changed

+132
-8
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ add_library(Common STATIC
566566
Common/Data/Collections/FixedSizeQueue.h
567567
Common/Data/Collections/Hashmaps.h
568568
Common/Data/Collections/TinySet.h
569+
Common/Data/Collections/FastVec.h
569570
Common/Data/Collections/ThreadSafeList.h
570571
Common/Data/Color/RGBAUtil.cpp
571572
Common/Data/Color/RGBAUtil.h

Common/Common.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@
859859
</ClCompile>
860860
<ClCompile Include="ArmEmitter.cpp" />
861861
<ClCompile Include="Buffer.cpp" />
862+
<ClCompile Include="Data\Collections\FastVec.h" />
862863
<ClCompile Include="Data\Color\RGBAUtil.cpp" />
863864
<ClCompile Include="Data\Convert\SmallDataConvert.cpp" />
864865
<ClCompile Include="Data\Encoding\Base64.cpp" />

Common/Common.vcxproj.filters

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,9 @@
938938
<ClCompile Include="GPU\OpenGL\GLMemory.cpp">
939939
<Filter>GPU\OpenGL</Filter>
940940
</ClCompile>
941+
<ClCompile Include="Data\Collections\FastVec.h">
942+
<Filter>Data\Collections</Filter>
943+
</ClCompile>
941944
</ItemGroup>
942945
<ItemGroup>
943946
<Filter Include="Crypto">
@@ -1086,4 +1089,4 @@
10861089
<Filter>ext\basis_universal</Filter>
10871090
</None>
10881091
</ItemGroup>
1089-
</Project>
1092+
</Project>

Common/Data/Collections/FastVec.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#pragma once
2+
3+
// Yet another replacement for std::vector, this time for use in graphics queues.
4+
// Its major difference is that you can append uninitialized structures and initialize them after.
5+
// This is not allows by std::vector but is very useful for our sometimes oversized unions.
6+
// Also, copies during resize are done by memcpy, not by any move constructor or similar.
7+
8+
#include <cstdlib>
9+
#include <cstring>
10+
11+
template<class T>
12+
class FastVec {
13+
public:
14+
FastVec() {}
15+
FastVec(size_t initialCapacity) {
16+
capacity_ = initialCapacity;
17+
data_ = (T *)malloc(initialCapacity * sizeof(T));
18+
}
19+
~FastVec() { if (data_) free(data_); }
20+
21+
T *push_back() {
22+
if (size_ < capacity_) {
23+
size_++;
24+
return data_ + size_ - 1;
25+
} else {
26+
T *oldData = data_;
27+
size_t newCapacity = capacity_ * 2;
28+
if (newCapacity < 16) {
29+
newCapacity = 16;
30+
}
31+
data_ = (T *)malloc(sizeof(T) * newCapacity);
32+
if (capacity_ != 0) {
33+
memcpy(data_, oldData, sizeof(T) * size_);
34+
free(oldData);
35+
}
36+
size_++;
37+
capacity_ = newCapacity;
38+
return data_ + size_ - 1;
39+
}
40+
}
41+
42+
void push_back(const T &t) {
43+
T *dest = push_back();
44+
*dest = t;
45+
}
46+
47+
// Move constructor
48+
FastVec(FastVec &&other) {
49+
data_ = other.data_;
50+
size_ = other.size_;
51+
capacity_ = other.capacity_;
52+
other.data_ = nullptr;
53+
other.size_ = 0;
54+
other.capacity_ = 0;
55+
}
56+
57+
FastVec &operator=(FastVec &&other) {
58+
if (this != &other) {
59+
delete[] data_;
60+
data_ = other.data_;
61+
size_ = other.size_;
62+
capacity_ = other.capacity_;
63+
other.data_ = nullptr;
64+
other.size_ = 0;
65+
other.capacity_ = 0;
66+
}
67+
return *this;
68+
}
69+
70+
// No copy constructor.
71+
FastVec(const FastVec &other) = delete;
72+
FastVec &operator=(const FastVec &other) = delete;
73+
74+
size_t size() const { return size_; }
75+
size_t capacity() const { return capacity_; }
76+
void clear() { size_ = 0; }
77+
78+
T *begin() { return data_; }
79+
T *end() { return data_ + size_; }
80+
const T *begin() const { return data_; }
81+
const T *end() const { return data_ + size_; }
82+
83+
// Out of bounds (past size() - 1) is undefined behavior.
84+
T &operator[] (const size_t index) { return data_[index]; }
85+
const T &operator[] (const size_t index) const { return data_[index]; }
86+
87+
// These two are invalid if empty().
88+
const T &back() const { return (*this)[size() - 1]; }
89+
const T &front() const { return (*this)[0]; }
90+
91+
private:
92+
T *data_ = nullptr;
93+
size_t size_ = 0;
94+
size_t capacity_ = 0;
95+
};

Common/GPU/OpenGL/GLQueueRunner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ static std::string GetStereoBufferLayout(const char *uniformName) {
118118
else return "undefined";
119119
}
120120

121-
void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls) {
121+
void GLQueueRunner::RunInitSteps(const FastVec<GLRInitStep> &steps, bool skipGLCalls) {
122122
if (skipGLCalls) {
123123
// Some bookkeeping still needs to be done.
124124
for (size_t i = 0; i < steps.size(); i++) {

Common/GPU/OpenGL/GLQueueRunner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "Common/GPU/Shader.h"
1212
#include "Common/GPU/thin3d.h"
1313
#include "Common/Data/Collections/TinySet.h"
14-
14+
#include "Common/Data/Collections/FastVec.h"
1515

1616
struct GLRViewport {
1717
float x, y, w, h, minZ, maxZ;
@@ -354,7 +354,7 @@ class GLQueueRunner {
354354
caps_ = caps;
355355
}
356356

357-
void RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls);
357+
void RunInitSteps(const FastVec<GLRInitStep> &steps, bool skipGLCalls);
358358

359359
void RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls, bool keepSteps, bool useVR);
360360

Common/GPU/OpenGL/GLRenderManager.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,12 @@ bool GLRenderManager::ThreadFrame() {
135135
while (true) {
136136
// Pop a task of the queue and execute it.
137137
// NOTE: We need to actually wait for a task, we can't just bail!
138-
139138
{
140139
std::unique_lock<std::mutex> lock(pushMutex_);
141140
while (renderThreadQueue_.empty()) {
142141
pushCondVar_.wait(lock);
143142
}
144-
task = renderThreadQueue_.front();
143+
task = std::move(renderThreadQueue_.front());
145144
renderThreadQueue_.pop();
146145
}
147146

Common/GPU/OpenGL/GLRenderManager.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ struct GLRRenderThreadTask {
208208
GLRRenderThreadTask(GLRRunType _runType) : runType(_runType) {}
209209

210210
std::vector<GLRStep *> steps;
211-
std::vector<GLRInitStep> initSteps;
211+
FastVec<GLRInitStep> initSteps;
212212

213213
int frame = -1;
214214
GLRRunType runType;
@@ -226,6 +226,9 @@ class GLRenderManager {
226226
GLRenderManager();
227227
~GLRenderManager();
228228

229+
GLRenderManager(GLRenderManager &) = delete;
230+
GLRenderManager &operator=(GLRenderManager &) = delete;
231+
229232
void SetInvalidationCallback(InvalidationCallback callback) {
230233
invalidationCallback_ = callback;
231234
}
@@ -859,7 +862,7 @@ class GLRenderManager {
859862

860863
GLRStep *curRenderStep_ = nullptr;
861864
std::vector<GLRStep *> steps_;
862-
std::vector<GLRInitStep> initSteps_;
865+
FastVec<GLRInitStep> initSteps_;
863866

864867
// Execution time state
865868
bool run_ = true;

unittest/UnitTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@
4747
#endif
4848

4949
#include "Common/Data/Collections/TinySet.h"
50+
#include "Common/Data/Collections/FastVec.h"
5051
#include "Common/Data/Convert/SmallDataConvert.h"
5152
#include "Common/Data/Text/Parsers.h"
5253
#include "Common/Data/Text/WrapText.h"
54+
#include "Common/Data/Collections/FastVec.h"
5355
#include "Common/Data/Encoding/Utf8.h"
5456
#include "Common/File/Path.h"
5557
#include "Common/Input/InputState.h"
@@ -365,6 +367,25 @@ bool TestTinySet() {
365367
return true;
366368
}
367369

370+
bool TestFastVec() {
371+
FastVec<int> a;
372+
EXPECT_EQ_INT((int)a.size(), 0);
373+
a.push_back(1);
374+
EXPECT_EQ_INT((int)a.size(), 1);
375+
a.push_back(2);
376+
EXPECT_EQ_INT((int)a.size(), 2);
377+
FastVec<int> b;
378+
b.push_back(8);
379+
b.push_back(9);
380+
b.push_back(10);
381+
EXPECT_EQ_INT((int)b.size(), 3);
382+
for (int i = 0; i < 100; i++) {
383+
b.push_back(33);
384+
}
385+
EXPECT_EQ_INT((int)b.size(), 103);
386+
return true;
387+
}
388+
368389
bool TestVFPUSinCos() {
369390
float sine, cosine;
370391
// Needed for VFPU tables.
@@ -977,6 +998,7 @@ TestItem availableTests[] = {
977998
TEST_ITEM(ThreadManager),
978999
TEST_ITEM(WrapText),
9791000
TEST_ITEM(TinySet),
1001+
TEST_ITEM(FastVec),
9801002
TEST_ITEM(SmallDataConvert),
9811003
TEST_ITEM(DepthMath),
9821004
TEST_ITEM(InputMapping),

0 commit comments

Comments
 (0)