public GpuConstantDefinition()
 {
     this.ConstantType = GpuConstantType.Unknown;
     PhysicalIndex     = Int32.MaxValue;
     this.ElementSize  = 0;
     this.ArraySize    = 1;
     this.Variability  = GpuParamVariability.Global;
 }
 public AutoConstantEntry(AutoConstantType type, int index, float fdata, GpuParamVariability variability,
                          int elementCount)
 {
     this.Type          = type;
     this.PhysicalIndex = index;
     this.FData         = fdata;
     this.Variability   = variability;
     this.ElementCount  = elementCount;
 }
            public AutoConstantEntry(AutoConstantType type, int index, int data, GpuParamVariability variability,
                                     int elementCount)
            {
                this.Type          = type;
                this.PhysicalIndex = index;
                this.Data          = data;
                this.Variability   = variability;
                this.ElementCount  = elementCount;

                // this is likeley obsolete in as ogre doesnt have this (anymore?)
                System.Diagnostics.Debug.Assert(type != AutoConstantType.SinTime_0_X);
            }
		public void UpdateAutoParams( AutoParamDataSource source, GpuParamVariability mask )
		{
			// abort early if no autos
			if ( !HasAutoConstantType )
			{
				return;
			}

			if ( ( mask & this._combinedVariability ) == 0 )
			{
				return;
			}

			this.activePassIterationIndex = int.MaxValue;

			Matrix3 m3;
			Vector4 vec4;
			Vector3 vec3;

			// loop through and update all constants based on their type
			foreach ( var entry in this.autoConstants )
			{
				// Only update needed slots
				if ( ( entry.Variability & mask ) == 0 )
				{
					continue;
				}

				switch ( entry.Type )
				{
					case AutoConstantType.ViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.ViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.TransposeViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.TransposeViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseTransposeViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseTransposeViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.ProjectionMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.ProjectionMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseProjectionMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseProjectionMatrix, entry.ElementCount );
						break;

					case AutoConstantType.TransposeProjectionMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.TransposeProjectionMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseTransposeProjectionMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseTransposeProjectionMatrix, entry.ElementCount );
						break;

					case AutoConstantType.ViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.ViewProjectionMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.TransposeViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.TransposeViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseTransposeViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseTransposeViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.RenderTargetFlipping:
						WriteRawConstant( entry.PhysicalIndex, source.CurrentRenderTarget.RequiresTextureFlipping ? -1.0f : 1.0f );
						break;

					case AutoConstantType.VertexWinding:
					{
						var rsys = Root.Instance.RenderSystem;
						WriteRawConstant( entry.PhysicalIndex, rsys.InvertVertexWinding ? -1.0f : 1.0f );
						break;
					}

						// NB ambient light still here because it's not related to a specific light
					case AutoConstantType.AmbientLightColor:
						WriteRawConstant( entry.PhysicalIndex, source.AmbientLight, entry.ElementCount );
						break;

					case AutoConstantType.DerivedAmbientLightColor:
						WriteRawConstant( entry.PhysicalIndex, source.DerivedAmbient, entry.ElementCount );
						break;

					case AutoConstantType.DerivedSceneColor:
						WriteRawConstant( entry.PhysicalIndex, source.DerivedSceneColor, entry.ElementCount );
						break;

					case AutoConstantType.FogColor:
						WriteRawConstant( entry.PhysicalIndex, source.FogColor );
						break;

					case AutoConstantType.FogParams:
						WriteRawConstant( entry.PhysicalIndex, source.FogParams, entry.ElementCount );
						break;

					case AutoConstantType.SurfaceAmbientColor:
						WriteRawConstant( entry.PhysicalIndex, source.SurfaceAmbient, entry.ElementCount );
						break;

					case AutoConstantType.SurfaceDiffuseColor:
						WriteRawConstant( entry.PhysicalIndex, source.SurfaceDiffuse, entry.ElementCount );
						break;

					case AutoConstantType.SurfaceSpecularColor:
						WriteRawConstant( entry.PhysicalIndex, source.SurfaceSpecular, entry.ElementCount );
						break;

					case AutoConstantType.SurfaceEmissiveColor:
						WriteRawConstant( entry.PhysicalIndex, source.SurfaceEmissive, entry.ElementCount );
						break;

					case AutoConstantType.SurfaceShininess:
						WriteRawConstant( entry.PhysicalIndex, source.SurfaceShininess );
						break;

					case AutoConstantType.CameraPosition:
						WriteRawConstant( entry.PhysicalIndex, source.CameraPosition, entry.ElementCount );
						break;

					case AutoConstantType.Time:
						WriteRawConstant( entry.PhysicalIndex, source.Time*entry.FData );
						break;

					case AutoConstantType.Time_0_X:
						WriteRawConstant( entry.PhysicalIndex, source.GetTime_0_X( entry.FData ) );
						break;

					case AutoConstantType.CosTime_0_X:
						WriteRawConstant( entry.PhysicalIndex, source.GetCosTime_0_X( entry.FData ) );
						break;

					case AutoConstantType.SinTime_0_X:
						WriteRawConstant( entry.PhysicalIndex, source.GetSinTime_0_X( entry.FData ) );
						break;

					case AutoConstantType.TanTime_0_X:
						WriteRawConstant( entry.PhysicalIndex, source.GetTanTime_0_X( entry.FData ) );
						break;

					case AutoConstantType.Time_0_X_Packed:
						WriteRawConstant( entry.PhysicalIndex, source.GetTime_0_X_Packed( entry.FData ), entry.ElementCount );
						break;

					case AutoConstantType.Time_0_1:
						WriteRawConstant( entry.PhysicalIndex, source.GetTime_0_1( entry.FData ) );
						break;

					case AutoConstantType.CosTime_0_1:
						WriteRawConstant( entry.PhysicalIndex, source.GetCosTime_0_1( entry.FData ) );
						break;

					case AutoConstantType.SinTime_0_1:
						WriteRawConstant( entry.PhysicalIndex, source.GetSinTime_0_1( entry.FData ) );
						break;

					case AutoConstantType.TanTime_0_1:
						WriteRawConstant( entry.PhysicalIndex, source.GetTanTime_0_1( entry.FData ) );
						break;

					case AutoConstantType.Time_0_1_Packed:
						WriteRawConstant( entry.PhysicalIndex, source.GetTime_0_1_Packed( entry.FData ), entry.ElementCount );
						break;

					case AutoConstantType.Time_0_2PI:
						WriteRawConstant( entry.PhysicalIndex, source.GetTime_0_2Pi( entry.FData ) );
						break;

					case AutoConstantType.CosTime_0_2PI:
						WriteRawConstant( entry.PhysicalIndex, source.GetCosTime_0_2Pi( entry.FData ) );
						break;

					case AutoConstantType.SinTime_0_2PI:
						WriteRawConstant( entry.PhysicalIndex, source.GetSinTime_0_2Pi( entry.FData ) );
						break;

					case AutoConstantType.TanTime_0_2PI:
						WriteRawConstant( entry.PhysicalIndex, source.GetTanTime_0_2Pi( entry.FData ) );
						break;

					case AutoConstantType.Time_0_2PI_Packed:
						WriteRawConstant( entry.PhysicalIndex, source.GetTime_0_2Pi_Packed( entry.FData ), entry.ElementCount );
						break;

					case AutoConstantType.FrameTime:
						WriteRawConstant( entry.PhysicalIndex, source.FrameTime*entry.FData );
						break;

					case AutoConstantType.FPS:
						WriteRawConstant( entry.PhysicalIndex, source.FPS );
						break;

					case AutoConstantType.ViewportWidth:
						WriteRawConstant( entry.PhysicalIndex, source.ViewportWidth );
						break;

					case AutoConstantType.ViewportHeight:
						WriteRawConstant( entry.PhysicalIndex, source.ViewportHeight );
						break;

					case AutoConstantType.InverseViewportWidth:
						WriteRawConstant( entry.PhysicalIndex, source.InverseViewportWidth );
						break;

					case AutoConstantType.InverseViewportHeight:
						WriteRawConstant( entry.PhysicalIndex, source.InverseViewportHeight );
						break;

					case AutoConstantType.ViewportSize:
					{
						WriteRawConstant( entry.PhysicalIndex,
						                  new Vector4( source.ViewportWidth, source.ViewportHeight, source.InverseViewportWidth,
						                               source.InverseViewportHeight ), entry.ElementCount );
					}
						break;

					case AutoConstantType.TexelOffsets:
					{
						var rsys = Root.Instance.RenderSystem;
						WriteRawConstant( entry.PhysicalIndex,
						                  new Vector4( rsys.HorizontalTexelOffset, rsys.VerticalTexelOffset,
						                               rsys.HorizontalTexelOffset*source.InverseViewportWidth,
						                               rsys.VerticalTexelOffset*source.InverseViewportHeight ), entry.ElementCount );
					}
						break;

					case AutoConstantType.TextureSize:
						WriteRawConstant( entry.PhysicalIndex, source.GetTextureSize( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.InverseTextureSize:
						WriteRawConstant( entry.PhysicalIndex, source.GetInverseTextureSize( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.PackedTextureSize:
						WriteRawConstant( entry.PhysicalIndex, source.GetPackedTextureSize( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.SceneDepthRange:
						WriteRawConstant( entry.PhysicalIndex, source.SceneDepthRange, entry.ElementCount );
						break;

					case AutoConstantType.ViewDirection:
						WriteRawConstant( entry.PhysicalIndex, source.ViewDirection );
						break;

					case AutoConstantType.ViewSideVector:
						WriteRawConstant( entry.PhysicalIndex, source.ViewSideVector );
						break;

					case AutoConstantType.ViewUpVector:
						WriteRawConstant( entry.PhysicalIndex, source.ViewUpVector );
						break;

					case AutoConstantType.FOV:
						WriteRawConstant( entry.PhysicalIndex, source.FOV );
						break;

					case AutoConstantType.NearClipDistance:
						WriteRawConstant( entry.PhysicalIndex, source.NearClipDistance );
						break;

					case AutoConstantType.FarClipDistance:
						WriteRawConstant( entry.PhysicalIndex, source.FarClipDistance );
						break;

					case AutoConstantType.PassNumber:
						WriteRawConstant( entry.PhysicalIndex, (float)source.PassNumber );
						break;

					case AutoConstantType.PassIterationNumber:
					{
						// this is actually just an initial set-up, it's bound separately, so still global
						WriteRawConstant( entry.PhysicalIndex, 0.0f );
						this.activePassIterationIndex = entry.PhysicalIndex;
					}
						break;

					case AutoConstantType.TextureMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.GetTextureTransformMatrix( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LODCameraPosition:
						WriteRawConstant( entry.PhysicalIndex, source.LodCameraPosition, entry.ElementCount );
						break;

					case AutoConstantType.TextureWorldViewProjMatrix:
						// can also be updated in lights
						WriteRawConstant( entry.PhysicalIndex, source.GetTextureWorldViewProjMatrix( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.TextureWorldViewProjMatrixArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							// can also be updated in lights
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetTextureWorldViewProjMatrix( l ),
							                  entry.ElementCount );
						}
						break;

					case AutoConstantType.SpotLightWorldViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.GetSpotlightWorldViewProjMatrix( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LightPositionObjectSpace:
					{
						vec4 = source.GetLightAs4DVector( entry.Data );
						vec3 = new Vector3( vec4.x, vec4.y, vec4.z );
						if ( vec4.w > 0.0f )
						{
							// point light
							vec3 = source.InverseWorldMatrix.TransformAffine( vec3 );
						}
						else
						{
							// directional light
							// We need the inverse of the inverse transpose 
							source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix( out m3 );
							vec3 = ( m3*vec3 ).ToNormalized();
						}
						WriteRawConstant( entry.PhysicalIndex, new Vector4( vec3.x, vec3.y, vec3.z, vec4.w ), entry.ElementCount );
					}
						break;

					case AutoConstantType.LightDirectionObjectSpace:
					{
						// We need the inverse of the inverse transpose 
						source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix( out m3 );
						vec3 = m3*source.GetLightDirection( entry.Data );
						vec3.Normalize();
						// Set as 4D vector for compatibility
						WriteRawConstant( entry.PhysicalIndex, new Vector4( vec3.x, vec3.y, vec3.z, 0.0f ), entry.ElementCount );
					}
						break;

					case AutoConstantType.LightDistanceObjectSpace:
					{
						vec3 = source.InverseWorldMatrix.TransformAffine( source.GetLightPosition( entry.Data ) );
						WriteRawConstant( entry.PhysicalIndex, vec3.Length );
					}
						break;

					case AutoConstantType.LightPositionObjectSpaceArray:
					{
						// We need the inverse of the inverse transpose 
						source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix( out m3 );
						for ( var l = 0; l < entry.Data; ++l )
						{
							vec4 = source.GetLightAs4DVector( l );
							vec3 = new Vector3( vec4.x, vec4.y, vec4.z );
							if ( vec4.w > 0.0f )
							{
								// point light
								vec3 = source.InverseWorldMatrix.TransformAffine( vec3 );
							}
							else
							{
								// directional light
								vec3 = ( m3*vec3 ).ToNormalized();
							}
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, new Vector4( vec3.x, vec3.y, vec3.z, vec4.w ),
							                  entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightDirectionObjectSpaceArray:
					{
						// We need the inverse of the inverse transpose 
						source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix( out m3 );
						for ( var l = 0; l < entry.Data; ++l )
						{
							vec3 = m3*source.GetLightDirection( l );
							vec3.Normalize();
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, new Vector4( vec3.x, vec3.y, vec3.z, 0.0f ),
							                  entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightDistanceObjectSpaceArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							vec3 = source.InverseWorldMatrix.TransformAffine( source.GetLightPosition( l ) );
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, vec3.Length );
						}
						break;

					case AutoConstantType.WorldMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.WorldMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseWorldMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseWorldMatrix, entry.ElementCount );
						break;

					case AutoConstantType.TransposeWorldMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.TransposeWorldMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseTransposeWorldMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseTransposeWorldMatrix, entry.ElementCount );
						break;

					case AutoConstantType.WorldMatrixArray3x4:
					{
						// Loop over matrices
						var pMatrix = source.WorldMatrixArray;
						var numMatrices = source.WorldMatrixCount;
						var index = entry.PhysicalIndex;
						var floatArray = new float[16];
						for ( var m = 0; m < numMatrices; ++m )
						{
							pMatrix[ m ].MakeFloatArray( floatArray );
							_writeRawConstants( index, floatArray, 12 );
							index += 12;
						}
					}
						break;

					case AutoConstantType.WorldMatrixArray:
						WriteRawConstant( entry.PhysicalIndex, source.WorldMatrixArray, source.WorldMatrixCount );
						break;

					case AutoConstantType.WorldViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.WorldViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseWorldViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseWorldViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.TransposeWorldViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.TransposeWorldViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseTransposeWorldViewMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseTransposeWorldViewMatrix, entry.ElementCount );
						break;

					case AutoConstantType.WorldViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.WorldViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseWorldViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseWorldViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.TransposeWorldViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.TransposeWorldViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.InverseTransposeWorldViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.InverseTransposeWorldViewProjMatrix, entry.ElementCount );
						break;

					case AutoConstantType.CameraPositionObjectSpace:
						WriteRawConstant( entry.PhysicalIndex, source.CameraPositionObjectSpace, entry.ElementCount );
						break;

					case AutoConstantType.LODCameraPositionObjectSpace:
						WriteRawConstant( entry.PhysicalIndex, source.LodCameraPositionObjectSpace, entry.ElementCount );
						break;

					case AutoConstantType.Custom:
					case AutoConstantType.AnimationParametric:
						source.CurrentRenderable.UpdateCustomGpuParameter( entry, this );
						break;

					case AutoConstantType.LightCustom:
						source.UpdateLightCustomGpuParameter( entry, this );
						break;

					case AutoConstantType.LightCount:
						WriteRawConstant( entry.PhysicalIndex, source.LightCount );
						break;

					case AutoConstantType.LightDiffuseColor:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightDiffuse( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LightSpecularColor:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightSpecular( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LightPosition:
					{
						// Get as 4D vector, works for directional lights too
						// Use element count in case uniform slot is smaller
						WriteRawConstant( entry.PhysicalIndex, source.GetLightAs4DVector( entry.Data ), entry.ElementCount );
					}
						break;

					case AutoConstantType.LightDirection:
					{
						vec3 = source.GetLightDirection( entry.Data );
						// Set as 4D vector for compatibility
						// Use element count in case uniform slot is smaller
						WriteRawConstant( entry.PhysicalIndex, new Vector4( vec3.x, vec3.y, vec3.z, 1.0f ), entry.ElementCount );
					}
						break;

					case AutoConstantType.LightPositionViewSpace:
					{
						vec4 = source.GetLightAs4DVector( entry.Data );
						WriteRawConstant( entry.PhysicalIndex, source.ViewMatrix.TransformAffine( vec4 ), entry.ElementCount );
					}
						break;

					case AutoConstantType.LightDirectionViewSpace:
					{
						source.InverseTransposeViewMatrix.Extract3x3Matrix( out m3 );
						// inverse transpose in case of scaling
						vec3 = m3*source.GetLightDirection( entry.Data );
						vec3.Normalize();
						// Set as 4D vector for compatibility
						WriteRawConstant( entry.PhysicalIndex, new Vector4( vec3.x, vec3.y, vec3.z, 0.0f ), entry.ElementCount );
					}
						break;

					case AutoConstantType.ShadowExtrusionDistance:
					{
						// extrusion is in object-space, so we have to rescale by the inverse
						// of the world scaling to deal with scaled objects
						source.WorldMatrix.Extract3x3Matrix( out m3 );
						WriteRawConstant( entry.PhysicalIndex,
						                  source.ShadowExtrusionDistance/
						                  Utility.Sqrt(
						                  	Utility.Max( Utility.Max( m3.GetColumn( 0 ).LengthSquared, m3.GetColumn( 1 ).LengthSquared ),
						                  	             m3.GetColumn( 2 ).LengthSquared ) ) );
					}
						break;

					case AutoConstantType.ShadowSceneDepthRange:
						WriteRawConstant( entry.PhysicalIndex, source.GetShadowSceneDepthRange( entry.Data ) );
						break;

					case AutoConstantType.ShadowColor:
						WriteRawConstant( entry.PhysicalIndex, source.ShadowColor, entry.ElementCount );
						break;

					case AutoConstantType.LightPowerScale:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightPowerScale( entry.Data ) );
						break;

					case AutoConstantType.LightDiffuseColorPowerScaled:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightDiffuseColorWithPower( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LightSpecularColorPowerScaled:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightSpecularColorWithPower( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LightNumber:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightNumber( entry.Data ) );
						break;

					case AutoConstantType.LightCastsShadows:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightCastsShadows( entry.Data ) );
						break;

					case AutoConstantType.LightAttenuation:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightAttenuation( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.SpotLightParams:
						WriteRawConstant( entry.PhysicalIndex, source.GetSpotlightParams( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.LightDiffuseColorArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightDiffuse( l ), entry.ElementCount );
						}
						break;

					case AutoConstantType.LightSpecularColorArray:
					{
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightSpecular( l ), entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightDiffuseColorPowerScaledArray:
					{
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightDiffuseColorWithPower( l ),
							                  entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightSpecularColorPowerScaledArray:
					{
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightSpecularColorWithPower( l ),
							                  entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightPositionArray:
					{
						// Get as 4D vector, works for directional lights too
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightAs4DVector( l ), entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightDirectionArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							vec3 = source.GetLightDirection( l );
							// Set as 4D vector for compatibility
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, new Vector4( vec3.x, vec3.y, vec3.z, 0.0f ),
							                  entry.ElementCount );
						}
						break;

					case AutoConstantType.LightPositionViewSpaceArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							vec4 = source.GetLightAs4DVector( l );
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.ViewMatrix.TransformAffine( vec4 ),
							                  entry.ElementCount );
						}
						break;

					case AutoConstantType.LightDirectionViewSpaceArray:
					{
						source.InverseTransposeViewMatrix.Extract3x3Matrix( out m3 );
						for ( var l = 0; l < entry.Data; ++l )
						{
							vec3 = m3*source.GetLightDirection( l );
							vec3.Normalize();
							// Set as 4D vector for compatibility
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, new Vector4( vec3.x, vec3.y, vec3.z, 0.0f ),
							                  entry.ElementCount );
						}
					}
						break;

					case AutoConstantType.LightPowerScaleArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightPowerScale( l ) );
						}
						break;

					case AutoConstantType.LightAttenuationArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetLightAttenuation( l ), entry.ElementCount );
						}
						break;

					case AutoConstantType.SpotLightParamsArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetSpotlightParams( l ), entry.ElementCount );
						}
						break;

					case AutoConstantType.DerivedLightDiffuseColor:
					{
						WriteRawConstant( entry.PhysicalIndex, source.GetLightDiffuseColorWithPower( entry.Data )*source.SurfaceDiffuse,
						                  entry.ElementCount );
					}
						break;

					case AutoConstantType.DerivedLightSpecularColor:
						WriteRawConstant( entry.PhysicalIndex, source.GetLightSpecularColorWithPower( entry.Data )*source.SurfaceSpecular,
						                  entry.ElementCount );
						break;

					case AutoConstantType.DerivedLightDiffuseColorArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount,
							                  source.GetLightDiffuseColorWithPower( l )*source.SurfaceDiffuse, entry.ElementCount );
						}
						break;

					case AutoConstantType.DerivedLightSpecularColorArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount,
							                  source.GetLightSpecularColorWithPower( l )*source.SurfaceSpecular, entry.ElementCount );
						}
						break;

					case AutoConstantType.TextureViewProjMatrix:
						// can also be updated in lights
						WriteRawConstant( entry.PhysicalIndex, source.GetTextureViewProjectionMatrix( entry.Data ), entry.ElementCount );
						break;

					case AutoConstantType.TextureViewProjMatrixArray:
						for ( var l = 0; l < entry.Data; ++l )
						{
							// can also be updated in lights
							WriteRawConstant( entry.PhysicalIndex + l*entry.ElementCount, source.GetTextureViewProjectionMatrix( l ),
							                  entry.ElementCount );
						}
						break;

					case AutoConstantType.SpotLightViewProjMatrix:
						WriteRawConstant( entry.PhysicalIndex, source.GetSpotlightViewProjMatrix( entry.Data ), entry.ElementCount );
						break;

					default:
						break;
				}
			}
		}
        public void UpdateAutoParams(AutoParamDataSource source, GpuParamVariability mask)
        {
            // abort early if no autos
            if (!HasAutoConstantType)
            {
                return;
            }

            if ((mask & this._combinedVariability) == 0)
            {
                return;
            }

            this.activePassIterationIndex = int.MaxValue;

            Matrix3 m3;
            Vector4 vec4;
            Vector3 vec3;

            // loop through and update all constants based on their type
            foreach (var entry in this.autoConstants)
            {
                // Only update needed slots
                if ((entry.Variability & mask) == 0)
                {
                    continue;
                }

                switch (entry.Type)
                {
                case AutoConstantType.ViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.TransposeViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.TransposeViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseTransposeViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseTransposeViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.ProjectionMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.ProjectionMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseProjectionMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseProjectionMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.TransposeProjectionMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.TransposeProjectionMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseTransposeProjectionMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseTransposeProjectionMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.ViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewProjectionMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.TransposeViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.TransposeViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseTransposeViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseTransposeViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.RenderTargetFlipping:
                    WriteRawConstant(entry.PhysicalIndex, source.CurrentRenderTarget.RequiresTextureFlipping ? -1.0f : 1.0f);
                    break;

                case AutoConstantType.VertexWinding:
                {
                    var rsys = Root.Instance.RenderSystem;
                    WriteRawConstant(entry.PhysicalIndex, rsys.InvertVertexWinding ? -1.0f : 1.0f);
                    break;
                }

                // NB ambient light still here because it's not related to a specific light
                case AutoConstantType.AmbientLightColor:
                    WriteRawConstant(entry.PhysicalIndex, source.AmbientLight, entry.ElementCount);
                    break;

                case AutoConstantType.DerivedAmbientLightColor:
                    WriteRawConstant(entry.PhysicalIndex, source.DerivedAmbient, entry.ElementCount);
                    break;

                case AutoConstantType.DerivedSceneColor:
                    WriteRawConstant(entry.PhysicalIndex, source.DerivedSceneColor, entry.ElementCount);
                    break;

                case AutoConstantType.FogColor:
                    WriteRawConstant(entry.PhysicalIndex, source.FogColor);
                    break;

                case AutoConstantType.FogParams:
                    WriteRawConstant(entry.PhysicalIndex, source.FogParams, entry.ElementCount);
                    break;

                case AutoConstantType.SurfaceAmbientColor:
                    WriteRawConstant(entry.PhysicalIndex, source.SurfaceAmbient, entry.ElementCount);
                    break;

                case AutoConstantType.SurfaceDiffuseColor:
                    WriteRawConstant(entry.PhysicalIndex, source.SurfaceDiffuse, entry.ElementCount);
                    break;

                case AutoConstantType.SurfaceSpecularColor:
                    WriteRawConstant(entry.PhysicalIndex, source.SurfaceSpecular, entry.ElementCount);
                    break;

                case AutoConstantType.SurfaceEmissiveColor:
                    WriteRawConstant(entry.PhysicalIndex, source.SurfaceEmissive, entry.ElementCount);
                    break;

                case AutoConstantType.SurfaceShininess:
                    WriteRawConstant(entry.PhysicalIndex, source.SurfaceShininess);
                    break;

                case AutoConstantType.CameraPosition:
                    WriteRawConstant(entry.PhysicalIndex, source.CameraPosition, entry.ElementCount);
                    break;

                case AutoConstantType.Time:
                    WriteRawConstant(entry.PhysicalIndex, source.Time * entry.FData);
                    break;

                case AutoConstantType.Time_0_X:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTime_0_X(entry.FData));
                    break;

                case AutoConstantType.CosTime_0_X:
                    WriteRawConstant(entry.PhysicalIndex, source.GetCosTime_0_X(entry.FData));
                    break;

                case AutoConstantType.SinTime_0_X:
                    WriteRawConstant(entry.PhysicalIndex, source.GetSinTime_0_X(entry.FData));
                    break;

                case AutoConstantType.TanTime_0_X:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTanTime_0_X(entry.FData));
                    break;

                case AutoConstantType.Time_0_X_Packed:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTime_0_X_Packed(entry.FData), entry.ElementCount);
                    break;

                case AutoConstantType.Time_0_1:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTime_0_1(entry.FData));
                    break;

                case AutoConstantType.CosTime_0_1:
                    WriteRawConstant(entry.PhysicalIndex, source.GetCosTime_0_1(entry.FData));
                    break;

                case AutoConstantType.SinTime_0_1:
                    WriteRawConstant(entry.PhysicalIndex, source.GetSinTime_0_1(entry.FData));
                    break;

                case AutoConstantType.TanTime_0_1:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTanTime_0_1(entry.FData));
                    break;

                case AutoConstantType.Time_0_1_Packed:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTime_0_1_Packed(entry.FData), entry.ElementCount);
                    break;

                case AutoConstantType.Time_0_2PI:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTime_0_2Pi(entry.FData));
                    break;

                case AutoConstantType.CosTime_0_2PI:
                    WriteRawConstant(entry.PhysicalIndex, source.GetCosTime_0_2Pi(entry.FData));
                    break;

                case AutoConstantType.SinTime_0_2PI:
                    WriteRawConstant(entry.PhysicalIndex, source.GetSinTime_0_2Pi(entry.FData));
                    break;

                case AutoConstantType.TanTime_0_2PI:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTanTime_0_2Pi(entry.FData));
                    break;

                case AutoConstantType.Time_0_2PI_Packed:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTime_0_2Pi_Packed(entry.FData), entry.ElementCount);
                    break;

                case AutoConstantType.FrameTime:
                    WriteRawConstant(entry.PhysicalIndex, source.FrameTime * entry.FData);
                    break;

                case AutoConstantType.FPS:
                    WriteRawConstant(entry.PhysicalIndex, source.FPS);
                    break;

                case AutoConstantType.ViewportWidth:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewportWidth);
                    break;

                case AutoConstantType.ViewportHeight:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewportHeight);
                    break;

                case AutoConstantType.InverseViewportWidth:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseViewportWidth);
                    break;

                case AutoConstantType.InverseViewportHeight:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseViewportHeight);
                    break;

                case AutoConstantType.ViewportSize:
                {
                    WriteRawConstant(entry.PhysicalIndex,
                                     new Vector4(source.ViewportWidth, source.ViewportHeight, source.InverseViewportWidth,
                                                 source.InverseViewportHeight), entry.ElementCount);
                }
                break;

                case AutoConstantType.TexelOffsets:
                {
                    var rsys = Root.Instance.RenderSystem;
                    WriteRawConstant(entry.PhysicalIndex,
                                     new Vector4(rsys.HorizontalTexelOffset, rsys.VerticalTexelOffset,
                                                 rsys.HorizontalTexelOffset * source.InverseViewportWidth,
                                                 rsys.VerticalTexelOffset * source.InverseViewportHeight), entry.ElementCount);
                }
                break;

                case AutoConstantType.TextureSize:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTextureSize(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.InverseTextureSize:
                    WriteRawConstant(entry.PhysicalIndex, source.GetInverseTextureSize(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.PackedTextureSize:
                    WriteRawConstant(entry.PhysicalIndex, source.GetPackedTextureSize(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.SceneDepthRange:
                    WriteRawConstant(entry.PhysicalIndex, source.SceneDepthRange, entry.ElementCount);
                    break;

                case AutoConstantType.ViewDirection:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewDirection);
                    break;

                case AutoConstantType.ViewSideVector:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewSideVector);
                    break;

                case AutoConstantType.ViewUpVector:
                    WriteRawConstant(entry.PhysicalIndex, source.ViewUpVector);
                    break;

                case AutoConstantType.FOV:
                    WriteRawConstant(entry.PhysicalIndex, source.FOV);
                    break;

                case AutoConstantType.NearClipDistance:
                    WriteRawConstant(entry.PhysicalIndex, source.NearClipDistance);
                    break;

                case AutoConstantType.FarClipDistance:
                    WriteRawConstant(entry.PhysicalIndex, source.FarClipDistance);
                    break;

                case AutoConstantType.PassNumber:
                    WriteRawConstant(entry.PhysicalIndex, (float)source.PassNumber);
                    break;

                case AutoConstantType.PassIterationNumber:
                {
                    // this is actually just an initial set-up, it's bound separately, so still global
                    WriteRawConstant(entry.PhysicalIndex, 0.0f);
                    this.activePassIterationIndex = entry.PhysicalIndex;
                }
                break;

                case AutoConstantType.TextureMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.GetTextureTransformMatrix(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LODCameraPosition:
                    WriteRawConstant(entry.PhysicalIndex, source.LodCameraPosition, entry.ElementCount);
                    break;

                case AutoConstantType.TextureWorldViewProjMatrix:
                    // can also be updated in lights
                    WriteRawConstant(entry.PhysicalIndex, source.GetTextureWorldViewProjMatrix(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.TextureWorldViewProjMatrixArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        // can also be updated in lights
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetTextureWorldViewProjMatrix(l),
                                         entry.ElementCount);
                    }
                    break;

                case AutoConstantType.SpotLightWorldViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.GetSpotlightWorldViewProjMatrix(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LightPositionObjectSpace:
                {
                    vec4 = source.GetLightAs4DVector(entry.Data);
                    vec3 = new Vector3(vec4.x, vec4.y, vec4.z);
                    if (vec4.w > 0.0f)
                    {
                        // point light
                        vec3 = source.InverseWorldMatrix.TransformAffine(vec3);
                    }
                    else
                    {
                        // directional light
                        // We need the inverse of the inverse transpose
                        source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix(out m3);
                        vec3 = (m3 * vec3).ToNormalized();
                    }
                    WriteRawConstant(entry.PhysicalIndex, new Vector4(vec3.x, vec3.y, vec3.z, vec4.w), entry.ElementCount);
                }
                break;

                case AutoConstantType.LightDirectionObjectSpace:
                {
                    // We need the inverse of the inverse transpose
                    source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix(out m3);
                    vec3 = m3 * source.GetLightDirection(entry.Data);
                    vec3.Normalize();
                    // Set as 4D vector for compatibility
                    WriteRawConstant(entry.PhysicalIndex, new Vector4(vec3.x, vec3.y, vec3.z, 0.0f), entry.ElementCount);
                }
                break;

                case AutoConstantType.LightDistanceObjectSpace:
                {
                    vec3 = source.InverseWorldMatrix.TransformAffine(source.GetLightPosition(entry.Data));
                    WriteRawConstant(entry.PhysicalIndex, vec3.Length);
                }
                break;

                case AutoConstantType.LightPositionObjectSpaceArray:
                {
                    // We need the inverse of the inverse transpose
                    source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix(out m3);
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        vec4 = source.GetLightAs4DVector(l);
                        vec3 = new Vector3(vec4.x, vec4.y, vec4.z);
                        if (vec4.w > 0.0f)
                        {
                            // point light
                            vec3 = source.InverseWorldMatrix.TransformAffine(vec3);
                        }
                        else
                        {
                            // directional light
                            vec3 = (m3 * vec3).ToNormalized();
                        }
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, new Vector4(vec3.x, vec3.y, vec3.z, vec4.w),
                                         entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightDirectionObjectSpaceArray:
                {
                    // We need the inverse of the inverse transpose
                    source.InverseTransposeWorldMatrix.Inverse().Extract3x3Matrix(out m3);
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        vec3 = m3 * source.GetLightDirection(l);
                        vec3.Normalize();
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, new Vector4(vec3.x, vec3.y, vec3.z, 0.0f),
                                         entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightDistanceObjectSpaceArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        vec3 = source.InverseWorldMatrix.TransformAffine(source.GetLightPosition(l));
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, vec3.Length);
                    }
                    break;

                case AutoConstantType.WorldMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.WorldMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseWorldMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseWorldMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.TransposeWorldMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.TransposeWorldMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseTransposeWorldMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseTransposeWorldMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.WorldMatrixArray3x4:
                {
                    // Loop over matrices
                    var pMatrix     = source.WorldMatrixArray;
                    var numMatrices = source.WorldMatrixCount;
                    var index       = entry.PhysicalIndex;
                    var floatArray  = new float[16];
                    for (var m = 0; m < numMatrices; ++m)
                    {
                        pMatrix[m].MakeFloatArray(floatArray);
                        _writeRawConstants(index, floatArray, 12);
                        index += 12;
                    }
                }
                break;

                case AutoConstantType.WorldMatrixArray:
                    WriteRawConstant(entry.PhysicalIndex, source.WorldMatrixArray, source.WorldMatrixCount);
                    break;

                case AutoConstantType.WorldViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.WorldViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseWorldViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseWorldViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.TransposeWorldViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.TransposeWorldViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseTransposeWorldViewMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseTransposeWorldViewMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.WorldViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.WorldViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseWorldViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseWorldViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.TransposeWorldViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.TransposeWorldViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.InverseTransposeWorldViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.InverseTransposeWorldViewProjMatrix, entry.ElementCount);
                    break;

                case AutoConstantType.CameraPositionObjectSpace:
                    WriteRawConstant(entry.PhysicalIndex, source.CameraPositionObjectSpace, entry.ElementCount);
                    break;

                case AutoConstantType.LODCameraPositionObjectSpace:
                    WriteRawConstant(entry.PhysicalIndex, source.LodCameraPositionObjectSpace, entry.ElementCount);
                    break;

                case AutoConstantType.Custom:
                case AutoConstantType.AnimationParametric:
                    source.CurrentRenderable.UpdateCustomGpuParameter(entry, this);
                    break;

                case AutoConstantType.LightCustom:
                    source.UpdateLightCustomGpuParameter(entry, this);
                    break;

                case AutoConstantType.LightCount:
                    WriteRawConstant(entry.PhysicalIndex, source.LightCount);
                    break;

                case AutoConstantType.LightDiffuseColor:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightDiffuse(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LightSpecularColor:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightSpecular(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LightPosition:
                {
                    // Get as 4D vector, works for directional lights too
                    // Use element count in case uniform slot is smaller
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightAs4DVector(entry.Data), entry.ElementCount);
                }
                break;

                case AutoConstantType.LightDirection:
                {
                    vec3 = source.GetLightDirection(entry.Data);
                    // Set as 4D vector for compatibility
                    // Use element count in case uniform slot is smaller
                    WriteRawConstant(entry.PhysicalIndex, new Vector4(vec3.x, vec3.y, vec3.z, 1.0f), entry.ElementCount);
                }
                break;

                case AutoConstantType.LightPositionViewSpace:
                {
                    vec4 = source.GetLightAs4DVector(entry.Data);
                    WriteRawConstant(entry.PhysicalIndex, source.ViewMatrix.TransformAffine(vec4), entry.ElementCount);
                }
                break;

                case AutoConstantType.LightDirectionViewSpace:
                {
                    source.InverseTransposeViewMatrix.Extract3x3Matrix(out m3);
                    // inverse transpose in case of scaling
                    vec3 = m3 * source.GetLightDirection(entry.Data);
                    vec3.Normalize();
                    // Set as 4D vector for compatibility
                    WriteRawConstant(entry.PhysicalIndex, new Vector4(vec3.x, vec3.y, vec3.z, 0.0f), entry.ElementCount);
                }
                break;

                case AutoConstantType.ShadowExtrusionDistance:
                {
                    // extrusion is in object-space, so we have to rescale by the inverse
                    // of the world scaling to deal with scaled objects
                    source.WorldMatrix.Extract3x3Matrix(out m3);
                    WriteRawConstant(entry.PhysicalIndex,
                                     source.ShadowExtrusionDistance /
                                     Sqrt(
                                         Max(Max(m3.GetColumn(0).LengthSquared, m3.GetColumn(1).LengthSquared),
                                             m3.GetColumn(2).LengthSquared)));
                }
                break;

                case AutoConstantType.ShadowSceneDepthRange:
                    WriteRawConstant(entry.PhysicalIndex, source.GetShadowSceneDepthRange(entry.Data));
                    break;

                case AutoConstantType.ShadowColor:
                    WriteRawConstant(entry.PhysicalIndex, source.ShadowColor, entry.ElementCount);
                    break;

                case AutoConstantType.LightPowerScale:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightPowerScale(entry.Data));
                    break;

                case AutoConstantType.LightDiffuseColorPowerScaled:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightDiffuseColorWithPower(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LightSpecularColorPowerScaled:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightSpecularColorWithPower(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LightNumber:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightNumber(entry.Data));
                    break;

                case AutoConstantType.LightCastsShadows:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightCastsShadows(entry.Data));
                    break;

                case AutoConstantType.LightAttenuation:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightAttenuation(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.SpotLightParams:
                    WriteRawConstant(entry.PhysicalIndex, source.GetSpotlightParams(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.LightDiffuseColorArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightDiffuse(l), entry.ElementCount);
                    }
                    break;

                case AutoConstantType.LightSpecularColorArray:
                {
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightSpecular(l), entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightDiffuseColorPowerScaledArray:
                {
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightDiffuseColorWithPower(l),
                                         entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightSpecularColorPowerScaledArray:
                {
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightSpecularColorWithPower(l),
                                         entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightPositionArray:
                {
                    // Get as 4D vector, works for directional lights too
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightAs4DVector(l), entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightDirectionArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        vec3 = source.GetLightDirection(l);
                        // Set as 4D vector for compatibility
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, new Vector4(vec3.x, vec3.y, vec3.z, 0.0f),
                                         entry.ElementCount);
                    }
                    break;

                case AutoConstantType.LightPositionViewSpaceArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        vec4 = source.GetLightAs4DVector(l);
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.ViewMatrix.TransformAffine(vec4),
                                         entry.ElementCount);
                    }
                    break;

                case AutoConstantType.LightDirectionViewSpaceArray:
                {
                    source.InverseTransposeViewMatrix.Extract3x3Matrix(out m3);
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        vec3 = m3 * source.GetLightDirection(l);
                        vec3.Normalize();
                        // Set as 4D vector for compatibility
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, new Vector4(vec3.x, vec3.y, vec3.z, 0.0f),
                                         entry.ElementCount);
                    }
                }
                break;

                case AutoConstantType.LightPowerScaleArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightPowerScale(l));
                    }
                    break;

                case AutoConstantType.LightAttenuationArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetLightAttenuation(l), entry.ElementCount);
                    }
                    break;

                case AutoConstantType.SpotLightParamsArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetSpotlightParams(l), entry.ElementCount);
                    }
                    break;

                case AutoConstantType.DerivedLightDiffuseColor:
                {
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightDiffuseColorWithPower(entry.Data) * source.SurfaceDiffuse,
                                     entry.ElementCount);
                }
                break;

                case AutoConstantType.DerivedLightSpecularColor:
                    WriteRawConstant(entry.PhysicalIndex, source.GetLightSpecularColorWithPower(entry.Data) * source.SurfaceSpecular,
                                     entry.ElementCount);
                    break;

                case AutoConstantType.DerivedLightDiffuseColorArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount,
                                         source.GetLightDiffuseColorWithPower(l) * source.SurfaceDiffuse, entry.ElementCount);
                    }
                    break;

                case AutoConstantType.DerivedLightSpecularColorArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount,
                                         source.GetLightSpecularColorWithPower(l) * source.SurfaceSpecular, entry.ElementCount);
                    }
                    break;

                case AutoConstantType.TextureViewProjMatrix:
                    // can also be updated in lights
                    WriteRawConstant(entry.PhysicalIndex, source.GetTextureViewProjectionMatrix(entry.Data), entry.ElementCount);
                    break;

                case AutoConstantType.TextureViewProjMatrixArray:
                    for (var l = 0; l < entry.Data; ++l)
                    {
                        // can also be updated in lights
                        WriteRawConstant(entry.PhysicalIndex + l * entry.ElementCount, source.GetTextureViewProjectionMatrix(l),
                                         entry.ElementCount);
                    }
                    break;

                case AutoConstantType.SpotLightViewProjMatrix:
                    WriteRawConstant(entry.PhysicalIndex, source.GetSpotlightViewProjMatrix(entry.Data), entry.ElementCount);
                    break;

                default:
                    break;
                }
            }
        }
        /// <summary>
        /// Update automatic parameters.
        /// </summary>
        /// <param name="source">The source of the parameters</param>
        /// <param name="mask">A mask of GpuParamVariability which identifies which autos will need updating</param>
	    public void UpdateAutoParams( AutoParamDataSource source, GpuParamVariability mask )
	    {
            // abort early if no autos
            if (!HasAutoConstantType)
                return;

            // Axiom TODO: implement this early out opt
            // abort early if variability doesn't match any param
            //if (!(mask & _combinedVariability))
            //    return; 

            PassIterationNumberIndex = int.MaxValue;

            // loop through and update all constants based on their type
            foreach ( var entry in autoConstantList )
            {
                // Only update needed slots
                if ((entry.Variability & mask) == 0)
                    continue;

                Matrix4[] matrices;
                int numMatrices;
                int index;

                switch (entry.Type)
                {
                    case AutoConstantType.ViewMatrix:
                        SetConstant(entry.PhysicalIndex, source.ViewMatrix);
                        break;
                    case AutoConstantType.InverseViewMatrix:
                        SetConstant(entry.PhysicalIndex, source.InverseViewMatrix);
                        break;
                    case AutoConstantType.InverseTransposeViewMatrix:
                        SetConstant(entry.PhysicalIndex, source.InverseTransposeViewMatrix);
                        break;

                    case AutoConstantType.ProjectionMatrix:
                        SetConstant(entry.PhysicalIndex, source.ProjectionMatrix);
                        break;

                    case AutoConstantType.ViewProjMatrix:
                        SetConstant(entry.PhysicalIndex, source.ViewProjectionMatrix);
                        break;

                    case AutoConstantType.RenderTargetFlipping:
                        SetIntConstant(entry.PhysicalIndex, source.RenderTarget.RequiresTextureFlipping ? -1 : 1);
                        break;

                    case AutoConstantType.VertexWinding:
                    {
                        var rsys = Root.Instance.RenderSystem;
                        SetIntConstant(entry.PhysicalIndex, rsys.InvertVertexWinding ? -1 : 1);
                        break;
                    }

                    case AutoConstantType.AmbientLightColor:
                        SetConstant( entry.PhysicalIndex, source.AmbientLight );
                        break;

                    case AutoConstantType.WorldMatrix:
                        SetConstant(entry.PhysicalIndex, source.WorldMatrix);
                        break;

                    case AutoConstantType.WorldMatrixArray:
                        SetConstant(entry.PhysicalIndex, source.WorldMatrixArray, source.WorldMatrixCount);
                        break;

                    case AutoConstantType.WorldMatrixArray3x4:
                        matrices = source.WorldMatrixArray;
                        numMatrices = source.WorldMatrixCount;
                        index = entry.PhysicalIndex;

                        for (int j = 0; j < numMatrices; j++)
                        {
                            Matrix4 m = matrices[j];
                            SetConstant(index++, m.m00, m.m01, m.m02, m.m03);
                            SetConstant(index++, m.m10, m.m11, m.m12, m.m13);
                            SetConstant(index++, m.m20, m.m21, m.m22, m.m23);
                        }

                        break;

                    case AutoConstantType.WorldViewMatrix:
                        SetConstant(entry.PhysicalIndex, source.WorldViewMatrix);
                        break;

                    case AutoConstantType.WorldViewProjMatrix:
                        SetConstant(entry.PhysicalIndex, source.WorldViewProjMatrix);
                        break;

                    case AutoConstantType.InverseWorldMatrix:
                        SetConstant(entry.PhysicalIndex, source.InverseWorldMatrix);
                        break;

                    case AutoConstantType.InverseWorldViewMatrix:
                        SetConstant(entry.PhysicalIndex, source.InverseWorldViewMatrix);
                        break;

                    case AutoConstantType.InverseTransposeWorldViewMatrix:
                        SetConstant(entry.PhysicalIndex, source.InverseTransposeWorldViewMatrix);
                        break;   

                    case AutoConstantType.CameraPositionObjectSpace:
                        SetConstant(entry.PhysicalIndex, source.CameraPositionObjectSpace);
                        break;

                    case AutoConstantType.CameraPosition:
                        SetConstant(entry.PhysicalIndex, source.CameraPosition);
                        break;

                    case AutoConstantType.TextureViewProjMatrix:
                        SetConstant(entry.PhysicalIndex, source.TextureViewProjectionMatrix);
                        break;

                    case AutoConstantType.Custom:
                    case AutoConstantType.AnimationParametric:
                        source.Renderable.UpdateCustomGpuParameter(entry, this);
                        break;
                    case AutoConstantType.FogParams:
                        SetConstant(entry.PhysicalIndex, source.FogParams);
                        break;
                    case AutoConstantType.ViewDirection:
                        SetConstant(entry.PhysicalIndex, source.ViewDirection);
                        break;
                    case AutoConstantType.ViewSideVector:
                        SetConstant(entry.PhysicalIndex, source.ViewSideVector);
                        break;
                    case AutoConstantType.ViewUpVector:
                        SetConstant(entry.PhysicalIndex, source.ViewUpVector);
                        break;
                    case AutoConstantType.NearClipDistance:
                        SetConstant(entry.PhysicalIndex, source.NearClipDistance, 0f, 0f, 0f);
                        break;
                    case AutoConstantType.FarClipDistance:
                        SetConstant(entry.PhysicalIndex, source.FarClipDistance, 0f, 0f, 0f);
                        break;
                    case AutoConstantType.MVShadowTechnique:
                        SetConstant(entry.PhysicalIndex, source.MVShadowTechnique);
                        break;
                    case AutoConstantType.Time:
                        SetConstant(entry.PhysicalIndex, source.Time * entry.FData, 0f, 0f, 0f);
                        break;
                    case AutoConstantType.Time_0_X:
                        SetConstant(entry.PhysicalIndex, source.Time % entry.FData, 0f, 0f, 0f);
                        break;
                    case AutoConstantType.SinTime_0_X:
                        SetConstant(entry.PhysicalIndex, Utility.Sin(source.Time % entry.FData), 0f, 0f, 0f);
                        break;
                    case AutoConstantType.Time_0_1:
                        SetConstant(entry.PhysicalIndex, (float)(source.Time % 1), 0f, 0f, 0f);
                        break;
                    
                    case AutoConstantType.PassNumber:
                        SetIntConstant(entry.PhysicalIndex, source.PassNumber);
                        break;
                    case AutoConstantType.PassIterationNumber:
                        SetConstant(entry.PhysicalIndex, 0.0f);
                        PassIterationNumberIndex = entry.PhysicalIndex;
                        break;
                    default:
                        throw new NotImplementedException();
                }
            }
	    }
		protected GpuLogicalIndexUse GetFloatConstantLogicalIndexUse( int logicalIndex, int requestedSize,
																	  GpuParamVariability variability )
		{
			if ( this.floatLogicalToPhysical == null )
			{
				return null;
			}

			GpuLogicalIndexUse indexUse = null;
			lock ( this.floatLogicalToPhysical.Mutex )
			{
				GpuLogicalIndexUse logi;
				if ( !this.floatLogicalToPhysical.Map.TryGetValue( logicalIndex, out logi ) )
				{
					if ( requestedSize != 0 )
					{
						var physicalIndex = this.floatConstants.Count;

						// Expand at buffer end
						for ( var i = 0; i < requestedSize; i++ )
						{
							this.floatConstants.Add( 0.0f );
						}

						// Record extended size for future GPU params re-using this information
						this.floatLogicalToPhysical.BufferSize = this.floatConstants.Count;

						// low-level programs will not know about mapping ahead of time, so 
						// populate it. Other params objects will be able to just use this
						// accepted mapping since the constant structure will be the same

						// Set up a mapping for all items in the count
						var currPhys = physicalIndex;
						var count = requestedSize/4;

						GpuLogicalIndexUse insertedIterator = null;
						for ( var logicalNum = 0; logicalNum < count; ++logicalNum )
						{
							var it = new GpuLogicalIndexUse( currPhys, requestedSize, variability );
							this.floatLogicalToPhysical.Map.Add( logicalIndex + logicalNum, it );
							currPhys += 4;

							if ( logicalNum == 0 )
							{
								insertedIterator = it;
							}
						}

						indexUse = insertedIterator;
					}
					else
					{
						// no match & ignore
						return null;
					}
				}
				else
				{
					var physicalIndex = logi.PhysicalIndex;
					indexUse = logi;
					// check size
					if ( logi.CurrentSize < requestedSize )
					{
						// init buffer entry wasn't big enough; could be a mistake on the part
						// of the original use, or perhaps a variable length we can't predict
						// until first actual runtime use e.g. world matrix array
						var insertCount = requestedSize - logi.CurrentSize;
						var insertPos = 0;
						insertPos += physicalIndex;

						for ( var i = 0; i < insertCount; i++ )
						{
							this.floatConstants.Insert( insertPos, 0.0f );
						}

						// shift all physical positions after this one
						foreach ( var i in this.floatLogicalToPhysical.Map )
						{
							if ( i.Value.PhysicalIndex > physicalIndex )
							{
								i.Value.PhysicalIndex += insertCount;
							}
						}

						this.floatLogicalToPhysical.BufferSize += insertCount;
						foreach ( var i in this.autoConstants )
						{
							AutoConstantDefinition def;
							if ( i.PhysicalIndex > physicalIndex && GetAutoConstantDefinition( i.Type.ToString(), out def ) &&
								 def.ElementType == ElementType.Real )
							{
								i.PhysicalIndex += insertCount;
							}
						}
						if ( this._namedConstants != null )
						{
							foreach ( var i in this._namedConstants.Map )
							{
								if ( i.Value.IsFloat && i.Value.PhysicalIndex > physicalIndex )
								{
									i.Value.PhysicalIndex += insertCount;
								}
							}
							this._namedConstants.FloatBufferSize += insertCount;
						}

						logi.CurrentSize += insertCount;
					}
				}

				if ( indexUse != null )
				{
					indexUse.Variability = variability;
				}

				return indexUse;
			}
		}
		public GpuProgramParameters( GpuProgramParameters other )
			: base()
		{
			// let compiler perform shallow copies of structures 
			// AutoConstantEntry, RealConstantEntry, IntConstantEntry
			this.floatConstants = new FloatConstantList( other.floatConstants ); // vector<float> in ogre => shallow copy
			this.intConstants = new IntConstantList( other.intConstants ); // vector<int> in ogre => shallow copy

			this.autoConstants = new AutoConstantsList(); // vector<AutoConstantEntry> in ogre => deep copy
			foreach ( var ac in other.autoConstants )
			{
				this.autoConstants.Add( ac.Clone() );
			}

			// copy value members
			this.floatLogicalToPhysical = other.floatLogicalToPhysical; // pointer in ogre => no Clone
			this.intLogicalToPhysical = other.intLogicalToPhysical; // pointer in ogre => no Clone
			this._namedConstants = other._namedConstants; // pointer in ogre => no Clone
			CopySharedParamSetUsage( other._sharedParamSets );

			this._combinedVariability = other._combinedVariability;
			TransposeMatrices = other.TransposeMatrices;
			this.ignoreMissingParameters = other.ignoreMissingParameters;
			this.activePassIterationIndex = other.activePassIterationIndex;
		}
		public GpuProgramParameters()
			: base()
		{
			this._combinedVariability = GpuParamVariability.Global;
			this.activePassIterationIndex = int.MaxValue;
		}
		public void ClearAutoConstants()
		{
			this.autoConstants.Clear();
			this._combinedVariability = GpuParamVariability.Global;
		}
		protected internal void SetRawAutoConstantReal( int physicalIndex, AutoConstantType acType, Real extraInfo,
														GpuParamVariability variability, int elementSize )
		{
			// update existing index if it exists
			var found = false;
			foreach ( var i in this.autoConstants )
			{
				if ( i.PhysicalIndex == physicalIndex )
				{
					i.Type = acType;
					i.FData = extraInfo;
					i.ElementCount = elementSize;
					i.Variability = variability;
					found = true;
					break;
				}
			}
			if ( !found )
			{
				this.autoConstants.Add( new AutoConstantEntry( acType, physicalIndex, extraInfo, variability, elementSize ) );
			}

			this._combinedVariability |= variability;
		}
		internal int GetIntConstantPhysicalIndex( int logicalIndex, int requestedSize, GpuParamVariability variability )
		{
			var indexUse = GetIntConstantLogicalIndexUse( logicalIndex, requestedSize, variability );
			return indexUse != null ? indexUse.PhysicalIndex : 0;
		}
 public AutoConstantEntry(AutoConstantType type, int index, float fdata, GpuParamVariability variability)
     : this(type, index, fdata, variability, 4)
 {
 }
 public GpuLogicalIndexUse()
 {
     this.PhysicalIndex = 99999;
     this.CurrentSize   = 0;
     this.Variability   = GpuParamVariability.Global;
 }
		public void CopyConstantsFrom( GpuProgramParameters source )
		{
			this.floatConstants.Clear();
			this.floatConstants.AddRange( source.floatConstants );

			this.intConstants.Clear();
			this.intConstants.AddRange( source.intConstants );

			// Iterate over auto parameters
			// Clear existing auto constants
			ClearAutoConstants();
			this.autoConstants.AddRange( source.autoConstants.Select( x => x.Clone() ) );

			this._combinedVariability = source._combinedVariability;
			CopySharedParamSetUsage( source._sharedParamSets );
		}
 public GpuLogicalIndexUse(int bufIdx, int curSz, GpuParamVariability v)
 {
     this.PhysicalIndex = bufIdx;
     this.CurrentSize   = curSz;
     this.Variability   = v;
 }
 public GpuConstantDefinition()
 {
     ConstantType = GpuConstantType.Unknown;
     PhysicalIndex = Int32.MaxValue;
     ElementSize = 0;
     ArraySize = 1;
     Variability = GpuParamVariability.Global;
 }