コード例 #1
0
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            if (Environment.OSVersion.Platform != PlatformID.Unix)
            {
                return(base.Process(input, context));
            }
            var code     = ResolveCode(input);
            var platform = context.TargetPlatform;
            var version  = typeof(EffectContent).Assembly.GetName().Version;

            string error = String.Empty;

            byte[] buf       = Mgfx.RunMGCB(code, platform.ToString(), WinePath, CompilerPath, out error);
            var    resultSer = JsonConvert.SerializeObject(new Result()
            {
                Compiled = buf, Error = error
            });
            var result = JsonDeSerializer(resultSer);

            if (!string.IsNullOrEmpty(result.Error))
            {
                throw new Exception(result.Error);
            }
            if (result.Compiled == null || result.Compiled.Length == 0)
            {
                throw new Exception("There was an error compiling the effect");
            }

            return(new CompiledEffectContent(result.Compiled));

            return(null);
        }
コード例 #2
0
        /// <summary>
        /// Processes a PaletteInfo object into a PaletteMaterialContent object.
        /// </summary>
        /// <param name="input">The PaletteInfo to process.</param>
        /// <param name="context">The processor context.</param>
        /// <returns>The processed PaletteMaterialContent</returns>
        public override PaletteMaterialContent Process(PaletteInfo input,
                                                       ContentProcessorContext context)
        {
#if XNA4
            throw new NotImplementedException();
#else
            // Set all the variables based on the input.
            EffectProcessor effectProcessor = new EffectProcessor();
            EffectContent   effectContent   = new EffectContent();
            effectContent.EffectCode = input.SourceCode;
            CompiledEffect compiled;
            if (context.TargetPlatform == TargetPlatform.Xbox360)
            {
                compiled = Effect.CompileEffectFromSource(
                    input.SourceCode, null, null, CompilerOptions.None, TargetPlatform.Xbox360);
            }
            else
            {
                compiled = effectProcessor.Process(effectContent, context);
            }
            PaletteMaterialContent content = new PaletteMaterialContent();
            content.PaletteSize = input.PaletteSize;
            content.ByteCode    = compiled.GetEffectCode();
            BasicMaterialContent basic = input.BasicContent;
            content.Alpha              = basic.Alpha;
            content.DiffuseColor       = basic.DiffuseColor;
            content.EmissiveColor      = basic.EmissiveColor;
            content.Name               = basic.Name;
            content.SpecularColor      = basic.SpecularColor;
            content.SpecularPower      = basic.SpecularPower;
            content.Texture            = basic.Texture;
            content.VertexColorEnabled = basic.VertexColorEnabled;
            return(content);
#endif
        }
コード例 #3
0
        static byte[] GetEffectCode(string filename)
        {
            var basePath       = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Content");
            var effectFileName = System.IO.Path.Combine(basePath, filename + ".fx");

            EffectContent effectSource = new EffectContent
            {
                Identity   = new ContentIdentity(effectFileName),
                EffectCode = File.ReadAllText(effectFileName),
            };
            EffectProcessor       processor      = new EffectProcessor();
            CompiledEffectContent compiledEffect = processor.Process(effectSource, new ProcessorContext());

            return(compiledEffect.GetEffectCode());

#if DEBUG_SHADER_CODE
            // NOTE: We may need to implement a CompilerIncludeHandler here if we ever use #include in our shaders.
            var compiledEffect = Effect.CompileEffectFromFile(effectFileName, null, null, CompilerOptions.Debug, TargetPlatform.Windows);
            if (!compiledEffect.Success)
            {
                throw new InvalidOperationException(compiledEffect.ErrorsAndWarnings);
            }
            return(compiledEffect.GetEffectCode());
#else
            // We have to use a file stream instead of passing the file name directly because the latter method just botches up non-ASCII paths. :(
            //using (var effectFileStream = File.OpenRead(effectFileName))
            //{
            //    // NOTE: We may need to implement a CompilerIncludeHandler here if we ever use #include in our shaders.
            //    var compiledEffect = Effect.CompileEffectFromFile(effectFileStream, null, null, CompilerOptions.None, TargetPlatform.Windows);
            //    if (!compiledEffect.Success)
            //        throw new InvalidOperationException(compiledEffect.ErrorsAndWarnings);
            //    return compiledEffect.GetEffectCode();
            //}
#endif
        }
コード例 #4
0
        /// <summary>
        /// Processes a PaletteInfo object into a PaletteMaterialContent object.
        /// </summary>
        /// <param name="input">The PaletteInfo to process.</param>
        /// <param name="context">The processor context.</param>
        /// <returns>The processed PaletteMaterialContent</returns>
        public override PaletteMaterialContent Process(PaletteInfo input,
                                                       ContentProcessorContext context)
        {
            // Set all the variables based on the input.
            EffectProcessor effectProcessor = new EffectProcessor();
            EffectContent   effectContent   = new EffectContent();

            effectContent.EffectCode = input.SourceCode;
            CompiledEffect         compiled = effectProcessor.Process(effectContent, context);
            PaletteMaterialContent content  = new PaletteMaterialContent();

            content.PaletteSize = input.PaletteSize;
            content.ByteCode    = compiled.GetEffectCode();
            BasicMaterialContent basic = input.BasicContent;

            content.Alpha              = basic.Alpha;
            content.DiffuseColor       = basic.DiffuseColor;
            content.EmissiveColor      = basic.EmissiveColor;
            content.Name               = basic.Name;
            content.SpecularColor      = basic.SpecularColor;
            content.SpecularPower      = basic.SpecularPower;
            content.Texture            = basic.Texture;
            content.VertexColorEnabled = basic.VertexColorEnabled;
            return(content);
        }
