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;
|
friend class MultiLineTextView;
|
||||||
static int DoKern(FT_Pos val, const FontAtlas& atlas);
|
static int DoKern(FT_Pos val, const FontAtlas& atlas);
|
||||||
|
|
||||||
|
void _commitResources(size_t capacity);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Resources
|
class Resources
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,21 +56,38 @@ class UniformBufferPool
|
||||||
{
|
{
|
||||||
boo::IGraphicsBufferD* buffer;
|
boo::IGraphicsBufferD* buffer;
|
||||||
uint8_t* cpuBuffer = nullptr;
|
uint8_t* cpuBuffer = nullptr;
|
||||||
|
size_t useCount = 0;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
Bucket() = default;
|
||||||
Bucket(const Bucket& other) = delete;
|
Bucket(const Bucket& other) = delete;
|
||||||
Bucket& operator=(const Bucket& other) = delete;
|
Bucket& operator=(const Bucket& other) = delete;
|
||||||
Bucket(Bucket&& other) = default;
|
Bucket(Bucket&& other) = default;
|
||||||
Bucket& operator=(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()
|
void updateBuffer()
|
||||||
{
|
{
|
||||||
buffer->unmap();
|
buffer->unmap();
|
||||||
cpuBuffer = nullptr;
|
cpuBuffer = nullptr;
|
||||||
dirty = false;
|
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;
|
std::vector<Bucket> m_buckets;
|
||||||
|
|
||||||
|
@ -90,7 +107,7 @@ public:
|
||||||
int idx = freeSpaces.find_first();
|
int idx = freeSpaces.find_first();
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
{
|
||||||
buckets.emplace_back(pool);
|
buckets.emplace_back();
|
||||||
m_index = freeSpaces.size();
|
m_index = freeSpaces.size();
|
||||||
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
||||||
}
|
}
|
||||||
|
@ -100,6 +117,9 @@ public:
|
||||||
}
|
}
|
||||||
freeSpaces.reset(m_index);
|
freeSpaces.reset(m_index);
|
||||||
m_div = pool.getBucketDiv(m_index);
|
m_div = pool.getBucketDiv(m_index);
|
||||||
|
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.increment(m_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -116,7 +136,11 @@ public:
|
||||||
~Token()
|
~Token()
|
||||||
{
|
{
|
||||||
if (m_index != -1)
|
if (m_index != -1)
|
||||||
|
{
|
||||||
m_pool.m_freeBlocks.set(m_index);
|
m_pool.m_freeBlocks.set(m_index);
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.decrement(m_pool);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformStruct& access()
|
UniformStruct& access()
|
||||||
|
|
|
@ -56,21 +56,38 @@ class VertexBufferPool
|
||||||
{
|
{
|
||||||
boo::IGraphicsBufferD* buffer;
|
boo::IGraphicsBufferD* buffer;
|
||||||
uint8_t* cpuBuffer = nullptr;
|
uint8_t* cpuBuffer = nullptr;
|
||||||
|
size_t useCount = 0;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
Bucket() = default;
|
||||||
Bucket(const Bucket& other) = delete;
|
Bucket(const Bucket& other) = delete;
|
||||||
Bucket& operator=(const Bucket& other) = delete;
|
Bucket& operator=(const Bucket& other) = delete;
|
||||||
Bucket(Bucket&& other) = default;
|
Bucket(Bucket&& other) = default;
|
||||||
Bucket& operator=(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()
|
void updateBuffer()
|
||||||
{
|
{
|
||||||
buffer->unmap();
|
buffer->unmap();
|
||||||
cpuBuffer = nullptr;
|
cpuBuffer = nullptr;
|
||||||
dirty = false;
|
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;
|
std::vector<Bucket> m_buckets;
|
||||||
|
|
||||||
|
@ -92,7 +109,7 @@ public:
|
||||||
int idx = freeSpaces.find_first_contiguous(count);
|
int idx = freeSpaces.find_first_contiguous(count);
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
{
|
||||||
buckets.emplace_back(pool);
|
buckets.emplace_back();
|
||||||
m_index = freeSpaces.size();
|
m_index = freeSpaces.size();
|
||||||
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
||||||
}
|
}
|
||||||
|
@ -102,6 +119,9 @@ public:
|
||||||
}
|
}
|
||||||
freeSpaces.reset(m_index, m_index + count);
|
freeSpaces.reset(m_index, m_index + count);
|
||||||
m_div = pool.getBucketDiv(m_index);
|
m_div = pool.getBucketDiv(m_index);
|
||||||
|
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.increment(pool);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Token(const Token& other) = delete;
|
Token(const Token& other) = delete;
|
||||||
|
@ -117,7 +137,11 @@ public:
|
||||||
~Token()
|
~Token()
|
||||||
{
|
{
|
||||||
if (m_index != -1)
|
if (m_index != -1)
|
||||||
|
{
|
||||||
m_pool.m_freeElements.set(m_index, m_index + m_count);
|
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()
|
VertStruct* access()
|
||||||
|
|
|
@ -221,6 +221,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
View(ViewResources& res, View& parentView);
|
View(ViewResources& res, View& parentView);
|
||||||
void buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res);
|
void buildResources(boo::IGraphicsDataFactory::Context& ctx, ViewResources& res);
|
||||||
|
void _commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc);
|
||||||
void commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc);
|
void commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "specter/RootView.hpp"
|
||||||
#include "specter/TextView.hpp"
|
#include "specter/TextView.hpp"
|
||||||
#include "specter/ViewResources.hpp"
|
#include "specter/ViewResources.hpp"
|
||||||
#include "utf8proc.h"
|
#include "utf8proc.h"
|
||||||
|
@ -296,6 +297,66 @@ void TextView::Resources::init(boo::VulkanDataFactory::Context& ctx, FontCache*
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void TextView::_commitResources(size_t capacity)
|
||||||
|
{
|
||||||
|
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 (m_fontAtlas.subpixel())
|
||||||
|
shader = res.m_textRes.m_subpixel;
|
||||||
|
else
|
||||||
|
shader = res.m_textRes.m_regular;
|
||||||
|
|
||||||
|
auto vBufInfo = m_glyphBuf->getBufferInfo();
|
||||||
|
auto uBufInfo = m_viewVertBlockBuf->getBufferInfo();
|
||||||
|
boo::IGraphicsBuffer* uBufs[] = {uBufInfo.first};
|
||||||
|
size_t uBufOffs[] = {size_t(uBufInfo.second)};
|
||||||
|
size_t uBufSizes[] = {sizeof(ViewBlock)};
|
||||||
|
boo::ITexture* texs[] = {m_fontAtlas.texture()};
|
||||||
|
|
||||||
|
if (!res.m_textRes.m_vtxFmt)
|
||||||
|
{
|
||||||
|
boo::VertexElementDescriptor vdescs[] =
|
||||||
|
{
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 0},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 1},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 2},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 3},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
|
||||||
|
{vBufInfo.first, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
||||||
|
};
|
||||||
|
m_vtxFmt = ctx.newVertexFormat(13, vdescs, 0, vBufInfo.second);
|
||||||
|
m_shaderBinding = ctx.newShaderDataBinding(shader, m_vtxFmt,
|
||||||
|
nullptr, vBufInfo.first, nullptr, 1,
|
||||||
|
uBufs, nullptr, uBufOffs, uBufSizes,
|
||||||
|
1, texs, 0, vBufInfo.second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_shaderBinding = ctx.newShaderDataBinding(shader, res.m_textRes.m_vtxFmt,
|
||||||
|
nullptr, vBufInfo.first, nullptr, 1,
|
||||||
|
uBufs, nullptr, uBufOffs, uBufSizes,
|
||||||
|
1, texs, 0, vBufInfo.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
TextView::TextView(ViewResources& res,
|
TextView::TextView(ViewResources& res,
|
||||||
View& parentView, const FontAtlas& font,
|
View& parentView, const FontAtlas& font,
|
||||||
Alignment align, size_t capacity)
|
Alignment align, size_t capacity)
|
||||||
|
@ -308,59 +369,7 @@ TextView::TextView(ViewResources& res,
|
||||||
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]",
|
Log.report(logvisor::Fatal, "bucket overflow [%" PRISize "/%" PRISize "]",
|
||||||
capacity, VertexBufferPool<RenderGlyph>::bucketCapacity());
|
capacity, VertexBufferPool<RenderGlyph>::bucketCapacity());
|
||||||
|
|
||||||
m_glyphs.reserve(capacity);
|
_commitResources(0);
|
||||||
commitResources(res, [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
|
|
||||||
{
|
|
||||||
buildResources(ctx, res);
|
|
||||||
|
|
||||||
m_glyphBuf.emplace(res.m_textRes.m_glyphPool.allocateBlock(res.m_factory, capacity));
|
|
||||||
|
|
||||||
boo::IShaderPipeline* shader;
|
|
||||||
if (font.subpixel())
|
|
||||||
shader = res.m_textRes.m_subpixel;
|
|
||||||
else
|
|
||||||
shader = res.m_textRes.m_regular;
|
|
||||||
|
|
||||||
auto vBufInfo = m_glyphBuf->getBufferInfo();
|
|
||||||
auto uBufInfo = m_viewVertBlockBuf->getBufferInfo();
|
|
||||||
boo::IGraphicsBuffer* uBufs[] = {uBufInfo.first};
|
|
||||||
size_t uBufOffs[] = {size_t(uBufInfo.second)};
|
|
||||||
size_t uBufSizes[] = {sizeof(ViewBlock)};
|
|
||||||
boo::ITexture* texs[] = {m_fontAtlas.texture()};
|
|
||||||
|
|
||||||
if (!res.m_textRes.m_vtxFmt)
|
|
||||||
{
|
|
||||||
boo::VertexElementDescriptor vdescs[] =
|
|
||||||
{
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 0},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 1},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 2},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::ModelView | boo::VertexSemantic::Instanced, 3},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
|
|
||||||
{vBufInfo.first, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
|
|
||||||
};
|
|
||||||
m_vtxFmt = ctx.newVertexFormat(13, vdescs, 0, vBufInfo.second);
|
|
||||||
m_shaderBinding = ctx.newShaderDataBinding(shader, m_vtxFmt,
|
|
||||||
nullptr, vBufInfo.first, nullptr, 1,
|
|
||||||
uBufs, nullptr, uBufOffs, uBufSizes,
|
|
||||||
1, texs, 0, vBufInfo.second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_shaderBinding = ctx.newShaderDataBinding(shader, res.m_textRes.m_vtxFmt,
|
|
||||||
nullptr, vBufInfo.first, nullptr, 1,
|
|
||||||
uBufs, nullptr, uBufOffs, uBufSizes,
|
|
||||||
1, texs, 0, vBufInfo.second);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity)
|
TextView::TextView(ViewResources& res, View& parentView, FontTag font, Alignment align, size_t capacity)
|
||||||
|
@ -398,43 +407,44 @@ int TextView::DoKern(FT_Pos val, const FontAtlas& atlas)
|
||||||
|
|
||||||
void TextView::typesetGlyphs(const std::string& str, const zeus::CColor& defaultColor)
|
void TextView::typesetGlyphs(const std::string& str, const zeus::CColor& defaultColor)
|
||||||
{
|
{
|
||||||
size_t rem = str.size();
|
UTF8Iterator it(str.begin());
|
||||||
const utf8proc_uint8_t* it = reinterpret_cast<const utf8proc_uint8_t*>(str.data());
|
size_t charLen = str.size() ? std::min(it.countTo(str.end()), size_t(1024)) : 0;
|
||||||
|
_commitResources(charLen);
|
||||||
|
|
||||||
uint32_t lCh = -1;
|
uint32_t lCh = -1;
|
||||||
m_glyphs.clear();
|
m_glyphs.clear();
|
||||||
m_glyphs.reserve(str.size());
|
m_glyphs.reserve(charLen);
|
||||||
m_glyphInfo.clear();
|
m_glyphInfo.clear();
|
||||||
m_glyphInfo.reserve(str.size());
|
m_glyphInfo.reserve(charLen);
|
||||||
int adv = 0;
|
int adv = 0;
|
||||||
|
|
||||||
while (rem)
|
if (charLen)
|
||||||
{
|
{
|
||||||
utf8proc_int32_t ch;
|
for (; it.iter() < str.end() ; ++it)
|
||||||
utf8proc_ssize_t sz = utf8proc_iterate(it, -1, &ch);
|
|
||||||
if (sz < 0)
|
|
||||||
Log.report(logvisor::Fatal, "invalid UTF-8 char");
|
|
||||||
if (ch == '\n')
|
|
||||||
break;
|
|
||||||
|
|
||||||
const FontAtlas::Glyph* glyph = m_fontAtlas.lookupGlyph(ch);
|
|
||||||
if (!glyph)
|
|
||||||
{
|
{
|
||||||
rem -= sz;
|
utf8proc_int32_t ch = *it;
|
||||||
it += sz;
|
if (ch == -1)
|
||||||
continue;
|
{
|
||||||
|
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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lCh != -1)
|
||||||
|
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
|
||||||
|
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
||||||
|
m_glyphInfo.emplace_back(ch, glyph->m_width, glyph->m_height, adv);
|
||||||
|
|
||||||
|
lCh = glyph->m_glyphIdx;
|
||||||
|
|
||||||
|
if (m_glyphs.size() == m_capacity)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lCh != -1)
|
|
||||||
adv += DoKern(m_fontAtlas.lookupKern(lCh, glyph->m_glyphIdx), m_fontAtlas);
|
|
||||||
m_glyphs.emplace_back(adv, *glyph, defaultColor);
|
|
||||||
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)
|
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)
|
void TextView::typesetGlyphs(const std::wstring& str, const zeus::CColor& defaultColor)
|
||||||
{
|
{
|
||||||
|
_commitResources(str.size());
|
||||||
|
|
||||||
uint32_t lCh = -1;
|
uint32_t lCh = -1;
|
||||||
m_glyphs.clear();
|
m_glyphs.clear();
|
||||||
m_glyphs.reserve(str.size());
|
m_glyphs.reserve(str.size());
|
||||||
|
@ -535,10 +547,13 @@ void TextView::colorGlyphsTypeOn(const zeus::CColor& newColor, float startInterv
|
||||||
|
|
||||||
void TextView::invalidateGlyphs()
|
void TextView::invalidateGlyphs()
|
||||||
{
|
{
|
||||||
RenderGlyph* out = m_glyphBuf->access();
|
if (m_glyphBuf)
|
||||||
size_t i = 0;
|
{
|
||||||
for (RenderGlyph& glyph : m_glyphs)
|
RenderGlyph* out = m_glyphBuf->access();
|
||||||
out[i++] = glyph;
|
size_t i = 0;
|
||||||
|
for (RenderGlyph& glyph : m_glyphs)
|
||||||
|
out[i++] = glyph;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextView::think()
|
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)
|
void View::commitResources(ViewResources& res, const boo::FactoryCommitFunc& commitFunc)
|
||||||
{
|
{
|
||||||
if (m_gfxData)
|
if (m_gfxData)
|
||||||
Log.report(logvisor::Fatal, "multiple resource commits not allowed");
|
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,
|
void View::VertexBufferBindingSolid::init(boo::IGraphicsDataFactory::Context& ctx,
|
||||||
ViewResources& res, size_t count,
|
ViewResources& res, size_t count,
|
||||||
const UniformBufferPool<ViewBlock>::Token& viewBlockBuf)
|
const UniformBufferPool<ViewBlock>::Token& viewBlockBuf)
|
||||||
|
|
Loading…
Reference in New Issue