示例#1
0
		internal override void WriteSourceCode( System.IO.StreamWriter stream, Program program )
		{
			var functionList = program.Functions;
			var parameterList = program.Parameters;

			//Generate source code header
			WriteProgramTitle( stream, program );
			stream.WriteLine();

			WriteProgramDependencies( stream, program );
			stream.WriteLine();

			WriteUniformParametersTitle( stream, program );
			stream.WriteLine();

			foreach ( var itUniformParam in parameterList )
			{
				WriteUniformParameter( stream, itUniformParam );
				stream.WriteLine( ";" );
			}
			stream.WriteLine();

			foreach ( var curFunction in functionList )
			{
				bool needToTranslateHlsl4Color = false;
				Parameter colorParameter;
				WriteFunctionTitle( stream, curFunction );
				WriteFunctionDeclaration( stream, curFunction, out needToTranslateHlsl4Color, out colorParameter );

				stream.WriteLine( "{" );

				var localParams = curFunction.LocalParameters;
				foreach ( var itParam in localParams )
				{
					stream.Write( "\t" );
					WriteLocalParameter( stream, itParam );
					stream.WriteLine( ";" );
				}

				if ( needToTranslateHlsl4Color )
				{
					stream.WriteLine( "\t" );
					WriteLocalParameter( stream, colorParameter );
					stream.WriteLine( ";" );
					stream.WriteLine();
					stream.WriteLine( "\tFFP_Assign(iHlsl4Color_0, " + colorParameter.Name + ");" );
				}

				curFunction.SortAtomInstances();
				var atomInstances = curFunction.AtomInstances;
				foreach ( var itAtom in atomInstances )
				{
					WriteAtomInstance( stream, itAtom );
				}

				stream.WriteLine( "}" );
			}
			stream.WriteLine();
		}
示例#2
0
		internal override void WriteSourceCode( System.IO.StreamWriter stream, Program program )
		{
			var functionList = program.Functions;
			var parameterList = program.Parameters;

			//Generate source code header
			WriteProgramTitle( stream, program );
			stream.WriteLine();
			//Generate dependencies
			WriteProgramDependencies( stream, program );
			stream.WriteLine();

			//Generate global variable code.
			WriteUniformParametersTitle( stream, program );
			stream.WriteLine();

			foreach ( var itUniformParam in parameterList )
			{
				WriteUniformParameter( stream, itUniformParam );
				stream.Write( ";\n" );
			}
			stream.WriteLine();

			//Write program function(s)
			foreach ( var curFunction in functionList )
			{
				Parameter colorParameter;

				WriteFunctionTitle( stream, curFunction );
				WriteFunctionDeclaration( stream, curFunction, out colorParameter );

				stream.Write( "{\n" );


				//Write local parameters
				var localParams = curFunction.LocalParameters;
				foreach ( var itParam in localParams )
				{
					stream.Write( "\t" );
					WriteLocalParameter( stream, itParam );
					stream.Write( ";\n" );
				}

				//Sort and write function atoms
				curFunction.SortAtomInstances();
				var atomInstances = curFunction.AtomInstances;
				foreach ( var itAtom in atomInstances )
				{
					WriteAtomInstance( stream, itAtom );
				}

				stream.Write( "}\n" );
			}
			stream.WriteLine();
		}
		private void BindTextureSampler( Program cpuProgram, GpuProgram gpuProgram )
		{
			var gpuParams = gpuProgram.DefaultParameters;
			var progParams = cpuProgram.Parameters;

			//Bind the samplers
			foreach ( var curParam in progParams )
			{
				if ( curParam.IsSampler )
				{
					gpuParams.SetNamedConstant( curParam.Name, curParam.Index );
				}
			}
		}
		private void BindTextureSamplers( Program cpuProgram, GpuProgram gpuProgram )
		{
			var gpuParams = gpuProgram.DefaultParameters;
			var progParams = cpuProgram.Parameters;

			//bind the samplers
			foreach ( var curParam in progParams )
			{
				if ( curParam.IsSampler )
				{
					// The optimizer may remove some unnecessary parameters, so we should ignore them
					gpuParams.IgnoreMissingParameters = true;
					gpuParams.SetNamedConstant( curParam.Name, curParam.Index );
				}
			}
		}
