Skip to content

Commit

Permalink
working on font system
Browse files Browse the repository at this point in the history
  • Loading branch information
Kbz-8 committed Dec 12, 2023
1 parent 6ccf2a1 commit d56b224
Show file tree
Hide file tree
Showing 11 changed files with 328 additions and 87 deletions.
83 changes: 83 additions & 0 deletions 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_library.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */
/* Updated: 2023/12/12 22:47:33 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */

#include <renderer/text_library.h>
#include <core/errors.h>
#include <renderer/renderer.h>
#include <algorithm>

namespace mlx
{
void TextData::init(std::string text, Font const* font, std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data)
{
_text = std::move(text);
_font = font;
#ifdef DEBUG
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
_vbo[i].create(sizeof(Vertex) * vbo_data.size(), static_cast<const void*>(vbo_data.data()), _text.c_str());
_ibo.create(sizeof(uint16_t) * ibo_data.size(), ibo_data.data(), _text.c_str());
#else
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
_vbo[i].create(sizeof(Vertex) * vbo_data.size(), static_cast<const void*>(vbo_data.data()), nullptr);
_ibo.create(sizeof(uint16_t) * ibo_data.size(), ibo_data.data(), nullptr);
#endif
}

void TextData::bind(Renderer& renderer) noexcept
{
_vbo[renderer.getActiveImageIndex()].bind(renderer);
_ibo.bind(renderer);
}

void TextData::destroy() noexcept
{
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
_vbo[i].destroy();
_ibo.destroy();
}

std::shared_ptr<TextData> TextLibrary::getTextData(TextID id)
{
if(!_cache.count(id))
core::error::report(e_kind::fatal_error, "Text Library : wrong text ID '%d'", id);
return _cache[id];
}

TextID TextLibrary::addTextToLibrary(std::shared_ptr<TextData> text)
{
auto it = std::find_if(_cache.begin(), _cache.end(), [=](const std::pair<TextID, std::shared_ptr<TextData>>& v)
{
return v.second->getText() == text->getText();
});
if(it != _cache.end())
return it->first;
_cache[_current_id] = text;
_current_id++;
return _current_id - 1;
}

void TextLibrary::removeTextFromLibrary(TextID id)
{
if(_cache.count(id))
{
_cache[id]->destroy();
_cache.erase(id);
}
}

void TextLibrary::clearLibrary()
{
for(auto [id, text] : _cache)
text->destroy();
_cache.clear();
}
}
53 changes: 35 additions & 18 deletions src/renderer/buffers/vk_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:55:57 by maldavid #+# #+# */
/* Updated: 2023/12/10 23:05:14 by kbz_8 ### ########.fr */
/* Updated: 2023/12/12 22:11:47 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */

Expand All @@ -23,9 +23,9 @@ namespace mlx
void Buffer::create(Buffer::kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data)
{
_usage = usage;
if(type == Buffer::kind::constant)
if(type == Buffer::kind::constant || type == Buffer::kind::dynamic_device_local)
{
if(data == nullptr)
if(data == nullptr && type == Buffer::kind::constant)
{
core::error::report(e_kind::warning, "Vulkan : trying to create constant buffer without data (constant buffers cannot be modified after creation)");
return;
Expand All @@ -45,7 +45,7 @@ namespace mlx
mapMem(&mapped);
std::memcpy(mapped, data, size);
unmapMem();
if(type == Buffer::kind::constant)
if(type == Buffer::kind::constant || type == Buffer::kind::dynamic_device_local)
pushToGPU();
}
}
Expand Down Expand Up @@ -83,20 +83,20 @@ namespace mlx
_size = size;
}

void Buffer::pushToGPU() noexcept
bool Buffer::copyFromBuffer(const Buffer& buffer) noexcept
{
VmaAllocationCreateInfo alloc_info{};
alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;

Buffer newBuffer;
newBuffer._usage = (_usage & 0xFFFFFFFC) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
#ifdef DEBUG
std::string new_name = _name + "_GPU";
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, new_name.c_str());
#else
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, nullptr);
#endif
if(!(_usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT))
{
core::error::report(e_kind::error, "Vulkan : buffer cannot be the destination of a copy because it does not have the correct usage flag");
return false;
}
if(!(buffer._usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT))
{
core::error::report(e_kind::error, "Vulkan : buffer cannot be the source of a copy because it does not have the correct usage flag");
return false;
}

