Séparation entre images et textures pour optimisation
Les images (chargées en RAM) sont séparées des textures (chargées en GPU) dans les dossiers et le gestionnaire de ressources. Le cache d'images est constitué de pointeurs faibles pour ne pas entrer en conflit avec la gestion de mémoire de SFGUI. On évite ainsi de recharger trop souvent les textures, mais on évite aussi des images qui resteraient indéfiniment en mémoire, affichées à l'écran. Ceci évite d'avoir des textures à la fois chargées en RAM et GPU et réduit donc l'impact mémoire inutile. Ceci pourrait résoudre le problème de l'invite "Ne répond pas" qui s'affiche de manière intempestive sans affecter le déroulement du programme.
This commit is contained in:
parent
b8f1ca5634
commit
8ea50f3202
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFGUI/Image.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
@ -18,6 +19,7 @@ private:
|
|||
/**
|
||||
* Chemins vers les différents dossiers de ressources
|
||||
*/
|
||||
boost::filesystem::path images_path;
|
||||
boost::filesystem::path textures_path;
|
||||
boost::filesystem::path fonts_path;
|
||||
boost::filesystem::path levels_path;
|
||||
|
@ -25,7 +27,7 @@ private:
|
|||
|
||||
std::unordered_map<
|
||||
std::string,
|
||||
std::shared_ptr<sf::Image>
|
||||
std::weak_ptr<sfg::Image>
|
||||
> images_cache;
|
||||
|
||||
std::unordered_map<
|
||||
|
@ -55,6 +57,11 @@ public:
|
|||
*/
|
||||
std::vector<boost::filesystem::path> getFiles(boost::filesystem::path path) const;
|
||||
|
||||
/**
|
||||
* Récupère le chemin vers le dossier des images
|
||||
*/
|
||||
const boost::filesystem::path& getImagesPath() const;
|
||||
|
||||
/**
|
||||
* Récupère le chemin vers le dossier des textures
|
||||
*/
|
||||
|
@ -78,9 +85,9 @@ public:
|
|||
/**
|
||||
* Charge l'image dont le chemin est donné en paramètre
|
||||
*/
|
||||
std::shared_ptr<sf::Image> getImage(boost::filesystem::path path);
|
||||
std::shared_ptr<sf::Image> getImage(std::string name);
|
||||
std::shared_ptr<sf::Image> getImage(const char* name);
|
||||
sfg::Image::Ptr getImage(boost::filesystem::path path);
|
||||
sfg::Image::Ptr getImage(std::string name);
|
||||
sfg::Image::Ptr getImage(const char* name);
|
||||
|
||||
/**
|
||||
* Charge l'image dont le chemin est donné en paramètre
|
||||
|
|
|
@ -39,9 +39,7 @@ sfg::Button::Ptr ActionToolbar::createButton(std::string name) {
|
|||
// création d'un bouton avec pour image l'image passée
|
||||
sfg::Button::Ptr button = sfg::Button::Create("");
|
||||
button->SetClass("icon");
|
||||
button->SetImage(sfg::Image::Create(
|
||||
*ResourceManager::get().getImage("toolbar/icon_" + name + ".tga")
|
||||
));
|
||||
button->SetImage(ResourceManager::get().getImage(name + ".tga"));
|
||||
|
||||
return button;
|
||||
}
|
||||
|
|
|
@ -69,9 +69,7 @@ ObjectToolbar::ObjectToolbar() {
|
|||
void ObjectToolbar::addCreator(std::string path, std::function<Object::Ptr()> creator) {
|
||||
// on crée un bouton d'objet correspondant au créateur donné
|
||||
ObjectButton::Ptr button = ObjectButton::Create(
|
||||
sfg::Image::Create(
|
||||
*ResourceManager::get().getImage("toolbar/" + path + ".tga")
|
||||
), creators_group
|
||||
ResourceManager::get().getImage(path + ".tga")
|
||||
);
|
||||
|
||||
creators[button] = creator;
|
||||
|
|
|
@ -11,6 +11,8 @@ const float Manager::GRID = 32;
|
|||
Manager::Manager() : title(sf::String(L"")), previous_time(sf::seconds(0)),
|
||||
previous_state(nullptr) {
|
||||
|
||||
ResourceManager& res = ResourceManager::get();
|
||||
|
||||
// ajout des polices dans le gestionnaire de ressources
|
||||
// de la librairie pour l'interface
|
||||
desktop.GetEngine().GetResourceManager().AddFont(
|
||||
|
@ -28,9 +30,7 @@ Manager::Manager() : title(sf::String(L"")), previous_time(sf::seconds(0)),
|
|||
// chargement du thème de l'interface
|
||||
desktop.LoadThemeFromFile("res/gui.theme");
|
||||
|
||||
// chargement des textures
|
||||
ResourceManager& res = ResourceManager::get();
|
||||
|
||||
// préchargement des textures dans le GPU
|
||||
for (const auto &texture : res.getFiles(res.getTexturesPath())) {
|
||||
res.getTexture(texture);
|
||||
|
||||
|
@ -41,6 +41,15 @@ Manager::Manager() : title(sf::String(L"")), previous_time(sf::seconds(0)),
|
|||
while (window.pollEvent(event)) {}
|
||||
}
|
||||
|
||||
// préchargement des images dans la RAM
|
||||
for (const auto &image : res.getFiles(res.getImagesPath())) {
|
||||
res.getImage(image);
|
||||
|
||||
// mêmes raisons que ci-dessus
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event)) {}
|
||||
}
|
||||
|
||||
// création de la fenêtre du jeu
|
||||
window.create(
|
||||
sf::VideoMode(704, 480), "Skizzle", sf::Style::Default,
|
||||
|
|
|
@ -14,6 +14,7 @@ ResourceManager::ResourceManager() : is_playing(false), is_muted(false) {
|
|||
// mise en mémoire des chemins vers les dossiers de ressources
|
||||
fs::path res_path = fs::current_path() / "res";
|
||||
|
||||
images_path = res_path / "images";
|
||||
textures_path = res_path / "textures";
|
||||
fonts_path = res_path / "fonts";
|
||||
levels_path = res_path / "levels";
|
||||
|
@ -40,6 +41,10 @@ std::vector<fs::path> ResourceManager::getFiles(fs::path path) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
const fs::path& ResourceManager::getImagesPath() const {
|
||||
return images_path;
|
||||
}
|
||||
|
||||
const fs::path& ResourceManager::getTexturesPath() const {
|
||||
return textures_path;
|
||||
}
|
||||
|
@ -56,34 +61,42 @@ const fs::path& ResourceManager::getMusicsPath() const {
|
|||
return musics_path;
|
||||
}
|
||||
|
||||
std::shared_ptr<sf::Image> ResourceManager::getImage(fs::path path) {
|
||||
sfg::Image::Ptr ResourceManager::getImage(fs::path path) {
|
||||
std::string path_str = path.string();
|
||||
|
||||
// si l'image a déjà été chargée, on retourne la
|
||||
// version en cache mémoire
|
||||
if (images_cache.count(path_str) > 0) {
|
||||
return images_cache[path_str];
|
||||
// le cache d'images est constitué de pointeurs "faibles", càd
|
||||
// que dès que la ressource n'est plus utilisée, le pointeur
|
||||
// s'invalide. Ceci parce que SFGUI maintient son propre cache.
|
||||
// on doit donc d'abord vérifier que le pointeur est toujours valide
|
||||
if (!images_cache[path_str].expired()) {
|
||||
return images_cache[path_str].lock();
|
||||
}
|
||||
}
|
||||
|
||||
// on tente de charger l'image depuis son emplacement
|
||||
auto image = std::shared_ptr<sf::Image>(new sf::Image);
|
||||
sf::Image image;
|
||||
|
||||
if (!image->loadFromFile(path_str)) {
|
||||
if (!image.loadFromFile(path_str)) {
|
||||
std::cerr << "Impossible de charger l'image :" << std::endl;
|
||||
std::cerr << path_str << std::endl << std::endl;
|
||||
}
|
||||
|
||||
// on met en cache l'image pour les requêtes suivantes
|
||||
// puis on la renvoie
|
||||
images_cache[path_str] = std::move(image);
|
||||
return images_cache[path_str];
|
||||
// création d'une nouvelle image SFGUI avec les infos chargées
|
||||
// et mise en cache du résultat
|
||||
sfg::Image::Ptr sfg_image = sfg::Image::Create(image);
|
||||
images_cache[path_str] = sfg_image;
|
||||
|
||||
return sfg_image;
|
||||
}
|
||||
|
||||
std::shared_ptr<sf::Image> ResourceManager::getImage(std::string name) {
|
||||
return getImage(textures_path / name);
|
||||
sfg::Image::Ptr ResourceManager::getImage(std::string name) {
|
||||
return getImage(images_path / name);
|
||||
}
|
||||
|
||||
std::shared_ptr<sf::Image> ResourceManager::getImage(const char* name) {
|
||||
sfg::Image::Ptr ResourceManager::getImage(const char* name) {
|
||||
return getImage(std::string(name));
|
||||
}
|
||||
|
||||
|
@ -95,14 +108,11 @@ std::shared_ptr<sf::Texture> ResourceManager::getTexture(fs::path path) {
|
|||
return textures_cache[path_str];
|
||||
}
|
||||
|
||||
// on récupère l'image depuis le disque
|
||||
std::shared_ptr<sf::Image> image = getImage(path);
|
||||
|
||||
// on transfère l'image vers le GPU
|
||||
// on tente de charger la texture depuis le disque vers le GPU
|
||||
auto texture = std::shared_ptr<sf::Texture>(new sf::Texture);
|
||||
texture->setSmooth(true);
|
||||
|
||||
if (!texture->loadFromImage(*image)) {
|
||||
if (!texture->loadFromFile(path_str)) {
|
||||
std::cerr << "Impossible de créer la texture :" << std::endl;
|
||||
std::cerr << path_str << std::endl << std::endl;
|
||||
}
|
||||
|
|
|
@ -282,15 +282,15 @@ void Level::frame() {
|
|||
sf::Vector2i window_size = (sf::Vector2i) window.getSize();
|
||||
|
||||
// mise à jour de l'icône du mute en fonction de l'état
|
||||
sf::Image image;
|
||||
sfg::Image::Ptr image;
|
||||
|
||||
if (ResourceManager::get().isMuted()) {
|
||||
image = *ResourceManager::get().getImage("toolbar/icon_no_music.tga");
|
||||
image = ResourceManager::get().getImage("no_music.tga");
|
||||
} else {
|
||||
image = *ResourceManager::get().getImage("toolbar/icon_music.tga");
|
||||
image = ResourceManager::get().getImage("music.tga");
|
||||
}
|
||||
|
||||
mute_button->SetImage(sfg::Image::Create(image));
|
||||
mute_button->SetImage(image);
|
||||
|
||||
// positionnement de la barre d'actions
|
||||
action_toolbar.getWindow()->SetAllocation(sf::FloatRect(
|
||||
|
|
Loading…
Reference in New Issue