Axiom.Graphics.Technique.Compile C# (CSharp) Method

Compile() private method

Compilation method for Techniques. See Axiom.Graphics.Material
private Compile ( bool autoManageTextureUnits ) : String
autoManageTextureUnits bool /// Determines whether or not the engine should split up extra texture unit requests /// into extra passes if the hardware does not have enough available units. ///
return String
		internal String Compile( bool autoManageTextureUnits )
		{
			StringBuilder compileErrors = new StringBuilder();
			// assume not supported unless it proves otherwise
			_isSupported = false;

			// grab a ref to the current hardware caps
			RenderSystemCapabilities caps = Root.Instance.RenderSystem.Capabilities;
			int numAvailTexUnits = caps.TextureUnitCount;

			int passNum = 0;

			for ( int i = 0; i < _passes.Count; i++, passNum++ )
			{
				Pass currPass = _passes[ i ];

				// Adjust pass index
				currPass.Index = passNum;

				// Check for advanced blending operation support
#warning Capabilities.AdvancedBlendOperation implementation required
				//if ( ( currPass.SceneBlendingOperation != SceneBlendingOperation.Add || currPass.SceneBlendingOperationAlpha != SceneBlendingOperation.Add ) &&
				//    !caps.HasCapability( Capabilities.AdvancedBlendOperations ) )
				//{
				//    return false;
				//}

				// Check texture unit requirements
				int numTexUnitsRequired = currPass.TextureUnitStageCount;

				// Don't trust getNumTextureUnits for programmable
				if ( !currPass.HasFragmentProgram )
				{
					if ( numTexUnitsRequired > numAvailTexUnits )
					{
						if ( !autoManageTextureUnits )
						{
							// The user disabled auto pass split
							compileErrors.AppendFormat( "Pass {0}: Too many texture units for the current hardware and no splitting allowed.", i );
						}
						else if ( currPass.HasVertexProgram )
						{
							// Can't do this one, and can't split a programmable pass
							compileErrors.AppendFormat( "Pass {0}: Too many texture units for the current hardware and cannot split programmable passes.", i );
						}
					}
				}

				// if this has a vertex program, check the syntax code to be sure the hardware supports it
				if ( currPass.HasVertexProgram )
				{
					// check vertex program version
					if ( !currPass.VertexProgram.IsSupported )
					{
						// can't do this one
						compileErrors.AppendFormat( "Pass {0}: Fragment Program {1} cannot be used - {2}",
											  i,
											  currPass.VertexProgramName,
											  currPass.VertexProgram.HasCompileError ? "Compile Error." : "Not Supported." );
					}
				}

				if ( currPass.HasGeometryProgram )
				{
					// check fragment program version
					if ( !currPass.GeometryProgram.IsSupported )
					{
						// can't do this one
						compileErrors.AppendFormat( "Pass {0}: Geometry Program {1} cannot be used - {2}",
											  i,
											  currPass.GeometryProgramName,
											  currPass.GeometryProgram.HasCompileError ? "Compile Error." : "Not Supported." );
					}
				}
				else
				{
					// check support for a few fixed function options while we are here
					for ( int j = 0; j < currPass.TextureUnitStageCount; j++ )
					{
						TextureUnitState texUnit = currPass.GetTextureUnitState( j );

						// check to make sure we have some cube mapping support
						if ( texUnit.Is3D && !caps.HasCapability( Capabilities.CubeMapping ) )
						{
							compileErrors.AppendFormat( "Pass {0} Tex {1} : Cube maps not supported by current environment.", i, j );
						}

						// if this is a Dot3 blending layer, make sure we can support it
						if ( texUnit.ColorBlendMode.operation == LayerBlendOperationEx.DotProduct && !caps.HasCapability( Capabilities.Dot3 ) )
						{
							compileErrors.AppendFormat( "Pass {0} Tex {1} : Volume textures not supported by current environment.", i, j );
						}
					}

					// keep splitting until the texture units required for this pass are available
					while ( numTexUnitsRequired > numAvailTexUnits )
					{
						// split this pass up into more passes
						currPass = currPass.Split( numAvailTexUnits );
						numTexUnitsRequired = currPass.TextureUnitStageCount;
					}
				}
			}
			// if we made it this far, we are good to go!
			_isSupported = true;

			// Compile for categorized illumination on demand
			ClearIlluminationPasses();
			_illuminationPassesCompilationPhase = IlluminationPassesCompilationPhase.NotCompiled;

			return compileErrors.ToString();
		}

Usage Example

        /// <summary>
        ///    'Compiles' this Material.
        /// </summary>
        /// <remarks>
        ///    Compiling a material involves determining which Techniques are supported on the
        ///    card on which the engine is currently running, and for fixed-function Passes within those
        ///    Techniques, splitting the passes down where they contain more TextureUnitState
        ///    instances than the curren card has texture units.
        ///    <p/>
        ///    This process is automatically done when the Material is loaded, but may be
        ///    repeated if you make some procedural changes.
        ///    <p/>
        ///    This method should be safe for use on threads other than the main render thread.
        /// </remarks>
        /// <param name="autoManageTextureUnits">
        ///    If true, when a fixed function pass has too many TextureUnitState
        ///    entries than the card has texture units, the Pass in question will be split into
        ///    more than one Pass in order to emulate the Pass. If you set this to false and
        ///    this situation arises, an Exception will be thrown.
        /// </param>
        public void Compile(bool autoManageTextureUnits)
        {
            // clear current list of supported techniques
            supportedTechniques.Clear();
            bestTechniquesByScheme.Clear();
            unsupportedReasons = "";
            string compileMessages = "";

            // compile each technique, adding supported ones to the list of supported techniques
            for (int i = 0; i < techniques.Count; i++)
            {
                Technique t = (Technique)techniques[i];

                // compile the technique, splitting texture passes if required
                compileMessages = t.Compile(autoManageTextureUnits);

                // if supported, add it to the list
                if (t.IsSupported)
                {
                    InsertSupportedTechnique(t);
                }
                else
                {
                    string s = "Material " + name + " Technique " + i;
                    if (t.Name != "")
                    {
                        s += " (" + t.Name + ")";
                    }
                    s += " is not supported.  " + compileMessages;
                    LogManager.Instance.Write(s);
                    unsupportedReasons = compileMessages;
                }
            }

            // TODO: Order best techniques

            compilationRequired = false;

            // Did we find any?
            if (supportedTechniques.Count == 0)
            {
                LogManager.Instance.Write("Warning: Material '{0}' has no supportable Techniques on this hardware.  Will be rendered blank.  Explanation: {1}",
                                          name, compileMessages);
            }
        }