diff --git a/src/render/filament/core/filament_context.cc b/src/render/filament/core/filament_context.cc index 1e386165..b6302e18 100644 --- a/src/render/filament/core/filament_context.cc +++ b/src/render/filament/core/filament_context.cc @@ -94,16 +94,17 @@ mjrfFrameHandle FilamentContext::Render( ValidateSwapChains(requests); - material_manager_->BeginFrame(); - std::unordered_map> scene_to_requests; for (const mjrfRenderRequest& request : requests) { scene_to_requests[request.scene].push_back(&request); } + + material_manager_->PrepareToRender(); for (auto& [scene, requests] : scene_to_requests) { SceneView::downcast(scene)->PrepareToRender(requests); } + material_manager_->RemoveUnusedMaterials(); bool render_began = false; mjrfRenderTarget* current_target = nullptr; @@ -159,7 +160,6 @@ mjrfFrameHandle FilamentContext::Render( if (render_began) { renderer_->endFrame(); - material_manager_->EndFrame(); } if constexpr (!UTILS_HAS_THREADING) { engine_->execute(); diff --git a/src/render/filament/core/material_manager.cc b/src/render/filament/core/material_manager.cc index a1da1716..111a3cb6 100644 --- a/src/render/filament/core/material_manager.cc +++ b/src/render/filament/core/material_manager.cc @@ -38,6 +38,13 @@ static void Combine(uint64_t& seed, const T* v) { seed ^= std::hash()(*v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } +static void Combine(uint64_t& seed, const mjrfTexture* texture) { + if (texture) { + const uint64_t id = Texture::downcast(texture)->Id(); + Combine(seed, &id); + } +} + template static uint64_t hash(const T& obj) { static_assert(std::is_trivially_copyable_v, @@ -77,9 +84,9 @@ MaterialManager::~MaterialManager() { } } -void MaterialManager::BeginFrame() { used_keys_.clear(); } +void MaterialManager::PrepareToRender() { used_keys_.clear(); } -void MaterialManager::EndFrame() { +void MaterialManager::RemoveUnusedMaterials() { if (instances_.size() == used_keys_.size()) { return; } @@ -102,6 +109,15 @@ static MaterialManager::MaterialKey BuildMaterialKey( uint64_t key = hash(material); Combine(key, &geom_type); Combine(key, &material_type); + Combine(key, material.color_texture); + Combine(key, material.opacity_texture); + Combine(key, material.normal_texture); + Combine(key, material.orm_texture); + Combine(key, material.metallic_texture); + Combine(key, material.roughness_texture); + Combine(key, material.occlusion_texture); + Combine(key, material.emissive_texture); + Combine(key, material.reflection_texture); return key; } diff --git a/src/render/filament/core/material_manager.h b/src/render/filament/core/material_manager.h index 4c68bb24..ab79abfd 100644 --- a/src/render/filament/core/material_manager.h +++ b/src/render/filament/core/material_manager.h @@ -52,10 +52,10 @@ class MaterialManager { // Marks the beginning of a new frame, allowing us to track which // MaterialInstances are used during the frame so they can be removed at the // end of the frame. - void BeginFrame(); + void PrepareToRender(); // Removes any unused MaterialInstances. - void EndFrame(); + void RemoveUnusedMaterials(); // Returns a MaterialType that best matches the given material data and mesh. MaterialType GetMaterialType(const mjrfMaterial& material, const Mesh* mesh); diff --git a/src/render/filament/core/texture.cc b/src/render/filament/core/texture.cc index 2e11d5b7..68d0ea7c 100644 --- a/src/render/filament/core/texture.cc +++ b/src/render/filament/core/texture.cc @@ -14,6 +14,7 @@ #include "render/filament/core/texture.h" +#include #include #include #include @@ -28,6 +29,8 @@ namespace mujoco { +static std::atomic g_next_texture_id{1}; + static constexpr int kNumFacesPerCube = 6; static bool IsCompressed(const mjrfTextureConfig& config) { @@ -115,7 +118,7 @@ static filament::Texture::InternalFormat GetTextureInternalFormat( Texture::Texture(filament::Engine* engine, const mjrfTextureConfig& config, InternalFlags flags) - : engine_(engine), config_(config) { + : id_(g_next_texture_id++), engine_(engine), config_(config) { if (IsCompressed(config_)) { // We defer creation of compressed textures until Upload() is called. In // the meantime, we don't really know anything about the texture (e.g. diff --git a/src/render/filament/core/texture.h b/src/render/filament/core/texture.h index 8fe4778d..230f12e0 100644 --- a/src/render/filament/core/texture.h +++ b/src/render/filament/core/texture.h @@ -15,6 +15,7 @@ #ifndef MUJOCO_SRC_RENDER_FILAMENT_CORE_TEXTURE_H_ #define MUJOCO_SRC_RENDER_FILAMENT_CORE_TEXTURE_H_ +#include #include #include #include @@ -57,6 +58,9 @@ class Texture : public mjrfTexture { // Returns the underlying filament texture. filament::Texture* GetFilamentTexture() const { return texture_; } + // Returns the unique id of the texture. + uint64_t Id() const { return id_; } + // Returns any spherical harmonics data associated with the texture. using SphericalHarmonics = filament::math::float3[9]; const SphericalHarmonics* GetSphericalHarmonics() const { @@ -73,6 +77,7 @@ class Texture : public mjrfTexture { private: void ReleaseData(); + uint64_t id_ = 0; filament::Engine* engine_ = nullptr; filament::Texture* texture_ = nullptr; mjrfTextureConfig config_;