示例#5
0
		private void WriteProgramDependencies( StreamWriter stream, Program program )
		{
			stream.WriteLine( "//-----------------------------------------------------------------------------" );
			stream.WriteLine( "//                    PROGRAM DEPENDENCIES" );
			stream.WriteLine( "//-----------------------------------------------------------------------------" );

			for ( int i = 0; i < program.DependencyCount; i++ )
			{
				string curDependency = program.GetDependency( i );

				stream.WriteLine( "#include " + '\"' + curDependency + "." + TargetLanguage + '\"' );
			}
		}
示例#6
0
		private bool AddPSInvocation( Program psProgram, int groupOrder, ref int internalCounter )
		{
			Function psMain = psProgram.EntryPointFunction;
			FunctionInvocation curFuncInvocation = null;

			ShadowTextureParams splitParams0 = this.shadowTextureParamsList[ 0 ];
			ShadowTextureParams splitParams1 = this.shadowTextureParamsList[ 1 ];
			ShadowTextureParams splitParams2 = this.shadowTextureParamsList[ 2 ];

			//Compute shadow factor
			curFuncInvocation = new FunctionInvocation( SGXFuncComputeShadowColor3, groupOrder, internalCounter++ );
			curFuncInvocation.PushOperand( this.psInDepth, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psSplitPoints, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams0.PSInLightPosition, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams1.PSInLightPosition, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams2.PSInLightPosition, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams0.TextureSampler, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams1.TextureSampler, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams2.TextureSampler, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams0.InvTextureSize, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams1.InvTextureSize, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( splitParams2.InvTextureSize, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.Out );
			psMain.AddAtomInstance( curFuncInvocation );

			//Apply shadow factor on diffuse color
			curFuncInvocation = new FunctionInvocation( SGXFuncApplyShadowFactorDiffuse, groupOrder, internalCounter++ );
			curFuncInvocation.PushOperand( this.psDerivedSceneColor, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psDiffuse, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.Out );
			psMain.AddAtomInstance( curFuncInvocation );

			//Apply shadow factor on specular color
			curFuncInvocation = new FunctionInvocation( SGXFuncModulateScalar, groupOrder, internalCounter++ );
			curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psSpecular, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psSpecular, Operand.OpSemantic.Out );
			psMain.AddAtomInstance( curFuncInvocation );

			//Assign the local diffuse to output diffuse
			curFuncInvocation = new FunctionInvocation( FFPRenderState.FFPFuncAssign, groupOrder, internalCounter++ );
			curFuncInvocation.PushOperand( this.psDiffuse, Operand.OpSemantic.In );
			curFuncInvocation.PushOperand( this.psOutDiffuse, Operand.OpSemantic.Out );
			psMain.AddAtomInstance( curFuncInvocation );

			return true;
		}
		private void BindSubShaders( Program program, GpuProgram gpuProgram )
		{
			if ( program.DependencyCount > 0 )
			{
				// Get all attached shaders so we do not attach shaders twice.
				// maybe GLSLProgram should take care of that ( prevent add duplicate shaders )
				string attachedShaders = string.Empty; //TODO: gpuProgram.GetParameter("attach");
				string subSharedDef = string.Empty;

				for ( int i = 0; i < program.DependencyCount; i++ )
				{
					// Here we append _VS and _FS to the library shaders (so max each lib shader
					// is compiled twice once as vertex and once as fragment shader)

					string subShaderName = program.GetDependency( i );
					if ( program.Type == GpuProgramType.Vertex )
					{
						subShaderName += "_VS";
					}
					else
					{
						subShaderName += "_FS";
					}

					//Check if the library shader already compiled
					if ( !HighLevelGpuProgramManager.Instance.ResourceExists( subShaderName ) )
					{
						//Create the library shader
						HighLevelGpuProgram subGpuProgram =
							HighLevelGpuProgramManager.Instance.CreateProgram( subShaderName,
							                                                   ResourceGroupManager.
							                                                   	DefaultResourceGroupName,
							                                                   TargetLanguage, program.Type );

						//Set the source name
						string sourceName = program.GetDependency( i ) + "." + TargetLanguage;
						subGpuProgram.SourceFile = sourceName;

						//If we have compiler errors than stop processing
						if ( subGpuProgram.HasCompileError )
						{
							throw new AxiomException( "Could not compile shader library from the source file: " +
							                          sourceName );
						}

						this.libraryPrograms.Add( subShaderName );
					}

					//Check if the lib shader already attached to this shader
					if ( attachedShaders.Contains( subShaderName ) )
					{
						subSharedDef += subShaderName + " ";
					}
				}

				//Check if we have something to attach
				if ( subSharedDef.Length > 0 )
				{
					var nvpl = new Axiom.Collections.NameValuePairList();
					nvpl.Add( "attach", subSharedDef );
					gpuProgram.SetParameters( nvpl );
				}
			}
		}
		internal override void WriteSourceCode( System.IO.StreamWriter stream, Program program )
		{
			var gpuType = program.Type;

			if ( gpuType == GpuProgramType.Geometry )
			{
				throw new Core.AxiomException( "Geometry Programs not supported in GLSL ES writer" );
			}

			this.fragInputParams.Clear();
			var functionList = program.Functions;
			var parameterList = program.Parameters;

			// Write the current version (this forces the driver to fulfill the glsl es standard)
			stream.WriteLine( "#version" + this.glslVersion.ToString() );

			//Default precision declaration is required in fragment and vertex shaders.
			stream.WriteLine( "precision highp float" );
			stream.WriteLine( "precision highp int" );

			//Generate source code header
			WriteProgramTitle( stream, program );
			stream.WriteLine();

			//Embed depndencies.
			WriteProgramDependencies( stream, program );
			stream.WriteLine();

			//Generate global variable code.
			WriteUniformParametersTitle( stream, program );
			stream.WriteLine();

			//Write the uniforms
			foreach ( var uniformParams in parameterList )
			{
				stream.Write( "uniform\t" );
				stream.Write( this.gpuConstTypeMap[ uniformParams.Type ] );
				stream.Write( "\t" );
				stream.Write( uniformParams.Name );
				if ( uniformParams.IsArray )
				{
					stream.Write( "[" + uniformParams.Size.ToString() + "]" );
				}
				stream.WriteLine( ";" );
			}
			stream.WriteLine();

			//Write program function(s)
			foreach ( var curFunction in functionList )
			{
				WriteFunctionTitle( stream, curFunction );

				this.inputToGLStatesMap.Clear();

				WriteInputParameters( stream, curFunction, gpuType );
				WriteOutParameters( stream, curFunction, gpuType );

				stream.WriteLine( "void main() {" );

				if ( gpuType == GpuProgramType.Fragment )
				{
					stream.WriteLine( "\tvec4 outputColor;" );
				}
				else if ( gpuType == GpuProgramType.Vertex )
				{
					stream.WriteLine( "\tvec4 outputPosition;" );
				}

				//Write local paraemters
				var localParam = curFunction.LocalParameters;

				foreach ( var itParam in localParam )
				{
					stream.Write( "\t" );
					WriteLocalParameter( stream, itParam );
					stream.WriteLine( ";" );
				}
				stream.WriteLine();

				//sort function atoms
				curFunction.SortAtomInstances();

				var atomInstances = curFunction.AtomInstances;
				foreach ( var itAtom in atomInstances )
				{
					var funcInvoc = (FunctionInvocation)itAtom;
					int itOperand = 0;
					int itOperandEnd = funcInvoc.OperandList.Count;

					var localOs = new StringBuilder();
					localOs.Append( "\t" + funcInvoc.FunctionName + "(" );

					int curIndLevel = 0;
					while ( itOperand != itOperandEnd )
					{
						Operand op = funcInvoc.OperandList[ itOperand ];
						Operand.OpSemantic opSemantic = op.Semantic;
						string paramName = op.Parameter.Name;
						Parameter.ContentType content = op.Parameter.Content;

						// Check if we write to a varying because the are only readable in fragment programs 
						if ( opSemantic == Operand.OpSemantic.Out || opSemantic == Operand.OpSemantic.InOut )
						{
							bool isVarying = false;

							if ( gpuType == GpuProgramType.Fragment )
							{
								if ( this.fragInputParams.Contains( paramName ) )
								{
									//Declare the copy variable
									string newVar = "local_" + paramName;
									string tempVar = paramName;
									isVarying = true;

									// We stored the original values in the mFragInputParams thats why we have to replace the first var with o
									// because all vertex output vars are prefixed with o in glsl the name has to match in the fragment program.
									tempVar.Remove( 0 );
									tempVar.Insert( 0, "o" );

									//Declare the copy variable and assign the original
									stream.WriteLine( "\t" + this.gpuConstTypeMap[ op.Parameter.Type ] + " " + newVar + " = " +
									                  tempVar + ";\n" );

									//Fromnow on we replace it automatic
									this.inputToGLStatesMap.Add( paramName, newVar );

									this.fragInputParams.Remove( paramName );
								}
							}

							if ( !isVarying )
							{
								foreach ( var param in parameterList )
								{
									if ( CompareUniformByName( param, paramName ) )
									{
										string newVar = "local_" + paramName;

										if ( this.inputToGLStatesMap.ContainsKey( newVar ) == false )
										{
											//Declare the copy variable and assign the original

											stream.WriteLine( "\t" + this.gpuConstTypeMap[ param.Type ] + " " + newVar +
											                  " = " + paramName + ";\n" );

											//From now on we replace it automatic
											this.inputToGLStatesMap.Add( paramName, newVar );
										}
									}
								}
							}

							string newParam;
							if ( this.inputToGLStatesMap.ContainsKey( paramName ) )
							{
								int mask = op.Mask; //our swizzle mask

								//Here we insert the renamed param name
								newParam = this.inputToGLStatesMap[ paramName ];

								if ( mask != (int)Operand.OpMask.All )
								{
									newParam += "." + Operand.GetMaskAsString( mask );
								}
									// Now that every texcoord is a vec4 (passed as vertex attributes) we
									// have to swizzle them according the desired type.
								else if ( gpuType == GpuProgramType.Vertex &&
								          content == Parameter.ContentType.TextureCoordinate0 ||
								          content == Parameter.ContentType.TextureCoordinate1 ||
								          content == Parameter.ContentType.TextureCoordinate2 ||
								          content == Parameter.ContentType.TextureCoordinate3 ||
								          content == Parameter.ContentType.TextureCoordinate4 ||
								          content == Parameter.ContentType.TextureCoordinate5 ||
								          content == Parameter.ContentType.TextureCoordinate6 ||
								          content == Parameter.ContentType.TextureCoordinate7 )
								{
									//Now generate the swizzle mask according
									// the type.
									switch ( op.Parameter.Type )
									{
										case GpuProgramParameters.GpuConstantType.Float1:
											newParam += ".x";
											break;
										case GpuProgramParameters.GpuConstantType.Float2:
											newParam += ".xy";
											break;
										case GpuProgramParameters.GpuConstantType.Float3:
											newParam += ".xyz";
											break;
										case GpuProgramParameters.GpuConstantType.Float4:
											newParam += ".xyzw";
											break;
										default:
											break;
									}
								}
							}
							else
							{
								newParam = op.ToString();
							}

							itOperand++;

							//Prepare for the next operand
							localOs.Append( newParam );

							int opIndLevel = 0;
							if ( itOperand != itOperandEnd )
							{
								opIndLevel = funcInvoc.OperandList[ itOperand ].IndirectionLevel;
							}

							if ( curIndLevel != 0 )
							{
								localOs.Append( ")" );
							}
							if ( curIndLevel < opIndLevel )
							{
								while ( curIndLevel < opIndLevel )
								{
									curIndLevel++;
									localOs.Append( "[" );
								}
							}
							else
							{
								while ( curIndLevel > opIndLevel )
								{
									curIndLevel--;
									localOs.Append( "]" );
								}
								if ( opIndLevel != 0 )
								{
									localOs.Append( "][" );
								}
								else if ( itOperand != itOperandEnd )
								{
									localOs.Append( ", " );
								}
							}
							if ( curIndLevel != 0 )
							{
								localOs.Append( "int(" );
							}
						}
						//Write function call closer
						localOs.AppendLine( ");" );
						localOs.AppendLine();
						stream.Write( localOs.ToString() );
					}
				}

				if ( gpuType == GpuProgramType.Fragment )
				{
					stream.WriteLine( "\tgl_FragColor = outputColor;" );
				}
				else if ( gpuType == GpuProgramType.Vertex )
				{
					stream.WriteLine( "\tgl_Position = outputPosition;" );
				}

				stream.WriteLine( "}" );
			}

			stream.WriteLine();
		}
		private void WriteProgramDependencies( StreamWriter stream, Program program )
		{
			for ( int i = 0; i < program.DependencyCount; i++ )
			{
				string curDependency = program.GetDependency( i );
				CacheDependencyFunctions( curDependency );
			}

			stream.WriteLine( "//-----------------------------------------------------------------------------" );
			stream.WriteLine( "//                        PROGRAM DEPENDENCIES" );
			stream.WriteLine();

			var forwardDecl = new List<FunctionInvocation>();
			var functionList = program.Functions;
			int itFunction = 0;
			Function curFunction = functionList[ 0 ];
			var atomInstances = curFunction.AtomInstances;
			int itAtom = 0;
			int itAtomEnd = atomInstances.Count;

			//Now iterate over all function atoms
			for ( ; itAtom != itAtomEnd; itAtom++ )
			{
				//Skip non function invocation atom
				if ( atomInstances[ itAtom ] is FunctionInvocation == false )
				{
					continue;
				}

				var funcInvoc = atomInstances[ itAtom ] as FunctionInvocation;
				forwardDecl.Add( funcInvoc );

				// Now look into that function for other non-builtin functions and add them to the declaration list
				// Look for non-builtin functions
				// Do so by assuming that these functions do not have several variations.
				// Also, because GLSL is C based, functions must be defined before they are used
				// so we can make the assumption that we already have this function cached.
				//
				// If we find a function, look it up in the map and write it out
				DiscoverFunctionDependencies( funcInvoc, forwardDecl );
			}

			//Now remove duplicate declarations
			forwardDecl.Sort();
			forwardDecl = forwardDecl.Distinct( new FunctionInvocation.FunctionInvocationComparer() ).ToList();

			for ( int i = 0; i < program.DependencyCount; i++ )
			{
				string curDependency = program.GetDependency( i );

				foreach ( var key in this.definesMap.Keys )
				{
					if ( this.definesMap[ key ] == curDependency )
					{
						stream.Write( this.definesMap[ key ] );
						stream.Write( "\n" );
					}
				}
			}
			// Parse the source shader and write out only the needed functions
			foreach ( var it in forwardDecl )
			{
				var invoc = new FunctionInvocation( string.Empty, 0, 0, string.Empty );

				string body = string.Empty;

				//find the function in the cache
				foreach ( var key in this.functionCacheMap.Keys )
				{
					if ( !( it == key ) )
					{
						continue;
					}

					invoc = key;
					body = this.functionCacheMap[ key ];
					break;
				}

				if ( invoc.FunctionName.Length > 0 )
				{
					//Write out the funciton name from the cached FunctionInvocation
					stream.Write( invoc.ReturnType );
					stream.Write( " " );
					stream.Write( invoc.FunctionName );
					stream.Write( "(" );

					int itOperand = 0;
					int itOperandEnd = invoc.OperandList.Count;

					while ( itOperand != itOperandEnd )
					{
						Operand op = invoc.OperandList[ itOperand ];
						Operand.OpSemantic opSemantic = op.Semantic;
						string paramName = op.Parameter.Name;
						int opMask = op.Mask;
						GpuProgramParameters.GpuConstantType gpuType = GpuProgramParameters.GpuConstantType.Unknown;

						switch ( opSemantic )
						{
							case Operand.OpSemantic.In:
								stream.Write( "in " );
								break;
							case Operand.OpSemantic.Out:
								stream.Write( "out " );
								break;
							case Operand.OpSemantic.InOut:
								stream.Write( "inout " );
								break;
							default:
								break;
						}

						//Swizzle masks are onluy defined for types like vec2, vec3, vec4
						if ( opMask == (int)Operand.OpMask.All )
						{
							gpuType = op.Parameter.Type;
						}
						else
						{
							gpuType = Operand.GetGpuConstantType( opMask );
						}

						//We need a valid type otherwise glsl compilation will not work
						if ( gpuType == GpuProgramParameters.GpuConstantType.Unknown )
						{
							throw new Core.AxiomException( "Cannot convert Operand.OpMask to GpuConstantType" );
						}

						stream.Write( this.gpuConstTypeMap[ gpuType ] + " " + paramName );

						itOperand++;

						//Prepare for the next operand
						if ( itOperand != itOperandEnd )
						{
							stream.Write( ", " );
						}
					}
					stream.WriteLine();
					stream.WriteLine( "{" );
					stream.WriteLine( body );
					stream.WriteLine( "}" );
					stream.WriteLine();
				}
			}
		}