コード例 #5
0
        private static string ResolveCode(EffectContent input)
        {
            var sb = new StringBuilder();

            foreach (var line in input.EffectCode.Split('\n'))
            {
                if (line.StartsWith("//", StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                if (line.StartsWith("#include", StringComparison.InvariantCultureIgnoreCase))
                {
                    var startIndex = line.IndexOf("\"", StringComparison.InvariantCultureIgnoreCase) + 1;
                    var file       = line.Substring(startIndex,
                                                    line.IndexOf("\"", startIndex, StringComparison.InvariantCultureIgnoreCase) - startIndex);
                    var root = Path.GetDirectoryName(input.Identity.SourceFilename);
                    ReadInclude(sb, Path.Combine(root ?? throw new NullReferenceException("Malformed .fx file"), file));
                }
                else
                {
                    sb.AppendLine(line.Trim());
                }
            }

            return(sb.ToString());
        }
コード例 #6
0
        public static byte[] GetEffectCodeBytes(string filename)
        {
            EffectContent         content  = importer.Import("./" + filename, new CustomImporterContext( ));
            CompiledEffectContent compiled = processor.Process(content, new CustomProcessorContext( ));

            return(compiled.GetEffectCode( ));
        }
コード例 #7
0
        string ResolveCode(EffectContent input)
        {
            StringBuilder sb = new StringBuilder();

            foreach (var line in input.EffectCode.Split(new char [] { '\n' }))
            {
                if (line.StartsWith("//", StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                if (line.StartsWith("#include", StringComparison.InvariantCultureIgnoreCase))
                {
                    // read the file
                    var startIndex = line.IndexOf("\"", StringComparison.InvariantCultureIgnoreCase) + 1;
                    var file       = line.Substring(startIndex, line.IndexOf("\"", startIndex, StringComparison.InvariantCultureIgnoreCase) - startIndex);
                    var root       = Path.GetDirectoryName(input.Identity.SourceFilename);
                    ReadInclude(sb, Path.Combine(root, file));
                }
                else
                {
                    sb.AppendLine(line.Trim());
                }
            }
            return(sb.ToString());
        }
コード例 #8
0
        string ExpandIncludes(EffectContent input)
        {
            var sb   = new StringBuilder();
            var root = Path.GetDirectoryName(input.Identity.SourceFilename);

            Include(sb, input.EffectCode.Split('\n'), root);

            return(sb.ToString());
        }
コード例 #9
0
        public static Effect Compile(GraphicsDevice g, string file)
        {
            EffectImporter  ei  = new EffectImporter();
            EffectContent   ec  = ei.Import(file, new XNADynImporterContext());
            EffectProcessor ep  = new EffectProcessor();
            var             cec = ep.Process(ec, new XNADynProcessorContext());

            return(new Effect(g, cec.GetEffectCode()));
        }
コード例 #10
0
ファイル: Program.cs プロジェクト: nusisschad/XNAGameStudio
        static int Main(string[] args)
        {
            // Make sure we have the right number of commandline arguments.
            if (args.Length != 4)
            {
                Console.Error.WriteLine("Usage: CompileEffect <targetPlatform> <targetProfile> <input.fx> <output.bin>");
                return(1);
            }

            // Parse the commandline arguments.
            TargetPlatform targetPlatform;

            if (!Enum.TryParse(args[0], true, out targetPlatform))
            {
                Console.Error.WriteLine("Invalid target platform {0}. Valid options are {1}.", args[0], GetEnumValues <TargetPlatform>());
                return(1);
            }

            GraphicsProfile targetProfile;

            if (!Enum.TryParse(args[1], true, out targetProfile))
            {
                Console.Error.WriteLine("Invalid target profile {0}. Valid options are {1}.", args[1], GetEnumValues <GraphicsProfile>());
                return(1);
            }

            string inputFilename  = args[2];
            string outputFilename = args[3];

            try
            {
                Console.WriteLine("Compiling {0} -> {1} for {2}, {3}", Path.GetFileName(inputFilename), outputFilename, targetPlatform, targetProfile);

                ContentBuildLogger logger = new CustomLogger();

                // Import the effect source code.
                EffectImporter         importer        = new EffectImporter();
                ContentImporterContext importerContext = new CustomImporterContext(logger);
                EffectContent          sourceEffect    = importer.Import(inputFilename, importerContext);

                // Compile the effect.
                EffectProcessor         processor        = new EffectProcessor();
                ContentProcessorContext processorContext = new CustomProcessorContext(targetPlatform, targetProfile, logger);
                CompiledEffectContent   compiledEffect   = processor.Process(sourceEffect, processorContext);

                // Write out the compiled effect code.
                File.WriteAllBytes(outputFilename, compiledEffect.GetEffectCode());
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("Error: {0}", e.Message);
                return(1);
            }

            return(0);
        }
コード例 #11
0
        public static byte[] ReadBytesFromSourceFile(string fileName)
        {
            EffectImporter  importer  = new EffectImporter( );
            EffectProcessor processor = new EffectProcessor( );

            EffectContent         content  = importer.Import(fileName, new ShaderImporterContext( ));
            CompiledEffectContent compiled = processor.Process(content, new ShaderProcessorContext( ));

            return(compiled.GetEffectCode( ));
        }
コード例 #12
0
        private static bool AttemptEffectCompilation(
            ContentProcessorContext context, StitchedEffectContent input,
            StitchedEffectSymbol stitchedEffect, ShaderProfile shaderProfile,
            out CompiledEffectContent compiledEffect)
        {
            // Generate effect code.
            StringWriter        writer        = new StringWriter();
            EffectCodeGenerator codeGenerator = new EffectCodeGenerator(stitchedEffect, shaderProfile, writer);

            codeGenerator.GenerateCode();
            string effectCode = writer.ToString();

            // Save effect code so that if there are errors, we'll be able to view the generated .fx file.
            string tempEffectFile = GetTempEffectFileName(input);

            File.WriteAllText(tempEffectFile, effectCode, Encoding.GetEncoding(1252));

            // Process effect code.
            EffectProcessor effectProcessor = new EffectProcessor
            {
                DebugMode = EffectProcessorDebugMode.Auto,
                Defines   = null
            };

            EffectContent effectContent = new EffectContent
            {
                EffectCode = effectCode,
                Identity   = new ContentIdentity(tempEffectFile),
                Name       = input.Name
            };

            try
            {
                compiledEffect = effectProcessor.Process(effectContent, context);

                // This is only needed if the compilation was successful - if it failed,
                // a more specific error message (with link to the generated file)
                // will be shown to the user.
                context.Logger.LogImportantMessage(string.Format("{0} : Stitched effect generated (double-click this message to view).", tempEffectFile));

                return(true);
            }
            catch (InvalidContentException ex)
            {
                if (ErrorIndicatesNeedForShaderModel3(ex.Message))
                {
                    compiledEffect = null;
                    return(false);
                }
                throw;
            }
        }
コード例 #13
0
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            if (Environment.OSVersion.Platform != PlatformID.Unix)
            {
                return(base.Process(input, context));
            }

            string hlslCode = ExpandIncludes(input.EffectCode);

            byte[] compiled = Compile(context.TargetPlatform, input.Identity, hlslCode);

            return(new CompiledEffectContent(compiled));
        }
コード例 #14
0
        public static CompiledEffectContent Compile(EffectContent output, string tempOutputPath, TargetPlatform platform, bool isDebug, string defines)
        {
            var processor = new EffectProcessor();
            var context   = new DummyContentProcessorContext(TargetPlatformCast.ToMonoGamePlatform(platform));

            context.ActualOutputFilename = tempOutputPath;
            processor.DebugMode          = isDebug
                ? EffectProcessorDebugMode.Debug
                : EffectProcessorDebugMode.Optimize;
            processor.Defines = defines + ";" + GetPlatformDefineForEffect(platform) + ";" +
                                (isDebug ? "CONFIGURATION_DEBUG" : "CONFIGURATION_RELEASE");
            return(processor.Process(output, context));
        }
コード例 #15
0
ファイル: Shaders.cs プロジェクト: dadulo3/openrails
        static byte[] GetEffectCode(string filename)
        {
            var basePath       = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Content");
            var effectFileName = System.IO.Path.Combine(basePath, filename + ".fx");

            var input = new EffectContent()
            {
                // Bizarrely, MonoGame loads the content from the identity's filename and ignores the EffectCode property, so we don't need to bother loading the file ourselves
                Identity = new ContentIdentity(effectFileName),
            };
            var context   = new ProcessorContext();
            var processor = new EffectProcessor();
            var effect    = processor.Process(input, context);

            return(effect.GetEffectCode());
        }
コード例 #16
0
        /// <summary>
        /// The compile.
        /// </summary>
        /// <param name="asset">
        /// The asset.
        /// </param>
        /// <param name="platform">
        /// The platform.
        /// </param>
        public void Compile(EffectAsset asset, TargetPlatform platform)
        {
            if (string.IsNullOrEmpty(asset.Code))
            {
                return;
            }

            var output = new EffectContent();

            output.EffectCode = this.GetEffectPrefixCode() + asset.Code;

            var tempPath = Path.GetTempFileName();

            using (var writer = new StreamWriter(tempPath))
            {
                writer.Write(output.EffectCode);
            }

            output.Identity = new ContentIdentity(tempPath);

            var tempOutputPath = Path.GetTempFileName();

            var processor = new EffectProcessor();
            var context   = new DummyContentProcessorContext(TargetPlatformCast.ToMonoGamePlatform(platform));

            context.ActualOutputFilename = tempOutputPath;
            var content = processor.Process(output, context);

            asset.PlatformData = new PlatformData {
                Platform = platform, Data = content.GetEffectCode()
            };

            File.Delete(tempPath);
            File.Delete(tempOutputPath);

            try
            {
                asset.ReloadEffect();
            }
            catch (NoAssetContentManagerException)
            {
            }
        }
コード例 #17
0
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                return(base.Process(input, context));
            }

            var code     = ResolveCode(input);
            var platform = context.TargetPlatform;
            var version  = typeof(EffectContent).Assembly.GetName().Version;
            var client   = new HttpClient
            {
                Timeout     = TimeSpan.FromMinutes(5),
                BaseAddress = new Uri("http://127.0.0.1:60321/")
            };
            var response = client.PostAsync("api/Effect", new StringContent(JsonSerializer(new Data
            {
                Platform = platform.ToString(),
                Code     = code,
                Version  = $"{version}",
            }), Encoding.UTF8, "application/json")).Result;

            if (!response.IsSuccessStatusCode)
            {
                throw new Exception(response.StatusCode.ToString());
            }

            var data   = response.Content.ReadAsStringAsync().Result;
            var result = JsonDeSerializer(data);

            if (!string.IsNullOrEmpty(result.Error))
            {
                throw new Exception(result.Error);
            }

            if (result.Compiled == null || result.Compiled.Length == 0)
            {
                throw new Exception("There was an error compiling the effect");
            }

            return(new CompiledEffectContent(result.Compiled));
        }
コード例 #18
0
ファイル: XnaEffectLoader.cs プロジェクト: chuz/tesla-engine
        public override Effect Load(IResource resource, LoaderParameters parameters)
        {
            FileInfo info = new FileInfo(resource.FullName);

            if (!info.Exists)
            {
                throw new FileNotFoundException("Effect file does not exist in directory");
            }
            EffectContent content = new EffectContent();

            content.Identity   = new ContentIdentity(resource.FullName);
            content.EffectCode = File.ReadAllText(resource.FullName);

            CompiledEffectContent compiled = _processor.Process(content, _xnaContext);

            Effect effect = new Effect(compiled.GetEffectCode());

            effect.Name = resource.Name;
            return(effect);
        }
コード例 #19
0
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            if (Environment.OSVersion.Platform != PlatformID.Unix)
            {
                return(base.Process(input, context));
            }

            var code     = ExpandIncludes(input);
            var platform = context.TargetPlatform;
            var buf      = RunMGCB(code, DockerImage, platform.ToString(), out var error);

            if (!string.IsNullOrEmpty(error))
            {
                throw new Exception(error);
            }
            if (buf == null || buf.Length == 0)
            {
                throw new Exception("There was an error compiling the effect");
            }

            return(new CompiledEffectContent(buf));
        }
