Browse Source

Refactored resource dependency tracking.
Reset material to defaults when reloading.

Lasse Öörni 12 years ago
parent
commit
245e678fd6

+ 3 - 0
Engine/Graphics/Direct3D9/D3D9Shader.cpp

@@ -49,6 +49,9 @@ Shader::Shader(Context* context) :
 
 Shader::~Shader()
 {
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    if (cache)
+        cache->ResetDependencies(this);
 }
 
 void Shader::RegisterObject(Context* context)

+ 24 - 13
Engine/Graphics/Material.cpp

@@ -105,22 +105,12 @@ OBJECTTYPESTATIC(Material);
 
 Material::Material(Context* context) :
     Resource(context),
-    cullMode_(CULL_CCW),
-    shadowCullMode_(CULL_CCW),
-    depthBias_(BiasParameters(0.0f, 0.0f)),
     auxViewFrameNumber_(0),
-    occlusion_(true),
-    specular_(false)
+    specular_(false),
+    occlusion_(true)
 {
     SetNumTechniques(1);
-    
-    // Setup often used default parameters
-    SetShaderParameter("UOffset", Vector4(1.0f, 0.0f, 0.0f, 0.0f));
-    SetShaderParameter("VOffset", Vector4(0.0f, 1.0f, 0.0f, 0.0f));
-    SetShaderParameter("MatDiffColor", Vector4::ONE);
-    SetShaderParameter("MatEmissiveColor", Vector4::ZERO);
-    SetShaderParameter("MatEnvMapColor", Vector4::ONE);
-    SetShaderParameter("MatSpecColor", Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+    ResetToDefaults();
 }
 
 Material::~Material()
@@ -141,6 +131,8 @@ bool Material::Load(Deserializer& source)
     if (!graphics)
         return true;
     
+    ResetToDefaults();
+    
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     
     SharedPtr<XMLFile> xml(new XMLFile(context_));
@@ -454,4 +446,23 @@ void Material::CheckOcclusion()
     }
 }
 
+void Material::ResetToDefaults()
+{
+    for (unsigned i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i)
+        textures_[i] = 0;
+    
+    shaderParameters_.Clear();
+    
+    SetShaderParameter("UOffset", Vector4(1.0f, 0.0f, 0.0f, 0.0f));
+    SetShaderParameter("VOffset", Vector4(0.0f, 1.0f, 0.0f, 0.0f));
+    SetShaderParameter("MatDiffColor", Vector4::ONE);
+    SetShaderParameter("MatEmissiveColor", Vector4::ZERO);
+    SetShaderParameter("MatEnvMapColor", Vector4::ONE);
+    SetShaderParameter("MatSpecColor", Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+    
+    cullMode_ = CULL_CCW;
+    shadowCullMode_ = CULL_CCW;
+    depthBias_ = BiasParameters(0.0f, 0.0f);
+}
+
 }

+ 2 - 0
Engine/Graphics/Material.h

@@ -145,6 +145,8 @@ public:
 private:
     /// Re-evaluate occlusion rendering.
     void CheckOcclusion();
+    /// Reset to defaults.
+    void ResetToDefaults();
     
     /// Techniques.
     Vector<TechniqueEntry> techniques_;

+ 50 - 33
Engine/Resource/ResourceCache.cpp

