Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
AssetManager.h
Go to the documentation of this file.
1#pragma once
18#include "MeshAsset.h"
19#include "MeshAssetRef.h"
20
23#include <filesystem>
24#include <memory>
25#include <optional>
26#include <string>
27#include <type_traits>
28#include <unordered_map>
29#include <unordered_set>
30
31namespace Engine::Entities
32{
33 class GltfSpawner;
34} // namespace Engine::Entities
35
36namespace Engine::Rendering
37{
38 class Renderer;
39} // namespace Engine::Rendering
40
41namespace Engine::Assets
42{
43 class Material;
44 class Mesh;
45 class ModelAssetManager;
46 class MeshAssetManager;
47 class RuntimeTexture;
48 class Texture;
49} // namespace Engine::Assets
50
51namespace Engine::Core
52{
54 class RenderingDataManager;
55
60 {
61 std::size_t operator()( const std::filesystem::path & p ) const noexcept
62 {
63 return std::hash<std::string>{}( p.string() ); // Hash the string representation
64 }
65 };
66
71 {
72 glm::vec3 position; // 12 bytes (Keep full precision)
73 uint32_t packedNormal; // 4 bytes (A2B10G10R10_SNORM)
74 uint32_t packedColor; // 4 bytes (R8G8B8A8_UNORM)
75 uint32_t packedTexCoord; // 4 bytes (R16G16_SFLOAT)
76 // Total: 24 bytes
77 };
78
79 // Pack vec3 normal [-1, 1] into A2B10G10R10_SNORM uint32_t
80 inline uint32_t packNormalA2B10G10R10_SNORM( const glm::vec3 & n )
81 {
82 // Clamp input just in case
83 float x = std::max( -1.0f, std::min( 1.0f, n.x ) );
84 float y = std::max( -1.0f, std::min( 1.0f, n.y ) );
85 float z = std::max( -1.0f, std::min( 1.0f, n.z ) );
86
87 // Scale to signed 10-bit range [-511, 511]
88 int32_t ix = static_cast<int32_t>( std::round( x * 511.0f ) );
89 int32_t iy = static_cast<int32_t>( std::round( y * 511.0f ) );
90 int32_t iz = static_cast<int32_t>( std::round( z * 511.0f ) );
91
92 // Pack into uint32_t (masking handles two's complement correctly)
93 // Layout: | 2 unused | 10 bits B | 10 bits G | 10 bits R |
94 return ( static_cast<uint32_t>( iz & 0x3FF ) << 20 ) | ( static_cast<uint32_t>( iy & 0x3FF ) << 10 ) |
95 ( static_cast<uint32_t>( ix & 0x3FF ) );
96 // Alpha bits (highest 2) remain 0
97 }
98
99 // Pack vec3 color [0, 1] into R8G8B8A8_UNORM uint32_t (Alpha = 1.0)
100 inline uint32_t packColorR8G8B8A8_UNORM( const glm::vec3 & c )
101 {
102 // Clamp input
103 float r = std::max( 0.0f, std::min( 1.0f, c.x ) );
104 float g = std::max( 0.0f, std::min( 1.0f, c.y ) );
105 float b = std::max( 0.0f, std::min( 1.0f, c.z ) );
106
107 // Scale to [0, 255]
108 uint32_t ur = static_cast<uint32_t>( std::round( r * 255.0f ) );
109 uint32_t ug = static_cast<uint32_t>( std::round( g * 255.0f ) );
110 uint32_t ub = static_cast<uint32_t>( std::round( b * 255.0f ) );
111 uint32_t ua = 255; // Fully opaque alpha
112
113 // Pack (assuming typical RGBA little-endian layout)
114 return ( ua << 24 ) | ( ub << 16 ) | ( ug << 8 ) | ur;
115 }
116
117 // Pack vec2 texCoord into R16G16_SFLOAT uint32_t
118 inline uint32_t packTexCoordR16G16_SFLOAT( const glm::vec2 & tc )
119 {
120 // Use glm's packing function (requires <glm/gtc/packing.hpp>)
121 // It converts two floats to two 16-bit half-floats and packs them.
122 return glm::packHalf2x16( tc );
123 }
124
129 {
133 uint32_t index = 0u;
134
138 std::shared_ptr<Assets::Texture> texture = nullptr;
139
140 template <typename T>
141 bool operator>( const T & other )
142 {
143 return index > other.index;
144 }
145
146 template <typename T>
147 bool operator<( const T & other )
148 {
149 return index < other.index;
150 }
151 };
152
154 {
158
159 public:
166
167 template <typename AssetClass, typename Key>
168 [[nodiscard]] auto getAsset( const Key & asset )
169 {
170 if constexpr ( std::is_same_v<AssetClass, Assets::Mesh> )
171 {
172 static_assert(
173 std::is_same_v<std::decay_t<Key>, Asset::MeshPath>,
174 "Mesh assets are keyed by Asset::MeshPath"
175 );
176
177 MeshAssetRef ref = meshAssetManager->getOrCreateRef( asset );
178 (void)getMeshAsset( asset );
179 return ref;
180 }
181 else if constexpr ( std::is_same_v<AssetClass, Assets::Audio> )
182 {
183 static_assert(
184 std::is_same_v<std::decay_t<Key>, Asset::Path> ||
185 std::is_same_v<std::decay_t<Key>, std::filesystem::path>,
186 "Audio assets are keyed by Asset::Path"
187 );
188
189 return loadAudioAsset( Asset::Path( asset ) );
190 }
191 else if constexpr ( std::is_same_v<AssetClass, Assets::Animation> )
192 {
193 static_assert(
194 std::is_same_v<std::decay_t<Key>, Asset::MeshPath>,
195 "Animation assets are keyed by Asset::MeshPath"
196 );
197
198 AnimationAssetRef ref = animationAssetManager_->getOrCreateRef( asset );
199 if ( animationAssetManager_->getAssetLoadingState( asset ) == Asset::UNLOADED )
200 {
201 loadEcsModel( asset.getFilePath() );
202 }
203 return ref;
204 }
205 else if constexpr ( std::is_same_v<AssetClass, Assets::Material> )
206 {
207 static_assert(
208 std::is_same_v<std::decay_t<Key>, Asset::MeshPath>,
209 "Material assets are keyed by Asset::MeshPath"
210 );
211
212 return materialAssetManager->getOrCreateRef( asset );
213 }
214 else if constexpr ( std::is_same_v<AssetClass, Assets::Skin> )
215 {
216 static_assert(
217 std::is_same_v<std::decay_t<Key>, Asset::MeshPath>,
218 "Skin assets are keyed by Asset::MeshPath"
219 );
220
221 SkinAssetRef ref = skinAssetManager_->getOrCreateRef( asset );
222 if ( skinAssetManager_->getAssetLoadingState( asset ) == Asset::UNLOADED )
223 {
224 loadEcsModel( asset.getFilePath() );
225 }
226 return ref;
227 }
228 else if constexpr ( std::is_same_v<AssetClass, Assets::Texture> )
229 {
230 static_assert(
231 std::is_same_v<std::decay_t<Key>, Asset::Path> ||
232 std::is_same_v<std::decay_t<Key>, std::filesystem::path>,
233 "Texture assets are keyed by Asset::Path"
234 );
235
236 const Asset::Path pathKey( asset );
237 TextureAssetRef ref = textureAssetManager->getOrCreateRef( pathKey );
238 const Asset::LoadState state = textureAssetManager->getAssetLoadingState( pathKey );
239 if ( state != Asset::LOADED && state != Asset::REQUESTED_LOAD && state != Asset::LOADING )
240 {
241 loadEcsTexture( pathKey.getFilePath() );
242 }
243 return ref;
244 }
245 else
246 {
247 static_assert(
248 std::is_same_v<AssetClass, void>, "Unsupported asset type for AssetManager::getAsset<T>()"
249 );
250 }
251 }
252
256
262
267 void setRenderingDataManager( RenderingDataManager * renderingDataManager );
268
269 private:
275 void loadEcsModel( const std::filesystem::path & path );
276
282 void loadEcsTexture( const std::filesystem::path & path );
283
284 public:
285 // TODO: loadEcsCubemap should be private and only load things via a getter so that all resources use
286 // the Ref resource handle.
290 Assets::CubemapTexture * loadEcsCubemap( const std::filesystem::path & path );
291
298 [[nodiscard]] uint32_t getTextureDescriptorIndex( const std::filesystem::path & path );
299
300 uint32_t getImageCount() const;
301
302 void cleanup();
303
304 std::vector<VkDescriptorImageInfo> getTextureDescriptorInfos() const;
305
310
315
321
327 [[nodiscard]] Assets::Audio * getAudioAsset( const Asset::Path & path );
328
334 {
335 return audioAssetManager_;
336 }
337
338 private:
344 [[nodiscard]] Assets::Mesh * getMeshAsset( const Asset::MeshPath & asset );
345
346 public:
352 {
354 }
355
360 [[nodiscard]] Assets::ModelAssetManager * getModelAssetManager() const
361 {
362 return modelAssetManager;
363 }
364
370 {
371 return meshAssetManager;
372 }
373
375 {
376 return skinAssetManager_;
377 }
378
383
392
397 [[nodiscard]] uint32_t reserveRuntimeTextureDescriptorIndex();
398
402 void releaseRuntimeTextureDescriptorIndex( uint32_t descriptorIndex );
403
404 private:
405 NamedThreadPool * threadPool_ = new NamedThreadPool( 2, "Asset Loader" );
406 NamedThreadPool * threadedCalculation_ = new NamedThreadPool( 2, "Bounding Sphere" );
407
412 Assets::ModelAssetManager * modelAssetManager;
415
416 // IMPORTANT: textureHandleRegistry_ must be declared BEFORE modelAssetPipeline
417 // because modelAssetPipeline's constructor receives 'this' and may access the registry.
418 // C++ initializes members in declaration order, not initializer list order.
421
423
426
427 public:
429 {
431 }
432
434 {
435 return threadPool_;
436 }
437
438 private:
440
443
444 std::unordered_map<std::filesystem::path, Assets::RuntimeTexture *, PathHasher> textures = {};
445 std::unordered_map<std::filesystem::path, std::unique_ptr<Assets::CubemapTexture>, PathHasher>
448
449 std::array<std::optional<Assets::RuntimeTexture>, MAX_TEXTURE_COUNT> textureData;
451 std::unordered_set<uint32_t> runtimeTextureDescriptorIndices_;
452
460 bool doesTextureAlreadyExist( const std::filesystem::path & path );
461
472 registerTexture( const std::filesystem::path & path, Assets::RuntimeTexture texture );
473
484 registerTextureFromPrepared( const std::filesystem::path & path, Assets::RuntimeTexture texture );
485
490 replaceTextureFromPrepared( const std::filesystem::path & path, Assets::RuntimeTexture texture );
491
494
495 TRACY_LOCKABLE( std::mutex, textureMutex, "Texture mutex" );
496
497 std::vector<TextureStorage> texturesToUpload{};
498 std::vector<Assets::RuntimeTexture *> texturesToCopyImageData;
499 };
500} // namespace Engine::Core
constexpr uint32_t MAX_TEXTURE_COUNT
Definition Settings.h:35
#define TRACY_LOCKABLE(type, varname, desc)
Maintains a one-to-one mapping that can be queried from either side.
Manages audio assets by filesystem path, providing dedup and lookup.
Definition AudioAsset.h:72
Holds decoded PCM audio data as an engine asset.
Definition AudioAsset.h:14
Owns Vulkan resources for a sampled cubemap texture.
Loads glTF files and converts tinygltf data into engine asset data.
Definition GltfLoader.h:38
Asset manager for materials keyed by source file path and material name.
the material asset is another wrapper for asset data which is stored in entt. It has the EngineCore::...
Stores mesh data with their primitives.
Definition MeshAsset.h:47
The mesh asset stores geometry data and.
Definition MeshAsset.h:20
Runtime-owned Vulkan texture resource.
Definition Texture.h:33
Asset manager for texture assets keyed by filesystem path.
Wrapper for texture data.
Central registry for texture handles, providing O(1) descriptor index lookup.
The application context is the core class which stores the basic openxr and vulkan objects.
bool doesTextureAlreadyExist(const std::filesystem::path &path)
Checks if a texture has already been loaded.
Assets::ModelAssetManager * modelAssetManager
Assets::Mesh * getMeshAsset(const Asset::MeshPath &asset)
Get a mesh asset by path. If not loaded, requests its model and returns nullptr.
DescriptorIndexAllocator textureAllocator
void discardSceneLoadingData()
Drops any queued or in-flight scene asset loading work.
Assets::TextureAssetRef TextureAssetRef
Assets::MaterialAssetManager * materialAssetManager
Assets::Textures::TextureHandleRegistry * getTextureHandleRegistry()
Gets the texture handle registry for O(1) descriptor index lookups.
Rendering::Renderer * renderer
std::unordered_map< std::filesystem::path, std::unique_ptr< Assets::CubemapTexture >, PathHasher > cubemapTextures
Assets::SkinAssetManager * skinAssetManager_
Assets::MaterialAssetManager * getMaterialAssetManager() const
Gets the material asset manager for material lookups.
uint32_t getImageCount() const
auto getAsset(const Key &asset)
std::vector< TextureStorage > texturesToUpload
Assets::RuntimeTexture * replaceTextureFromPrepared(const std::filesystem::path &path, Assets::RuntimeTexture texture)
Replace an already registered texture while preserving its descriptor index.
Assets::AudioAssetRef AudioAssetRef
Assets::MeshAssetRef MeshAssetRef
void setRenderingDataManager(RenderingDataManager *renderingDataManager)
Sets the RenderingDataManager on asset pipelines for hook notifications.
Assets::Textures::TextureHandleRegistry textureHandleRegistry_
Registry for type-safe texture handles.
Ecs::AudioAssetPipeline & getAudioAssetPipeline()
void loadEcsTexture(const std::filesystem::path &path)
Loads a texture (.png / .jpg / .exr)
Assets::Loaders::GltfLoader gltfLoader
Assets::MeshAssetManager * meshAssetManager
std::vector< VkDescriptorImageInfo > getTextureDescriptorInfos() const
NamedThreadPool * threadPool_
Assets::AudioAssetManager * getAudioAssetManager() const
Gets the audio asset manager for direct access.
Assets::AudioAssetManager * audioAssetManager_
Assets::Audio * getAudioAsset(const Asset::Path &path)
Get a loaded audio asset by path.
Assets::AnimationAssetRef AnimationAssetRef
AssetManager(ApplicationContext *context)
Ecs::TextureAssetPipeline texturePipeline
Assets::MaterialAssetRef MaterialAssetRef
Assets::AnimationAssetManager * animationAssetManager_
void unregisterTexture(Assets::RuntimeTexture *texture)
Assets::RuntimeTexture * registerTexture(const std::filesystem::path &path, Assets::RuntimeTexture texture)
Registers a texture with the texture manager which prevents the same texture from being loaded twice.
Assets::ModelAssetManager * getModelAssetManager() const
Gets the model asset manager for model/GLTF file loading state lookups.
Assets::RuntimeTexture * registerTextureFromPrepared(const std::filesystem::path &path, Assets::RuntimeTexture texture)
Register a texture whose Vulkan resources are already created. Skips createResources() — only allocat...
void loadEcsModel(const std::filesystem::path &path)
Submits a gltf model for loading. You provide the path of the model to load. This can include 3D data...
Assets::TextureAssetManager * textureAssetManager
Ecs::AudioAssetPipeline audioAssetPipeline_
std::vector< Assets::RuntimeTexture * > texturesToCopyImageData
Ecs::TextureAssetPipeline & getTextureAssetPipeline()
NamedThreadPool * getAssetLoaderPool() const
NamedThreadPool * getCalculationPool() const
NamedThreadPool * threadedCalculation_
void attachToRenderer(Rendering::Renderer *renderer)
Sets what renderer the render process belongs to.
Assets::SkinAssetRef SkinAssetRef
Ecs::ModelAssetPipeline modelAssetPipeline
BidirectionalMap< uint32_t, Assets::RuntimeTexture * > textureIndexMap
uint32_t reserveRuntimeTextureDescriptorIndex()
Assets::CubemapTexture * loadEcsCubemap(const std::filesystem::path &path)
Loads a six-face cubemap asset from a directory.
void releaseRuntimeTextureDescriptorIndex(uint32_t descriptorIndex)
uint32_t getTextureDescriptorIndex(const std::filesystem::path &path)
Gets the descriptor index of a loaded texture by path.
Assets::AnimationAssetManager * getAnimationAssetManager() const
std::unordered_map< std::filesystem::path, Assets::RuntimeTexture *, PathHasher > textures
Assets::MeshAssetManager * getMeshAssetManager() const
Gets the mesh asset manager for mesh asset lookups.
ApplicationContext * context
std::unordered_set< uint32_t > runtimeTextureDescriptorIndices_
std::array< std::optional< Assets::RuntimeTexture >, MAX_TEXTURE_COUNT > textureData
Assets::SkinAssetManager * getSkinAssetManager() const
AudioAssetRef loadAudioAsset(const Asset::Path &path)
Submit an audio file for async loading through the pipeline.
Ecs::ModelAssetPipeline & getMeshAssetPipeline()
Use this class to manage a finite amount of memory. The idea is to have an array which stores objects...
Async pipeline for loading audio assets (WAV, FLAC, MP3)
The model asset pipeline loads a gltf scene and loads and loads the mesh and material data....
Infrastructure to load images into the ecs.
Utility class for spawning GLTF meshes into a scene.
Definition GltfSpawner.h:15
The renderer is the main class for rendering. It owns all data which is used any time in any frame....
Definition Renderer.h:77
Tracy-named thread pool using BS_tracy::tracy_thread_pool.
@ LOADED
All components of the asset have been loaded, and it is ready to be used.
Definition Asset.h:40
@ REQUESTED_LOAD
An asset has been requested to load and is waiting for an asset pipeline to start working on it.
Definition Asset.h:32
@ LOADING
While the asset is currently being processed in the asset pipeline.
Definition Asset.h:36
@ UNLOADED
When the asset is not loaded yet but the frame is already existing for the heavy data to be loaded in...
Definition Asset.h:27
CpuLoadingState LoadState
Definition Asset.h:47
Asset::Ref< Asset::MeshPath, Animation > AnimationAssetRef
Asset::Ref< Asset::Path, Audio > AudioAssetRef
Asset::Ref< Asset::Path, Texture > TextureAssetRef
Asset::Ref< Asset::MeshPath, Skin > SkinAssetRef
Asset::Ref< Asset::MeshPath, Mesh > MeshAssetRef
Asset::Ref< Asset::MeshPath, Material > MaterialAssetRef
Manages IBL (Image-Based Lighting) resources for specular reflections.
uint32_t packTexCoordR16G16_SFLOAT(const glm::vec2 &tc)
uint32_t packColorR8G8B8A8_UNORM(const glm::vec3 &c)
uint32_t packNormalA2B10G10R10_SNORM(const glm::vec3 &n)
Identifies a named mesh-like asset inside an asset file.
Definition AssetPath.h:40
Identifies a single asset file on disk.
Definition AssetPath.h:13
const std::filesystem::path & getFilePath() const
Definition AssetPath.h:19
Compact vertex format used by mesh packing code.
Hash functor for filesystem paths used in unordered containers.
std::size_t operator()(const std::filesystem::path &p) const noexcept
Texture asset entry paired with its descriptor index.
std::shared_ptr< Assets::Texture > texture
Managed texture asset.
bool operator<(const T &other)
bool operator>(const T &other)
uint32_t index
Descriptor or storage index assigned to the texture.