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
11
13#include <Engine/Mesh/Mesh.h>
16#include <filesystem>
17#include <future>
18#include <memory>
19#include <optional>
20#include <string>
21#include <tiny_gltf.h>
22#include <unordered_map>
23
24namespace EngineCore
25{
26 class MeshAsset;
27 class MeshAssetManager;
30 class TextureAsset;
31 struct UnifiedMeshlet;
32 struct MeshletBounds;
33 class RenderProcess;
34 class Renderer;
35} // namespace EngineCore
36
37namespace EngineCore
38{
39 class Engine;
40
42 {
43 std::size_t operator()( const std::filesystem::path & p ) const noexcept
44 {
45 return std::hash<std::string>{}( p.string() ); // Hash the string representation
46 }
47 };
48
50 {
51 glm::vec3 position; // 12 bytes (Keep full precision)
52 uint32_t packedNormal; // 4 bytes (A2B10G10R10_SNORM)
53 uint32_t packedColor; // 4 bytes (R8G8B8A8_UNORM)
54 uint32_t packedTexCoord; // 4 bytes (R16G16_SFLOAT)
55 // Total: 24 bytes
56 };
57
58 // Pack vec3 normal [-1, 1] into A2B10G10R10_SNORM uint32_t
59 inline uint32_t packNormalA2B10G10R10_SNORM( const glm::vec3 & n )
60 {
61 // Clamp input just in case
62 float x = std::max( -1.0f, std::min( 1.0f, n.x ) );
63 float y = std::max( -1.0f, std::min( 1.0f, n.y ) );
64 float z = std::max( -1.0f, std::min( 1.0f, n.z ) );
65
66 // Scale to signed 10-bit range [-511, 511]
67 int32_t ix = static_cast<int32_t>( std::round( x * 511.0f ) );
68 int32_t iy = static_cast<int32_t>( std::round( y * 511.0f ) );
69 int32_t iz = static_cast<int32_t>( std::round( z * 511.0f ) );
70
71 // Pack into uint32_t (masking handles two's complement correctly)
72 // Layout: | 2 unused | 10 bits B | 10 bits G | 10 bits R |
73 return ( static_cast<uint32_t>( iz & 0x3FF ) << 20 ) | ( static_cast<uint32_t>( iy & 0x3FF ) << 10 ) |
74 ( static_cast<uint32_t>( ix & 0x3FF ) );
75 // Alpha bits (highest 2) remain 0
76 }
77
78 // Pack vec3 color [0, 1] into R8G8B8A8_UNORM uint32_t (Alpha = 1.0)
79 inline uint32_t packColorR8G8B8A8_UNORM( const glm::vec3 & c )
80 {
81 // Clamp input
82 float r = std::max( 0.0f, std::min( 1.0f, c.x ) );
83 float g = std::max( 0.0f, std::min( 1.0f, c.y ) );
84 float b = std::max( 0.0f, std::min( 1.0f, c.z ) );
85
86 // Scale to [0, 255]
87 uint32_t ur = static_cast<uint32_t>( std::round( r * 255.0f ) );
88 uint32_t ug = static_cast<uint32_t>( std::round( g * 255.0f ) );
89 uint32_t ub = static_cast<uint32_t>( std::round( b * 255.0f ) );
90 uint32_t ua = 255; // Fully opaque alpha
91
92 // Pack (assuming typical RGBA little-endian layout)
93 return ( ua << 24 ) | ( ub << 16 ) | ( ug << 8 ) | ur;
94 }
95
96 // Pack vec2 texCoord into R16G16_SFLOAT uint32_t
97 inline uint32_t packTexCoordR16G16_SFLOAT( const glm::vec2 & tc )
98 {
99 // Use glm's packing function (requires <glm/gtc/packing.hpp>)
100 // It converts two floats to two 16-bit half-floats and packs them.
101 return glm::packHalf2x16( tc );
102 }
103
105 {
106 uint32_t index = 0u;
107 std::shared_ptr<Texture> texture = nullptr;
108
109 template <typename T>
110 bool operator>( const T & other )
111 {
112 return index > other.index;
113 }
114
115 template <typename T>
116 bool operator<( const T & other )
117 {
118 return index < other.index;
119 }
120 };
121
123 {
126
127 public:
128 AssetManager();
131
141
150 void setRenderingDataManager( RenderingDataManager * renderingDataManager );
151
157 void loadEcsModel( const std::filesystem::path & path );
158
168 MeshAsset * getMeshAsset( const Asset::Path & asset );
169
178 void loadEcsTexture( const std::filesystem::path & path );
179
189 [[nodiscard]] uint32_t getTextureDescriptorIndex( const std::filesystem::path & path );
190
196 [[nodiscard]] std::vector<const Mesh *> getAllMeshes() const;
197 [[nodiscard]] uint32_t getTotalPrimitiveCount() const;
198
210 bool doesMeshAlreadyExist( const std::filesystem::path & meshPath ) const;
211
212 uint32_t getImageCount() const;
213
214 void logAllLoadedAssets() const;
215 void reloadMeshOffsets();
216
217 void cleanup();
218
219
220
221 std::vector<VkDescriptorImageInfo> getTextureDescriptorInfos() const;
222
223 uint32_t getShaderCount() const;
224 std::vector<MaterialShader *> getShaders() const;
225
226 PipelineNames materialNameFromString( const std::string & string );
227
228 MaterialShader * getShaderByName( const std::string & shaderName );
229 MaterialShader * getShaderByName( const PipelineNames & shaderName );
230
231 std::unordered_map<Mesh *, uint32_t> getMeshOffsets() const
232 {
233 return meshOffsets;
234 }
235
236 std::vector<Texture *> getTexturesToUpload();
237 uint32_t getMeshOffset( Mesh * mesh ) const;
238
239 MaterialShader * registerShader( MaterialShader shader, const PipelineNames & materialName );
240 void unregisterShader( MaterialShader * shader );
241
243
246 void unloadAllData() const;
247
248 [[nodiscard]] MeshAsset * getMeshAsset( const Asset::Path & asset ) const;
249
258 {
260 }
261
270 {
271 return modelAssetManager;
272 }
273
281 [[nodiscard]] MeshAssetManager * getMeshAssetManager() const
282 {
283 return meshAssetManager;
284 }
285
297
298 private:
299 NamedThreadPool * threadPool = new NamedThreadPool( 4, "Asset Loader" );
300 NamedThreadPool * threadedCalculation = new NamedThreadPool( 10, "Bounding Sphere" );
301
307
308 // IMPORTANT: textureHandleRegistry_ must be declared BEFORE modelAssetPipeline
309 // because modelAssetPipeline's constructor receives 'this' and may access the registry.
310 // C++ initializes members in declaration order, not initializer list order.
312
314
315 std::vector<CpuMeshData> cpuMeshData;
316
317 std::vector<UnifiedMeshlet> meshlets;
318 std::vector<MeshletBounds> meshletBounds;
319 std::vector<ObjectCullingData> objectCullingData;
320 std::vector<PrimitiveMeshletData> objectMeshletData;
321
322 std::vector<const MeshPrimitive *>
323 getMeshPrimitivesFromMeshes( const std::vector<const Mesh *> & meshes ) const;
324 std::vector<MeshPrimitive *> getMeshPrimitivesFromMeshes( const std::vector<Mesh *> & meshes );
325 uint32_t getMeshletCount( const std::vector<const Mesh *> & meshes ) const;
326
327 public:
329 {
330 return threadedCalculation;
331 }
332
334 {
335 return threadPool;
336 }
337
338 private:
340
341 template <typename T>
342 void initMaterialStorageBuffer( PipelineNames name, uint32_t materialCount );
343
347 template <typename T>
348 uint32_t addMaterialData( T data );
349
354 template <typename MaterialDataType>
356 {
357 public:
358 explicit MaterialData( uint32_t materialCount );
359
360 [[nodiscard]] std::vector<MaterialDataType> getData() const;
361 [[nodiscard]] const DescriptorIndexAllocator & getIndexAllocator() const;
362
363 uint32_t addMaterialData( MaterialDataType materialData );
364
365 [[nodiscard]] size_t getMaterialCount() const;
366
367 void removeFromIndex( uint32_t materialIndex );
368
369 [[nodiscard]] size_t getCapacity() const;
370
371 private:
372 std::vector<MaterialDataType> data{};
374 };
375
376 std::unordered_map<PipelineNames, VulkanBuffer> materialStorageBuffers;
377
379 std::array<std::optional<MaterialShader>, 100> shaderData;
380 std::vector<MaterialShader *> shaders;
381 std::unordered_map<PipelineNames, MaterialShader *> shadersByName;
382
383 std::unordered_map<MaterialShader *, uint32_t> shaderOffsets;
384
386 Renderer * renderer = nullptr;
387
388 std::unordered_map<std::filesystem::path, Texture *, PathHasher> textures = {};
391
392 std::array<std::optional<Texture>, MAX_TEXTURE_COUNT> textureData;
394
402 bool doesTextureAlreadyExist( const std::filesystem::path & path );
403
413 Texture * registerTexture( const std::filesystem::path & path, Texture texture );
414 void unregisterTexture( Texture * texture );
415
416 TRACY_LOCKABLE( std::mutex, textureMutex, "Texture mutex" );
417 TRACY_LOCKABLE( std::mutex, meshesMutex, "Meshes mutex" );
418
419 Mesh * registerMesh( const std::filesystem::path & path, GltfLoader::GltfMeshData & gltfMeshData );
420 void unregisterMesh( Mesh * mesh );
421
422 std::array<std::optional<Mesh>, MAX_MESH_COUNT> meshData{};
424 std::unordered_map<std::filesystem::path, Mesh *, PathHasher> meshes = {};
425
426 bool bIsMeshDirty = true;
427 std::unordered_map<Mesh *, uint32_t> meshOffsets;
428
429 std::vector<TextureStorage> texturesToUpload{};
430 std::vector<Texture *> texturesToCopyImageData;
431 };
432
433 template <typename T>
434 void AssetManager::initMaterialStorageBuffer( const PipelineNames name, const uint32_t materialCount )
435 {
437
438 const size_t bufferSize = sizeof( T ) * materialCount;
439
440 materialStorageBuffers[name].overrideSize( bufferSize );
441 materialStorageBuffers[name].create(
442 bufferSize,
443 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
444 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
445 );
446 materialStorageBuffers[name].setDebugName( MaterialShader::getPipelineNameFromString( name ) + " Buffer" );
447
448 PLOGI << "Created material storage buffer with size " << bufferSize << " bytes and a count of "
449 << materialCount;
450 }
451
452 template <typename T>
454 {
456 /*constexpr PipelineNames materialName = MaterialNameTrait<T>::value;
457
458 if constexpr ( materialName == NORMALS_SHADER )
459 {
460 return normalMaterialData.addMaterialData( data );
461 }
462 if constexpr ( materialName == DIFFUSE_FLAT_COLOR )
463 {
464 return diffuseFlatColorMaterialData.addMaterialData( data );
465 }
466 // TODO: Add rest of all material data
467 throw std::runtime_error( "Material not yet implemented!" );*/
468 }
469
470 template <typename T>
472 : data( materialCount ), allocator( materialCount )
473 {
474 }
475
476 template <typename T>
478 {
479 return data;
480 }
481
482 template <typename T>
487
488 template <typename T>
490 {
491 uint32_t freeIndex = allocator.allocate();
492 data[freeIndex] = materialData;
493 return freeIndex;
494 }
495
496 template <typename T>
498 {
499 return allocator.getUsedIndices().size();
500 }
501
502 template <typename T>
504 {
505 allocator.free( materialIndex );
506 data[materialIndex] = {};
507 }
508
509 template <typename T>
511 {
512 return allocator.getCapacity();
513 }
514} // namespace EngineCore
#define FUNCTION_DEPRECATED_RETURN
constexpr uint32_t MAX_MESH_COUNT
Definition Settings.h:36
constexpr uint32_t MAX_TEXTURE_COUNT
Definition Settings.h:35
#define TRACY_LOCKABLE(type, varname, desc)
The model asset pipeline loads a gltf scene and loads and loads the mesh and material data....
Infrastructure to load images into the ecs.
std::vector< MaterialDataType > data
const DescriptorIndexAllocator & getIndexAllocator() const
std::vector< MaterialDataType > getData() const
DescriptorIndexAllocator allocator
uint32_t addMaterialData(MaterialDataType materialData)
MaterialData(uint32_t materialCount)
void removeFromIndex(uint32_t materialIndex)
NamedThreadPool * threadedCalculation
uint32_t getMeshletCount(const std::vector< const Mesh * > &meshes) const
uint32_t getMeshOffset(Mesh *mesh) const
std::unordered_map< Mesh *, uint32_t > getMeshOffsets() const
std::unordered_map< MaterialShader *, uint32_t > shaderOffsets
MaterialShader * registerShader(MaterialShader shader, const PipelineNames &materialName)
BidirectionalMap< uint32_t, Mesh * > meshIndexMap
MeshAssetManager * getMeshAssetManager() const
Gets the mesh asset manager for mesh asset lookups.
Ecs::ModelAssetPipeline & getMeshAssetPipeline()
std::vector< UnifiedMeshlet > meshlets
NamedThreadPool * getAssetLoaderPool() const
uint32_t addMaterialData(T data)
std::vector< CpuMeshData > cpuMeshData
uint32_t getTextureDescriptorIndex(const std::filesystem::path &path)
Gets the descriptor index of a loaded texture by path.
DescriptorIndexAllocator textureAllocator
std::vector< MaterialShader * > shaders
std::unordered_map< PipelineNames, VulkanBuffer > materialStorageBuffers
void unregisterMesh(Mesh *mesh)
BidirectionalMap< uint32_t, Texture * > textureIndexMap
MeshAsset * getMeshAsset(const Asset::Path &asset)
Get a mesh from the asset manager. If it does not exist it requests the asset from the asset loader.
std::vector< PrimitiveMeshletData > objectMeshletData
DescriptorIndexAllocator shaderAllocator
DescriptorIndexAllocator meshAllocator
void unregisterTexture(Texture *texture)
std::unordered_map< PipelineNames, MaterialShader * > shadersByName
ApplicationContext * context
std::unordered_map< std::filesystem::path, Texture *, PathHasher > textures
void unregisterShader(MaterialShader *shader)
MeshAssetManager * meshAssetManager
MaterialShader * getShaderByName(const std::string &shaderName)
Ecs::TextureAssetPipeline texturePipeline
VulkanBuffer & getMaterialStorageBufferByName(PipelineNames name)
std::unordered_map< Mesh *, uint32_t > meshOffsets
bool doesTextureAlreadyExist(const std::filesystem::path &path)
Checks if a texture has already been loaded.
TextureAssetManager * textureAssetManager
NamedThreadPool * threadPool
std::vector< const Mesh * > getAllMeshes() const
Gets a copy of all meshes which are currently loaded in the asset manager.
std::vector< Texture * > texturesToCopyImageData
std::array< std::optional< Mesh >, MAX_MESH_COUNT > meshData
uint32_t getTotalPrimitiveCount() const
Mesh * registerMesh(const std::filesystem::path &path, GltfLoader::GltfMeshData &gltfMeshData)
TextureHandleRegistry textureHandleRegistry_
Registry for type-safe texture handles.
void setRenderingDataManager(RenderingDataManager *renderingDataManager)
Sets the RenderingDataManager on asset pipelines for hook notifications.
void attachToRenderer(Renderer *renderer)
Sets what renderer the render process belongs to.
std::vector< const MeshPrimitive * > getMeshPrimitivesFromMeshes(const std::vector< const Mesh * > &meshes) const
PipelineNames materialNameFromString(const std::string &string)
uint32_t getImageCount() const
std::vector< MeshletBounds > meshletBounds
Ecs::ModelAssetPipeline modelAssetPipeline
MaterialAssetManager * materialAssetManager
std::unordered_map< std::filesystem::path, Mesh *, PathHasher > meshes
std::vector< ObjectCullingData > objectCullingData
ModelAssetManager * modelAssetManager
MaterialAssetManager * getMaterialAssetManager() const
Gets the material asset manager for material lookups.
std::array< std::optional< MaterialShader >, 100 > shaderData
Ecs::TextureAssetPipeline & getTextureAssetPipeline()
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...
ModelAssetManager * getModelAssetManager() const
Gets the model asset manager for model/GLTF file loading state lookups.
std::vector< VkDescriptorImageInfo > getTextureDescriptorInfos() const
void loadEcsTexture(const std::filesystem::path &path)
Loads a texture (.png / .jpg / .exr)
std::vector< TextureStorage > texturesToUpload
NamedThreadPool * getCalculationPool() const
TextureHandleRegistry * getTextureHandleRegistry()
Gets the texture handle registry for O(1) descriptor index lookups.
uint32_t getShaderCount() const
std::vector< MaterialShader * > getShaders() const
std::vector< Texture * > getTexturesToUpload()
void initMaterialStorageBuffer(PipelineNames name, uint32_t materialCount)
Texture * registerTexture(const std::filesystem::path &path, Texture texture)
Registers a texture with the texture manager which prevents the same texture from being loaded twice.
std::array< std::optional< Texture >, MAX_TEXTURE_COUNT > textureData
bool doesMeshAlreadyExist(const std::filesystem::path &meshPath) const
Checks if a mesh is already present in the loaded meshes in RAM.
Use this class to manage a finite amount of memory. The idea is to have an array which stores objects...
Stores mesh data with their primitives.
Definition MeshAsset.h:54
The mesh asset stores geometry data and.
Definition MeshAsset.h:15
The render process class consolidates all the resources that needs to be duplicated for each frame th...
The renderer is the main class for rendering. It owns all data which is used any time in any frame....
Definition Renderer.h:72
The rendering data manager is supposed to hold all methods to update the contents of the buffers whic...
Wrapper for texture data.
Central registry for texture handles, providing O(1) descriptor index lookup.
RAII wrapper for Vulkan buffer and device memory.
Tracy-named thread pool using BS_tracy::tracy_thread_pool.
Log category system implementation.
uint32_t packTexCoordR16G16_SFLOAT(const glm::vec2 &tc)
uint32_t packNormalA2B10G10R10_SNORM(const glm::vec3 &n)
uint32_t packColorR8G8B8A8_UNORM(const glm::vec3 &c)
static std::string getPipelineNameFromString(PipelineNames pipelineName)
Gets the pipeline name as string.
Used in meshlet culling.
Definition RenderData.h:92
std::size_t operator()(const std::filesystem::path &p) const noexcept
std::shared_ptr< Texture > texture
bool operator<(const T &other)
bool operator>(const T &other)
Information about the wereabouts of a meshlet in memory on the gpu.
Definition RenderData.h:76