@@ -44,7 +44,7 @@ static const String checkDirs[] = {
     "Music",
     "Objects",
     "Particle",
-	"PostProcess",
+    "PostProcess",
     "RenderPaths",
     "Scenes",
     "Scripts",
@@ -600,30 +600,28 @@ void ResourceCache::StoreNameHash(const String& name)
 
 void ResourceCache::StoreResourceDependency(Resource* resource, const String& dependency)
 {
-    Vector<WeakPtr<Resource> >& dependents = dependentResources_[StringHash(dependency)];
-    WeakPtr<Resource> resourceWeak(resource);
-    if (!dependents.Contains(resourceWeak))
-        dependents.Push(resourceWeak);
+    // If resource reloading is not on, do not create the dependency data structure (saves memory)
+    if (!resource || !autoReloadResources_)
+        return;
+    
+    StringHash nameHash(resource->GetName());
+    HashSet<StringHash>& dependents = dependentResources_[StringHash(dependency)];
+    dependents.Insert(nameHash);
 }
 
 void ResourceCache::ResetDependencies(Resource* resource)
 {
-    WeakPtr<Resource> resourceWeak(resource);
+    if (!resource || !autoReloadResources_)
+        return;
     
-    for (HashMap<StringHash, Vector<WeakPtr<Resource> > >::Iterator i = dependentResources_.Begin(); i !=
+    StringHash nameHash(resource->GetName());
+    
+    for (HashMap<StringHash, HashSet<StringHash> >::Iterator i = dependentResources_.Begin(); i !=
         dependentResources_.End();)
     {
-        Vector<WeakPtr<Resource> >& dependents = i->second_;
-        bool remove = false;
-        
-        if (dependents.Contains(resourceWeak))
-        {
-            dependents.Remove(resourceWeak);
-            if (dependents.Empty())
-                remove = true;
-        }
-        
-        if (remove)
+        HashSet<StringHash>& dependents = i->second_;
+        dependents.Erase(nameHash);
+        if (dependents.Empty())
             i = dependentResources_.Erase(i);
         else
             ++i;
@@ -642,6 +640,18 @@ const SharedPtr<Resource>& ResourceCache::FindResource(ShortStringHash type, Str
     return j->second_;
 }
 
+const SharedPtr<Resource>& ResourceCache::FindResource(StringHash nameHash)
+{
+    for (HashMap<ShortStringHash, ResourceGroup>::Iterator i = resourceGroups_.Begin(); i != resourceGroups_.End(); ++i)
+    {
+        HashMap<StringHash, SharedPtr<Resource> >::Iterator j = i->second_.resources_.Find(nameHash);
+        if (j != i->second_.resources_.End())
+            return j->second_;
+    }
+    
+    return noResource;
+}
+
 void ResourceCache::ReleasePackageResources(PackageFile* package, bool force)
 {
     HashSet<ShortStringHash> affectedGroups;
@@ -722,26 +732,33 @@ void ResourceCache::HandleBeginFrame(StringHash eventType, VariantMap& eventData
         {
             StringHash fileNameHash(fileName);
             // If the filename is a resource we keep track of, reload it
-            for (HashMap<ShortStringHash, ResourceGroup>::Iterator j = resourceGroups_.Begin(); j != resourceGroups_.End(); ++j)
+            const SharedPtr<Resource>& resource = FindResource(fileNameHash);
+            if (resource)
             {
-                HashMap<StringHash, SharedPtr<Resource> >::Iterator k = j->second_.resources_.Find(fileNameHash);
-                if (k != j->second_.resources_.End())
-                {
-                    LOGDEBUG("Reloading changed resource " + fileName);
-                    ReloadResource(k->second_);
-                }
+                LOGDEBUG("Reloading changed resource " + fileName);
+                ReloadResource(resource);
             }
-            // Check if this is a dependency resource, reload dependents
-            HashMap<StringHash, Vector<WeakPtr<Resource> > >::Iterator j = dependentResources_.Find(fileNameHash);
-            if (j != dependentResources_.End())
+            else
             {
-                Vector<WeakPtr<Resource> >& dependents = j->second_;
-                for (unsigned k = 0; k < dependents.Size(); ++k)
+                // Check if this is a dependency resource, reload dependents
+                HashMap<StringHash, HashSet<StringHash> >::ConstIterator j = dependentResources_.Find(fileNameHash);
+                if (j != dependentResources_.End())
                 {
-                    if (dependents[k])
+                    // Reloading a resource may modify the dependency tracking structure. Therefore collect the
+                    // resources we need to reload first
+                    Vector<SharedPtr<Resource> > dependents;
+                    
+                    for (HashSet<StringHash>::ConstIterator k = j->second_.Begin(); k != j->second_.End(); ++k)
+                    {
+                        const SharedPtr<Resource>& dependent = FindResource(*k);
+                        if (dependent)
+                            dependents.Push(dependent);
+                    }
+                    
+                    for (unsigned i = 0; i < dependents.Size(); ++i)
                     {
-                        LOGDEBUG("Reloading resource " + dependents[k]->GetName() + " depending on " + fileName);
-                        ReloadResource(dependents[k]);
+                        LOGDEBUG("Reloading resource " + dependents[i]->GetName() + " depending on " + fileName);
+                        ReloadResource(dependents[i]);
                     }
                 }
             }

+ 3 - 1
Engine/Resource/ResourceCache.h

@@ -140,6 +140,8 @@ public:
 private:
     /// Find a resource.
     const SharedPtr<Resource>& FindResource(ShortStringHash type, StringHash nameHash);
+    /// Find a resource by name only. Searches all type groups.
+    const SharedPtr<Resource>& FindResource(StringHash nameHash);
     /// Release resources loaded from a package file.
     void ReleasePackageResources(PackageFile* package, bool force = false);
     /// Update a resource group. Recalculate memory use and release resources if over memory budget.
@@ -158,7 +160,7 @@ private:
     /// Mapping of hashes to filenames.
     HashMap<StringHash, String> hashToName_;
     /// Dependent resources.
-    HashMap<StringHash, Vector<WeakPtr<Resource> > > dependentResources_;
+    HashMap<StringHash, HashSet<StringHash> > dependentResources_;
     /// Automatic resource reloading flag.
     bool autoReloadResources_;
 };