mirror of https://github.com/AxioDL/metaforce.git
Use atomics for pool buffer ref-counts
This commit is contained in:
parent
b269d4a445
commit
121f566848
|
@ -4,6 +4,7 @@
|
||||||
#include <boo/boo.hpp>
|
#include <boo/boo.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <atomic>
|
||||||
#include "BitVector.hpp"
|
#include "BitVector.hpp"
|
||||||
|
|
||||||
namespace hecl
|
namespace hecl
|
||||||
|
@ -56,7 +57,7 @@ class UniformBufferPool
|
||||||
{
|
{
|
||||||
boo::IGraphicsBufferD* buffer;
|
boo::IGraphicsBufferD* buffer;
|
||||||
uint8_t* cpuBuffer = nullptr;
|
uint8_t* cpuBuffer = nullptr;
|
||||||
size_t useCount = 0;
|
std::atomic_size_t useCount = {};
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
Bucket() = default;
|
Bucket() = default;
|
||||||
Bucket(const Bucket& other) = delete;
|
Bucket(const Bucket& other) = delete;
|
||||||
|
@ -74,23 +75,21 @@ class UniformBufferPool
|
||||||
|
|
||||||
void increment(UniformBufferPool& pool)
|
void increment(UniformBufferPool& pool)
|
||||||
{
|
{
|
||||||
if (!useCount)
|
if (useCount.fetch_add(1) == 0)
|
||||||
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform,
|
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform,
|
||||||
pool.m_stride, pool.m_countPerBucket);
|
pool.m_stride, pool.m_countPerBucket);
|
||||||
++useCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decrement(UniformBufferPool& pool)
|
void decrement(UniformBufferPool& pool)
|
||||||
{
|
{
|
||||||
--useCount;
|
if (useCount.fetch_sub(1) == 1)
|
||||||
if (!useCount)
|
|
||||||
{
|
{
|
||||||
pool.m_token.deletePoolBuffer(buffer);
|
pool.m_token.deletePoolBuffer(buffer);
|
||||||
buffer = nullptr;
|
buffer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::vector<Bucket> m_buckets;
|
std::vector<std::unique_ptr<Bucket>> m_buckets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** User block-owning token */
|
/** User block-owning token */
|
||||||
|
@ -104,11 +103,10 @@ public:
|
||||||
: m_pool(pool)
|
: m_pool(pool)
|
||||||
{
|
{
|
||||||
auto& freeSpaces = pool.m_freeBlocks;
|
auto& freeSpaces = pool.m_freeBlocks;
|
||||||
auto& buckets = pool.m_buckets;
|
|
||||||
int idx = freeSpaces.find_first();
|
int idx = freeSpaces.find_first();
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
{
|
||||||
buckets.emplace_back();
|
pool.m_buckets.push_back(std::make_unique<Bucket>());
|
||||||
m_index = freeSpaces.size();
|
m_index = freeSpaces.size();
|
||||||
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +117,7 @@ public:
|
||||||
freeSpaces.reset(m_index);
|
freeSpaces.reset(m_index);
|
||||||
m_div = pool.getBucketDiv(m_index);
|
m_div = pool.getBucketDiv(m_index);
|
||||||
|
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
bucket.increment(m_pool);
|
bucket.increment(m_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,14 +137,14 @@ public:
|
||||||
if (m_index != -1)
|
if (m_index != -1)
|
||||||
{
|
{
|
||||||
m_pool.m_freeBlocks.set(m_index);
|
m_pool.m_freeBlocks.set(m_index);
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
bucket.decrement(m_pool);
|
bucket.decrement(m_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformStruct& access()
|
UniformStruct& access()
|
||||||
{
|
{
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
if (!bucket.cpuBuffer)
|
if (!bucket.cpuBuffer)
|
||||||
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
|
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
|
||||||
bucket.dirty = true;
|
bucket.dirty = true;
|
||||||
|
@ -155,7 +153,7 @@ public:
|
||||||
|
|
||||||
std::pair<boo::IGraphicsBufferD*, IndexTp> getBufferInfo() const
|
std::pair<boo::IGraphicsBufferD*, IndexTp> getBufferInfo() const
|
||||||
{
|
{
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
return {bucket.buffer, m_div.rem * m_pool.m_stride};
|
return {bucket.buffer, m_div.rem * m_pool.m_stride};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -167,9 +165,9 @@ public:
|
||||||
/** Load dirty buffer data into GPU */
|
/** Load dirty buffer data into GPU */
|
||||||
void updateBuffers()
|
void updateBuffers()
|
||||||
{
|
{
|
||||||
for (Bucket& bucket : m_buckets)
|
for (auto& bucket : m_buckets)
|
||||||
if (bucket.dirty)
|
if (bucket->dirty)
|
||||||
bucket.updateBuffer();
|
bucket->updateBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocate free block into client-owned Token */
|
/** Allocate free block into client-owned Token */
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <boo/boo.hpp>
|
#include <boo/boo.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <atomic>
|
||||||
#include "BitVector.hpp"
|
#include "BitVector.hpp"
|
||||||
|
|
||||||
namespace hecl
|
namespace hecl
|
||||||
|
@ -56,13 +57,13 @@ class VertexBufferPool
|
||||||
{
|
{
|
||||||
boo::IGraphicsBufferD* buffer;
|
boo::IGraphicsBufferD* buffer;
|
||||||
uint8_t* cpuBuffer = nullptr;
|
uint8_t* cpuBuffer = nullptr;
|
||||||
size_t useCount = 0;
|
std::atomic_size_t useCount = {};
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
Bucket() = default;
|
Bucket() = default;
|
||||||
Bucket(const Bucket& other) = delete;
|
Bucket(const Bucket& other) = delete;
|
||||||
Bucket& operator=(const Bucket& other) = delete;
|
Bucket& operator=(const Bucket& other) = delete;
|
||||||
Bucket(Bucket&& other) = default;
|
Bucket(Bucket&& other) = delete;
|
||||||
Bucket& operator=(Bucket&& other) = default;
|
Bucket& operator=(Bucket&& other) = delete;
|
||||||
|
|
||||||
void updateBuffer()
|
void updateBuffer()
|
||||||
{
|
{
|
||||||
|
@ -74,23 +75,21 @@ class VertexBufferPool
|
||||||
|
|
||||||
void increment(VertexBufferPool& pool)
|
void increment(VertexBufferPool& pool)
|
||||||
{
|
{
|
||||||
if (!useCount)
|
if (useCount.fetch_add(1) == 0)
|
||||||
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex,
|
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex,
|
||||||
pool.m_stride, pool.m_countPerBucket);
|
pool.m_stride, pool.m_countPerBucket);
|
||||||
++useCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decrement(VertexBufferPool& pool)
|
void decrement(VertexBufferPool& pool)
|
||||||
{
|
{
|
||||||
--useCount;
|
if (useCount.fetch_sub(1) == 1)
|
||||||
if (!useCount)
|
|
||||||
{
|
{
|
||||||
pool.m_token.deletePoolBuffer(buffer);
|
pool.m_token.deletePoolBuffer(buffer);
|
||||||
buffer = nullptr;
|
buffer = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::vector<Bucket> m_buckets;
|
std::vector<std::unique_ptr<Bucket>> m_buckets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** User element-owning token */
|
/** User element-owning token */
|
||||||
|
@ -106,11 +105,10 @@ public:
|
||||||
{
|
{
|
||||||
assert(count <= pool.m_countPerBucket && "unable to fit in bucket");
|
assert(count <= pool.m_countPerBucket && "unable to fit in bucket");
|
||||||
auto& freeSpaces = pool.m_freeElements;
|
auto& freeSpaces = pool.m_freeElements;
|
||||||
auto& buckets = pool.m_buckets;
|
|
||||||
int idx = freeSpaces.find_first_contiguous(count, pool.m_countPerBucket);
|
int idx = freeSpaces.find_first_contiguous(count, pool.m_countPerBucket);
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
{
|
||||||
buckets.emplace_back();
|
pool.m_buckets.push_back(std::make_unique<Bucket>());
|
||||||
m_index = freeSpaces.size();
|
m_index = freeSpaces.size();
|
||||||
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +119,7 @@ public:
|
||||||
freeSpaces.reset(m_index, m_index + count);
|
freeSpaces.reset(m_index, m_index + count);
|
||||||
m_div = pool.getBucketDiv(m_index);
|
m_div = pool.getBucketDiv(m_index);
|
||||||
|
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
bucket.increment(pool);
|
bucket.increment(pool);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
@ -140,14 +138,14 @@ public:
|
||||||
if (m_index != -1)
|
if (m_index != -1)
|
||||||
{
|
{
|
||||||
m_pool.m_freeElements.set(m_index, m_index + m_count);
|
m_pool.m_freeElements.set(m_index, m_index + m_count);
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
bucket.decrement(m_pool);
|
bucket.decrement(m_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VertStruct* access()
|
VertStruct* access()
|
||||||
{
|
{
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
if (!bucket.cpuBuffer)
|
if (!bucket.cpuBuffer)
|
||||||
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
|
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
|
||||||
bucket.dirty = true;
|
bucket.dirty = true;
|
||||||
|
@ -156,7 +154,7 @@ public:
|
||||||
|
|
||||||
std::pair<boo::IGraphicsBufferD*, IndexTp> getBufferInfo() const
|
std::pair<boo::IGraphicsBufferD*, IndexTp> getBufferInfo() const
|
||||||
{
|
{
|
||||||
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
|
||||||
return {bucket.buffer, m_div.rem};
|
return {bucket.buffer, m_div.rem};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -168,9 +166,9 @@ public:
|
||||||
/** Load dirty buffer data into GPU */
|
/** Load dirty buffer data into GPU */
|
||||||
void updateBuffers()
|
void updateBuffers()
|
||||||
{
|
{
|
||||||
for (Bucket& bucket : m_buckets)
|
for (auto& bucket : m_buckets)
|
||||||
if (bucket.dirty)
|
if (bucket->dirty)
|
||||||
bucket.updateBuffer();
|
bucket->updateBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocate free block into client-owned Token */
|
/** Allocate free block into client-owned Token */
|
||||||
|
|
Loading…
Reference in New Issue