public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            //System.Diagnostics.Debugger.Launch();

            // If this isn't a MonoGame platform then do the default processing.
            var platform = ContentHelper.GetMonoGamePlatform();
            if (platform == MonoGamePlatform.None)
                return base.Process(input, context);

            var options = new Options();
            options.SourceFile = input.Identity.SourceFilename;
            options.Profile = platform == MonoGamePlatform.Windows8 ? ShaderProfile.DirectX_11 : ShaderProfile.OpenGL;
            options.Debug = DebugMode == EffectProcessorDebugMode.Debug;
            options.OutputFile = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);
                foreach (var dep in shaderInfo.Dependencies)
                    context.AddDependency(dep);
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            EffectObject effect = null;
            var shaderErrorsAndWarnings = string.Empty;
            try
            {
                effect = EffectObject.CompileEffect(shaderInfo, out shaderErrorsAndWarnings);
            }
            catch (ShaderCompilerException)
            {
                throw ProcessErrorsAndWarnings(shaderErrorsAndWarnings, input, context);
            }

            // Write out the effect to a runtime format.
            CompiledEffectContent result;
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", input.Identity, ex);
            }

            return result;
        }
Beispiel #2
0
        public void Write(BinaryWriter writer, Options options)
        {
            writer.Write(IsVertexShader);

            writer.Write(ShaderCode.Length);
            writer.Write(ShaderCode);

            writer.Write((byte)_samplers.Length);
            foreach (var sampler in _samplers)
            {
                writer.Write((byte)sampler.type);
                writer.Write((byte)sampler.textureSlot);
                writer.Write((byte)sampler.samplerSlot);

				if (sampler.state != null)
				{
					writer.Write(true);
					writer.Write((byte)sampler.state.AddressU);
					writer.Write((byte)sampler.state.AddressV);
					writer.Write((byte)sampler.state.AddressW);
                    writer.Write(sampler.state.BorderColor.R);
                    writer.Write(sampler.state.BorderColor.G);
                    writer.Write(sampler.state.BorderColor.B);
                    writer.Write(sampler.state.BorderColor.A);
					writer.Write((byte)sampler.state.Filter);
					writer.Write(sampler.state.MaxAnisotropy);
					writer.Write(sampler.state.MaxMipLevel);
					writer.Write(sampler.state.MipMapLevelOfDetailBias);
				}
				else
					writer.Write(false);

                if (options.Profile == ShaderProfile.OpenGL)
                    writer.Write(sampler.samplerName);

                writer.Write((byte)sampler.parameter);
            }

            writer.Write((byte)_cbuffers.Length);
            foreach (var cb in _cbuffers)
                writer.Write((byte)cb);

            if (options.Profile != ShaderProfile.OpenGL)
                return;

            // The rest of this is for GL only!

            writer.Write((byte)_attributes.Length);
            foreach (var attrib in _attributes)
            {
                writer.Write(attrib.name);
                writer.Write((byte)attrib.usage);
                writer.Write((byte)attrib.index);
                writer.Write((short)0); // Unused
            }
        }
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            //System.Diagnostics.Debugger.Launch();

            // If this isn't a MonoGame platform then do the default processing.
            var platform = ContentHelper.GetMonoGamePlatform();
            if (platform == MonoGamePlatform.None)
                return base.Process(input, context);

            var options = new Options();
            options.SourceFile = input.Identity.SourceFilename;
            options.DX11Profile = platform == MonoGamePlatform.Windows8 ? true : false;
            options.OutputFile = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to parse the effect!", ex);
            }

            // Create the effect object.
            DXEffectObject effect;
            try
            {
                effect = DXEffectObject.FromShaderInfo(shaderInfo);
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to create the effect!", ex);
            }

            // Write out the effect to a runtime format.
            CompiledEffectContent result;
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", ex);
            }

            return result;
        }
        public void Write(BinaryWriter writer, Options options)
        {
            writer.Write(IsVertexShader);

            writer.Write((ushort)ShaderCode.Length);
            writer.Write(ShaderCode);

            writer.Write((byte)_samplers.Length);
            foreach (var sampler in _samplers)
            {
                writer.Write((byte)sampler.type);
                writer.Write((byte)sampler.index);

				if (sampler.state != null)
				{
					writer.Write(true);
					writer.Write((byte)sampler.state.AddressU);
					writer.Write((byte)sampler.state.AddressV);
					writer.Write((byte)sampler.state.AddressW);
					writer.Write((byte)sampler.state.Filter);
					writer.Write(sampler.state.MaxAnisotropy);
					writer.Write(sampler.state.MaxMipLevel);
					writer.Write(sampler.state.MipMapLevelOfDetailBias);
				}
				else
					writer.Write(false);

                if (!options.DX11Profile)
                    writer.Write(sampler.samplerName);

                writer.Write((byte)sampler.parameter);
            }

            writer.Write((byte)_cbuffers.Length);
            foreach (var cb in _cbuffers)
                writer.Write((byte)cb);

            if (options.DX11Profile)
                return;

            // The rest of this is for GL only!

            writer.Write((byte)_attributes.Length);
            foreach (var attrib in _attributes)
            {
                writer.Write(attrib.name);
                writer.Write((byte)attrib.usage);
                writer.Write((byte)attrib.index);
                writer.Write(attrib.format);
            }
        }
        public void Write(BinaryWriter writer, Options options)
        {
            if (options.Profile == ShaderProfile.OpenGL)
                writer.Write(Name);

            writer.Write((ushort)Size);

            writer.Write((byte)ParameterIndex.Count);
            for (var i=0; i < ParameterIndex.Count; i++)
            {
                writer.Write((byte)ParameterIndex[i]);
                writer.Write((ushort)ParameterOffset[i]);
            }
        }
        /// <summary>
        /// Writes the effect for loading later.
        /// </summary>
        public void Write(BinaryWriter writer, Options options)
        {
            // Write a very simple header for identification and versioning.
            writer.Write(Header.ToCharArray());
            writer.Write((byte)Version);

            // Write an simple identifier for DX11 vs GLSL
            // so we can easily detect the correct shader type.
            var profile = (byte)( options.DX11Profile ? 1 : 0 );
            writer.Write(profile);

            // Write all the constant buffers.
            writer.Write((byte)ConstantBuffers.Count);
            foreach (var cbuffer in ConstantBuffers)
                cbuffer.Write(writer, options);

            // Write all the shaders.
            writer.Write((byte)Shaders.Count);
            foreach (var shader in Shaders)
                shader.Write(writer, options);

            // Write the parameters.
            WriteParameters(writer, Parameters, Parameters.Length);

            // Write the techniques.
            writer.Write((byte)Techniques.Length);
            foreach (var technique in Techniques)
            {
                writer.Write(technique.name);
                WriteAnnotations(writer, technique.annotation_handles);

                // Write the passes.
                writer.Write((byte)technique.pass_count);
                for (var p = 0; p < technique.pass_count; p++)
                {
                    var pass = technique.pass_handles[p];

                    writer.Write(pass.name);
                    WriteAnnotations(writer, pass.annotation_handles);

                    // Write the index for the vertex and pixel shaders.
                    var vertexShader = GetShaderIndex(STATE_CLASS.VERTEXSHADER, pass.states);
                    var pixelShader = GetShaderIndex(STATE_CLASS.PIXELSHADER, pass.states);
                    writer.Write((byte)vertexShader);
                    writer.Write((byte)pixelShader);

                    // Write the state objects too!
					if (pass.blendState != null)
					{
						writer.Write(true);
						writer.Write((byte)pass.blendState.AlphaBlendFunction);
						writer.Write((byte)pass.blendState.AlphaDestinationBlend);
						writer.Write((byte)pass.blendState.AlphaSourceBlend);
						writer.Write(pass.blendState.BlendFactor.R);
						writer.Write(pass.blendState.BlendFactor.G);
						writer.Write(pass.blendState.BlendFactor.B);
						writer.Write(pass.blendState.BlendFactor.A);
						writer.Write((byte)pass.blendState.ColorBlendFunction);
						writer.Write((byte)pass.blendState.ColorDestinationBlend);
						writer.Write((byte)pass.blendState.ColorSourceBlend);
						writer.Write((byte)pass.blendState.ColorWriteChannels);
						writer.Write((byte)pass.blendState.ColorWriteChannels1);
						writer.Write((byte)pass.blendState.ColorWriteChannels2);
						writer.Write((byte)pass.blendState.ColorWriteChannels3);
						writer.Write(pass.blendState.MultiSampleMask);
					}
					else
						writer.Write(false);

					if (pass.depthStencilState != null)
					{
						writer.Write(true);
						writer.Write((byte)pass.depthStencilState.CounterClockwiseStencilDepthBufferFail);
						writer.Write((byte)pass.depthStencilState.CounterClockwiseStencilFail);
						writer.Write((byte)pass.depthStencilState.CounterClockwiseStencilFunction);
						writer.Write((byte)pass.depthStencilState.CounterClockwiseStencilPass);
						writer.Write(pass.depthStencilState.DepthBufferEnable);
						writer.Write((byte)pass.depthStencilState.DepthBufferFunction);
						writer.Write(pass.depthStencilState.DepthBufferWriteEnable);
						writer.Write(pass.depthStencilState.ReferenceStencil);
						writer.Write((byte)pass.depthStencilState.StencilDepthBufferFail);
						writer.Write(pass.depthStencilState.StencilEnable);
						writer.Write((byte)pass.depthStencilState.StencilFail);
						writer.Write((byte)pass.depthStencilState.StencilFunction);
						writer.Write(pass.depthStencilState.StencilMask);
						writer.Write((byte)pass.depthStencilState.StencilPass);
						writer.Write(pass.depthStencilState.StencilWriteMask);
						writer.Write(pass.depthStencilState.TwoSidedStencilMode);
					}
					else
						writer.Write(false);

					if (pass.rasterizerState != null)
					{
						writer.Write(true);
						writer.Write((byte)pass.rasterizerState.CullMode);
						writer.Write(pass.rasterizerState.DepthBias);
						writer.Write((byte)pass.rasterizerState.FillMode);
						writer.Write(pass.rasterizerState.MultiSampleAntiAlias);
						writer.Write(pass.rasterizerState.ScissorTestEnable);
						writer.Write(pass.rasterizerState.SlopeScaleDepthBias);
					}
					else
						writer.Write(false);


                }
            }
        }
        /// <summary>
        /// Writes the effect for loading later.
        /// </summary>
        public void Write(BinaryWriter writer, Options options)
        {
            // Write a very simple header for identification and versioning.
            writer.Write(Header.ToCharArray());
            writer.Write((byte)Version);

            // Write an simple identifier for DX11 vs GLSL
            // so we can easily detect the correct shader type.
            var profile = (byte)options.Profile;
            writer.Write(profile);

            // Write the rest to a memory stream.
            using(MemoryStream memStream = new MemoryStream())
            using(BinaryWriter memWriter = new BinaryWriter(memStream))
            {
            // Write all the constant buffers.
                memWriter.Write((byte)ConstantBuffers.Count);
            foreach (var cbuffer in ConstantBuffers)
                    cbuffer.Write(memWriter, options);

            // Write all the shaders.
                memWriter.Write((byte)Shaders.Count);
            foreach (var shader in Shaders)
                    shader.Write(memWriter, options);

            // Write the parameters.
                WriteParameters(memWriter, Parameters, Parameters.Length);

            // Write the techniques.
                memWriter.Write((byte)Techniques.Length);
            foreach (var technique in Techniques)
            {
                    memWriter.Write(technique.name);
                    WriteAnnotations(memWriter, technique.annotation_handles);

                // Write the passes.
                    memWriter.Write((byte)technique.pass_count);
                for (var p = 0; p < technique.pass_count; p++)
                {
                    var pass = technique.pass_handles[p];

                        memWriter.Write(pass.name);
                        WriteAnnotations(memWriter, pass.annotation_handles);

                    // Write the index for the vertex and pixel shaders.
                    var vertexShader = GetShaderIndex(STATE_CLASS.VERTEXSHADER, pass.states);
                    var pixelShader = GetShaderIndex(STATE_CLASS.PIXELSHADER, pass.states);
                        memWriter.Write((byte)vertexShader);
                        memWriter.Write((byte)pixelShader);

                    // Write the state objects too!
					if (pass.blendState != null)
					{
                            memWriter.Write(true);
                            memWriter.Write((byte)pass.blendState.AlphaBlendFunction);
                            memWriter.Write((byte)pass.blendState.AlphaDestinationBlend);
                            memWriter.Write((byte)pass.blendState.AlphaSourceBlend);
                            memWriter.Write(pass.blendState.BlendFactor.R);
                            memWriter.Write(pass.blendState.BlendFactor.G);
                            memWriter.Write(pass.blendState.BlendFactor.B);
                            memWriter.Write(pass.blendState.BlendFactor.A);
                            memWriter.Write((byte)pass.blendState.ColorBlendFunction);
                            memWriter.Write((byte)pass.blendState.ColorDestinationBlend);
                            memWriter.Write((byte)pass.blendState.ColorSourceBlend);
                            memWriter.Write((byte)pass.blendState.ColorWriteChannels);
                            memWriter.Write((byte)pass.blendState.ColorWriteChannels1);
                            memWriter.Write((byte)pass.blendState.ColorWriteChannels2);
                            memWriter.Write((byte)pass.blendState.ColorWriteChannels3);
                            memWriter.Write(pass.blendState.MultiSampleMask);
					}
					else
                            memWriter.Write(false);

					if (pass.depthStencilState != null)
					{
                            memWriter.Write(true);
                            memWriter.Write((byte)pass.depthStencilState.CounterClockwiseStencilDepthBufferFail);
                            memWriter.Write((byte)pass.depthStencilState.CounterClockwiseStencilFail);
                            memWriter.Write((byte)pass.depthStencilState.CounterClockwiseStencilFunction);
                            memWriter.Write((byte)pass.depthStencilState.CounterClockwiseStencilPass);
                            memWriter.Write(pass.depthStencilState.DepthBufferEnable);
                            memWriter.Write((byte)pass.depthStencilState.DepthBufferFunction);
                            memWriter.Write(pass.depthStencilState.DepthBufferWriteEnable);
                            memWriter.Write(pass.depthStencilState.ReferenceStencil);
                            memWriter.Write((byte)pass.depthStencilState.StencilDepthBufferFail);
                            memWriter.Write(pass.depthStencilState.StencilEnable);
                            memWriter.Write((byte)pass.depthStencilState.StencilFail);
                            memWriter.Write((byte)pass.depthStencilState.StencilFunction);
                            memWriter.Write(pass.depthStencilState.StencilMask);
                            memWriter.Write((byte)pass.depthStencilState.StencilPass);
                            memWriter.Write(pass.depthStencilState.StencilWriteMask);
                            memWriter.Write(pass.depthStencilState.TwoSidedStencilMode);
					}
					else
                            memWriter.Write(false);

					if (pass.rasterizerState != null)
					{
                            memWriter.Write(true);
                            memWriter.Write((byte)pass.rasterizerState.CullMode);
                            memWriter.Write(pass.rasterizerState.DepthBias);
                            memWriter.Write((byte)pass.rasterizerState.FillMode);
                            memWriter.Write(pass.rasterizerState.MultiSampleAntiAlias);
                            memWriter.Write(pass.rasterizerState.ScissorTestEnable);
                            memWriter.Write(pass.rasterizerState.SlopeScaleDepthBias);
					}
					else
                            memWriter.Write(false);
                    }
                }

                // Calculate a hash code from memory stream
                // and write it to the header.
                var effectKey = MonoGame.Utilities.Hash.ComputeHash(memStream);
                writer.Write((Int32)effectKey);

                //write content from memory stream to final stream.
                memStream.WriteTo(writer.BaseStream);
            }
        }