// TODO, use global cmd buffer pool to manage resources
CmdPool cmdpool;
cmdpool.init();
CmdBuffer cmdBuffer;
Expand All @@ -106,16 +106,33 @@ namespace mlx

VkBufferCopy copyRegion{};
copyRegion.size = _size;
vkCmdCopyBuffer(cmdBuffer.get(), _buffer, newBuffer._buffer, 1, &copyRegion);
vkCmdCopyBuffer(cmdBuffer.get(), buffer._buffer, _buffer, 1, &copyRegion);

cmdBuffer.endRecord();
cmdBuffer.submitIdle();

cmdBuffer.destroy();
cmdpool.destroy();

this->swap(newBuffer);
return true;
}

void Buffer::pushToGPU() noexcept
{
VmaAllocationCreateInfo alloc_info{};
alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;

Buffer newBuffer;
newBuffer._usage = (_usage & 0xFFFFFFFC) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
#ifdef DEBUG
std::string new_name = _name + "_GPU";
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, new_name.c_str());
#else
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, nullptr);
#endif

if(newBuffer.copyFromBuffer(*this)) // if the copy succeded we swap the buffers, else the new one is deleted
this->swap(newBuffer);
newBuffer.destroy();
}

Expand Down
5 changes: 3 additions & 2 deletions src/renderer/buffers/vk_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 23:18:52 by maldavid #+# #+# */
/* Updated: 2023/12/11 19:47:39 by kbz_8 ### ########.fr */
/* Updated: 2023/12/12 21:12:44 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */

Expand All @@ -22,7 +22,7 @@ namespace mlx
class Buffer
{
public:
enum class kind { dynamic, uniform, constant };
enum class kind { dynamic, dynamic_device_local, uniform, constant };

void create(kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data = nullptr);
void destroy() noexcept;
Expand All @@ -32,6 +32,7 @@ namespace mlx
inline void unmapMem() noexcept { Render_Core::get().getAllocator().unmapMemory(_allocation); _is_mapped = false; }

void flush(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0);
bool copyFromBuffer(const Buffer& buffer) noexcept;

inline VkBuffer& operator()() noexcept { return _buffer; }
inline VkBuffer& get() noexcept { return _buffer; }
Expand Down
26 changes: 25 additions & 1 deletion src/renderer/buffers/vk_vbo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:28:08 by maldavid #+# #+# */
/* Updated: 2023/11/10 08:33:52 by maldavid ### ########.fr */
/* Updated: 2023/12/12 22:17:14 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */

Expand All @@ -18,7 +18,10 @@ namespace mlx
void VBO::setData(uint32_t size, const void* data)
{
if(size > getSize())
{
core::error::report(e_kind::error, "Vulkan : trying to store to much data in a vertex buffer (%d bytes in %d bytes)", size, getSize());
return;
}

if(data == nullptr)
core::error::report(e_kind::warning, "Vulkan : mapping null data in a vertex buffer");
Expand All @@ -28,4 +31,25 @@ namespace mlx
std::memcpy(temp, data, static_cast<size_t>(size));
unmapMem();
}

void D_VBO::setData(uint32_t size, const void* data)
{
if(size > getSize())
{
core::error::report(e_kind::error, "Vulkan : trying to store to much data in a vertex buffer (%d bytes in %d bytes)", size, getSize());
return;
}

if(data == nullptr)
core::error::report(e_kind::warning, "Vulkan : mapping null data in a vertex buffer");

Buffer tmp_buf;
#ifdef DEBUG
tmp_buf.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, "tmp_buffer", data);
#else
tmp_buf.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, nullptr, data);
#endif
copyFromBuffer(tmp_buf);
tmp_buf.destroy();
}
}
12 changes: 10 additions & 2 deletions src/renderer/buffers/vk_vbo.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:27:38 by maldavid #+# #+# */
/* Updated: 2023/12/08 19:06:45 by kbz_8 ### ########.fr */
/* Updated: 2023/12/12 22:46:21 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */

