mirror of https://github.com/AxioDL/metaforce.git
Buffer pool intrinsic garbage collection
This commit is contained in:
parent
0384119bd4
commit
db542135df
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue