Browse Source

Simplified shader register mapping code.

Lasse Öörni 14 years ago
parent
commit
7f09ddcb14

+ 2 - 2
Docs/Reference.dox

@@ -425,11 +425,11 @@ For details on how Direct3D9 and OpenGL rendering differs, see \ref APIDifferenc
 
 
 \page APIDifferences Differences between Direct3D9 and OpenGL
 \page APIDifferences Differences between Direct3D9 and OpenGL
 
 
-- On Direct3D9 shader uniform parameters are global. On OpenGL they are shader-specific. To ensure correct operation also on OpenGL, first set the shaders, then query Graphics whether each shader parameter is needed, and set the corresponding parameter if needed. This includes also frame-global parameters, which on Direct3D9 need to be set only once per frame.
+- On Direct3D9 shader uniform parameters are global. On OpenGL they are shader-specific. To ensure correct operation also on OpenGL, first set the shaders, then query Graphics whether each shader parameter is needed, and set the corresponding parameter if needed. This includes also frame-global parameters, which on Direct3D9 need to be set only once per frame, if the uniform register assignments are fixed.
 
 
 - On OpenGL vertex attribute bindings also depend on the currently set shaders. To ensure correct operation, first set the shaders, then the vertex buffers.
 - On OpenGL vertex attribute bindings also depend on the currently set shaders. To ensure correct operation, first set the shaders, then the vertex buffers.
 
 
-- On Direct3D9 the depth stencil surface can be equal size or larger than the color render target. On OpenGL the sizes must always match. Furthermore, OpenGL can not use the system depth stencil buffer when rendering to a texture. To overcome these limitations, Graphics will create correctly sized depth stencil buffers on demand whenever a texture is set as a color render target, and a null depth stencil is specified.
+- On Direct3D9 the depth stencil surface can be equal or larger in size than the color render target. On OpenGL the sizes must always match. Furthermore, OpenGL can not use the system depth stencil buffer when rendering to a texture. To overcome these limitations, Graphics will create correctly sized depth stencil buffers on demand whenever a texture is set as a color render target, and a null depth stencil is specified.
 
 
 - On Direct3D9 setting the first color render target resets the viewport dimensions. On OpenGL there is no such mechanism, but as sometimes (for example in shadow rendering) only a depth stencil buffer is set for rendering, Graphics will instead reset the viewport when the depth stencil buffer is set. To ensure correct operation on both APIs, first set the render targets, then the depth stencil buffer, and finally the viewport, if you need it to be less than the whole render target.
 - On Direct3D9 setting the first color render target resets the viewport dimensions. On OpenGL there is no such mechanism, but as sometimes (for example in shadow rendering) only a depth stencil buffer is set for rendering, Graphics will instead reset the viewport when the depth stencil buffer is set. To ensure correct operation on both APIs, first set the render targets, then the depth stencil buffer, and finally the viewport, if you need it to be less than the whole render target.
 
 

+ 88 - 166
Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -866,6 +866,17 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
 {
 {
     if (vs != vertexShader_)
     if (vs != vertexShader_)
     {
     {
+        // Clear all previous register mappings. If shader parameters overlap, also clear remembered sources
+        for (HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Begin(); i != shaderParameters_.End(); ++i)
+        {
+            if (i->second_.type_ == VS)
+            {
+                i->second_.register_ = M_MAX_UNSIGNED;
+                if (shaderParametersOverlap_)
+                    i->second_.lastSource_ = (void*)M_MAX_UNSIGNED;
+            }
+        }
+        
         // Create the shader now if not yet created. If already attempted, do not retry
         // Create the shader now if not yet created. If already attempted, do not retry
         if (vs && !vs->IsCreated())
         if (vs && !vs->IsCreated())
         {
         {
@@ -887,7 +898,18 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
         }
         }
         
         
         if (vs && vs->GetShaderType() == VS)
         if (vs && vs->GetShaderType() == VS)
+        {
             impl_->device_->SetVertexShader((IDirect3DVertexShader9*)vs->GetGPUObject());
             impl_->device_->SetVertexShader((IDirect3DVertexShader9*)vs->GetGPUObject());
+            
+            // Update the parameter-to-register mappings
+            const HashMap<StringHash, ShaderParameter>& parameters = vs->GetParameters();
+            for (HashMap<StringHash, ShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)
+            {
+                HashMap<StringHash, ShaderParameter>::Iterator j = shaderParameters_.Find(i->first_);
+                if (j != parameters.End())
+                    j->second_.register_ = i->second_.register_;
+            }
+        }
         else
         else
         {
         {
             impl_->device_->SetVertexShader(0);
             impl_->device_->SetVertexShader(0);
@@ -899,6 +921,16 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
     
     
     if (ps != pixelShader_)
     if (ps != pixelShader_)
     {
     {
+        for (HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Begin(); i != shaderParameters_.End(); ++i)
+        {
+            if (i->second_.type_ == PS)
+            {
+                i->second_.register_ = M_MAX_UNSIGNED;
+                if (shaderParametersOverlap_)
+                    i->second_.lastSource_ = (void*)M_MAX_UNSIGNED;
+            }
+        }
+        
         if (ps && !ps->IsCreated())
         if (ps && !ps->IsCreated())
         {
         {
             if (!ps->IsFailed())
             if (!ps->IsFailed())
@@ -919,7 +951,17 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
         }
         }
         
         
         if (ps && ps->GetShaderType() == PS)
         if (ps && ps->GetShaderType() == PS)
+        {
             impl_->device_->SetPixelShader((IDirect3DPixelShader9*)ps->GetGPUObject());
             impl_->device_->SetPixelShader((IDirect3DPixelShader9*)ps->GetGPUObject());
+            
+            const HashMap<StringHash, ShaderParameter>& parameters = ps->GetParameters();
+            for (HashMap<StringHash, ShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)
+            {
+                HashMap<StringHash, ShaderParameter>::Iterator j = shaderParameters_.Find(i->first_);
+                if (j != parameters.End())
+                    j->second_.register_ = i->second_.register_;
+            }
+        }
         else
         else
         {
         {
             impl_->device_->SetPixelShader(0);
             impl_->device_->SetPixelShader(0);
@@ -933,23 +975,19 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
 void Graphics::SetShaderParameter(StringHash param, const float* data, unsigned count)
 void Graphics::SetShaderParameter(StringHash param, const float* data, unsigned count)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
-    unsigned reg = GetParameterRegister(i, count / 4);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, data, count / 4);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, data, count / 4);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, data, count / 4);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, data, count / 4);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, float value)
 void Graphics::SetShaderParameter(StringHash param, float value)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
     float data[4];
     float data[4];
@@ -959,36 +997,28 @@ void Graphics::SetShaderParameter(StringHash param, float value)
     data[2] = 0.0f;
     data[2] = 0.0f;
     data[3] = 0.0f;
     data[3] = 0.0f;
     
     
-    unsigned reg = GetParameterRegister(i, 1);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, &data[0], 1);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, &data[0], 1);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data[0], 1);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data[0], 1);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Color& color)
 void Graphics::SetShaderParameter(StringHash param, const Color& color)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
-    unsigned reg = GetParameterRegister(i, 1);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, color.GetData(), 1);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, color.GetData(), 1);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, color.GetData(), 1);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, color.GetData(), 1);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Matrix3& matrix)
 void Graphics::SetShaderParameter(StringHash param, const Matrix3& matrix)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
     float data[12];
     float data[12];
@@ -1006,20 +1036,16 @@ void Graphics::SetShaderParameter(StringHash param, const Matrix3& matrix)
     data[10] = matrix.m22_;
     data[10] = matrix.m22_;
     data[11] = 0.0f;
     data[11] = 0.0f;
     
     
-    unsigned reg = GetParameterRegister(i, 3);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, &data[0], 3);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, &data[0], 3);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data[0], 3);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data[0], 3);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Vector3& vector)
 void Graphics::SetShaderParameter(StringHash param, const Vector3& vector)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
     float data[4];
     float data[4];
@@ -1029,62 +1055,46 @@ void Graphics::SetShaderParameter(StringHash param, const Vector3& vector)
     data[2] = vector.z_;
     data[2] = vector.z_;
     data[3] = 0.0f;
     data[3] = 0.0f;
     
     
-    unsigned reg = GetParameterRegister(i, 1);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, &data[0], 1);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, &data[0], 1);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, &data[0], 1);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, &data[0], 1);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Matrix4& matrix)
 void Graphics::SetShaderParameter(StringHash param, const Matrix4& matrix)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
-    unsigned reg = GetParameterRegister(i, 4);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, matrix.GetData(), 4);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, matrix.GetData(), 4);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, matrix.GetData(), 4);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, matrix.GetData(), 4);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Vector4& vector)
 void Graphics::SetShaderParameter(StringHash param, const Vector4& vector)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
-    unsigned reg = GetParameterRegister(i, 1);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, vector.GetData(), 1);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, vector.GetData(), 1);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, vector.GetData(), 1);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, vector.GetData(), 1);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Matrix3x4& matrix)
 void Graphics::SetShaderParameter(StringHash param, const Matrix3x4& matrix)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return;
         return;
     
     
-    unsigned reg = GetParameterRegister(i, 3);
-    if (reg < MAX_CONSTANT_REGISTERS)
-    {
-        if (i->second_.type_ == VS)
-            impl_->device_->SetVertexShaderConstantF(reg, matrix.GetData(), 3);
-        else
-            impl_->device_->SetPixelShaderConstantF(reg, matrix.GetData(), 3);
-    }
+    if (i->second_.type_ == VS)
+        impl_->device_->SetVertexShaderConstantF(i->second_.register_, matrix.GetData(), 3);
+    else
+        impl_->device_->SetPixelShaderConstantF(i->second_.register_, matrix.GetData(), 3);
 }
 }
 
 
 void Graphics::RegisterShaderParameter(StringHash param, const ShaderParameter& definition)
 void Graphics::RegisterShaderParameter(StringHash param, const ShaderParameter& definition)
@@ -1113,7 +1123,7 @@ void Graphics::RegisterShaderParameter(StringHash param, const ShaderParameter&
             i->second_.regCount_ = definition.regCount_;
             i->second_.regCount_ = definition.regCount_;
     }
     }
     
     