Beispiel #8
0
		static public ShaderInfo FromFile(string path, Options options)
		{
			var effectSource = File.ReadAllText(path);
			return FromString(effectSource, path, options);
		}
Beispiel #9
0
		static public ShaderInfo FromString(string effectSource, string filePath, Options options)
		{
			var macros = new List<SharpDX.Direct3D.ShaderMacro>();
			macros.Add(new SharpDX.Direct3D.ShaderMacro("MGFX", 1));

			// Under the DX11 profile we pass a few more macros.
			if (options.DX11Profile)
			{
				macros.Add(new SharpDX.Direct3D.ShaderMacro("HLSL", 1));
				macros.Add(new SharpDX.Direct3D.ShaderMacro("SM4", 1));
			}

			// If we're building shaders for debug set that flag too.
			if (options.Debug)
				macros.Add(new SharpDX.Direct3D.ShaderMacro("DEBUG", 1));

			// Use the D3DCompiler to pre-process the file resolving 
			// all #includes and macros.... this even works for GLSL.
			string newFile;
		    var full = Path.GetFullPath(filePath);
		    var dir = Path.GetDirectoryName(full);
			using (var includer = new CompilerInclude(Path.GetDirectoryName(Path.GetFullPath(filePath))))
                newFile = SharpDX.D3DCompiler.ShaderBytecode.Preprocess(effectSource, macros.ToArray(), includer, Path.GetFullPath(filePath));

			// Parse the resulting file for techniques and passes.
			var tree = new Parser(new Scanner()).Parse(newFile, filePath);
			if (tree.Errors.Count > 0)
			{
                var errors = String.Empty;
                foreach (var error in tree.Errors)
                    errors += string.Format("{0}({1},{2}) : {3}\r\n", error.File, error.Line, error.Column, error.Message);

				throw new Exception(errors);
			}

			// Evaluate the results of the parse tree.
			var result = tree.Eval() as ShaderInfo;
			result.fileName = filePath;
			result.fileContent = newFile;

            // Remove empty techniques.
            for (var i=0; i < result.Techniques.Count; i++)
            {
                var tech = result.Techniques[i];
                if (tech.Passes.Count <= 0)
                {
                    result.Techniques.RemoveAt(i);
                    i--;
                }
            }

            // We must have at least one technique.
            if (result.Techniques.Count <= 0)
                throw new Exception("The effect must contain at least one technique and pass!");

            // Finally remove the techniques from the file.
            //
            // TODO: Do we really need to do this, or will the HLSL 
            // compiler just ignore it as we compile shaders?
            //
			/*
			var extra = 2;
			var offset = 0;
			foreach (var tech in result.Techniques)
			{
				// Remove the technique from the file.
				newFile = newFile.Remove(tech.startPos + offset, tech.length + extra);
				offset -= tech.length + extra;

				techniques.Add(tech);
			}
			*/

			result.DX11Profile = options.DX11Profile;
			result.Debug = options.Debug;

			return result;
		}
