Bladeren bron

Reverted the previous shader parameter query optimization. Instead, added possibility to rehash a hashmap/hashset manually to a specified bucket count.

Lasse Öörni 14 jaren geleden
bovenliggende
commit
91500591c3

+ 20 - 0
Engine/Container/HashMap.h

@@ -305,6 +305,26 @@ public:
             ptrs_[i] = 0;
     }
     
+    /// Rehash to a specific bucket count, which must be a power of two. Return true if successful.
+    bool Rehash(unsigned numBuckets)
+    {
+        if (numBuckets == numBuckets_)
+            return true;
+        if (!numBuckets || numBuckets < size_ / MAX_LOAD_FACTOR)
+            return false;
+        
+        // Check for being power of two
+        unsigned check = numBuckets;
+        while (!(check & 1))
+            check >>= 1;
+        if (check != 1)
+            return false;
+        
+        numBuckets_ = numBuckets;
+        Rehash();
+        return true;
+    }
+    
     /// Return iterator to the pair with key, or end iterator if not found.
     Iterator Find(const T& key)
     {

+ 20 - 0
Engine/Container/HashSet.h

@@ -275,6 +275,26 @@ public:
             ptrs_[i] = 0;
     }
     
+    /// Rehash to a specific bucket count, which must be a power of two. Return true if successful.
+    bool Rehash(unsigned numBuckets)
+    {
+        if (numBuckets == numBuckets_)
+            return true;
+        if (!numBuckets || numBuckets < size_ / MAX_LOAD_FACTOR)
+            return false;
+        
+        // Check for being power of two
+        unsigned check = numBuckets;
+        while (!(check & 1))
+            check >>= 1;
+        if (check != 1)
+            return false;
+        
+        numBuckets_ = numBuckets;
+        Rehash();
+        return true;
+    }
+    
     /// Return iterator to the key, or end iterator if not found.
     Iterator Find(const T& key)
     {

+ 20 - 20
Engine/Graphics/Batch.cpp

@@ -101,47 +101,47 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
     }
     
     // Set viewport and camera shader parameters
-    if (graphics->NeedParameterUpdate(VS, VSP_CAMERAPOS, camera_))
+    if (graphics->NeedParameterUpdate(VSP_CAMERAPOS, camera_))
         graphics->SetShaderParameter(VSP_CAMERAPOS, camera_->GetWorldPosition());
     
-    if (graphics->NeedParameterUpdate(VS, VSP_CAMERAROT, camera_))
+    if (graphics->NeedParameterUpdate(VSP_CAMERAROT, camera_))
         graphics->SetShaderParameter(VSP_CAMERAROT, camera_->GetWorldTransform().RotationMatrix());
     
     if (overrideView_)
     {
         // If we override the view matrix, also disable any projection jittering
         /// \todo This may not be correct in all cases (skybox rendering?)
-        if (graphics->NeedParameterUpdate(VS, VSP_VIEWPROJ, ((unsigned char*)camera_) + 4))
+        if (graphics->NeedParameterUpdate(VSP_VIEWPROJ, ((unsigned char*)camera_) + 4))
             graphics->SetShaderParameter(VSP_VIEWPROJ, camera_->GetProjection(false));
     }
     else
     {
-        if (graphics->NeedParameterUpdate(VS, VSP_VIEWPROJ, camera_))
+        if (graphics->NeedParameterUpdate(VSP_VIEWPROJ, camera_))
             graphics->SetShaderParameter(VSP_VIEWPROJ, camera_->GetProjection() *
                 camera_->GetInverseWorldTransform());
     }
     
-    if (graphics->NeedParameterUpdate(VS, VSP_VIEWRIGHTVECTOR, camera_))
+    if (graphics->NeedParameterUpdate(VSP_VIEWRIGHTVECTOR, camera_))
         graphics->SetShaderParameter(VSP_VIEWRIGHTVECTOR, camera_->GetRightVector());
     
