diff --git a/Source/GltfImporter.cpp b/Source/GltfImporter.cpp index b96ec21a..eefe3953 100644 --- a/Source/GltfImporter.cpp +++ b/Source/GltfImporter.cpp @@ -574,6 +574,7 @@ namespace uint32_t frameIndex, const cgltf_material* mat, TextureManager& textureManager, + bool isReplacement, const std::filesystem::path& gltfFolder, std::string_view gltfPath ) { @@ -726,7 +727,7 @@ namespace if( !materialName.empty() ) { textureManager.TryCreateImportedMaterial( - cmd, frameIndex, materialName, fullPaths, samplers, pbrSwizzling ); + cmd, frameIndex, materialName, fullPaths, samplers, pbrSwizzling, isReplacement ); } if( auto t = mat->pbr_metallic_roughness.metallic_roughness_texture.texture ) @@ -967,6 +968,7 @@ RTGL1::GltfImporter::~GltfImporter() auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures, uint32_t frameIndex, TextureManager& textureManager, + bool isReplacement, const TextureMetaManager& textureMeta ) const -> WholeModelFile { cgltf_node* mainNode = FindMainRootNode( data ); @@ -1042,7 +1044,7 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures, // mesh auto AppendMeshPrimitives = - [ this, &cmdForTextures, &frameIndex, &textureManager, &textureMeta ]( + [ this, &cmdForTextures, &frameIndex, &textureManager, &isReplacement, & textureMeta ]( std::vector< WholeModelFile::RawModelData::RawPrimitiveData >& target, const cgltf_node* atnode, const RgTransform* transform ) { @@ -1112,6 +1114,7 @@ auto RTGL1::GltfImporter::ParseFile( VkCommandBuffer cmdForTextures, frameIndex, srcPrim.material, textureManager, + isReplacement, gltfFolder, gltfPath ); diff --git a/Source/GltfImporter.h b/Source/GltfImporter.h index 5451c867..ab24d406 100644 --- a/Source/GltfImporter.h +++ b/Source/GltfImporter.h @@ -84,6 +84,7 @@ class GltfImporter [[nodiscard]] auto ParseFile( VkCommandBuffer cmdForTextures, uint32_t frameIndex, TextureManager& textureManager, + bool isReplacement, const TextureMetaManager& textureMeta ) const -> WholeModelFile; explicit operator bool() const; diff --git a/Source/Scene.cpp b/Source/Scene.cpp index 5246262c..ea1ea4c6 100644 --- a/Source/Scene.cpp +++ b/Source/Scene.cpp @@ -517,8 +517,7 @@ void RTGL1::Scene::NewScene( VkCommandBuffer cmd, staticLights.clear(); { - // TODO: free only static-scene related if !reimportReplacements - textureManager.FreeAllImportedMaterials( frameIndex ); + textureManager.FreeAllImportedMaterials( frameIndex, reimportReplacements ); } assert( !makingStatic ); @@ -536,7 +535,7 @@ void RTGL1::Scene::NewScene( VkCommandBuffer cmd, { if( auto i = GltfImporter{ path, worldTransform, worldScale } ) { - auto wholeGltf = i.ParseFile( cmd, frameIndex, textureManager, textureMeta ); + auto wholeGltf = i.ParseFile( cmd, frameIndex, textureManager, true, textureMeta ); if( !wholeGltf.lights.empty() ) { @@ -592,7 +591,7 @@ void RTGL1::Scene::NewScene( VkCommandBuffer cmd, { debug::Verbose( "Starting new static scene..." ); const auto sceneFile = - staticScene.ParseFile( cmd, frameIndex, textureManager, textureMeta ); + staticScene.ParseFile( cmd, frameIndex, textureManager, false, textureMeta ); for( const auto& [ name, m ] : sceneFile.models ) { diff --git a/Source/TextureManager.cpp b/Source/TextureManager.cpp index 6bf92c47..25680283 100644 --- a/Source/TextureManager.cpp +++ b/Source/TextureManager.cpp @@ -30,6 +30,7 @@ #include "Generated/ShaderCommonC.h" #include +#include using namespace RTGL1; @@ -541,7 +542,8 @@ bool TextureManager::TryCreateImportedMaterial( VkCommandBuffer const std::string& materialName, std::span< std::filesystem::path > fullPaths, std::span< SamplerManager::Handle > samplers, - RgTextureSwizzling customPbrSwizzling ) + RgTextureSwizzling customPbrSwizzling, + bool isReplacement ) { assert( fullPaths.size() == TEXTURES_PER_MATERIAL_COUNT ); assert( samplers.size() == TEXTURES_PER_MATERIAL_COUNT ); @@ -552,9 +554,18 @@ bool TextureManager::TryCreateImportedMaterial( VkCommandBuffer return false; } - if( importedMaterials.contains( materialName ) ) + // check if already uploaded { - return true; + auto found = importedMaterials.find( materialName ); + if( found != importedMaterials.end() ) + { + if( isReplacement ) + { + // promote to a stronger type + found->second = ImportedType::ForReplacement; + } + return true; + } } if( PreferExistingMaterials ) @@ -607,19 +618,36 @@ bool TextureManager::TryCreateImportedMaterial( VkCommandBuffer static_assert( TEXTURE_OCCLUSION_ROUGHNESS_METALLIC_INDEX == 1 ); // to free later / to prevent export from ExportOriginalMaterialTextures - importedMaterials.insert( materialName ); + auto [ iter, isNew ] = importedMaterials.emplace( + materialName, isReplacement ? ImportedType::ForReplacement : ImportedType::ForStatic ); + assert( isNew ); MakeMaterial( cmd, frameIndex, materialName, ovrd, samplers, swizzlings ); return true; } -void TextureManager::FreeAllImportedMaterials( uint32_t frameIndex ) +void TextureManager::FreeAllImportedMaterials( uint32_t frameIndex, bool freeReplacements ) { - for( const auto& materialName : importedMaterials ) + if( freeReplacements ) { - TryDestroyMaterial( frameIndex, materialName.c_str() ); + for( const auto& materialName : importedMaterials | std::views::keys ) + { + TryDestroyMaterial( frameIndex, materialName.c_str() ); + } + importedMaterials.clear(); + } + else + { + for( const auto& [ materialName, importType ] : importedMaterials ) + { + if( importType != ImportedType::ForReplacement ) + { + TryDestroyMaterial( frameIndex, materialName.c_str() ); + } + } + erase_if( importedMaterials, + []( const auto& kv ) { return kv.second != ImportedType::ForReplacement; } ); } - importedMaterials.clear(); } uint32_t TextureManager::PrepareTexture( VkCommandBuffer cmd, diff --git a/Source/TextureManager.h b/Source/TextureManager.h index a68cb011..47d22a43 100644 --- a/Source/TextureManager.h +++ b/Source/TextureManager.h @@ -81,8 +81,9 @@ class TextureManager : public IFileDependency const std::string& materialName, std::span< std::filesystem::path > fullPaths, std::span< SamplerManager::Handle > samplers, - RgTextureSwizzling customPbrSwizzling ); - void FreeAllImportedMaterials( uint32_t frameIndex ); + RgTextureSwizzling customPbrSwizzling, + bool isReplacement ); + void FreeAllImportedMaterials( uint32_t frameIndex, bool freeReplacements ); bool TryDestroyMaterial( uint32_t frameIndex, const char* materialName ); @@ -216,8 +217,14 @@ class TextureManager : public IFileDependency std::vector< Texture > texturesToDestroy[ MAX_FRAMES_IN_FLIGHT ]; std::vector< std::filesystem::path > texturesToReload; - rgl::string_map< Material > materials; - rgl::string_set importedMaterials; + enum class ImportedType + { + ForReplacement, + ForStatic, + }; + + rgl::string_map< Material > materials; + rgl::string_map< ImportedType > importedMaterials; uint32_t waterNormalTextureIndex; uint32_t dirtMaskTextureIndex;