Make kart textures loading ondemand if needed

This commit is contained in:
Benau 2022-08-13 11:44:06 +08:00
parent e0636495f0
commit f777e01a21
13 changed files with 183 additions and 7 deletions

View File

@ -3,8 +3,10 @@
#include <IVideoDriver.h>
#include <matrix4.h>
#include <cstdint>
#include <string>
#include <unordered_set>
namespace GE
{
@ -14,6 +16,7 @@ struct GEConfig
bool m_disable_npot_texture;
bool m_convert_irrlicht_mesh;
bool m_texture_compression;
std::unordered_set<std::string> m_ondemand_load_texture_paths;
};
void setVideoDriver(irr::video::IVideoDriver* driver);

View File

@ -13,7 +13,12 @@ std::chrono::steady_clock::time_point g_mono_start =
void setVideoDriver(irr::video::IVideoDriver* driver)
{
if (driver != g_driver)
{
// Reset everytime driver is recreated
g_config.m_ondemand_load_texture_paths.clear();
g_driver = driver;
}
}
irr::video::IVideoDriver* getDriver()

View File

@ -43,6 +43,8 @@ GEVulkanTexture::GEVulkanTexture(const std::string& path,
return;
}
auto& paths = getGEConfig()->m_ondemand_load_texture_paths;
m_ondemand_load = (paths.find(m_full_path.c_str()) != paths.end());
if (m_ondemand_load)
{
video::IImageLoader* loader = NULL;

View File

@ -214,6 +214,10 @@ public:
return getImageViewLive();
}
// ------------------------------------------------------------------------
virtual bool useOnDemandLoad() const { return m_ondemand_load; }
// ------------------------------------------------------------------------
virtual const io::path& getFullPath() const { return m_full_path; }
// ------------------------------------------------------------------------
VkFormat getInternalFormat() const { return m_internal_format; }
}; // GEVulkanTexture

View File

@ -204,6 +204,10 @@ public:
virtual void reload() {}
virtual bool loadingFailed() const { return LoadingFailed; }
virtual bool useOnDemandLoad() const { return false; }
virtual const io::path& getFullPath() const { return NamedPath.getPath(); }
protected:
//! Helper function, helps to get the desired texture creation format from the flags.

View File

@ -1132,6 +1132,8 @@ void IrrDriver::applyResolutionSettings(bool recreate_device)
kart_properties_manager->loadAllKarts();
kart_properties_manager->onDemandLoadKartTextures(
{ UserConfigParams::m_default_kart }, false/*unload_unused*/);
attachment_manager->loadModels();
file_manager->popTextureSearchPath();

View File

@ -119,6 +119,9 @@ public:
return getTexture(filename, std::string(error_message),
std::string(detail));
} // getTexture
// ------------------------------------------------------------------------
std::unordered_map<std::string, irr::video::ITexture*>& getAllTextures()
{ return m_all_textures; }
}; // STKTexManager

View File