-    if (graphics->NeedParameterUpdate(VS, VSP_VIEWUPVECTOR, camera_))
+    if (graphics->NeedParameterUpdate(VSP_VIEWUPVECTOR, camera_))
         graphics->SetShaderParameter(VSP_VIEWUPVECTOR, camera_->GetUpVector());
     
     // Set model transform
-    if (setModelTransform && graphics->NeedParameterUpdate(VS, VSP_MODEL, worldTransform_))
+    if (setModelTransform && graphics->NeedParameterUpdate(VSP_MODEL, worldTransform_))
         graphics->SetShaderParameter(VSP_MODEL, *worldTransform_);
     
     // Set skinning transforms
     if (shaderData_ && shaderDataSize_)
     {
-        if (graphics->NeedParameterUpdate(VS, VSP_SKINMATRICES, shaderData_))
+        if (graphics->NeedParameterUpdate(VSP_SKINMATRICES, shaderData_))
             graphics->SetShaderParameter(VSP_SKINMATRICES, shaderData_, shaderDataSize_);
     }
     
     // Set light-related shader parameters
     if (light_)
     {
-        if (graphics->NeedParameterUpdate(VS, VSP_SPOTPROJ, light_))
+        if (graphics->NeedParameterUpdate(VSP_SPOTPROJ, light_))
         {
             Matrix3x4 spotView(light_->GetWorldPosition(), light_->GetWorldRotation(), 1.0f);
             Matrix4 spotProj(Matrix4::ZERO);
@@ -166,13 +166,13 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
             graphics->SetShaderParameter(VSP_SPOTPROJ, texAdjust * spotProj * spotView.Inverse());
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_LIGHTATTEN, light_))
+        if (graphics->NeedParameterUpdate(PSP_LIGHTATTEN, light_))
         {
             Vector4 lightAtten(1.0f / Max(light_->GetRange(), M_EPSILON), 0.0f, 0.0f, 0.0f);
             graphics->SetShaderParameter(PSP_LIGHTATTEN, lightAtten);
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_LIGHTCOLOR, light_))
+        if (graphics->NeedParameterUpdate(PSP_LIGHTCOLOR, light_))
         {
             float fade = 1.0f;
             float fadeEnd = light_->GetDrawDistance();
@@ -186,13 +186,13 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
                 light_->GetSpecularIntensity()) * fade);
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_LIGHTDIR, light_))
+        if (graphics->NeedParameterUpdate(PSP_LIGHTDIR, light_))
             graphics->SetShaderParameter(PSP_LIGHTDIR, light_->GetWorldRotation() * Vector3::BACK);
         
-        if (graphics->NeedParameterUpdate(PS, PSP_LIGHTPOS, light_))
+        if (graphics->NeedParameterUpdate(PSP_LIGHTPOS, light_))
             graphics->SetShaderParameter(PSP_LIGHTPOS, light_->GetWorldPosition() - camera_->GetWorldPosition());
         