コード例 #20
0
        public IProgram Link(Shader shader, IEnumerable <object> units)
        {
            var sources = units.Cast <Tuple <ShaderType, SourceDescription> >();
            //var frag = sources.Where(t => t.Item1 == ShaderType.FragmentShader).Select(t => t.Item2);
            //var vert = sources.Where(t => t.Item1 == ShaderType.VertexShader).Select(t => t.Item2);
            var all = sources.Select(t => t.Item2);

            var merged = all.Skip(1).Aggregate(all.First(), (current, d) => current.Merge(d));


            // XNA doesnt support shader compilation so we have to generate a .fx file
            // with everything merged

            var cp = new SLContentProcessorContext();
            var ep = new EffectProcessor();
            var ec = new EffectContent {
                EffectCode = merged.ToHlslFx()
            };

            var compiledEffect = ep.Process(ec, cp);

            return(new Program(compiledEffect));
        }
コード例 #21
0
        public Effect?Build(GraphicsDevice device, string path)
        {
            var content = new EffectContent
            {
                Identity   = new ContentIdentity(path),
                EffectCode = File.ReadAllText(path)
            };

            var processor = new EffectProcessor();

            try
            {
                var compiled = processor.Process(content, new ProcessorContext(this.Logger, path));
                return(new Effect(device, compiled.GetEffectCode()));
            }
            catch (InvalidContentException cex)
            {
                var match = this.EffectCompilerPattern.Match(cex.Message);
                if (match.Success)
                {
                    var line    = match.Captures[0].Value;
                    var message = $"At {line}";
                    this.Logger.Error($"Failed to reload {path}\n\n{message}");
                }
                else
                {
                    this.Logger.Error(cex, "Failed to reload {@file}", path);
                }
            }
            catch (Exception ex)
            {
                this.Logger.Error(ex, "Failed to reload {@file}", path);
            }

            return(null);
        }
