Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
TextureHandleRegistry.cpp
Go to the documentation of this file.
2
3#include <mutex>
4#include <plog/Log.h>
5
6namespace EngineCore {
7
8namespace {
9 // Normalize path for consistent lookup - handles relative vs absolute, different separators, etc.
10 std::string normalizePath(const std::filesystem::path& path) {
11 // Use generic_string for consistent forward slashes
12 std::string pathStr = path.generic_string();
13
14 // Remove any leading "./" if present
15 if (pathStr.size() >= 2 && pathStr[0] == '.' && pathStr[1] == '/') {
16 pathStr = pathStr.substr(2);
17 }
18
19 return pathStr;
20 }
21}
22
24 std::string pathKey = normalizePath(path);
25 PLOGI << "TextureHandleRegistry::getOrCreateHandleImpl - normalized path: '" << pathKey << "' from '" << path.generic_string() << "'";
26
27 // First try with shared (read) lock for the common case
28 {
29 std::shared_lock<std::shared_mutex> readLock(mutex_);
30 auto it = pathToHandleId_.find(pathKey);
31 if (it != pathToHandleId_.end()) {
32 // Handle already exists - verify type matches
33 const Entry& entry = entries_[it->second];
34 if (entry.type != type) {
35 PLOGW << "TextureHandleRegistry: Type mismatch for path '" << pathKey
36 << "' - existing type=" << static_cast<int>(entry.type)
37 << " requested type=" << static_cast<int>(type)
38 << ". Using existing type.";
39 }
40 return TextureHandle(it->second, entry.type);
41 }
42 }
43
44 // Need to create a new entry - acquire exclusive (write) lock
45 std::unique_lock<std::shared_mutex> writeLock(mutex_);
46
47 // Double-check after acquiring write lock (another thread may have added it)
48 auto it = pathToHandleId_.find(pathKey);
49 if (it != pathToHandleId_.end()) {
50 const Entry& entry = entries_[it->second];
51 return TextureHandle(it->second, entry.type);
52 }
53
54 // Create new entry
55 uint32_t newId = static_cast<uint32_t>(entries_.size());
56 Entry newEntry;
57 newEntry.path = path;
58 newEntry.type = type;
59 newEntry.texture = nullptr;
61
62 entries_.push_back(std::move(newEntry));
63 pathToHandleId_[pathKey] = newId;
64
65 PLOGD << "TextureHandleRegistry: Created handle " << newId
66 << " for path '" << pathKey << "' with type " << static_cast<int>(type);
67
68 return TextureHandle(newId, type);
69}
70
72 if (!handle.isValid()) {
74 }
75
76 std::shared_lock<std::shared_mutex> lock(mutex_);
77
78 uint32_t id = handle.getId();
79 if (id >= entries_.size()) {
80 PLOGW << "TextureHandleRegistry: Invalid handle ID " << id
81 << " (entries size=" << entries_.size() << ")";
83 }
84
85 return entries_[id].descriptorIndex;
86}
87
89 if (!handle.isValid()) {
91 }
92
93 std::shared_lock<std::shared_mutex> lock(mutex_);
94
95 uint32_t id = handle.getId();
96 if (id >= entries_.size()) {
98 }
99
100 return entries_[id].type;
101}
102
103TextureType TextureHandleRegistry::getTextureTypeForPath(const std::filesystem::path& path) const {
104 std::string pathKey = normalizePath(path);
105 PLOGI << "TextureHandleRegistry::getTextureTypeForPath - normalized path: '" << pathKey << "'";
106
107 std::shared_lock<std::shared_mutex> lock(mutex_);
108
109 auto it = pathToHandleId_.find(pathKey);
110 if (it == pathToHandleId_.end()) {
112 }
113
114 return entries_[it->second].type;
115}
116
117void TextureHandleRegistry::onTextureLoaded(const std::filesystem::path& path, Texture* texture, uint32_t descriptorIndex) {
118 std::string pathKey = normalizePath(path);
119 PLOGI << "TextureHandleRegistry::onTextureLoaded - normalized path: '" << pathKey << "' from '" << path.generic_string() << "'";
120
121 std::unique_lock<std::shared_mutex> lock(mutex_);
122
123 auto it = pathToHandleId_.find(pathKey);
124 if (it == pathToHandleId_.end()) {
125 PLOGW << "TextureHandleRegistry: onTextureLoaded called for unregistered path '" << pathKey << "'";
126 return;
127 }
128
129 Entry& entry = entries_[it->second];
130 entry.texture = texture;
131 entry.descriptorIndex = descriptorIndex;
132
133 PLOGD << "TextureHandleRegistry: Texture loaded for handle " << it->second
134 << " path='" << pathKey << "' descriptorIndex=" << descriptorIndex;
135}
136
137void TextureHandleRegistry::onTextureUnloaded(const std::filesystem::path& path) {
138 std::string pathKey = normalizePath(path);
139
140 std::unique_lock<std::shared_mutex> lock(mutex_);
141
142 auto it = pathToHandleId_.find(pathKey);
143 if (it == pathToHandleId_.end()) {
144 return; // Not registered, nothing to do
145 }
146
147 Entry& entry = entries_[it->second];
148 entry.texture = nullptr;
150
151 PLOGD << "TextureHandleRegistry: Texture unloaded for handle " << it->second
152 << " path='" << pathKey << "'";
153}
154
156 std::shared_lock<std::shared_mutex> lock(mutex_);
157 return entries_.size();
158}
159
160std::filesystem::path TextureHandleRegistry::getPathForHandle(TextureHandle handle) const {
161 if (!handle.isValid()) {
162 return {};
163 }
164
165 std::shared_lock<std::shared_mutex> lock(mutex_);
166
167 uint32_t id = handle.getId();
168 if (id >= entries_.size()) {
169 return {};
170 }
171
172 return entries_[id].path;
173}
174
176 std::unique_lock<std::shared_mutex> lock(mutex_);
177 entries_.clear();
178 pathToHandleId_.clear();
179 PLOGD << "TextureHandleRegistry: Cleared all entries";
180}
181
182} // namespace EngineCore
std::filesystem::path getPathForHandle(TextureHandle handle) const
Get the path associated with a handle (for debugging/validation)
uint32_t resolveDescriptorIndex(TextureHandle handle) const
Resolve a handle to its descriptor index (O(1) operation)
TextureHandle getOrCreateHandleImpl(const std::filesystem::path &path, TextureType type)
Internal implementation of getOrCreateHandle.
void clear()
Clear all registry entries (typically called on shutdown)
void onTextureLoaded(const std::filesystem::path &path, Texture *texture, uint32_t descriptorIndex)
Called when a texture finishes loading.
void onTextureUnloaded(const std::filesystem::path &path)
Called when a texture is unloaded.
std::unordered_map< std::string, uint32_t > pathToHandleId_
TextureType getTextureTypeForPath(const std::filesystem::path &path) const
Get the texture type for a path (if registered)
size_t getHandleCount() const
Get the total number of registered texture handles.
TextureType getTextureType(TextureHandle handle) const
Get the texture type for a handle.
Type-erased texture handle for runtime storage.
static constexpr uint32_t INVALID_ID
bool isValid() const
Check if this handle points to a valid registry entry.
uint32_t getId() const
Get the registry ID for this handle.
Log category system implementation.
TextureType
Represents the semantic type of a texture, determining its Vulkan format.
Definition TextureType.h:18
@ Unknown
Fallback type, uses SRGB as default.
Definition TextureType.h:24
Registry entry storing texture metadata.