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/Graphics.hpp>
|
||||||
#include <SFML/Audio.hpp>
|
#include <SFML/Audio.hpp>
|
||||||
|
#include <SFGUI/Image.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -18,6 +19,7 @@ private:
|
||||||
/**
|
/**
|
||||||
* Chemins vers les différents dossiers de ressources
|
* Chemins vers les différents dossiers de ressources
|
||||||
*/
|
*/
|
||||||
|
boost::filesystem::path images_path;
|
||||||
boost::filesystem::path textures_path;
|
boost::filesystem::path textures_path;
|
||||||
boost::filesystem::path fonts_path;
|
boost::filesystem::path fonts_path;
|
||||||
boost::filesystem::path levels_path;
|
boost::filesystem::path levels_path;
|
||||||
|
@ -25,7 +27,7 @@ private:
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
std::string,
|
std::string,
|
||||||
std::shared_ptr<sf::Image>
|
std::weak_ptr<sfg::Image>
|
||||||
> images_cache;
|
> images_cache;
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
|
@ -55,6 +57,11 @@ public:
|
||||||
*/
|
*/
|
||||||
std::vector<boost::filesystem::path> getFiles(boost::filesystem::path path) const;
|
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
|
* 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
|
* Charge l'image dont le chemin est donné en paramètre
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<sf::Image> getImage(boost::filesystem::path path);
|
sfg::Image::Ptr getImage(boost::filesystem::path path);
|
||||||
std::shared_ptr<sf::Image> getImage(std::string name);
|
sfg::Image::Ptr getImage(std::string name);
|
||||||
std::shared_ptr<sf::Image> getImage(const char* name);
|
sfg::Image::Ptr getImage(const char* name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Charge l'image dont le chemin est donné en paramètre
|
* 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
|
// création d'un bouton avec pour image l'image passée
|
||||||
sfg::Button::Ptr button = sfg::Button::Create("");
|
sfg::Button::Ptr button = sfg::Button::Create("");
|
||||||
button->SetClass("icon");
|
button->SetClass("icon");
|
||||||
button->SetImage(sfg::Image::Create(
|
button->SetImage(ResourceManager::get().getImage(name + ".tga"));
|
||||||
*ResourceManager::get().getImage("toolbar/icon_" + name + ".tga")
|
|
||||||
));
|
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,7 @@ ObjectToolbar::ObjectToolbar() {
|
||||||
void ObjectToolbar::addCreator(std::string path, std::function<Object::Ptr()> creator) {
|
void ObjectToolbar::addCreator(std::string path, std::function<Object::Ptr()> creator) {
|
||||||
// on crée un bouton d'objet correspondant au créateur donné
|
// on crée un bouton d'objet correspondant au créateur donné
|
||||||
ObjectButton::Ptr button = ObjectButton::Create(
|
ObjectButton::Ptr button = ObjectButton::Create(
|
||||||
sfg::Image::Create(
|
ResourceManager::get().getImage(path + ".tga")
|
||||||
*ResourceManager::get().getImage("toolbar/" + path + ".tga")
|
|
||||||
), creators_group
|
|
||||||
);
|
);
|
||||||
|
|
||||||
creators[button] = creator;
|
creators[button] = creator;
|
||||||
|
|
|
@ -11,6 +11,8 @@ const float Manager::GRID = 32;
|
||||||
Manager::Manager() : title(sf::String(L"")), previous_time(sf::seconds(0)),
|
Manager::Manager() : title(sf::String(L"")), previous_time(sf::seconds(0)),
|
||||||
previous_state(nullptr) {
|
previous_state(nullptr) {
|
||||||
|
|
||||||
|
ResourceManager& res = ResourceManager::get();
|
||||||
|
|
||||||
// ajout des polices dans le gestionnaire de ressources
|
// ajout des polices dans le gestionnaire de ressources
|
||||||
// de la librairie pour l'interface
|
// de la librairie pour l'interface
|
||||||
desktop.GetEngine().GetResourceManager().AddFont(
|
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
|
// chargement du thème de l'interface
|
||||||
desktop.LoadThemeFromFile("res/gui.theme");
|
desktop.LoadThemeFromFile("res/gui.theme");
|
||||||
|
|
||||||
// chargement des textures
|
// préchargement des textures dans le GPU
|
||||||
ResourceManager& res = ResourceManager::get();
|
|
||||||
|
|
||||||
for (const auto &texture : res.getFiles(res.getTexturesPath())) {
|
for (const auto &texture : res.getFiles(res.getTexturesPath())) {
|
||||||
res.getTexture(texture);
|
res.getTexture(texture);
|
||||||
|
|
||||||
|
@ -41,6 +41,15 @@ Manager::Manager() : title(sf::String(L"")), previous_time(sf::seconds(0)),
|
||||||
while (window.pollEvent(event)) {}
|
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
|
// création de la fenêtre du jeu
|
||||||
window.create(
|
window.create(
|
||||||
sf::VideoMode(704, 480), "Skizzle", sf::Style::Default,
|
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
|
// mise en mémoire des chemins vers les dossiers de ressources
|
||||||
fs::path res_path = fs::current_path() / "res";
|
fs::path res_path = fs::current_path() / "res";
|
||||||
|
|
||||||
|
images_path = res_path / "images";
|
||||||
textures_path = res_path / "textures";
|
textures_path = res_path / "textures";
|
||||||
fonts_path = res_path / "fonts";
|
fonts_path = res_path / "fonts";
|
||||||
levels_path = res_path / "levels";
|
levels_path = res_path / "levels";
|
||||||
|
@ -40,6 +41,10 @@ std::vector<fs::path> ResourceManager::getFiles(fs::path path) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fs::path& ResourceManager::getImagesPath() const {
|
||||||
|
return images_path;
|
||||||
|
}
|
||||||
|
|
||||||
const fs::path& ResourceManager::getTexturesPath() const {
|
const fs::path& ResourceManager::getTexturesPath() const {
|
||||||
return textures_path;
|
return textures_path;
|
||||||
}
|
}
|
||||||
|
@ -56,34 +61,42 @@ const fs::path& ResourceManager::getMusicsPath() const {
|
||||||
return musics_path;
|
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();
|
std::string path_str = path.string();
|
||||||
|
|
||||||
// si l'image a déjà été chargée, on retourne la
|
// si l'image a déjà été chargée, on retourne la
|
||||||
// version en cache mémoire
|
// version en cache mémoire
|
||||||
if (images_cache.count(path_str) > 0) {
|
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
|
// 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 << "Impossible de charger l'image :" << std::endl;
|
||||||
std::cerr << path_str << std::endl << std::endl;
|
std::cerr << path_str << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// on met en cache l'image pour les requêtes suivantes
|
// création d'une nouvelle image SFGUI avec les infos chargées
|
||||||
// puis on la renvoie
|
// et mise en cache du résultat
|
||||||
images_cache[path_str] = std::move(image);
|
sfg::Image::Ptr sfg_image = sfg::Image::Create(image);
|
||||||
return images_cache[path_str];
|
images_cache[path_str] = sfg_image;
|
||||||
|
|
||||||
|
return sfg_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<sf::Image> ResourceManager::getImage(std::string name) {
|
sfg::Image::Ptr ResourceManager::getImage(std::string name) {
|
||||||
return getImage(textures_path / 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));
|
return getImage(std::string(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,14 +108,11 @@ std::shared_ptr<sf::Texture> ResourceManager::getTexture(fs::path path) {
|
||||||
return textures_cache[path_str];
|
return textures_cache[path_str];
|
||||||
}
|
}
|
||||||
|
|
||||||
// on récupère l'image depuis le disque
|
// on tente de charger la texture depuis le disque vers le GPU
|
||||||
std::shared_ptr<sf::Image> image = getImage(path);
|
|
||||||
|
|
||||||
// on transfère l'image vers le GPU
|
|
||||||
auto texture = std::shared_ptr<sf::Texture>(new sf::Texture);
|
auto texture = std::shared_ptr<sf::Texture>(new sf::Texture);
|
||||||
texture->setSmooth(true);
|
texture->setSmooth(true);
|
||||||
|
|
||||||
if (!texture->loadFromImage(*image)) {
|
if (!texture->loadFromFile(path_str)) {
|
||||||
std::cerr << "Impossible de créer la texture :" << std::endl;
|
std::cerr << "Impossible de créer la texture :" << std::endl;
|
||||||
std::cerr << path_str << std::endl << 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();
|
sf::Vector2i window_size = (sf::Vector2i) window.getSize();
|
||||||
|
|
||||||
// mise à jour de l'icône du mute en fonction de l'état
|
// mise à jour de l'icône du mute en fonction de l'état
|
||||||
sf::Image image;
|
sfg::Image::Ptr image;
|
||||||
|
|
||||||
if (ResourceManager::get().isMuted()) {
|
if (ResourceManager::get().isMuted()) {
|
||||||
image = *ResourceManager::get().getImage("toolbar/icon_no_music.tga");
|
image = ResourceManager::get().getImage("no_music.tga");
|
||||||
} else {
|
} 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
|
// positionnement de la barre d'actions
|
||||||
action_toolbar.getWindow()->SetAllocation(sf::FloatRect(
|
action_toolbar.getWindow()->SetAllocation(sf::FloatRect(
|
||||||
|
|
Loading…
Reference in New Issue