コード例 #22
0
        private Exception ProcessErrorsAndWarnings(string errorsAndWarnings, EffectContent input, ContentProcessorContext context)
        {
            // Split the errors by lines.
            var errors = errorsAndWarnings.Split('\n');

            // Process each error line extracting the location and message information.
            for (var i = 0; i < errors.Length; i++)
            {
                // Skip blank lines.
                if (errors[i].StartsWith(Environment.NewLine))
                {
                    break;
                }

                // find some unique characters in the error string
                var openIndex  = errors[i].IndexOf('(');
                var closeIndex = errors[i].IndexOf(')');

                // can't process the message if it has no line counter
                if (openIndex == -1 || closeIndex == -1)
                {
                    continue;
                }

                // find the error number, then move forward into the message
                var errorIndex = errors[i].IndexOf('X', closeIndex);
                if (errorIndex < 0)
                {
                    return(new InvalidContentException(errors[i], input.Identity));
                }

                // trim out the data we need to feed the logger
                var fileName      = errors[i].Remove(openIndex);
                var lineAndColumn = errors[i].Substring(openIndex + 1, closeIndex - openIndex - 1);
                var description   = errors[i].Substring(errorIndex);

                // when the file name is not present, the error can be found in the root file
                if (string.IsNullOrEmpty(fileName))
                {
                    fileName = input.Identity.SourceFilename;
                }

                // ensure that the file data points toward the correct file
                var fileInfo = new FileInfo(fileName);
                if (!fileInfo.Exists)
                {
                    var parentFile = new FileInfo(input.Identity.SourceFilename);
                    fileInfo = new FileInfo(Path.Combine(parentFile.Directory.FullName, fileName));
                }
                fileName = fileInfo.FullName;

                // construct the temporary content identity and file the error or warning
                var identity = new ContentIdentity(fileName, input.Identity.SourceTool, lineAndColumn);
                if (errors[i].Contains("warning"))
                {
                    description = "A warning was generated when compiling the effect.\n" + description;
                    context.Logger.LogWarning(string.Empty, identity, description, string.Empty);
                }
                else if (errors[i].Contains("error"))
                {
                    description = "Unable to compile the effect.\n" + description;
                    return(new InvalidContentException(description, identity));
                }
            }

            // if no exceptions were created in the above loop, generate a generic one here
            return(new InvalidContentException(errorsAndWarnings, input.Identity));
        }