-        if (graphics->NeedParameterUpdate(PS, PSP_LIGHTSPLITS, light_))
+        if (graphics->NeedParameterUpdate(PSP_LIGHTSPLITS, light_))
         {
             float nearFadeRange = light_->GetNearFadeRange();
             float farFadeRange = light_->GetFarFadeRange();
@@ -204,7 +204,7 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
                 farFadeStart / depthRange, 1.0f / (farFadeRange / depthRange)));
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_LIGHTVECROT, light_))
+        if (graphics->NeedParameterUpdate(PSP_LIGHTVECROT, light_))
         {
             Matrix3x4 lightVecRot;
             // Use original light if available (split lights)
@@ -217,7 +217,7 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
             graphics->SetShaderParameter(PSP_LIGHTVECROT, lightVecRot);
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_SPOTPROJ, light_))
+        if (graphics->NeedParameterUpdate(PSP_SPOTPROJ, light_))
         {
             Matrix3x4 viewPos(camera_->GetWorldPosition(), Quaternion::IDENTITY, Vector3::UNITY);
             Matrix3x4 spotView(light_->GetWorldPosition(), light_->GetWorldRotation(), 1.0f);
@@ -251,7 +251,7 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
     
     if (shadowMap)
     {
-        if (graphics->NeedParameterUpdate(VS, VSP_SHADOWPROJ, light_))
+        if (graphics->NeedParameterUpdate(VSP_SHADOWPROJ, light_))
         {
             Camera* shadowCamera = light_->GetShadowCamera();
             Matrix3x4 shadowView(shadowCamera->GetInverseWorldTransform());
@@ -270,13 +270,13 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
             graphics->SetShaderParameter(VSP_SHADOWPROJ, texAdjust * shadowProj * shadowView);
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_SAMPLEOFFSETS, shadowMap))
+        if (graphics->NeedParameterUpdate(PSP_SAMPLEOFFSETS, shadowMap))
         {
             float invWidth = 1.0f / (float)shadowMap->GetWidth();
             graphics->SetShaderParameter(PSP_SAMPLEOFFSETS, Vector4(0.5f * invWidth, -0.5f * invWidth, 0.0f, 0.0f));
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_SHADOWINTENSITY, light_))
+        if (graphics->NeedParameterUpdate(PSP_SHADOWINTENSITY, light_))
         {
             float intensity = light_->GetShadowIntensity();
             float fadeStart = light_->GetShadowFadeDistance();
@@ -287,7 +287,7 @@ void Batch::Prepare(Graphics* graphics, const HashMap<StringHash, Vector4>& shad
             graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues, intensity, 0.0f, 0.0f));
         }
         
-        if (graphics->NeedParameterUpdate(PS, PSP_SHADOWPROJ, light_))
+        if (graphics->NeedParameterUpdate(PSP_SHADOWPROJ, light_))
         {
             Camera* shadowCamera = light_->GetShadowCamera();
             Matrix3x4 viewPos(camera_->GetWorldPosition(), Quaternion::IDENTITY, Vector3::UNITY);

+ 7 - 30
Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -1104,8 +1104,15 @@ void Graphics::SetShaderParameter(StringHash param, const Matrix3x4& matrix)
 
 void Graphics::DefineShaderParameter(StringHash param, ShaderType type, unsigned hwReg)
 {
+    unsigned oldSize = shaderParameters_.Size();
+    
     shaderParameters_[param].type_ = type;
     shaderParameters_[param].register_ = hwReg;
+    
+    // Rehash if necessary to ensure minimum load factor and fast queries
+    unsigned newSize = shaderParameters_.Size();
+    if (newSize > oldSize)
+        shaderParameters_.Rehash(NextPowerOfTwo(newSize));
 }
 
 bool Graphics::NeedParameterUpdate(StringHash param, const void* source)
@@ -1134,36 +1141,6 @@ bool Graphics::NeedParameterUpdate(StringHash param, const void* source)
     return false;
 }
 
