Buffer pool intrinsic garbage collection

This commit is contained in:
Jack Andersen 2016-12-10 20:17:49 -10:00
parent 0384119bd4
commit db542135df
6 changed files with 168 additions and 98 deletions

View File

@ -54,6 +54,8 @@ private:
friend class MultiLineTextView;
static int DoKern(FT_Pos val, const FontAtlas& atlas);
void _commitResources(size_t capacity);
public:
class Resources
{

View File

@ -56,21 +56,38 @@ class UniformBufferPool
{
boo::IGraphicsBufferD* buffer;
uint8_t* cpuBuffer = nullptr;
size_t useCount = 0;
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(UniformBufferPool& pool)
{
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform, pool.m_stride, pool.m_countPerBucket);
}
void updateBuffer()
{
buffer->unmap();
cpuBuffer = nullptr;
dirty = false;
}
void increment(UniformBufferPool& pool)
{
if (!useCount)
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform,
pool.m_stride, pool.m_countPerBucket);
++useCount;
}
void decrement(UniformBufferPool& pool)
{
--useCount;
if (!useCount)
{
pool.m_token.deletePoolBuffer(buffer);
buffer = nullptr;
}
}
};
std::vector<Bucket> m_buckets;
@ -90,7 +107,7 @@ public:
int idx = freeSpaces.find_first();
if (idx == -1)
{
buckets.emplace_back(pool);
buckets.emplace_back();
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
}
@ -100,6 +117,9 @@ public:
}
freeSpaces.reset(m_index);
m_div = pool.getBucketDiv(m_index);
Bucket& bucket = m_pool.m_buckets[m_div.quot];
bucket.increment(m_pool);
}
public:
@ -116,7 +136,11 @@ public:
~Token()
{
if (m_index != -1)
{
m_pool.m_freeBlocks.set(m_index);
Bucket& bucket = m_pool.m_buckets[m_div.quot];
bucket.decrement(m_pool);
}
}
UniformStruct& access()

View File

@ -56,21 +56,38 @@ class VertexBufferPool
{
boo::IGraphicsBufferD* buffer;
uint8_t* cpuBuffer = nullptr;
size_t useCount = 0;
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(VertexBufferPool& pool)
{
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex, pool.m_stride, pool.m_countPerBucket);
}
void updateBuffer()
{
buffer->unmap();
cpuBuffer = nullptr;
dirty = false;
}
void increment(VertexBufferPool& pool)
{
if (!useCount)
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex,
pool.m_stride, pool.m_countPerBucket);
++useCount;
}
void decrement(VertexBufferPool& pool)
{
--useCount;
if (!useCount)
{
pool.m_token.deletePoolBuffer(buffer);
buffer = nullptr;
}
}
};
std::vector<Bucket> m_buckets;
@ -92,7 +109,7 @@ public:
int idx = freeSpaces.find_first_contiguous(count);
if (idx == -1)
{
buckets.emplace_back(pool);
buckets.emplace_back();
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
}
@ -102,6 +119,9 @@ public:
}
freeSpaces.reset(m_index, m_index + count);
m_div = pool.getBucketDiv(m_index);
Bucket& bucket = m_pool.m_buckets[m_div.quot];
bucket.increment(pool);
}
public:
Token(const Token& other) = delete;
@ -117,7 +137,11 @@ public:
~Token()
{
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.decrement(m_pool);
}
}
VertStruct* access()

View File

@ -221,6 +221,7 @@ public:
protected:
View(ViewResources& res, View& parentView);
void buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res);
void _commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc);
void commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc);
public:

View File