コード例 #23
0
        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.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);
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            DXEffectObject effect = null;

            try
            {
                effect = DXEffectObject.FromShaderInfo(shaderInfo);
            }
            catch (Exception ex)
            {
                throw ProcessErrorsAndWarnings(ex.Message, 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);
        }
コード例 #24
0
        public override TOutput Process(TInput input, ContentProcessorContext context)
        {
            Dictionary <string, Q3BSPMaterialContent> processedDictionary = new Dictionary <string, Q3BSPMaterialContent>();

            #region Initialize StreamWriter, if necessary
#if DEBUG
            StreamWriter sw = new StreamWriter(context.OutputFilename.Substring(0, context.OutputFilename.LastIndexOf('.')) + ".compiled.txt");
#else
            StreamWriter sw = null;
#endif
            #endregion

            for (int i = 0; i < input.Count; i++)
            {
                Q3BSPMaterialContent shader = input[i];

                #region Throw any errors in the parsed shader
                if (shader.stages.Count > 8)
                {
                    throw new InvalidContentException(shader.shaderName + " has " + shader.stages.Count + " stages, but the maximum supported is 8.");
                }
                if (processedDictionary.ContainsKey(shader.shaderName))
                {
                    context.Logger.LogWarning("", new ContentIdentity(), "Material " + shader.shaderName + " is defined more than once.");
                    continue;
                    //throw new InvalidContentException("Material " + shader.shaderName + " is defined more than once.");
                }
                #endregion

                #region Log any needed warnings
                if (shader.stages.Count > 4 && shaderModel == ShaderModel.ShaderModel1)
                {
                    context.Logger.LogWarning("", new ContentIdentity(), shader.shaderName + " has more than 4 stages, Shader Model 2.0 is required.");
                }
                #endregion
                EffectProcessor processor = new EffectProcessor();
                processor.DebugMode = EffectProcessorDebugMode.Debug;
                EffectContent effectContent = new EffectContent();
                effectContent.EffectCode = GenerateEffectFromShader(shader, sw);
                #region Compile the Effect
#if DEBUG
                CompiledEffectContent compiledEffect = processor.Process(effectContent, context);
                //CompiledEffect compiledEffect = Effect.CompileEffectFromSource(GenerateEffectFromShader(shader, sw), null, null, CompilerOptions.Debug, TargetPlatform.Windows);
#else
                processor.DebugMode = EffectProcessorDebugMode.Auto;
                CompiledEffectContent compiledEffect = processor.Process(effectContent, context);
                //CompiledEffect compiledEffect = Effect.CompileEffectFromSource(GenerateEffectFromShader(shader, sw), null, null, CompilerOptions.None, TargetPlatform.Windows);
#endif
                #endregion

                /*
                 * if (compiledEffect.ErrorsAndWarnings.Contains("error"))
                 * {
                 *  throw new InvalidContentException(shader.shaderName + ": " + compiledEffect.ErrorsAndWarnings);
                 * }
                 */
                shader.compiledEffect = compiledEffect;
                shader.ShaderCode     = compiledEffect.GetEffectCode();
                processedDictionary.Add(shader.shaderName, shader);
            }
#if DEBUG
            sw.Flush();
            sw.Dispose();
#endif

            return(processedDictionary);
        }
