Use atomics for pool buffer ref-counts

This commit is contained in:
Jack Andersen 2016-12-14 12:56:32 -10:00
parent b269d4a445
commit 121f566848
2 changed files with 28 additions and 32 deletions

View File

@ -4,6 +4,7 @@
#include <boo/boo.hpp>
#include <vector>
#include <cstdlib>
#include <atomic>
#include "BitVector.hpp"
namespace hecl
@ -56,7 +57,7 @@ class UniformBufferPool
{
boo::IGraphicsBufferD* buffer;
uint8_t* cpuBuffer = nullptr;
size_t useCount = 0;
std::atomic_size_t useCount = {};
bool dirty = false;
Bucket() = default;
Bucket(const Bucket& other) = delete;
@ -74,23 +75,21 @@ class UniformBufferPool
void increment(UniformBufferPool& pool)
{
if (!useCount)
if (useCount.fetch_add(1) == 0)
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform,
pool.m_stride, pool.m_countPerBucket);
++useCount;
}
void decrement(UniformBufferPool& pool)
{
--useCount;
if (!useCount)
if (useCount.fetch_sub(1) == 1)
{
pool.m_token.deletePoolBuffer(buffer);
buffer = nullptr;
}
}
};
std::vector<Bucket> m_buckets;
std::vector<std::unique_ptr<Bucket>> m_buckets;
public:
/** User block-owning token */
@ -104,11 +103,10 @@ public:
: m_pool(pool)
{
auto& freeSpaces = pool.m_freeBlocks;
auto& buckets = pool.m_buckets;
int idx = freeSpaces.find_first();
if (idx == -1)
{
buckets.emplace_back();
pool.m_buckets.push_back(std::make_unique<Bucket>());
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
}
@ -119,7 +117,7 @@ public:
freeSpaces.reset(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);
}
@ -139,14 +137,14 @@ public:
if (m_index != -1)
{
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);
}
}
UniformStruct& access()
{
Bucket& bucket = m_pool.m_buckets[m_div.quot];
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
if (!bucket.cpuBuffer)
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
bucket.dirty = true;
@ -155,7 +153,7 @@ public:
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};
}
};
@ -167,9 +165,9 @@ public:
/** Load dirty buffer data into GPU */
void updateBuffers()
{
for (Bucket& bucket : m_buckets)
if (bucket.dirty)
bucket.updateBuffer();
for (auto& bucket : m_buckets)
if (bucket->dirty)
bucket->updateBuffer();
}
/** Allocate free block into client-owned Token */

View File

@ -4,6 +4,7 @@
#include <boo/boo.hpp>
#include <vector>
#include <cstdlib>
#include <atomic>
#include "BitVector.hpp"
namespace hecl
@ -56,13 +57,13 @@ class VertexBufferPool
{
boo::IGraphicsBufferD* buffer;
uint8_t* cpuBuffer = nullptr;
size_t useCount = 0;
std::atomic_size_t useCount = {};
bool dirty = false;
Bucket() = default;
Bucket(const Bucket& other) = delete;
Bucket& operator=(const Bucket& other) = delete;
Bucket(Bucket&& other) = default;
Bucket& operator=(Bucket&& other) = default;
Bucket(Bucket&& other) = delete;
Bucket& operator=(Bucket&& other) = delete;
void updateBuffer()
{
@ -74,23 +75,21 @@ class VertexBufferPool
void increment(VertexBufferPool& pool)
{
if (!useCount)
if (useCount.fetch_add(1) == 0)
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex,
pool.m_stride, pool.m_countPerBucket);
++useCount;
}
void decrement(VertexBufferPool& pool)
{
--useCount;
if (!useCount)
if (useCount.fetch_sub(1) == 1)
{
pool.m_token.deletePoolBuffer(buffer);
buffer = nullptr;
}
}
};
std::vector<Bucket> m_buckets;
std::vector<std::unique_ptr<Bucket>> m_buckets;
public:
/** User element-owning token */
@ -106,11 +105,10 @@ public:
{
assert(count <= pool.m_countPerBucket && "unable to fit in bucket");
auto& freeSpaces = pool.m_freeElements;
auto& buckets = pool.m_buckets;
int idx = freeSpaces.find_first_contiguous(count, pool.m_countPerBucket);
if (idx == -1)
{
buckets.emplace_back();
pool.m_buckets.push_back(std::make_unique<Bucket>());
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
}
@ -121,7 +119,7 @@ public:
freeSpaces.reset(m_index, m_index + count);
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);
}
public:
@ -140,14 +138,14 @@ public:
if (m_index != -1)
{
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);
}
}
VertStruct* access()
{
Bucket& bucket = m_pool.m_buckets[m_div.quot];
Bucket& bucket = *m_pool.m_buckets[m_div.quot];
if (!bucket.cpuBuffer)
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
bucket.dirty = true;
@ -156,7 +154,7 @@ public:
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};
}
};
@ -168,9 +166,9 @@ public:
/** Load dirty buffer data into GPU */
void updateBuffers()
{
for (Bucket& bucket : m_buckets)
if (bucket.dirty)
bucket.updateBuffer();
for (auto& bucket : m_buckets)
if (bucket->dirty)
bucket->updateBuffer();
}
/** Allocate free block into client-owned Token */