From 121f566848db4d753491bf631447f8c42449cad3 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 14 Dec 2016 12:56:32 -1000 Subject: [PATCH] Use atomics for pool buffer ref-counts --- hecl/include/hecl/UniformBufferPool.hpp | 28 ++++++++++------------ hecl/include/hecl/VertexBufferPool.hpp | 32 ++++++++++++------------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/hecl/include/hecl/UniformBufferPool.hpp b/hecl/include/hecl/UniformBufferPool.hpp index 0a45d82e8..4f24f6b6e 100644 --- a/hecl/include/hecl/UniformBufferPool.hpp +++ b/hecl/include/hecl/UniformBufferPool.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #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 m_buckets; + std::vector> 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()); 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(bucket.buffer->map(m_sizePerBucket)); bucket.dirty = true; @@ -155,7 +153,7 @@ public: std::pair 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 */ diff --git a/hecl/include/hecl/VertexBufferPool.hpp b/hecl/include/hecl/VertexBufferPool.hpp index 3a639db60..3759ce9db 100644 --- a/hecl/include/hecl/VertexBufferPool.hpp +++ b/hecl/include/hecl/VertexBufferPool.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #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 m_buckets; + std::vector> 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()); 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(bucket.buffer->map(m_sizePerBucket)); bucket.dirty = true; @@ -156,7 +154,7 @@ public: std::pair 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 */