コード例 #25
0
        public void Compile(UberEffectAsset asset, TargetPlatform platform)
        {
            if (string.IsNullOrEmpty(asset.Code))
            {
                return;
            }

            var allPassed   = true;
            var effectCodes = new Dictionary <string, Tuple <string, byte[], byte[]> >();

            foreach (var rawLine in asset.Code.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var line = rawLine.Trim();
                if (line.StartsWith("#line"))
                {
                    continue;
                }
                if (!line.StartsWith("// uber "))
                {
                    break;
                }

                var components = line.Substring("// uber ".Length).Split(':');
                var name       = components[0].Trim();
                var defines    = components[1].Trim();

                Console.WriteLine();
                Console.Write("Compiling uber shader variant " + name + "... ");

                var output = new EffectContent();
                output.EffectCode = this.GetEffectPrefixCode() + asset.Code;

                string tempPath = null, tempOutputPath = null;
                try
                {
                    tempPath       = Path.GetTempFileName();
                    tempOutputPath = Path.GetTempFileName();

                    using (var writer = new StreamWriter(tempPath))
                    {
                        writer.Write(output.EffectCode);
                    }

                    output.Identity = new ContentIdentity(tempPath);

                    var debugContent = EffectCompilerHelper.Compile(
                        output,
                        tempOutputPath,
                        platform,
                        true,
                        defines);
                    var releaseContent = EffectCompilerHelper.Compile(
                        output,
                        tempOutputPath,
                        platform,
                        false,
                        defines);

                    effectCodes[name] = new Tuple <string, byte[], byte[]>(defines, debugContent.GetEffectCode(), releaseContent.GetEffectCode());
                    Console.Write("done.");
                }
                catch (InvalidContentException ex)
                {
                    Console.WriteLine("failed.");
                    Console.Write(ex.Message.Trim());
                    allPassed = false;
                }
                finally
                {
                    if (tempOutputPath != null)
                    {
                        File.Delete(tempOutputPath);
                    }

                    if (tempOutputPath != null)
                    {
                        File.Delete(tempPath);
                    }
                }
            }

            Console.WriteLine();
            Console.Write("Finalizing uber shader compilation... ");

            if (!allPassed)
            {
                throw new Exception("One or more uber shader variants failed to compile (see above!)");
            }

            using (var memory = new MemoryStream())
            {
                using (var writer = new BinaryWriter(memory))
                {
                    writer.Write((uint)2);
                    writer.Write((uint)effectCodes.Count);
                    foreach (var kv in effectCodes)
                    {
                        writer.Write(kv.Key);
                        writer.Write(kv.Value.Item1);
                        writer.Write(kv.Value.Item2.Length);
                        writer.Write(kv.Value.Item2);
                        writer.Write(kv.Value.Item3.Length);
                        writer.Write(kv.Value.Item3);
                    }

                    var len  = memory.Position;
                    var data = new byte[len];
                    memory.Seek(0, SeekOrigin.Begin);
                    memory.Read(data, 0, data.Length);
                    asset.PlatformData = new PlatformData {
                        Platform = platform, Data = data
                    };
                }
            }

            try
            {
                asset.ReadyOnGameThread();
            }
            catch (NoAssetContentManagerException)
            {
            }
        }
コード例 #26
0
        public async Task CompileAsync(IAssetFsFile assetFile, IAssetDependencies assetDependencies, TargetPlatform platform, IWritableSerializedAsset output)
        {
            var code = string.Empty;

            using (var reader = new StreamReader(await assetFile.GetContentStream().ConfigureAwait(false)))
            {
                code = await reader.ReadToEndAsync().ConfigureAwait(false);
            }

            if (code.Contains("// uber"))
            {
                // Do nothing with this file.
                return;
            }

            var dirName = Path.GetDirectoryName(assetFile.Name.Replace(".", "/"));

            code = await ResolveIncludes(assetDependencies, dirName.Replace(Path.DirectorySeparatorChar, '.'), code).ConfigureAwait(false);

            var effectContent = new EffectContent();

            effectContent.EffectCode = this.GetEffectPrefixCode() + code;

            var tempPath = Path.GetTempFileName();

            using (var writer = new StreamWriter(tempPath))
            {
                writer.Write(effectContent.EffectCode);
            }

            effectContent.Identity = new ContentIdentity(tempPath);

            var tempOutputPath = Path.GetTempFileName();

            var debugContent = EffectCompilerHelper.Compile(
                effectContent,
                tempOutputPath,
                platform,
                true,
                string.Empty);
            var releaseContent = EffectCompilerHelper.Compile(
                effectContent,
                tempOutputPath,
                platform,
                false,
                string.Empty);

            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    // Magic flag that indicates new compiled effect format.
                    writer.Write((uint)0x12345678);

                    // Version 1 of new effect format.
                    writer.Write((uint)1);

                    var debugCode   = debugContent.GetEffectCode();
                    var releaseCode = releaseContent.GetEffectCode();

                    writer.Write(debugCode.Length);
                    writer.Write(debugCode);
                    writer.Write(releaseCode.Length);
                    writer.Write(releaseCode);

                    var p = stream.Position;
                    var b = new byte[p];
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(b, 0, b.Length);

                    output.SetLoader <IAssetLoader <EffectAsset> >();
                    output.SetPlatform(platform);
                    output.SetByteArray("Data", b);
                }
            }

            File.Delete(tempPath);
            File.Delete(tempOutputPath);
        }
