texture cache refactor to later allow async loading
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Has been cancelled
ContinuousDelivery / windows (push) Has been cancelled
ContinuousDelivery / windows-asan (push) Has been cancelled
ContinuousIntegration / linux (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled

This commit is contained in:
Green Sky 2024-12-16 00:32:07 +01:00
parent f2027befc8
commit 11ae259f67
No known key found for this signature in database
9 changed files with 54 additions and 41 deletions

@ -1 +1 @@
Subproject commit 717748e8fc6ecd2170aa98ca442727fb1fe32834
Subproject commit 85bbbb0e5a572b61067f3db188f3cfbda0948e7e

View File

@ -71,27 +71,27 @@ std::optional<TextureEntry> BitsetImageLoader::haveToTexture(TextureUploaderI& t
BitsetImageLoader::BitsetImageLoader(void) {
}
std::optional<TextureEntry> BitsetImageLoader::load(TextureUploaderI& tu, ObjectHandle o) {
TextureLoaderResult BitsetImageLoader::load(TextureUploaderI& tu, ObjectHandle o) {
if (!static_cast<bool>(o)) {
std::cerr << "BIL error: trying to load invalid object\n";
return std::nullopt;
return {std::nullopt};
}
if (!o.any_of<ObjComp::F::LocalHaveBitset, ObjComp::F::RemoteHaveBitset>()) {
// after completion, this is called until the texture times out
//std::cout << "BIL: no local have bitset\n";
return std::nullopt;
return {std::nullopt};
}
if (o.all_of<ObjComp::F::LocalHaveBitset>()) {
auto& have = o.get<ObjComp::F::LocalHaveBitset>().have;
assert(have.size_bits() > 0);
return haveToTexture(tu, have, o);
return {haveToTexture(tu, have, o)};
} else if (o.all_of<ObjComp::F::RemoteHaveBitset>()) {
auto& list = o.get<ObjComp::F::RemoteHaveBitset>().others;
if (list.empty()) {
std::cout << "BIL: remote set list empty\n";
return std::nullopt;
return {std::nullopt};
}
const auto& first_entry = list.begin()->second;
@ -115,10 +115,10 @@ std::optional<TextureEntry> BitsetImageLoader::load(TextureUploaderI& tu, Object
}
}
return haveToTexture(tu, _tmp_bitset, o);
return {haveToTexture(tu, _tmp_bitset, o)};
}
return std::nullopt;
return {std::nullopt};
}
std::optional<TextureEntry> BitsetImageLoader::load(TextureUploaderI& tu, ObjectContactSub ocs) {

View File

@ -30,7 +30,7 @@ class BitsetImageLoader {
public:
BitsetImageLoader(void);
std::optional<TextureEntry> load(TextureUploaderI& tu, ObjectHandle o);
TextureLoaderResult load(TextureUploaderI& tu, ObjectHandle o);
std::optional<TextureEntry> load(TextureUploaderI& tu, ObjectContactSub ocs);
};

View File

@ -30,29 +30,29 @@ MessageImageLoader::MessageImageLoader(void) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLImage>());
}
std::optional<TextureEntry> MessageImageLoader::load(TextureUploaderI& tu, Message3Handle m) {
TextureLoaderResult MessageImageLoader::load(TextureUploaderI& tu, Message3Handle m) {
if (!static_cast<bool>(m)) {
return std::nullopt;
return {std::nullopt};
}
if (m.all_of<Message::Components::TagNotImage>()) {
return std::nullopt;
return {std::nullopt};
}
if (!m.all_of<Message::Components::MessageFileObject>()) {
// not a file message
return std::nullopt;
return {std::nullopt};
}
const auto& o = m.get<Message::Components::MessageFileObject>().o;
if (!static_cast<bool>(o)) {
std::cerr << "MIL error: invalid object in file message\n";
return std::nullopt;
return {std::nullopt};
}
if (!o.all_of<ObjComp::Ephemeral::Backend, ObjComp::F::SingleInfo>()) {
std::cerr << "MIL error: object missing backend (?)\n";
return std::nullopt;
return {std::nullopt};
}
// TODO: handle collections
@ -60,40 +60,40 @@ std::optional<TextureEntry> MessageImageLoader::load(TextureUploaderI& tu, Messa
if (file_size > 50*1024*1024) {
std::cerr << "MIL error: image file too large\n";
return std::nullopt;
return {std::nullopt};
}
if (file_size == 0) {
std::cerr << "MIL warning: empty file\n";
return std::nullopt;
return {std::nullopt};
}
if (!o.all_of<ObjComp::F::TagLocalHaveAll>()) {
// not ready yet
return std::nullopt;
return {std::nullopt};
}
auto* file_backend = o.get<ObjComp::Ephemeral::Backend>().ptr;
if (file_backend == nullptr) {
std::cerr << "MIL error: object backend nullptr\n";
return std::nullopt;
return {std::nullopt};
}
auto file2 = file_backend->file2(o, StorageBackendI::FILE2_READ);
if (!file2 || !file2->isGood() || !file2->can_read) {
std::cerr << "MIL error: creating file2 from object via backendI\n";
return std::nullopt;
return {std::nullopt};
}
auto read_data = file2->read(file_size, 0);
if (read_data.ptr == nullptr) {
std::cerr << "MMIL error: reading from file2 returned nullptr\n";
return std::nullopt;
return {std::nullopt};
}
if (read_data.size != file_size) {
std::cerr << "MIL error: reading from file2 size missmatch, should be " << file_size << ", is " << read_data.size << "\n";
return std::nullopt;
return {std::nullopt};
}
// try all loaders after another
@ -107,7 +107,7 @@ std::optional<TextureEntry> MessageImageLoader::load(TextureUploaderI& tu, Messa
new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0;
for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height);
const auto n_t = tu.upload(data.data(), res.width, res.height);
new_entry.textures.push_back(n_t);
new_entry.frame_duration.push_back(ms);
}
@ -117,10 +117,10 @@ std::optional<TextureEntry> MessageImageLoader::load(TextureUploaderI& tu, Messa
std::cout << "MIL: loaded image file o:" << /*file_path*/ entt::to_integral(o.entity()) << "\n";
return new_entry;
return {new_entry};
}
std::cerr << "MIL error: failed to load message (unhandled format)\n";
return std::nullopt;
return {std::nullopt};
}

View File

@ -12,6 +12,6 @@ class MessageImageLoader {
public:
MessageImageLoader(void);
std::optional<TextureEntry> load(TextureUploaderI& tu, Message3Handle m);
TextureLoaderResult load(TextureUploaderI& tu, Message3Handle m);
};

View File

@ -46,7 +46,7 @@ TextureEntry generateTestAnim(TextureUploaderI& tu) {
}
}
const auto n_t = tu.uploadRGBA(pixels.data(), width, height);
const auto n_t = tu.upload(pixels.data(), width, height);
// this is so ugly
new_entry.textures.emplace_back(n_t);

View File

@ -6,6 +6,7 @@
#include <entt/container/dense_set.hpp>
#include <iostream>
#include <optional>
struct TextureEntry {
uint32_t width {0};
@ -70,6 +71,11 @@ struct TextureEntry {
}
};
struct TextureLoaderResult {
std::optional<TextureEntry> texture;
bool keep_trying{false}; // if set, cant be cleared, as some async might be going on
};
TextureEntry generateTestAnim(TextureUploaderI& tu);
// fwd
@ -188,12 +194,12 @@ struct TextureCache {
for (; it != _to_load.end(); it++) {
if (_cache.count(*it)) {
auto new_entry_opt = _l.load(_tu, *it);
if (new_entry_opt.has_value()) {
if (new_entry_opt.texture.has_value()) {
auto old_entry = _cache.at(*it);
for (const auto& tex_id : old_entry.textures) {
_tu.destroy(tex_id);
}
auto [new_it, _] = _cache.insert_or_assign(*it, new_entry_opt.value());
auto [new_it, _] = _cache.insert_or_assign(*it, new_entry_opt.texture.value());
//new_it->second.current_texture = old_entry.current_texture; // ??
new_it->second.rendered_this_frame = old_entry.rendered_this_frame;
new_it->second.timestamp_last_rendered = old_entry.timestamp_last_rendered;
@ -202,15 +208,21 @@ struct TextureCache {
// TODO: not a good idea?
break; // end load from queue/onlyload 1 per update
} else if (!new_entry_opt.keep_trying) {
// failed to load and the loader is done
it = _to_load.erase(it);
}
} else {
auto new_entry_opt = _l.load(_tu, *it);
if (new_entry_opt.has_value()) {
_cache.emplace(*it, new_entry_opt.value());
if (new_entry_opt.texture.has_value()) {
_cache.emplace(*it, new_entry_opt.texture.value());
it = _to_load.erase(it);
// TODO: not a good idea?
break; // end load from queue/onlyload 1 per update
} else if (!new_entry_opt.keep_trying) {
// failed to load and the loader is done
it = _to_load.erase(it);
}
}
}

View File

@ -4,6 +4,7 @@
#include "./image_loader_qoi.hpp"
#include "./image_loader_webp.hpp"
#include "./image_loader_sdl_image.hpp"
#include "texture_uploader.hpp"
#include <solanaceae/contact/components.hpp>
#include <solanaceae/tox_contacts/components.hpp>
@ -119,9 +120,9 @@ static std::vector<uint8_t> generateToxIdenticon(const ToxKey& key) {
return pixels;
}
std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3 c) {
TextureLoaderResult ToxAvatarLoader::load(TextureUploaderI& tu, Contact3 c) {
if (!_cr.valid(c)) {
return std::nullopt;
return {std::nullopt};
}
if (_cr.all_of<Contact::Components::AvatarMemory>(c)) {
@ -134,13 +135,13 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
new_entry.width = a_m.width;
new_entry.height = a_m.height;
const auto n_t = tu.uploadRGBA(a_m.data.data(), a_m.width, a_m.height);
const auto n_t = tu.upload(a_m.data.data(), a_m.width, a_m.height);
new_entry.textures.push_back(n_t);
new_entry.frame_duration.push_back(250);
std::cout << "TAL: loaded memory buffer\n";
return new_entry;
return {new_entry};
}
if (_cr.all_of<Contact::Components::AvatarFile>(c)) {
@ -169,7 +170,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0;
for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height);
const auto n_t = tu.upload(data.data(), res.width, res.height);
new_entry.textures.push_back(n_t);
new_entry.frame_duration.push_back(ms);
}
@ -179,7 +180,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
std::cout << "TAL: loaded image file " << a_f.file_path << "\n";
return new_entry;
return {new_entry};
}
}
} // continues if loading img fails
@ -190,7 +191,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
Contact::Components::ToxGroupPeerPersistent,
Contact::Components::ID
>(c)) {
return std::nullopt;
return {std::nullopt};
}
std::vector<uint8_t> pixels;
@ -212,7 +213,7 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
new_entry.timestamp_last_rendered = Message::getTimeMS();
new_entry.current_texture = 0;
const auto n_t = tu.uploadRGBA(pixels.data(), 5, 5, TextureUploaderI::NEAREST);
const auto n_t = tu.upload(pixels.data(), 5, 5, TextureUploaderI::RGBA, TextureUploaderI::NEAREST);
new_entry.textures.push_back(n_t);
new_entry.frame_duration.push_back(250);
@ -221,6 +222,6 @@ std::optional<TextureEntry> ToxAvatarLoader::load(TextureUploaderI& tu, Contact3
std::cout << "TAL: generated ToxIdenticon\n";
return new_entry;
return {new_entry};
}

View File

@ -14,6 +14,6 @@ class ToxAvatarLoader {
public:
ToxAvatarLoader(Contact3Registry& cr);
std::optional<TextureEntry> load(TextureUploaderI& tu, Contact3 c);
TextureLoaderResult load(TextureUploaderI& tu, Contact3 c);
};