-bool Graphics::NeedParameterUpdate(ShaderType type, StringHash param, const void* source)
-{
-    if (type == VS)
-    {
-        if (vertexShader_ && vertexShader_->HasParameter(param))
-        {
-            HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-            if (i != shaderParameters_.End() && i->second_.lastSource_ != source)
-            {
-                i->second_.lastSource_ = source;
-                return true;
-            }
-        }
-    }
-    else
-    {
-        if (pixelShader_ && pixelShader_->HasParameter(param))
-        {
-            HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-            if (i != shaderParameters_.End() && i->second_.lastSource_ != source)
-            {
-                i->second_.lastSource_ = source;
-                return true;
-            }
-        }
-    }
-    
-    return false;
-}
-
 bool Graphics::NeedTextureUnit(TextureUnit unit)
 {
     return pixelShader_ && pixelShader_->HasTextureUnit(unit);

+ 0 - 2
Engine/Graphics/Direct3D9/D3D9Graphics.h

@@ -135,8 +135,6 @@ public:
     void DefineShaderParameter(StringHash param, ShaderType type, unsigned hwReg);
     /// Check whether a shader parameter in the currently set shaders needs update.
     bool NeedParameterUpdate(StringHash param, const void* source);
-    /// Check whether a shader parameter in the currently set shaders needs update, optimized version.
-    bool NeedParameterUpdate(ShaderType type, StringHash param, const void* source);
     /// Check whether the current pixel shader uses a texture unit.
     bool NeedTextureUnit(TextureUnit unit);
     /// Clear remembered shader parameter sources.

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

@@ -119,6 +119,8 @@ bool Shader::Load(Deserializer& source)
                 variation->SetUseParameter(StringHash(parameters[j].first_), true);
         }
         
+        variation->OptimizeParameters();
+        
         for (unsigned j = 0; j < numTextureUnits; ++j)
         {
             if (source.ReadBool())

+ 5 - 0
Engine/Graphics/Direct3D9/D3D9ShaderVariation.cpp

@@ -126,6 +126,11 @@ void ShaderVariation::SetUseTextureUnit(TextureUnit unit, bool enable)
     useTextureUnit_[unit] = enable;
 }
 
+void ShaderVariation::OptimizeParameters()
+{
+    useParameter_.Rehash(NextPowerOfTwo(useParameter_.Size()));
+}
+
 void ShaderVariation::ClearParameters()
 {
     useParameter_.Clear();

+ 2 - 0
Engine/Graphics/Direct3D9/D3D9ShaderVariation.h

@@ -53,6 +53,8 @@ public:
     void SetUseParameter(StringHash param, bool enable);
     /// %Set to use a texture unit.
     void SetUseTextureUnit(TextureUnit unit, bool enable);
+    /// Optimize the parameter map for optimal query speed
+    void OptimizeParameters();
     /// Clear parameter and texture unit use flags.
     void ClearParameters();
     

+ 0 - 8
Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -1021,14 +1021,6 @@ bool Graphics::NeedParameterUpdate(StringHash param, const void* source)
     return false;
 }
 
-bool Graphics::NeedParameterUpdate(ShaderType type, StringHash param, const void* source)
-{
-    if (shaderProgram_)
-        return shaderProgram_->NeedParameterUpdate(param, source, shaderParameterFrame_);
-    
-    return false;
-}
-
 bool Graphics::NeedTextureUnit(TextureUnit unit)
 {
     if (shaderProgram_ && shaderProgram_->HasTextureUnit(unit))

+ 0 - 2
Engine/Graphics/OpenGL/OGLGraphics.h

@@ -122,8 +122,6 @@ public:
     void SetShaderParameter(StringHash param, const Matrix3x4& matrix);
     /// Check whether a shader parameter in the currently set shaders needs update.
     bool NeedParameterUpdate(StringHash param, const void* source);
-    /// Check whether a shader parameter in the currently set shaders needs update, optimized version.
-    bool NeedParameterUpdate(ShaderType type, StringHash param, const void* source);
     /// Check whether the current pixel shader uses a texture unit.
     bool NeedTextureUnit(TextureUnit unit);
     /// Clear remembered shader parameter sources.

+ 3 - 0
Engine/Graphics/OpenGL/OGLShaderProgram.cpp

@@ -165,6 +165,9 @@ bool ShaderProgram::Link()
     attributeLocations_[8] = glGetAttribLocation(object_, "iBlendWeights");
     attributeLocations_[9] = glGetAttribLocation(object_, "iBlendIndices");
     
+    // Rehash the parameter map to ensure minimal load factor
+    shaderParameters_.Rehash(NextPowerOfTwo(shaderParameters_.Size()));
+    
     return true;
 }