Rendering Engine 0.2.0
Modular Graphics Rendering Engine | v0.2.0
Loading...
Searching...
No Matches
texture_cache.cpp
Go to the documentation of this file.
1// Copyright (c) 2025 Alexander Obzherin — Licensed under the zlib License. See LICENSE.md.
2
3#include "texture_cache.hpp"
4#include "image_data_gpu.hpp"
5#include "i_renderer.hpp"
6#include <string>
7#include <vector>
8#include "boost/filesystem.hpp"
9#include "utility.hpp"
10
11namespace rendering_engine
12{
13
15 :
16 mRenderer(renderer),
19{
20 mRenderer->RegisterObserver(this);
21}
22
24{
25 mRenderer->UnregisterObserver(this);
26}
27
28void TextureCache::LoadTexturesFromFolder(std::string pathToFolder)
29{
30 // 1. Check if path is valid and exist
31 boost::filesystem::path pathToDirectory = boost::filesystem::path(pathToFolder);
32 const bool isValidFolderPath = boost::filesystem::exists(boost::filesystem::path(pathToFolder)) && boost::filesystem::is_directory(boost::filesystem::path(pathToFolder));
33 if (!isValidFolderPath)
34 {
35 return;
36 }
37 // 2. Iterate through files in the folder.
38 // if file is in the list of supported extensions
39 for (boost::filesystem::directory_entry& x : boost::filesystem::directory_iterator(pathToDirectory))
40 {
41 auto textureName = UploadTextureToRAM(x.path().string());
42 if (!textureName.empty())
43 {
44 UploadTextureToGPU(textureName);
45 }
46 }
47}
48
50{
51 const auto& entries = Utility::GetPackEntries();
52
53 std::string folderEntry = { "Textures/" };
54 for (auto& entry : entries)
55 {
56 const std::string& virtualPath = entry.first;
57 if (virtualPath.rfind(folderEntry, 0) == 0) // starts with Textures/
58 {
59 std::string textureFileName = virtualPath.substr(folderEntry.size());
60
61 std::vector<uint8_t> binaryFileData = Utility::ReadPackedFile(virtualPath);
62 if (binaryFileData.empty())
63 {
64 std::cerr << "[TextureCache] Could not read packed texture: "
65 << virtualPath << std::endl;
66 continue;
67 }
68
69 // Upload to RAM with textureName + binaryFileData
70 auto textureName = UploadTextureToRAM(textureFileName, binaryFileData);
71 if (!textureName.empty())
72 {
73 UploadTextureToGPU(textureName);
74 }
75 }
76 }
77}
78
79std::string TextureCache::UploadTextureToRAM(std::string path)
80{
81 auto filePath = boost::filesystem::path(path);
82 if (!boost::filesystem::is_regular_file(filePath))
83 {
84 return std::string{};
85 }
86
87 const std::string ext = filePath.extension().string();
88 const bool isExtensionSupported = (ext == ".jpg") || (ext == ".png");
89 if (!isExtensionSupported)
90 {
91 return std::string{};
92 }
93
94 std::string filename = filePath.stem().string();
95 // If texture is already loaded into RAM yet, do not add again.
96 if (auto search = mTextures.find(filename); search != mTextures.end())
97 {
98 return std::string{};
99 }
100 mTextures[filename] = std::make_shared<ImageDataGpu>(path, mRenderer);
101
102 size_t size = mTextures.at(filename)->GetSizeInRAM();
103 mTotalSizeRAM += size;
104
105 return filename;
106}
107
108std::string TextureCache::UploadTextureToRAM(std::string textureFileName, std::vector<uint8_t> const& fileBytes)
109{
110 auto textureName = boost::filesystem::path(textureFileName).stem().string();
111 // If texture is already loaded into RAM yet, do not add again.
112 if (auto search = mTextures.find(textureName); search != mTextures.end())
113 {
114 return std::string{};
115 }
116 mTextures[textureName] = std::make_shared<ImageDataGpu>(fileBytes, mRenderer);
117
118 size_t size = mTextures.at(textureName)->GetSizeInRAM();
119 mTotalSizeRAM += size;
120
121 return textureName;
122}
123
124void TextureCache::UploadTextureToGPU(std::string filename)
125{
126 // If texture is not loaded in RAM yet, skip loading to GPU.
127 if (auto search = mTextures.find(filename); search == mTextures.end())
128 {
129 return;
130 }
131 if (mTextures[filename]->IsOnGPU())
132 {
133 return;
134 }
135
136 mTextures[filename]->UploadToGPU();
137 size_t size = mTextures[filename]->GetSizeInGPU();
138 mTotalSizeGPU += size;
139}
140
141void TextureCache::ReleaseTextureFromGPU(std::string filename)
142{
143 if (auto search = mTextures.find(filename); search == mTextures.end())
144 {
145 return;
146 }
147
148 auto& texture = mTextures[filename];
149 size_t size = texture->GetSizeInGPU();
150 texture->ReleaseFromGPU();
151
152 mTotalSizeGPU -= size;
153}
154
156{
157 for (auto& texture : mTextures)
158 {
159 texture.second->ReleaseFromGPU();
160 }
161 mTotalSizeGPU = 0;
162}
163
165{
167 mTextures.clear();
168 mTotalSizeRAM = 0;
169 mTotalSizeGPU = 0;
170}
171
172std::shared_ptr<ImageDataGpu> TextureCache::GetTextureResources(std::string filename)
173{
174 auto search = mTextures.find(filename);
175 if (search == mTextures.end())
176 {
177 return nullptr;
178 }
179 return search->second;
180}
181
183{
184 if (auto search = mTextures.find(filename); search == mTextures.end())
185 {
186 return nullptr;
187 }
188
189 return mTextures.at(filename)->GetTextureRenderResources();
190}
191
193{
194 return mTotalSizeRAM;
195}
196
198{
199 return mTotalSizeGPU;
200}
201
206
208{
209 for (auto& texture : mTextures)
210 {
211 texture.second->UploadToGPU();
212 size_t size = texture.second->GetSizeInGPU();
213 mTotalSizeGPU += size;
214 }
215}
216
217}
Defines an abstract interface for rendering backends.
Interface for backend-specific GPU texture resource management.
void OnRenderResourcesRelease() override
Renderer callback: release all GPU resources (used during device loss/reset).
std::unordered_map< std::string, std::shared_ptr< ImageDataGpu > > mTextures
void LoadTexturesFromPackage()
Loads all textures from the packed asset archive.
void ReleaseAll()
Fully clears the texture cache, including both RAM and GPU resources.
void OnRenderResourcesRebuild() override
Renderer callback: re-upload or recreate all GPU resources (used after device reset/rebuild).
std::shared_ptr< ImageDataGpu > GetTextureResources(std::string filename)
Retrieves the full texture resource wrapper from cache.
void ReleaseAllFromGPU()
Releases all cached textures from GPU memory.
std::string UploadTextureToRAM(std::string path)
Loads a single texture into RAM from the given file path.
ITextureRenderResources * GetTextureRenderResources(std::string filename)
Retrieves only the GPU render resources of a cached texture.
size_t GetSizeInRAM() const
Gets the total size of all currently cached textures in RAM.
void UploadTextureToGPU(std::string filename)
Uploads a texture (previously loaded into RAM) to GPU.
void LoadTexturesFromFolder(std::string pathToFolder)
Loads all supported texture files (*.jpg, *.png) from a specified folder into RAM and uploads them to...
TextureCache(IRenderer *renderer)
Constructs the TextureCache with a reference to the renderer.
size_t GetSizeInGPU() const
Gets the total size of all textures currently uploaded to GPU.
void ReleaseTextureFromGPU(std::string filename)
Releases a texture from GPU memory.
static const PackEntries & GetPackEntries()
Returns the manifest of packed files.
Definition utility.cpp:219
static std::vector< uint8_t > ReadPackedFile(const std::string &entryPath)
Reads raw bytes of a file stored inside Pack.bin.
Definition utility.cpp:260