Beispiel #10
0
        bool DoBuild(string _effectSource)
        {
            CreateUIParameters(_effectSource);


            OutputClear();

            var options = new Options();
            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                options.Debug = true;
                options.Profile = ShaderProfile.DirectX_11;
                options.SourceFile = string.Empty;
                options.OutputFile = string.Empty;

                var strpathApp = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);

                shaderInfo = ShaderInfo.FromString(_effectSource, strpathApp, options, this);

            }
            catch (Exception ex)
            {
                OutputAppend(ex.Message);
                OutputAppend("Failed to parse !");
                return false;
            }

            // Create the effect object.
            EffectObject effect;
            var shaderErrorsAndWarnings = string.Empty;
            try
            {
                effect = EffectObject.CompileEffect(shaderInfo, out shaderErrorsAndWarnings);

                if (!string.IsNullOrEmpty(shaderErrorsAndWarnings))
                    OutputAppend(shaderErrorsAndWarnings);
            }
            catch (ShaderCompilerException)
            {
                // Write the compiler errors and warnings and let the user know what happened.
                OutputAppend(shaderErrorsAndWarnings);
                OutputAppend("Failed to compile !");
                return false;
            }
            catch (Exception ex)
            {
                // First write all the compiler errors and warnings.
                if (!string.IsNullOrEmpty(shaderErrorsAndWarnings))
                    OutputAppend(shaderErrorsAndWarnings);

                // If we have an exception message then write that.
                if (!string.IsNullOrEmpty(ex.Message))
                    OutputAppend(ex.Message);

                // Let the user know what happened.
                OutputAppend("Unexpected error compiling !");
                return false;
            }

            OutputAppend("Shader successed Compiled !");

            //Create Effect for Game View
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryWriter bw = new BinaryWriter(stream);
                effect.Write(bw, options);

                byte[] bytecode = stream.ToArray();
                m_game.SetEffectBytesCode(bytecode);
            }

            return true;
        }