@ -1,3 +1,4 @@
#include "specter/RootView.hpp"
#include "specter/TextView.hpp"
#include "specter/ViewResources.hpp"
#include "utf8proc.h"
@ -296,27 +297,19 @@ void TextView::Resources::init(boo::VulkanDataFactory::Context& ctx, FontCache*
#endif
TextView::TextView(ViewResources& res,
View& parentView, const FontAtlas& font,
Alignment align, size_t capacity)
: View(res, parentView),
m_capacity(capacity),
m_fontAtlas(font),
m_align(align)
void TextView::_commitResources(size_t capacity)
{
if (size_t(VertexBufferPool<RenderGlyph>::bucketCapacity()) < capacity)
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]",
capacity, VertexBufferPool<RenderGlyph>::bucketCapacity());
m_glyphs.reserve(capacity);
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
auto& res = rootView().viewRes();
View::_commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
buildResources(ctx, res);
if (capacity)
{
m_glyphBuf.emplace(res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity));
boo::IShaderPipeline* shader;
if (font.subpixel())
if (m_fontAtlas.subpixel())
shader = res.m_textRes.m_subpixel;
else
shader = res.m_textRes.m_regular;
@ -359,10 +352,26 @@ TextView::TextView(ViewResources& res,
uBufs, nullptr, uBufOffs, uBufSizes,
1, texs, 0, vBufInfo.second);
}
}
return true;
});
}
TextView::TextView(ViewResources& res,
View& parentView, const FontAtlas& font,
Alignment align, size_t capacity)
: View(res, parentView),
m_capacity(capacity),
m_fontAtlas(font),
m_align(align)
{
if (size_t(VertexBufferPool<RenderGlyph>::bucketCapacity()) < capacity)
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]",
capacity, VertexBufferPool<RenderGlyph>::bucketCapacity());
_commitResources(0);
}
TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity)
: TextView(res, parentView, res.m_textRes.m_fcache->lookupAtlas(font), align, capacity) {}
@ -398,31 +407,33 @@ int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
void TextView::typesetGlyphs(const std::string& str, const zeus::CColor& defaultColor)
{
size_t rem = str.size();
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
UTF8Iterator it(str.begin());
size_t charLen = str.size() ? std::min(it.countTo(str.end()), size_t(1024)) : 0;
_commitResources(charLen);
uint32_t lCh = -1;
m_glyphs.clear();
m_glyphs.reserve(str.size());
m_glyphs.reserve(charLen);
m_glyphInfo.clear();
m_glyphInfo.reserve(str.size());
m_glyphInfo.reserve(charLen);
int adv = 0;
while (rem)
if (charLen)
{
utf8proc_int32_t ch;
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
if (sz < 0)
Log.report(logvisor::Fatal, "invalid UTF-8 char");
if (ch == '\n')
for (; it.iter() < str.end() ; ++it)
{
utf8proc_int32_t ch = *it;
if (ch == -1)
{
Log.report(logvisor::Warning, "invalid UTF-8 char");
break;
}
if (ch == '\n' || ch == '\0')
break;
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
if (!glyph)
{
rem -= sz;
it += sz;
continue;
}
if (lCh != -1)
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
@ -430,12 +441,11 @@ void TextView::typesetGlyphs(const std::string& str, const zeus::CColor& default
m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
lCh = glyph->m_glyphIdx;
rem -= sz;
it += sz;
if (m_glyphs.size() == m_capacity)
break;
}
}
if (m_align == Alignment::Right)
{
@ -467,6 +477,8 @@ void TextView::typesetGlyphs(const std::string& str, const zeus::CColor& default
void TextView::typesetGlyphs(const std::wstring& str, const zeus::CColor& defaultColor)
{
_commitResources(str.size());
uint32_t lCh = -1;
m_glyphs.clear();
m_glyphs.reserve(str.size());
@ -534,12 +546,15 @@ void TextView::colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterv
}
void TextView::invalidateGlyphs()
{
if (m_glyphBuf)
{
RenderGlyph* out = m_glyphBuf->access();
size_t i = 0;
for (RenderGlyph& glyph : m_glyphs)
out[i++] = glyph;
}
}
void TextView::think()
{

View File

@ -373,14 +373,18 @@ void View::draw(boo::IGraphicsCommandQueue* gfxQ)
}
}
void View::_commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc)
{
m_gfxData = res.m_factory->commitTransaction(commitFunc);
}
void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc)
{
if (m_gfxData)
Log.report(logvisor::Fatal, "multiple resource commits not allowed");
m_gfxData = res.m_factory->commitTransaction(commitFunc);
_commitResources(res, commitFunc);
}
void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx,
ViewResources& res, size_t count,
const UniformBufferPool<ViewBlock>::Token& viewBlockBuf)