Add FastVec, start using it for InitSteps

This commit is contained in:
Henrik Rydgård committed 2023-05-23 08:54:40 +02:00
1 parent 78eaa8c235
commit 956d784bde
9 files changed
+132 -8

No files matched your search

+1
View File
@@ -566,6 +566,7 @@ add_library(Common STATIC
Common/Data/Collections/FixedSizeQueue.h
Common/Data/Collections/Hashmaps.h
Common/Data/Collections/TinySet.h
Common/Data/Collections/FastVec.h
Common/Data/Collections/ThreadSafeList.h
Common/Data/Color/RGBAUtil.cpp
Common/Data/Color/RGBAUtil.h
+1
View File
@@ -859,6 +859,7 @@
</ClCompile>
<ClCompile Include="ArmEmitter.cpp" />
<ClCompile Include="Buffer.cpp" />
<ClCompile Include="Data\Collections\FastVec.h" />
<ClCompile Include="Data\Color\RGBAUtil.cpp" />
<ClCompile Include="Data\Convert\SmallDataConvert.cpp" />
<ClCompile Include="Data\Encoding\Base64.cpp" />
+4 -1
View File
@@ -938,6 +938,9 @@
<ClCompile Include="GPU\OpenGL\GLMemory.cpp">
<Filter>GPU\OpenGL</Filter>
</ClCompile>
<ClCompile Include="Data\Collections\FastVec.h">
<Filter>Data\Collections</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Crypto">
@@ -1086,4 +1089,4 @@
<Filter>ext\basis_universal</Filter>
</None>
</ItemGroup>
</Project>
</Project>
+95
View File
@@ -0,0 +1,95 @@
#pragma once
// Yet another replacement for std::vector, this time for use in graphics queues.
// Its major difference is that you can append uninitialized structures and initialize them after.
// This is not allows by std::vector but is very useful for our sometimes oversized unions.
// Also, copies during resize are done by memcpy, not by any move constructor or similar.
#include <cstdlib>
#include <cstring>
template<class T>
class FastVec {
public:
FastVec() {}
FastVec(size_t initialCapacity) {
capacity_ = initialCapacity;
data_ = (T *)malloc(initialCapacity * sizeof(T));
}
~FastVec() { if (data_) free(data_); }
T *push_back() {
if (size_ < capacity_) {
size_++;
return data_ + size_ - 1;
} else {
T *oldData = data_;
size_t newCapacity = capacity_ * 2;
if (newCapacity < 16) {
newCapacity = 16;
}
data_ = (T *)malloc(sizeof(T) * newCapacity);
if (capacity_ != 0) {
memcpy(data_, oldData, sizeof(T) * size_);
free(oldData);
}
size_++;
capacity_ = newCapacity;
return data_ + size_ - 1;
}
}
void push_back(const T &t) {
T *dest = push_back();
*dest = t;
}
// Move constructor
FastVec(FastVec &&other) {
data_ = other.data_;
size_ = other.size_;
capacity_ = other.capacity_;
other.data_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
}
FastVec &operator=(FastVec &&other) {
if (this != &other) {
delete[] data_;
data_ = other.data_;
size_ = other.size_;
capacity_ = other.capacity_;
other.data_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
}
return *this;
}
// No copy constructor.
FastVec(const FastVec &other) = delete;
FastVec &operator=(const FastVec &other) = delete;
size_t size() const { return size_; }
size_t capacity() const { return capacity_; }
void clear() { size_ = 0; }
T *begin() { return data_; }
T *end() { return data_ + size_; }
const T *begin() const { return data_; }
const T *end() const { return data_ + size_; }
// Out of bounds (past size() - 1) is undefined behavior.
T &operator[] (const size_t index) { return data_[index]; }
const T &operator[] (const size_t index) const { return data_[index]; }
// These two are invalid if empty().
const T &back() const { return (*this)[size() - 1]; }
const T &front() const { return (*this)[0]; }
private:
T *data_ = nullptr;
size_t size_ = 0;
size_t capacity_ = 0;
};
+1 -1
View File
@@ -118,7 +118,7 @@ static std::string GetStereoBufferLayout(const char *uniformName) {
else return "undefined";
}
void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls) {
void GLQueueRunner::RunInitSteps(const FastVec<GLRInitStep> &steps, bool skipGLCalls) {
if (skipGLCalls) {
// Some bookkeeping still needs to be done.
for (size_t i = 0; i < steps.size(); i++) {
+2 -2
View File
@@ -11,7 +11,7 @@
#include "Common/GPU/Shader.h"
#include "Common/GPU/thin3d.h"
#include "Common/Data/Collections/TinySet.h"
#include "Common/Data/Collections/FastVec.h"
struct GLRViewport {
float x, y, w, h, minZ, maxZ;
@@ -354,7 +354,7 @@ public:
caps_ = caps;
}
void RunInitSteps(const std::vector<GLRInitStep> &steps, bool skipGLCalls);
void RunInitSteps(const FastVec<GLRInitStep> &steps, bool skipGLCalls);
void RunSteps(const std::vector<GLRStep *> &steps, bool skipGLCalls, bool keepSteps, bool useVR);
+1 -2
View File
@@ -135,13 +135,12 @@ bool GLRenderManager::ThreadFrame() {
while (true) {
// Pop a task of the queue and execute it.
// NOTE: We need to actually wait for a task, we can't just bail!
{
std::unique_lock<std::mutex> lock(pushMutex_);
while (renderThreadQueue_.empty()) {
pushCondVar_.wait(lock);
}
task = renderThreadQueue_.front();
task = std::move(renderThreadQueue_.front());
renderThreadQueue_.pop();
}
+5 -2
View File
@@ -208,7 +208,7 @@ struct GLRRenderThreadTask {
GLRRenderThreadTask(GLRRunType _runType) : runType(_runType) {}
std::vector<GLRStep *> steps;
std::vector<GLRInitStep> initSteps;
FastVec<GLRInitStep> initSteps;
int frame = -1;
GLRRunType runType;
@@ -226,6 +226,9 @@ public:
GLRenderManager();
~GLRenderManager();
GLRenderManager(GLRenderManager &) = delete;
GLRenderManager &operator=(GLRenderManager &) = delete;
void SetInvalidationCallback(InvalidationCallback callback) {
invalidationCallback_ = callback;
}
@@ -859,7 +862,7 @@ private:
GLRStep *curRenderStep_ = nullptr;
std::vector<GLRStep *> steps_;
std::vector<GLRInitStep> initSteps_;
FastVec<GLRInitStep> initSteps_;
// Execution time state
bool run_ = true;
+22
View File
@@ -47,9 +47,11 @@
#endif
#include "Common/Data/Collections/TinySet.h"
#include "Common/Data/Collections/FastVec.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Data/Text/WrapText.h"
#include "Common/Data/Collections/FastVec.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/File/Path.h"
#include "Common/Input/InputState.h"
@@ -365,6 +367,25 @@ bool TestTinySet() {
return true;
}
bool TestFastVec() {
FastVec<int> a;
EXPECT_EQ_INT((int)a.size(), 0);
a.push_back(1);
EXPECT_EQ_INT((int)a.size(), 1);
a.push_back(2);
EXPECT_EQ_INT((int)a.size(), 2);
FastVec<int> b;
b.push_back(8);
b.push_back(9);
b.push_back(10);
EXPECT_EQ_INT((int)b.size(), 3);
for (int i = 0; i < 100; i++) {
b.push_back(33);
}
EXPECT_EQ_INT((int)b.size(), 103);
return true;
}
bool TestVFPUSinCos() {
float sine, cosine;
// Needed for VFPU tables.
@@ -977,6 +998,7 @@ TestItem availableTests[] = {
TEST_ITEM(ThreadManager),
TEST_ITEM(WrapText),
TEST_ITEM(TinySet),
TEST_ITEM(FastVec),
TEST_ITEM(SmallDataConvert),
TEST_ITEM(DepthMath),
TEST_ITEM(InputMapping),