Beispiel #11
0
        public static int Main(string[] args)
        {
            if (!Environment.Is64BitProcess && Environment.OSVersion.Platform != PlatformID.Unix)
            {
                Console.Error.WriteLine("The MonoGame content tools only work on a 64bit OS.");
                return -1;
            }

            var options = new Options();
            var parser = new Utilities.CommandLineParser(options);
            parser.Title = "2MGFX - Converts Microsoft FX files to a compiled MonoGame Effect.";

            if (!parser.ParseCommandLine(args))
                return 1;

            // Validate the input file exits.
            if (!File.Exists(options.SourceFile))
            {
                Console.Error.WriteLine("The input file '{0}' was not found!", options.SourceFile);
                return 1;
            }
            
            // TODO: This would be where we would decide the user
            // is trying to convert an FX file to a MGFX glsl file.
            //
            // For now we assume we're going right to a compiled MGFXO file.

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options, new ConsoleEffectCompilerOutput());
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine("Failed to parse '{0}'!", options.SourceFile);
                return 1;
            }

            // Create the effect object.
            EffectObject effect;
            var shaderErrorsAndWarnings = string.Empty;
            try
            {
                effect = EffectObject.CompileEffect(shaderInfo, out shaderErrorsAndWarnings);

                if (!string.IsNullOrEmpty(shaderErrorsAndWarnings))
                    Console.Error.WriteLine(shaderErrorsAndWarnings);
            }
            catch (ShaderCompilerException)
            {
                // Write the compiler errors and warnings and let the user know what happened.
                Console.Error.WriteLine(shaderErrorsAndWarnings);
                Console.Error.WriteLine("Failed to compile '{0}'!", options.SourceFile);
                return 1;
            }
            catch (Exception ex)
            {
                // First write all the compiler errors and warnings.
                if (!string.IsNullOrEmpty(shaderErrorsAndWarnings))
                    Console.Error.WriteLine(shaderErrorsAndWarnings);

                // If we have an exception message then write that.
                if (!string.IsNullOrEmpty(ex.Message))
                    Console.Error.WriteLine(ex.Message);

                // Let the user know what happened.
                Console.Error.WriteLine("Unexpected error compiling '{0}'!", options.SourceFile);
                return 1;
            }
            
            // Get the output file path.
            if (options.OutputFile == string.Empty)
                options.OutputFile = Path.GetFileNameWithoutExtension(options.SourceFile) + ".mgfxo";

            // Write out the effect to a runtime format.
            try
            {
                using (var stream = new FileStream(options.OutputFile, FileMode.Create, FileAccess.Write))
                using (var writer = new BinaryWriter(stream))
                    effect.Write(writer, options);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine("Failed to write '{0}'!", options.OutputFile);
                return 1;
            }

            // We finished succesfully.
            Console.WriteLine("Compiled '{0}' to '{1}'.", options.SourceFile, options.OutputFile);
            return 0;
        }