示例#10
0
		private void WriteForwardDeclarations( StreamWriter stream, Program program )
		{
			stream.WriteLine( "//-----------------------------------------------------------------------------" );
			stream.WriteLine( "//                FORWARD DECLARATIONS" );
			stream.WriteLine( "//-----------------------------------------------------------------------------" );

			var forwardDecl = new List<string>(); // hold all generated function declarations
			var functionList = program.Functions;

			foreach ( var curFunction in functionList )
			{
				var atomInstances = curFunction.AtomInstances;

				for ( int i = 0; i < atomInstances.Count; i++ )
				{
					var itAtom = atomInstances[ i ];

					//Skip non function invocation atoms
					if ( !( itAtom is FunctionInvocation ) )
					{
						continue;
					}

					var funcInvoc = itAtom as FunctionInvocation;

					int itOperator = 0;
					int itOperatorEnd = funcInvoc.OperandList.Count;

					//Start with function declaration
					string funcDecl = funcInvoc.ReturnType + " " + funcInvoc.FunctionName + "(";

					//Now iterate overall operands
					while ( itOperator != itOperatorEnd )
					{
						Parameter param = funcInvoc.OperandList[ itOperator ].Parameter;
						Operand.OpSemantic opSemantic = funcInvoc.OperandList[ itOperator ].Semantic;
						int opMask = funcInvoc.OperandList[ itOperator ].Mask;
						Axiom.Graphics.GpuProgramParameters.GpuConstantType gpuType =
							GpuProgramParameters.GpuConstantType.Unknown;

						//Write the semantic in, out, inout
						switch ( opSemantic )
						{
							case Operand.OpSemantic.In:
								funcDecl += "in ";
								break;
							case Operand.OpSemantic.Out:
								funcDecl += "out ";
								break;
							case Operand.OpSemantic.InOut:
								funcDecl += "inout ";
								break;
							default:
								break;
						}

						//Swizzle masks are only defined fro types like vec2, vec3, vec4
						if ( opMask == (int)Operand.OpMask.All )
						{
							gpuType = param.Type;
						}
						else
						{
							//Now we have to conver the mask to operator
							gpuType = Operand.GetGpuConstantType( opMask );
						}

						//We need a valid type otherwise glsl compilation will not work
						if ( gpuType == GpuProgramParameters.GpuConstantType.Unknown )
						{
							throw new Core.AxiomException( "Cannot convert Operand.OpMask to GpuConstantType" );
						}

						//Write the operand type.
						funcDecl += this.gpuConstTypeMap[ gpuType ];

						itOperator++;
						//move over all operators with indirection
						while ( ( itOperator != itOperatorEnd ) &&
						        ( funcInvoc.OperandList[ itOperator ].IndirectionLevel != 0 ) )
						{
							itOperator++;
						}

						//Prepare for the next operand
						if ( itOperator != itOperatorEnd )
						{
							funcDecl += ", ";
						}
					}

					//Write function call closer.
					funcDecl += ");\n";

					//Push the generated declaration into the vector
					//duplicate declarations will be removed later.
					forwardDecl.Add( funcDecl );
				}
			}
			//Now remove duplicate declaration, first we have to sort the vector.
			forwardDecl.Sort();
			forwardDecl = forwardDecl.Distinct().ToList();

			foreach ( var it in forwardDecl )
			{
				stream.Write( it );
			}
		}