@ -47,6 +47,9 @@
#include <stdexcept>
#include <string>
#ifndef SERVER_ONLY
#include <ge_main.hpp>
#endif
float KartProperties::UNDEFINED = -99.9f;
@ -116,13 +119,28 @@ KartProperties::KartProperties(const std::string &filename)
KartProperties::~KartProperties()
{
#ifndef SERVER_ONLY
if (CVS->isGLSL() && m_kart_model.use_count() == 1)
if (m_kart_model.use_count() == 1)
{
if (CVS->isGLSL())
{
m_kart_model = nullptr;
SP::SPShaderManager::get()->removeUnusedShaders();
ShaderFilesManager::getInstance()->removeUnusedShaderFiles();
SP::SPTextureManager::get()->removeUnusedTextures();
}
if (GE::getDriver()->getDriverType() != video::EDT_VULKAN)
return;
auto& paths = GE::getGEConfig()->m_ondemand_load_texture_paths;
auto it = paths.begin();
while (it != paths.end())
{
if (StringUtils::startsWith(*it, m_root_absolute_path))
it = paths.erase(it);
else
it++;
}
}
#endif
} // ~KartProperties
@ -176,6 +194,33 @@ void KartProperties::copyFrom(const KartProperties *source)
}
} // copyFrom
//-----------------------------------------------------------------------------
void KartProperties::handleOnDemandLoadTexture()
{
#ifndef SERVER_ONLY
if (GE::getDriver()->getDriverType() != video::EDT_VULKAN)
return;
std::set<std::string> files;
// Remove the last /
m_root_absolute_path = StringUtils::getPath(m_root);
m_root_absolute_path = file_manager->getFileSystem()
->getAbsolutePath(m_root_absolute_path.c_str()).c_str();
file_manager->listFiles(files, m_root_absolute_path,
true/*make_full_path*/);
std::set<std::string> image_extensions =
{
"png", "jpg", "jpeg", "jpe", "svg"
};
for (const std::string& f : files)
{
if (image_extensions.find(StringUtils::getExtension(f)) !=
image_extensions.end())
GE::getGEConfig()->m_ondemand_load_texture_paths.insert(f);
}
#endif
} // handleOnDemandLoadTexture
//-----------------------------------------------------------------------------
/** Loads the kart properties from a file.
* \param filename Filename to load.
@ -220,6 +265,7 @@ void KartProperties::load(const std::string &filename, const std::string &node)
m_is_addon = true;
}
handleOnDemandLoadTexture();
try
{
if(!root || root->getName()!="kart")

View File

@ -60,7 +60,7 @@ class KartProperties
{
private:
/** Base directory for this kart. */
std::string m_root;
std::string m_root, m_root_absolute_path;
/** AI Properties for this kart, as a separate object in order to
* reduce dependencies (and therefore compile time) when changing
@ -209,6 +209,8 @@ private:
// closely (+-0,1%) with the specifications in kart_characteristics.xml
m_wheel_base = fabsf(kart_length / 1.425f);
}
void handleOnDemandLoadTexture();
public:
/** Returns the string representation of a handicap level. */
static std::string getHandicapAsString(HandicapLevel h);

View File

@ -38,6 +38,12 @@
#include <stdexcept>
#include <iostream>
#ifndef SERVER_ONLY
#include <ge_main.hpp>
#include <ge_vulkan_driver.hpp>
#include "graphics/stk_tex_manager.hpp"
#endif
KartPropertiesManager *kart_properties_manager=0;
std::vector<std::string> KartPropertiesManager::m_kart_search_path;
@ -611,4 +617,83 @@ void KartPropertiesManager::getRandomKartList(int count,
assert(count==0);
} // getRandomKartList
//-----------------------------------------------------------------------------
void KartPropertiesManager::onDemandLoadKartTextures(
const std::set<std::string>& kart_list,
bool unload_unused)
{
#ifndef SERVER_ONLY
if (kart_list.empty())
return;
GE::GEVulkanDriver* gevd = GE::getVKDriver();
if (!gevd)
return;
gevd->waitIdle();
gevd->setDisableWaitIdle(true);
std::set<std::string> karts_folder;
for (auto& dir : m_kart_search_path)
{
std::string kart_dir = file_manager->getFileSystem()
->getAbsolutePath(dir.c_str()).c_str();
karts_folder.insert(StringUtils::getPath(kart_dir));
}
std::set<std::string> ingame_karts_folder;
for (auto& kart : kart_list)
{
const KartProperties* kp = getKart(kart);
if (!kp)
continue;
std::string kart_dir = file_manager->getFileSystem()
->getAbsolutePath(kp->getKartDir().c_str()).c_str();
ingame_karts_folder.insert(StringUtils::getPath(kart_dir));
}
bool unloaded_unused = false;
for (auto tex : STKTexManager::getInstance()->getAllTextures())
{
if (!tex.second || !tex.second->useOnDemandLoad())
continue;
std::string full_path = tex.second->getFullPath().c_str();
bool is_kart_texture = false;
bool in_use = false;
for (auto& dir : karts_folder)
{
if (StringUtils::startsWith(full_path, dir))
{
is_kart_texture = true;
break;
}
}
if (is_kart_texture)
{
for (auto& dir : ingame_karts_folder)
{
if (StringUtils::startsWith(full_path, dir))
{
in_use = true;
break;
}
}
}
// This will load the ondemand kart textures now or unload the unused
// kart textures
if (in_use)
tex.second->getTextureHandler();
else if (unload_unused)
{
unloaded_unused = true;
tex.second->reload();
}
}
gevd->setDisableWaitIdle(false);
if (unloaded_unused)
gevd->handleDeletedTextures();
#endif
} // onDemandLoadKartTextures
/* EOF */