Beispiel #12
0
        public static int Main(string[] args)
        {
            var options = new Options();
            var parser = new Utilities.CommandLineParser(options);
            parser.Title = "2MGFX - Converts Microsoft FX files to a compiled MonoGame Effect.";

            if (!parser.ParseCommandLine(args))
                return 1;

            // Validate the input file exits.
            if (!File.Exists(options.SourceFile))
            {
                Console.Error.WriteLine("The input file '{0}' was not found!", options.SourceFile);
                return 1;
            }
            
            // TODO: This would be where we would decide the user
            // is trying to convert an FX file to a MGFX glsl file.
            //
            // For now we assume we're going right to a compiled MGFXO file.

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine("Failed to parse '{0}'!", options.SourceFile);
                return 1;
            }

            // Create the effect object.
            EffectObject effect;
            try
            {
                effect = EffectObject.FromShaderInfo(shaderInfo);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine("Failed to compile '{0}'!", options.SourceFile);
                return 1;
            }
            
            // Get the output file path.
            if (options.OutputFile == string.Empty)
                options.OutputFile = Path.GetFileNameWithoutExtension(options.SourceFile) + ".mgfxo";

            // Write out the effect to a runtime format.
            try
            {
                using (var stream = new FileStream(options.OutputFile, FileMode.Create, FileAccess.Write))
                using (var writer = new BinaryWriter(stream))
                    effect.Write(writer, options);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine("Failed to write '{0}'!", options.OutputFile);
                return 1;
            }

            // We finished succesfully.
            Console.WriteLine("Compiled '{0}' to '{1}'.", options.SourceFile, options.OutputFile);
            return 0;
        }