示例#11
0
		internal override void WriteSourceCode( System.IO.StreamWriter stream, Program program )
		{
			var gpuType = program.Type;
			if ( gpuType == GpuProgramType.Geometry )
			{
				throw new Core.AxiomException( "Geometry Program not supported iin GLSL writer" );
			}

			this.fragInputParams.Clear();
			var functionList = program.Functions;
			var parameterList = program.Parameters;

			// Write the current version (this force the driver to more fulfill the glsl standard)
			stream.WriteLine( "#version " + this.glslVersion.ToString() );

			//Generate source code header
			WriteProgramTitle( stream, program );
			stream.WriteLine();

			//Write forward declarations
			WriteForwardDeclarations( stream, program );
			stream.WriteLine();

			//Generate global variable code
			WriteUniformParametersTitle( stream, program );
			stream.WriteLine();

			//Write the uniforms
			foreach ( var uniformParam in parameterList )
			{
				stream.Write( "uniform\t" );
				stream.Write( this.gpuConstTypeMap[ uniformParam.Type ] );
				stream.Write( "\t" );
				stream.Write( uniformParam.Name );
				if ( uniformParam.IsArray )
				{
					stream.Write( "[" + uniformParam.Size.ToString() + "]" );
				}
				stream.Write( ";" );
				stream.WriteLine();
			}
			stream.WriteLine();

			//Write program function(s)
			foreach ( var curFunction in functionList )
			{
				WriteFunctionTitle( stream, curFunction );

				//Clear output mapping this map is used when we use
				//glsl built in types like gl_Color for example
				this.inputToGLStatesMap.Clear();

				//Write inout params and fill inputToGLStatesMap
				WriteInputParameters( stream, curFunction, gpuType );
				WriteOutParameters( stream, curFunction, gpuType );

				stream.Write( "void main() {" );
				stream.WriteLine();
				//Write local parameters
				var localParams = curFunction.LocalParameters;

				foreach ( var itParam in localParams )
				{
					stream.Write( "\t" );
					WriteLocalParameter( stream, itParam );
					stream.Write( ";" );
					stream.WriteLine();
				}

				stream.WriteLine();
				//Sort function atoms
				curFunction.SortAtomInstances();
				var atomInstances = curFunction.AtomInstances;

				foreach ( var itAtom in atomInstances )
				{
					var funcInvoc = itAtom as FunctionInvocation;

					var localOs = new StringBuilder();

					//Write function name
					localOs.Append( "\t" + funcInvoc.FunctionAtomType + "(" );
					int curIndLevel = 0;

					int itOperand = 0;
					int itOperandEnd = funcInvoc.OperandList.Count;

					while ( itOperand != itOperandEnd )
					{
						Operand op = funcInvoc.OperandList[ itOperand ];
						Operand.OpSemantic opSemantic = op.Semantic;
						string paramName = op.Parameter.Name;
						Parameter.ContentType content = op.Parameter.Content;

						if ( opSemantic == Operand.OpSemantic.Out || opSemantic == Operand.OpSemantic.InOut )
						{
							bool isVarying = false;

							// Check if we write to an varying because the are only readable in fragment programs 
							if ( gpuType == GpuProgramType.Fragment )
							{
								if ( this.fragInputParams.Contains( paramName ) )
								{
									//Declare the copy variable
									string newVar = "local_" + paramName;
									string tempVar = paramName;
									isVarying = true;

									// We stored the original values in the mFragInputParams thats why we have to replace the first var with o
									// because all vertex output vars are prefixed with o in glsl the name has to match in the fragment program.
									tempVar = tempVar.Remove( 0 );
									tempVar = tempVar.Insert( 0, "o" );

									//Declare the copy variable and assign the original
									stream.WriteLine( "\t" + this.gpuConstTypeMap[ op.Parameter.Type ] + " " + newVar + " = " +
									                  tempVar );

									//From now on we replace it automatic
									this.inputToGLStatesMap[ paramName ] = newVar;

									//Remove the param because now it is replaced automatic with the local variable
									//(which could be written).
									this.fragInputParams.Remove( paramName );
								}
							}

							//If its not varying param check if a uniform is written
							if ( !isVarying )
							{
								foreach ( var param in parameterList )
								{
									if ( GLSLProgramWriter.CompareUniformByName( param, paramName ) )
									{
										//Declare the copy variable
										string newVar = "local_" + paramName;

										//now we check if we already declared a uniform redirector var
										if ( this.inputToGLStatesMap.ContainsKey( newVar ) == false )
										{
											//Declare the copy variable and assign the original
											stream.WriteLine( "\t" + this.gpuConstTypeMap[ param.Type ] + " " + newVar +
											                  paramName + ";\n" );

											//From now on we replace it automatic
											this.inputToGLStatesMap.Add( paramName, newVar );
										}
									}
								}
							}
						}
						if ( this.inputToGLStatesMap.ContainsKey( paramName ) )
						{
							int mask = op.Mask; // our swizzle mask

							//Here we insert the renamed param name
							localOs.Append( "." + Operand.GetMaskAsString( mask ) );

							if ( mask != (int)Operand.OpMask.All )
							{
								localOs.Append( "." + Operand.GetMaskAsString( mask ) );
							}

								//Now that every texcoord is a vec4 (passed as vertex attributes)
								//we have to swizzle them aoccording the desired type.
							else if ( gpuType == GpuProgramType.Vertex &&
							          content == Parameter.ContentType.TextureCoordinate0 ||
							          content == Parameter.ContentType.TextureCoordinate1 ||
							          content == Parameter.ContentType.TextureCoordinate2 ||
							          content == Parameter.ContentType.TextureCoordinate3 ||
							          content == Parameter.ContentType.TextureCoordinate4 ||
							          content == Parameter.ContentType.TextureCoordinate5 ||
							          content == Parameter.ContentType.TextureCoordinate6 ||
							          content == Parameter.ContentType.TextureCoordinate7 )
							{
								//Now generate the swizzel mask according
								//the type.
								switch ( op.Parameter.Type )
								{
									case GpuProgramParameters.GpuConstantType.Float1:
										localOs.Append( ".x" );
										break;
									case GpuProgramParameters.GpuConstantType.Float2:
										localOs.Append( ".xy" );
										break;
									case GpuProgramParameters.GpuConstantType.Float3:
										localOs.Append( ".xyz" );
										break;
									case GpuProgramParameters.GpuConstantType.Float4:
										localOs.Append( ".xyzw" );
										break;
									default:
										break;
								}
							}
						}
						else
						{
							localOs.Append( op.ToString() );
						}
						itOperand++;

						//Prepare for the next operand
						int opIndLevel = 0;
						if ( itOperand != itOperandEnd )
						{
							opIndLevel = funcInvoc.OperandList[ itOperand ].IndirectionLevel;
						}

						if ( curIndLevel < opIndLevel )
						{
							while ( curIndLevel < opIndLevel )
							{
								curIndLevel++;
								localOs.Append( "[" );
							}
						}
						else
						{
							while ( curIndLevel > opIndLevel )
							{
								curIndLevel--;
								localOs.Append( "]" );
							}
							if ( opIndLevel != 0 )
							{
								localOs.Append( "][" );
							}
							else if ( itOperand != itOperandEnd )
							{
								localOs.Append( ", " );
							}
						}
						if ( curIndLevel != 0 )
						{
							localOs.Append( "int(" );
						}
					}

					//Write function call closer
					localOs.AppendLine( ");" );
					localOs.AppendLine();
					stream.Write( localOs.ToString() );
				}
				stream.WriteLine( "}" );
			}
			stream.WriteLine();
		}