コード例 #27
0
        public async Task CompileAsync(IAssetFsFile assetFile, IAssetDependencies assetDependencies, TargetPlatform platform, IWritableSerializedAsset output)
        {
            var code = string.Empty;

            using (var reader = new StreamReader(await assetFile.GetContentStream().ConfigureAwait(false)))
            {
                code = await reader.ReadToEndAsync().ConfigureAwait(false);
            }

            if (!code.Contains("// uber"))
            {
                // Do nothing with this file.
                return;
            }

            var dirName = Path.GetDirectoryName(assetFile.Name.Replace(".", "/"));

            code = await ResolveIncludes(assetDependencies, dirName.Replace(Path.DirectorySeparatorChar, '.'), code).ConfigureAwait(false);

            var allPassed   = true;
            var effectCodes = new Dictionary <string, Tuple <string, byte[], byte[]> >();

            foreach (var rawLine in code.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var line = rawLine.Trim();
                if (line.StartsWith("#line"))
                {
                    continue;
                }
                if (!line.StartsWith("// uber "))
                {
                    break;
                }

                var components = line.Substring("// uber ".Length).Split(':');
                var name       = components[0].Trim();
                var defines    = components[1].Trim();

                Console.WriteLine();
                Console.Write("Compiling uber shader variant " + name + "... ");

                var effectOutput = new EffectContent();
                effectOutput.EffectCode = this.GetEffectPrefixCode() + code;

                string tempPath = null, tempOutputPath = null;
                try
                {
                    tempPath       = Path.GetTempFileName();
                    tempOutputPath = Path.GetTempFileName();

                    using (var writer = new StreamWriter(tempPath))
                    {
                        writer.Write(effectOutput.EffectCode);
                    }

                    effectOutput.Identity = new ContentIdentity(tempPath);

                    var debugContent = EffectCompilerHelper.Compile(
                        effectOutput,
                        tempOutputPath,
                        platform,
                        true,
                        defines);
                    var releaseContent = EffectCompilerHelper.Compile(
                        effectOutput,
                        tempOutputPath,
                        platform,
                        false,
                        defines);

                    effectCodes[name] = new Tuple <string, byte[], byte[]>(defines, debugContent.GetEffectCode(), releaseContent.GetEffectCode());
                    Console.Write("done.");
                }
                catch (InvalidContentException ex)
                {
                    Console.WriteLine("failed.");
                    Console.Write(ex.Message.Trim());
                    allPassed = false;
                }
                finally
                {
                    if (tempOutputPath != null)
                    {
                        File.Delete(tempOutputPath);
                    }

                    if (tempOutputPath != null)
                    {
                        File.Delete(tempPath);
                    }
                }
            }

            Console.WriteLine();
            Console.Write("Finalizing uber shader compilation... ");

            if (!allPassed)
            {
                throw new Exception("One or more uber shader variants failed to compile (see above!)");
            }

            using (var memory = new MemoryStream())
            {
                using (var writer = new BinaryWriter(memory))
                {
                    writer.Write((uint)2);
                    writer.Write((uint)effectCodes.Count);
                    foreach (var kv in effectCodes)
                    {
                        writer.Write(kv.Key);
                        writer.Write(kv.Value.Item1);
                        writer.Write(kv.Value.Item2.Length);
                        writer.Write(kv.Value.Item2);
                        writer.Write(kv.Value.Item3.Length);
                        writer.Write(kv.Value.Item3);
                    }

                    var len  = memory.Position;
                    var data = new byte[len];
                    memory.Seek(0, SeekOrigin.Begin);
                    memory.Read(data, 0, data.Length);

                    output.SetLoader <IAssetLoader <UberEffectAsset> >();
                    output.SetPlatform(platform);
                    output.SetByteArray("Data", data);
                }
            }
        }
コード例 #28
0
        public void Compile(EffectAsset asset, TargetPlatform platform)
        {
            if (string.IsNullOrEmpty(asset.Code))
            {
                return;
            }

            var output = new EffectContent();

            output.EffectCode = this.GetEffectPrefixCode() + asset.Code;

            var tempPath = Path.GetTempFileName();

            using (var writer = new StreamWriter(tempPath))
            {
                writer.Write(output.EffectCode);
            }

            output.Identity = new ContentIdentity(tempPath);

            var tempOutputPath = Path.GetTempFileName();

            var debugContent = EffectCompilerHelper.Compile(
                output,
                tempOutputPath,
                platform,
                true,
                string.Empty);
            var releaseContent = EffectCompilerHelper.Compile(
                output,
                tempOutputPath,
                platform,
                false,
                string.Empty);

            using (var stream = new MemoryStream())
            {
                using (var writer = new BinaryWriter(stream))
                {
                    // Magic flag that indicates new compiled effect format.
                    writer.Write((uint)0x12345678);

                    // Version 1 of new effect format.
                    writer.Write((uint)1);

                    var debugCode   = debugContent.GetEffectCode();
                    var releaseCode = releaseContent.GetEffectCode();

                    writer.Write(debugCode.Length);
                    writer.Write(debugCode);
                    writer.Write(releaseCode.Length);
                    writer.Write(releaseCode);

                    var p = stream.Position;
                    var b = new byte[p];
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(b, 0, b.Length);

                    asset.PlatformData = new PlatformData {
                        Platform = platform, Data = b
                    };
                }
            }

            File.Delete(tempPath);
            File.Delete(tempOutputPath);

            try
            {
                asset.ReloadEffect();
            }
            catch (NoAssetContentManagerException)
            {
            }
        }
