Quellcode durchsuchen

Calculate a shader parameter hash value to eliminate setting of unnecessary constants/uniforms when rendering with multiple materials that have the same parameters.

Lasse Öörni vor 11 Jahren
Ursprung
Commit
c08fa5e94d

+ 1 - 1
Source/Urho3D/Graphics/Batch.cpp

@@ -548,7 +548,7 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
     // Set material-specific shader parameters and textures
     if (material_)
     {
-        if (graphics->NeedParameterUpdate(SP_MATERIAL, material_))
+        if (graphics->NeedParameterUpdate(SP_MATERIAL, (const void*)material_->GetShaderParameterHash()))
         {
             const HashMap<StringHash, MaterialShaderParameter>& parameters = material_->GetShaderParameters();
             for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)

+ 32 - 3
Source/Urho3D/Graphics/Material.cpp

@@ -25,6 +25,7 @@
 #include "../IO/FileSystem.h"
 #include "../Graphics/Graphics.h"
 #include "../IO/Log.h"
+#include "../IO/VectorBuffer.h"
 #include "../Graphics/Material.h"
 #include "../Math/Matrix3x4.h"
 #include "../Core/Profiler.h"
@@ -153,9 +154,11 @@ Material::Material(Context* context) :
     Resource(context),
     auxViewFrameNumber_(0),
     numUsedTextureUnits_(0),
+    shaderParameterHash_(0),
     occlusion_(true),
     specular_(false),
-    subscribed_(false)
+    subscribed_(false),
+    batchedParameterUpdate_(false)
 {
     ResetToDefaults();
 }
@@ -298,6 +301,7 @@ bool Material::Load(const XMLElement& source)
         textureElem = textureElem.GetNext("texture");
     }
 
+    batchedParameterUpdate_ = true;
     XMLElement parameterElem = source.GetChild("parameter");
     while (parameterElem)
     {
@@ -305,6 +309,7 @@ bool Material::Load(const XMLElement& source)
         SetShaderParameter(name, ParseShaderParameterValue(parameterElem.GetAttribute("value")));
         parameterElem = parameterElem.GetNext("parameter");
     }
+    batchedParameterUpdate_ = false;
 
     XMLElement parameterAnimationElem = source.GetChild("parameteranimation");
     while (parameterAnimationElem)
@@ -346,6 +351,7 @@ bool Material::Load(const XMLElement& source)
     if (depthBiasElem)
         SetDepthBias(BiasParameters(depthBiasElem.GetFloat("constant"), depthBiasElem.GetFloat("slopescaled")));
 
+    RefreshShaderParameterHash();
     RefreshMemoryUse();
     CheckOcclusion();
     return true;
@@ -461,7 +467,11 @@ void Material::SetShaderParameter(const String& name, const Variant& value)
         }
     }
 
-    RefreshMemoryUse();
+    if (!batchedParameterUpdate_)
+    {
+        RefreshShaderParameterHash();
+        RefreshMemoryUse();
+    }
 }
 
 void Material::SetShaderParameterAnimation(const String& name, ValueAnimation* animation, WrapMode wrapMode, float speed)
@@ -595,6 +605,7 @@ void Material::RemoveShaderParameter(const String& name)
     if (nameHash == PSP_MATSPECCOLOR)
         specular_ = false;
 
+    RefreshShaderParameterHash();
     RefreshMemoryUse();
 }
 
@@ -729,22 +740,40 @@ void Material::ResetToDefaults()
     for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
         textures_[i] = 0;
 
+    batchedParameterUpdate_ = true;
     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", Vector3::ZERO);
     SetShaderParameter("MatEnvMapColor", Vector3::ONE);
     SetShaderParameter("MatSpecColor", Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+    batchedParameterUpdate_ = false;
 
     cullMode_ = CULL_CCW;
     shadowCullMode_ = CULL_CCW;
     depthBias_ = BiasParameters(0.0f, 0.0f);
 
+    RefreshShaderParameterHash();
     RefreshMemoryUse();
 }
 
+void Material::RefreshShaderParameterHash()
+{
+    VectorBuffer temp;
+    for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = shaderParameters_.Begin(); i != shaderParameters_.End(); ++i)
+    {
+        temp.WriteStringHash(i->first_);
+        temp.WriteVariant(i->second_.value_);
+    }
+
+    shaderParameterHash_ = 0;
+    const unsigned char* data = temp.GetData();
+    unsigned dataSize = temp.GetSize();
+    for (unsigned i = 0; i < dataSize; ++i)
+        shaderParameterHash_ = SDBMHash(shaderParameterHash_, data[i]);
+}
+
 void Material::RefreshMemoryUse()
 {
     unsigned memoryUse = sizeof(Material);

+ 9 - 1
Source/Urho3D/Graphics/Material.h

@@ -191,6 +191,8 @@ public:
     Scene* GetScene() const;
     /// Return the last non-null texture unit + 1. Used as an optimization when applying the material to render state.
     unsigned GetNumUsedTextureUnits() const { return numUsedTextureUnits_; }
+    /// Return shader parameter hash value. Used as an optimization to avoid setting shader parameters unnecessarily.
+    unsigned GetShaderParameterHash() const { return shaderParameterHash_; }
 
     /// Return name for texture unit.
     static String GetTextureUnitName(TextureUnit unit);
@@ -202,6 +204,8 @@ private:
     void CheckOcclusion();
     /// Reset to defaults.
     void ResetToDefaults();
+    /// Recalculate shader parameter hash.
+    void RefreshShaderParameterHash();
     /// Recalculate the memory used by the material.
     void RefreshMemoryUse();
     /// Return shader parameter animation info.
@@ -210,7 +214,7 @@ private:
     void UpdateEventSubscription();
     /// Update shader parameter animations.
     void HandleAttributeAnimationUpdate(StringHash eventType, VariantMap& eventData);
-
+    
     /// Techniques.
     Vector<TechniqueEntry> techniques_;
     /// Textures.
@@ -229,12 +233,16 @@ private:
     unsigned auxViewFrameNumber_;
     /// Number of maximum non-null texture unit + 1.
     unsigned numUsedTextureUnits_;
+    /// Shader parameter hash value.
+    unsigned shaderParameterHash_;
     /// Render occlusion flag.
     bool occlusion_;
     /// Specular lighting flag.
     bool specular_;
     /// Flag for whether is subscribed to animation updates.
     bool subscribed_;
+    /// Flag to suppress parameter hash and memory use recalculation when setting multiple shader parameters (loading or resetting the material.)
+    bool batchedParameterUpdate_;
     /// XML file used while loading.
     SharedPtr<XMLFile> loadXMLFile_;
     /// Associated scene for shader parameter animation updates.