Beispiel #13
0
		static public ShaderInfo FromString(string effectSource, string filePath, Options options)
		{
			var macros = new List<SharpDX.Direct3D.ShaderMacro>();
			macros.Add(new SharpDX.Direct3D.ShaderMacro("MGFX", 1));

			// Under the DX11 profile we pass a few more macros.
			if (options.Profile == ShaderProfile.DirectX_11)
			{
				macros.Add(new SharpDX.Direct3D.ShaderMacro("HLSL", 1));
				macros.Add(new SharpDX.Direct3D.ShaderMacro("SM4", 1));
			}
            else if (options.Profile == ShaderProfile.OpenGL)
            {
                macros.Add(new SharpDX.Direct3D.ShaderMacro("GLSL", 1));
                macros.Add(new SharpDX.Direct3D.ShaderMacro("OPENGL", 1));
            }
            else if (options.Profile == ShaderProfile.PlayStation4)
            {
                throw new NotSupportedException("PlayStation 4 support isn't available in this build.");
            }

			// If we're building shaders for debug set that flag too.
			if (options.Debug)
				macros.Add(new SharpDX.Direct3D.ShaderMacro("DEBUG", 1));

		    if (!string.IsNullOrEmpty(options.Defines))
		    {
		        var defines = options.Defines.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		        macros.AddRange(defines.Select(define => new SharpDX.Direct3D.ShaderMacro(define, 1)));
		    }

		    // Use the D3DCompiler to pre-process the file resolving 
			// all #includes and macros.... this even works for GLSL.
			string newFile;
		    var fullPath = Path.GetFullPath(filePath);
		    var dependencies = new List<string>();
            using (var includer = new CompilerInclude(Path.GetDirectoryName(Path.GetFullPath(filePath)), dependencies))
                newFile = SharpDX.D3DCompiler.ShaderBytecode.Preprocess(effectSource, macros.ToArray(), includer, fullPath);

			// Parse the resulting file for techniques and passes.
            var tree = new Parser(new Scanner()).Parse(newFile, fullPath);
			if (tree.Errors.Count > 0)
			{
                var errors = String.Empty;
                foreach (var error in tree.Errors)
                    errors += string.Format("{0}({1},{2}) : {3}\r\n", error.File, error.Line, error.Column, error.Message);

				throw new Exception(errors);
			}

            // Evaluate the results of the parse tree.
            var result = tree.Eval() as ShaderInfo;
            result.Dependencies = dependencies;
            result.FilePath = fullPath;
            result.FileContent = newFile;
            if (!string.IsNullOrEmpty(options.OutputFile))
                result.OutputFilePath = Path.GetFullPath(options.OutputFile);
            result.AdditionalOutputFiles = new List<string>();

            // Remove empty techniques.
            for (var i=0; i < result.Techniques.Count; i++)
            {
                var tech = result.Techniques[i];
                if (tech.Passes.Count <= 0)
                {
                    result.Techniques.RemoveAt(i);
                    i--;
                }
            }

            // We must have at least one technique.
            if (result.Techniques.Count <= 0)
                throw new Exception("The effect must contain at least one technique and pass!");

            // Finally remove the techniques from the file.
            //
            // TODO: Do we really need to do this, or will the HLSL 
            // compiler just ignore it as we compile shaders?
            //
			/*
			var extra = 2;
			var offset = 0;
			foreach (var tech in result.Techniques)
			{
				// Remove the technique from the file.
				newFile = newFile.Remove(tech.startPos + offset, tech.length + extra);
				offset -= tech.length + extra;

				techniques.Add(tech);
			}
			*/

			result.Profile = options.Profile;
			result.Debug = options.Debug;

			return result;
		}
Beispiel #14
0
        static public ShaderInfo FromFile(string path, Options options, IEffectCompilerOutput output)
		{
			var effectSource = File.ReadAllText(path);
			return FromString(effectSource, path, options, output);
		}