diff --git a/specter/include/specter/UniformBufferPool.hpp b/specter/include/specter/UniformBufferPool.hpp index d5299acf6..7d63f2f89 100644 --- a/specter/include/specter/UniformBufferPool.hpp +++ b/specter/include/specter/UniformBufferPool.hpp @@ -12,7 +12,7 @@ namespace specter #define SPECTER_UBUFPOOL_ALLOCATION_BLOCK 262144 /** This class provides a uniform structure for packing instanced uniform-buffer - * data with consistent stride into a vector of 64K 'Buckets'. + * data with consistent stride into a vector of 256K 'Buckets'. * * This results in a space-efficient way of managing GPU data of things like UI * widgets. These can potentially have numerous binding instances, so this avoids @@ -21,7 +21,11 @@ template class UniformBufferPool { /* Resolve div_t type using ssize_t as basis */ +#if _WIN32 + using IndexTp = SSIZE_T; +#else using IndexTp = ssize_t; +#endif struct InvalidTp {}; using DivTp = std::conditional_t::value, std::lldiv_t, std::conditional_t::value, std::ldiv_t, @@ -32,10 +36,10 @@ class UniformBufferPool static constexpr IndexTp m_stride = ROUND_UP_256(sizeof(UniformStruct)); static_assert(m_stride <= SPECTER_UBUFPOOL_ALLOCATION_BLOCK, "Stride too large for uniform pool"); - /** Number of rounded elements per 64K bucket */ + /** Number of rounded elements per 256K bucket */ static constexpr IndexTp m_countPerBucket = SPECTER_UBUFPOOL_ALLOCATION_BLOCK / m_stride; - /** Buffer size per bucket (ideally 64K) */ + /** Buffer size per bucket (ideally 256K) */ static constexpr IndexTp m_sizePerBucket = m_stride * m_countPerBucket; /** BitVector indicating free allocation blocks */ @@ -51,20 +55,20 @@ class UniformBufferPool struct Bucket { boo::IGraphicsBufferD* buffer; - std::unique_ptr cpuBuffer; + uint8_t* cpuBuffer = nullptr; bool dirty = false; Bucket(const Bucket& other) = delete; Bucket& operator=(const Bucket& other) = delete; Bucket(Bucket&& other) = default; Bucket& operator=(Bucket&& other) = default; Bucket(UniformBufferPool& pool) - : cpuBuffer(new uint8_t[pool.m_sizePerBucket]) { buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform, pool.m_stride, pool.m_countPerBucket); } - void updateBuffer(UniformBufferPool& pool) + void updateBuffer() { - buffer->load(cpuBuffer.get(), pool.m_sizePerBucket); + buffer->unmap(); + cpuBuffer = nullptr; dirty = false; } }; @@ -118,6 +122,8 @@ public: UniformStruct& access() { Bucket& bucket = m_pool.m_buckets[m_div.quot]; + if (!bucket.cpuBuffer) + bucket.cpuBuffer = reinterpret_cast(bucket.buffer->map(m_sizePerBucket)); bucket.dirty = true; return reinterpret_cast(bucket.cpuBuffer[m_div.rem * m_pool.m_stride]); } @@ -138,7 +144,7 @@ public: { for (Bucket& bucket : m_buckets) if (bucket.dirty) - bucket.updateBuffer(*this); + bucket.updateBuffer(); } /** Allocate free block into client-owned Token */ diff --git a/specter/include/specter/VertexBufferPool.hpp b/specter/include/specter/VertexBufferPool.hpp index 147ad049c..befa3cbf1 100644 --- a/specter/include/specter/VertexBufferPool.hpp +++ b/specter/include/specter/VertexBufferPool.hpp @@ -12,7 +12,7 @@ namespace specter #define SPECTER_VBUFPOOL_ALLOCATION_BLOCK 262144 /** This class provides a uniform structure for packing instanced vertex-buffer - * data with consistent stride into a vector of 64K 'Buckets'. + * data with consistent stride into a vector of 256K 'Buckets'. * * This results in a space-efficient way of managing GPU data of things like UI * widgets. These can potentially have numerous binding instances, so this avoids @@ -21,7 +21,11 @@ template class VertexBufferPool { /* Resolve div_t type using ssize_t as basis */ +#if _WIN32 + using IndexTp = SSIZE_T; +#else using IndexTp = ssize_t; +#endif struct InvalidTp {}; using DivTp = std::conditional_t::value, std::lldiv_t, std::conditional_t::value, std::ldiv_t, @@ -32,10 +36,10 @@ class VertexBufferPool static constexpr IndexTp m_stride = sizeof(VertStruct); static_assert(m_stride <= SPECTER_VBUFPOOL_ALLOCATION_BLOCK, "Stride too large for vertex pool"); - /** Number of elements per 64K bucket */ + /** Number of elements per 256K bucket */ static constexpr IndexTp m_countPerBucket = SPECTER_VBUFPOOL_ALLOCATION_BLOCK / m_stride; - /** Buffer size per bucket (ideally 64K) */ + /** Buffer size per bucket (ideally 256K) */ static constexpr IndexTp m_sizePerBucket = m_stride * m_countPerBucket; /** BitVector indicating free allocation elements */ @@ -51,20 +55,20 @@ class VertexBufferPool struct Bucket { boo::IGraphicsBufferD* buffer; - std::unique_ptr cpuBuffer; + uint8_t* cpuBuffer = nullptr; bool dirty = false; Bucket(const Bucket& other) = delete; Bucket& operator=(const Bucket& other) = delete; Bucket(Bucket&& other) = default; Bucket& operator=(Bucket&& other) = default; Bucket(VertexBufferPool& pool) - : cpuBuffer(new uint8_t[pool.m_sizePerBucket]) { buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex, pool.m_stride, pool.m_countPerBucket); } - void updateBuffer(VertexBufferPool& pool) + void updateBuffer() { - buffer->load(cpuBuffer.get(), pool.m_sizePerBucket); + buffer->unmap(); + cpuBuffer = nullptr; dirty = false; } }; @@ -119,6 +123,8 @@ public: VertStruct* access() { Bucket& bucket = m_pool.m_buckets[m_div.quot]; + if (!bucket.cpuBuffer) + bucket.cpuBuffer = reinterpret_cast(bucket.buffer->map(m_sizePerBucket)); bucket.dirty = true; return reinterpret_cast(&bucket.cpuBuffer[m_div.rem * m_pool.m_stride]); } @@ -139,7 +145,7 @@ public: { for (Bucket& bucket : m_buckets) if (bucket.dirty) - bucket.updateBuffer(*this); + bucket.updateBuffer(); } /** Allocate free block into client-owned Token */ diff --git a/specter/lib/TextView.cpp b/specter/lib/TextView.cpp index de300a582..c42e1889c 100644 --- a/specter/lib/TextView.cpp +++ b/specter/lib/TextView.cpp @@ -304,7 +304,7 @@ TextView::TextView(ViewResources& res, m_fontAtlas(font), m_align(align) { - if (VertexBufferPool::bucketCapacity() < capacity) + if (size_t(VertexBufferPool::bucketCapacity()) < capacity) Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]", capacity, VertexBufferPool::bucketCapacity()); @@ -324,7 +324,7 @@ TextView::TextView(ViewResources& res, auto vBufInfo = m_glyphBuf->getBufferInfo(); auto uBufInfo = m_viewVertBlockBuf->getBufferInfo(); boo::IGraphicsBuffer* uBufs[] = {uBufInfo.first}; - size_t uBufOffs[] = {uBufInfo.second}; + size_t uBufOffs[] = {size_t(uBufInfo.second)}; size_t uBufSizes[] = {sizeof(ViewBlock)}; boo::ITexture* texs[] = {m_fontAtlas.texture()}; diff --git a/specter/lib/View.cpp b/specter/lib/View.cpp index dc2b72e40..749c4519e 100644 --- a/specter/lib/View.cpp +++ b/specter/lib/View.cpp @@ -390,7 +390,7 @@ void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ct auto uBufInfo = viewBlockBuf.getBufferInfo(); boo::IGraphicsBuffer* bufs[] = {uBufInfo.first}; - size_t bufOffs[] = {uBufInfo.second}; + size_t bufOffs[] = {size_t(uBufInfo.second)}; size_t bufSizes[] = {sizeof(ViewBlock)}; if (!res.m_viewRes.m_solidVtxFmt) @@ -426,7 +426,7 @@ void View::VertexBufferBindingTex::init(boo::IGraphicsDataFactory::Context& ctx, auto uBufInfo = viewBlockBuf.getBufferInfo(); boo::IGraphicsBuffer* bufs[] = {uBufInfo.first}; - size_t bufOffs[] = {uBufInfo.second}; + size_t bufOffs[] = {size_t(uBufInfo.second)}; size_t bufSizes[] = {sizeof(ViewBlock)}; boo::ITexture* tex[] = {texture};