View File

@ -23,6 +23,7 @@
#include "utils/ptr_vector.hpp"
#include <map>
#include <memory>
#include <set>
#include "network/remote_kart_info.hpp"
#include "utils/no_copy.hpp"
@ -137,6 +138,9 @@ public:
const unsigned int getNumberOfKarts() const {
return (unsigned int)m_karts_properties.size();
} // getNumberOfKarts
// ------------------------------------------------------------------------
void onDemandLoadKartTextures(const std::set<std::string>& kart_list,
bool unload_unused = true);
};
extern KartPropertiesManager *kart_properties_manager;

View File

@ -2282,6 +2282,8 @@ int main(int argc, char *argv[])
GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI_ICON,
"options_video.png"));
kart_properties_manager -> loadAllKarts ();
kart_properties_manager->onDemandLoadKartTextures(
{ UserConfigParams::m_default_kart }, false/*unload_unused*/);
OfficialKarts::load();
handleXmasMode();
handleEasterEarMode();

View File

@ -449,6 +449,12 @@ void RaceManager::startNew(bool from_overworld)
Log::verbose("RaceManager", "Nb of karts=%u, ghost karts:%u ai:%lu players:%lu\n",
(unsigned int) m_num_karts, m_num_ghost_karts, m_ai_kart_list.size(), m_player_karts.size());
std::set<std::string> used_karts;
for (auto& kart : m_ai_kart_list)
used_karts.insert(kart);
for (auto& kart : m_player_karts)
used_karts.insert(kart.getKartName());
kart_properties_manager->onDemandLoadKartTextures(used_karts);
assert((unsigned int)m_num_karts == m_num_ghost_karts+m_ai_kart_list.size()+m_player_karts.size());
@ -979,6 +985,7 @@ void RaceManager::exitRace(bool delete_world)
setNumKarts(0);
setNumPlayers(0);
std::set<std::string> used_karts;
if (some_human_player_well_ranked)
{
startSingleRace("gpwin", 999,
@ -987,6 +994,9 @@ void RaceManager::exitRace(bool delete_world)
scene->push();
scene->setKarts(winners);
scene->setPlayerWon(some_human_player_won);
std::set<std::string> karts;
for (auto& kart : winners)
used_karts.insert(kart.first);
}
else
{
@ -998,6 +1008,8 @@ void RaceManager::exitRace(bool delete_world)
if (humanLosers.size() >= 1)
{
scene->setKarts(humanLosers);
for (auto& kart : humanLosers)
used_karts.insert(kart.first);
}
else
{
@ -1005,9 +1017,11 @@ void RaceManager::exitRace(bool delete_world)
"This should have never happened\n");
std::vector<std::pair<std::string, float> > karts;
karts.emplace_back(UserConfigParams::m_default_kart, 0.0f);
used_karts.insert(UserConfigParams::m_default_kart);
scene->setKarts(karts);
}
}
kart_properties_manager->onDemandLoadKartTextures(used_karts);
}
if (delete_world)