コード例 #29
0
        public override T Load <T>(string assetName)
        {
            var g = (IGraphicsDeviceService)ServiceProvider.GetService(typeof(IGraphicsDeviceService));

            if (typeof(T) == typeof(Texture2D))
            {
                if (_textures.ContainsKey(assetName))
                {
                    return((T)(object)_textures[assetName]);
                }

                using (var img = Image.FromFile(ContentProjectManager.GetTexturePath(assetName)))
                {
                    var bmp  = new Bitmap(img);
                    var data = new uint[bmp.Width * bmp.Height];
                    for (var y = 0; y < bmp.Height; ++y)
                    {
                        for (var x = 0; x < bmp.Width; ++x)
                        {
                            var pixel = bmp.GetPixel(x, y);
                            data[x + y * bmp.Width] =
                                Microsoft.Xna.Framework.Color.FromNonPremultiplied(pixel.R, pixel.G, pixel.B, pixel.A).
                                PackedValue;
                        }
                    }
                    if (g != null)
                    {
                        var t = new Texture2D(g.GraphicsDevice, img.Width, img.Height);
                        t.SetData(data);
                        _textures.Add(assetName, t);
                        return((T)(object)t);
                    }
                    else
                    {
                        throw new InvalidOperationException("Must wait with loading until graphics device is initialized.");
                    }
                }
            }
            else if (typeof(T) == typeof(Effect))
            {
                if (_shaders.ContainsKey(assetName))
                {
                    return((T)(object)_shaders[assetName]);
                }

                var shaderPath = ContentProjectManager.GetShaderPath(assetName);
                if (shaderPath != null)
                {
                    using (var file = File.OpenText(shaderPath))
                    {
                        var sourceCode = file.ReadToEnd();

                        var effectSource = new EffectContent
                        {
                            EffectCode = sourceCode,
                            Identity   = new ContentIdentity {
                                SourceFilename = assetName
                            }
                        };
                        var processor      = new EffectProcessor();
                        var compiledEffect = processor.Process(effectSource, new DummyProcessorContext());
                        var effect         = new Effect(g.GraphicsDevice, compiledEffect.GetEffectCode());
                        _shaders.Add(assetName, effect);
                        return((T)(object)effect);
                    }
                }
            }
            else if (typeof(T) == typeof(ParticleEffect))
            {
                using (var xmlReader = XmlReader.Create(ContentProjectManager.GetEffectPath(assetName)))
                {
                    var effect = IntermediateSerializer.Deserialize <ParticleEffect>(xmlReader, null);
                    effect.Initialise();
                    effect.LoadContent(this);
                    return((T)(object)effect);
                }
            }
            else if (typeof(T) == typeof(IFactory[]))
            {
                return((T)(object)FactoryManager.GetFactoriesFromFile(assetName).ToArray());
            }
            else if (typeof(T) == typeof(ItemPool[]))
            {
                return((T)(object)ItemPoolManager.GetItemPools().ToArray());
            }
            else if (typeof(T) == typeof(AttributePool[]))
            {
                return((T)(object)AttributePoolManager.GetAttributePools().ToArray());
            }
            return(default(T));
        }
コード例 #30
0
        public override EffectBinary Process(EffectSourceCode input, ContentProcessorContext context)
        {
            // Remove comments
            Regex  commentRegex = new Regex("//.*$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            string effectCode   = commentRegex.Replace(input.EffectCode, "");

            // Remove carriage returns and line feeds
            commentRegex = new Regex(@"(\r\n)|\n", RegexOptions.IgnoreCase);
            effectCode   = commentRegex.Replace(effectCode, "");

            // Check effect validity
            // EffectProcessor should check almost all potential errors in the effect code
            EffectContent content = new EffectContent {
                EffectCode = effectCode
            };
            EffectProcessor compiler = new EffectProcessor {
                DebugMode = EffectProcessorDebugMode.Auto
            };

            compiler.Process(content, context);

            // If we are here, the effect is assumed to be ok!

            // Extract techniques
            IEnumerable <EffectTechnique> techniques = ExtractTechniques(effectCode);

            // Now we have to find entry points for each pass and compile them
            Compiler     helper = new Compiler();
            EffectBinary result = new EffectBinary();

            foreach (var technique in techniques)
            {
                EffectTechniqueBinary effectTechniqueBinary = new EffectTechniqueBinary {
                    Name = technique.Name
                };

                foreach (var pass in technique.Passes)
                {
                    List <string> errors = new List <string>();

                    // Compiling vertex shader
                    CompilerResult vsResult = helper.Process(effectCode, errors, "vs_2_0", pass.VertexShaderEntryPoint, 3, false, true);

                    // This should not happen but...
                    if (errors.Count > 0)
                    {
                        ExceptionHelper.RaiseException(String.Join("\n", errors));
                    }

                    // Compiling pixel shader
                    CompilerResult psResult = helper.Process(effectCode, errors, "ps_2_0", pass.PixelShaderEntryPoint, 3, false, true);

                    // This should not happen but...
                    if (errors.Count > 0)
                    {
                        ExceptionHelper.RaiseException(String.Join("\n", errors));
                    }

                    // Generating a pass binary
                    EffectPassBinary passBinary = new EffectPassBinary
                    {
                        Name                   = pass.Name,
                        RenderStates           = pass.RenderStates,
                        VertexShaderByteCode   = vsResult.ShaderCode,
                        VertexShaderParameters = Encoding.Unicode.GetBytes(vsResult.ConstantsDefinition),
                        PixelShaderByteCode    = psResult.ShaderCode,
                        PixelShaderParameters  = Encoding.Unicode.GetBytes(psResult.ConstantsDefinition)
                    };

                    effectTechniqueBinary.PassBinaries.Add(passBinary);
                }

                result.TechniquesBinaries.Add(effectTechniqueBinary);
            }

            return(result);
        }