Expand All @@ -22,7 +22,15 @@ namespace mlx
class VBO : public Buffer
{
public:
inline void create(uint32_t size, const char* name) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name); }
inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); }
void setData(uint32_t size, const void* data);
inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); }
};

class D_VBO : public Buffer
{
public:
inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::dynamic_device_local, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); }
void setData(uint32_t size, const void* data);
inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); }
};
Expand Down
84 changes: 84 additions & 0 deletions src/renderer/font.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* font.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/11 22:06:09 by kbz_8 #+# #+# */
/* Updated: 2023/12/12 23:57:53 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */

#include <renderer/font.h>
#include <renderer/renderer.h>
#include <fstream>

constexpr const int RANGE = 1024;

namespace mlx
{
Font::Font(Renderer& renderer, const std::filesystem::path& path, float scale) : non_copyable(), _name(path.string())
{
std::vector<uint8_t> tmp_bitmap(RANGE * RANGE);
std::vector<uint8_t> vulkan_bitmap(RANGE * RANGE * 4);

std::ifstream file(path, std::ios::binary);
if(!file.is_open())
{
core::error::report(e_kind::error, "Font load : cannot open font file, %s", _name.c_str());
return;
}
std::ifstream::pos_type fileSize = std::filesystem::file_size(path);
file.seekg(0, std::ios::beg);
std::vector<uint8_t> bytes(fileSize);
file.read(reinterpret_cast<char*>(bytes.data()), fileSize);
file.close();

stbtt_pack_context pc;
stbtt_PackBegin(&pc, tmp_bitmap.data(), RANGE, RANGE, RANGE, 1, nullptr);
stbtt_PackFontRange(&pc, bytes.data(), 0, scale, 32, 96, _cdata.data());
stbtt_PackEnd(&pc);
for(int i = 0, j = 0; i < RANGE * RANGE; i++, j += 4)
{
vulkan_bitmap[j + 0] = tmp_bitmap[i];
vulkan_bitmap[j + 1] = tmp_bitmap[i];
vulkan_bitmap[j + 2] = tmp_bitmap[i];
vulkan_bitmap[j + 3] = tmp_bitmap[i];
}
#ifdef DEBUG
_atlas.create(vulkan_bitmap.data(), RANGE, RANGE, VK_FORMAT_R8G8B8A8_UNORM, std::string(name + "_font_altas").c_str(), true);
#else
_atlas.create(vulkan_bitmap.data(), RANGE, RANGE, VK_FORMAT_R8G8B8A8_UNORM, nullptr, true);
#endif
_atlas.setDescriptor(renderer.getFragDescriptorSet().duplicate());
}

Font::Font(class Renderer& renderer, const std::string& name, const std::vector<uint8_t>& ttf_data, float scale)
{
std::vector<uint8_t> tmp_bitmap(RANGE * RANGE);
std::vector<uint8_t> vulkan_bitmap(RANGE * RANGE * 4);
stbtt_pack_context pc;
stbtt_PackBegin(&pc, tmp_bitmap.data(), RANGE, RANGE, RANGE, 1, nullptr);
stbtt_PackFontRange(&pc, ttf_data.data(), 0, 6.0, 32, 96, _cdata.data());
stbtt_PackEnd(&pc);
for(int i = 0, j = 0; i < RANGE * RANGE; i++, j += 4)
{
vulkan_bitmap[j + 0] = tmp_bitmap[i];
vulkan_bitmap[j + 1] = tmp_bitmap[i];
vulkan_bitmap[j + 2] = tmp_bitmap[i];
vulkan_bitmap[j + 3] = tmp_bitmap[i];
}
#ifdef DEBUG
_atlas.create(vulkan_bitmap.data(), RANGE, RANGE, VK_FORMAT_R8G8B8A8_UNORM, std::string(name + "_font_altas").c_str(), true);
#else
_atlas.create(vulkan_bitmap.data(), RANGE, RANGE, VK_FORMAT_R8G8B8A8_UNORM, nullptr, true);
#endif
_atlas.setDescriptor(renderer.getFragDescriptorSet().duplicate());
}

Font::~Font()
{
_atlas.destroy();
}
}
Loading

0 comments on commit d56b224

Please sign in to comment.