-    // Check if parameter overlaps any other parameters, and activate overlapping check in that case
+    // Check if parameter overlaps any other parameters
     if (definition.type_ == VS)
     if (definition.type_ == VS)
     {
     {
         for (unsigned j = definition.register_; j < definition.register_ + definition.regCount_; ++j)
         for (unsigned j = definition.register_; j < definition.register_ + definition.regCount_; ++j)
@@ -1145,48 +1155,16 @@ void Graphics::RegisterShaderParameter(StringHash param, const ShaderParameter&
 bool Graphics::NeedParameterUpdate(StringHash param, const void* source)
 bool Graphics::NeedParameterUpdate(StringHash param, const void* source)
 {
 {
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
     HashMap<StringHash, ShaderParameter>::Iterator i = shaderParameters_.Find(param);
-    if (i == shaderParameters_.End())
+    if (i == shaderParameters_.End() || i->second_.register_ >= MAX_CONSTANT_REGISTERS)
         return false;
         return false;
     
     
-    ShaderParameter& globalParam = i->second_;
-    if (globalParam.type_ == VS)
+    if (i->second_.lastSource_ != source)
     {
     {
-        if (!vertexShader_)
-            return false;
-        
-        const ShaderParameter& localParam = vertexShader_->GetParameter(param);
-        // Check that parameter exists
-        if (!localParam.regCount_)
-            return false;
-        
-        // If source is different, or the current register does not match, need to update
-        if (globalParam.lastSource_ != source || globalParam.register_ != localParam.register_)
-        {
-            globalParam.lastSource_ = source;
-            return true;
-        }
-        else
-            return false;
+        i->second_.lastSource_ = source;
+        return true;
     }
     }
     else
     else
-    {
-        if (!pixelShader_)
-            return false;
-        
-        const ShaderParameter& localParam = pixelShader_->GetParameter(param);
-        if (!localParam.regCount_)
-            return false;
-        
-        if (globalParam.lastSource_ != source || globalParam.register_ != localParam.register_)
-        {
-            globalParam.lastSource_ = source;
-            return true;
-        }
-        else
-            return false;
-    }
-    
-    return false;
+        return false;
 }
 }
 
 
 bool Graphics::NeedTextureUnit(TextureUnit unit)
 bool Graphics::NeedTextureUnit(TextureUnit unit)
@@ -2360,62 +2338,6 @@ void Graphics::SetTextureUnitMappings()
     textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
     textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
 }
 }
 
 
-unsigned Graphics::GetParameterRegister(HashMap<StringHash, ShaderParameter>::Iterator i, unsigned regCount)
-{
-    ShaderParameter& globalParam = i->second_;
-    
-    if (globalParam.type_ == VS)
-    {
-        if (!vertexShader_)
-            return M_MAX_UNSIGNED;
-        
-        const ShaderParameter& localParam = vertexShader_->GetParameter(i->first_);
-        // Check that parameter exists
-        if (!localParam.regCount_)
-            return M_MAX_UNSIGNED;
-        
-        globalParam.register_ = localParam.register_;
-        
-        // Check if this parameter overwrites other parameters, and clear their register assignments
-        if (shaderParametersOverlap_)
-        {
-            for (HashMap<StringHash, ShaderParameter>::Iterator j = shaderParameters_.Begin(); j != shaderParameters_.End(); ++j)
-            {
-                ShaderParameter& otherGlobalParam = j->second_;
-                if (j != i && otherGlobalParam.type_ == VS && otherGlobalParam.register_ < localParam.register_ + regCount &&
-                    localParam.register_ < otherGlobalParam.register_ + otherGlobalParam.regCount_)
-                    otherGlobalParam.register_ = M_MAX_UNSIGNED;
-            }
-        }
-        
-        return globalParam.register_;
-    }
-    else
-    {
-        if (!pixelShader_)
-            return M_MAX_UNSIGNED;
-        
-        const ShaderParameter& localParam = pixelShader_->GetParameter(i->first_);
-        if (!localParam.regCount_)
-            return M_MAX_UNSIGNED;
-        
-        globalParam.register_ = localParam.register_;
-        
-        if (shaderParametersOverlap_)
-        {
-            for (HashMap<StringHash, ShaderParameter>::Iterator j = shaderParameters_.Begin(); j != shaderParameters_.End(); ++j)
-            {
-                ShaderParameter& otherGlobalParam = j->second_;
-                if (j != i && otherGlobalParam.type_ == PS && otherGlobalParam.register_ < localParam.register_ + regCount &&
-                    localParam.register_ < otherGlobalParam.register_ + otherGlobalParam.regCount_)
-                    otherGlobalParam.register_ = M_MAX_UNSIGNED;
-            }
-        }
-        
-        return globalParam.register_;
-    }
-}
-
 void Graphics::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
 void Graphics::HandleWindowMessage(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace WindowMessage;
     using namespace WindowMessage;

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

@@ -352,8 +352,6 @@ private:
     void ResetCachedState();
     void ResetCachedState();
     /// Initialize texture unit mappings.
     /// Initialize texture unit mappings.
     void SetTextureUnitMappings();
     void SetTextureUnitMappings();
-    /// Return the hardware register index of a shader parameter in the current shader and update the register assignments.
-    unsigned GetParameterRegister(HashMap<StringHash, ShaderParameter>::Iterator i, unsigned regCount);
     /// Handle operating system window message.
     /// Handle operating system window message.
     void HandleWindowMessage(StringHash eventType, VariantMap& eventData);
     void HandleWindowMessage(StringHash eventType, VariantMap& eventData);
 
 

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

@@ -31,8 +31,6 @@
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
-static ShaderParameter emptyShaderParameter;
-
 ShaderVariation::ShaderVariation(Shader* shader, ShaderType type, bool isSM3) :
 ShaderVariation::ShaderVariation(Shader* shader, ShaderType type, bool isSM3) :
     GPUObject(shader->GetSubsystem<Graphics>()),
     GPUObject(shader->GetSubsystem<Graphics>()),
     shaderType_(type),
     shaderType_(type),
@@ -141,9 +139,3 @@ bool ShaderVariation::IsCreated() const
 {
 {
     return object_ != 0;
     return object_ != 0;
 }
 }
-
-const ShaderParameter& ShaderVariation::GetParameter(StringHash param) const
-{
-    HashMap<StringHash, ShaderParameter>::ConstIterator i = parameters_.Find(param);
-    return i != parameters_.End() ? i->second_ : emptyShaderParameter;
-}

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

@@ -103,8 +103,8 @@ public:
     bool HasParameter(StringHash param) const { return parameters_.Contains(param); }
     bool HasParameter(StringHash param) const { return parameters_.Contains(param); }
     /// Return whether uses a texture unit (only for pixel shaders.)
     /// Return whether uses a texture unit (only for pixel shaders.)
     bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
     bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
-    /// Return the parameter definition.
-    const ShaderParameter& GetParameter(StringHash param) const;
+    /// Return all parameter definitions.
+    const HashMap<StringHash, ShaderParameter>& GetParameters() const { return parameters_; }
     
     
 private:
 private:
     /// Shader type.
     /// Shader type.