예제 #1
0
        public static ShaderClassType ParseSource(string shaderSource, LoggerResult log)
        {
            var parsingResult = XenkoShaderParser.TryParse(shaderSource, null);

            parsingResult.CopyTo(log);

            if (parsingResult.HasErrors)
            {
                return(null);
            }

            var shader      = parsingResult.Shader;
            var shaderClass = shader.Declarations.OfType <ShaderClassType>().SingleOrDefault();

            if (shaderClass == null)
            {
                var queue = new Queue <NamespaceBlock>(shader.Declarations.OfType <NamespaceBlock>());
                while (queue.Count > 0 && shaderClass == null)
                {
                    var namespaceNode = queue.Dequeue();
                    shaderClass = namespaceNode.Body.OfType <ShaderClassType>().SingleOrDefault();
                    foreach (var subNamespace in namespaceNode.Body.OfType <NamespaceBlock>())
                    {
                        queue.Enqueue(subNamespace);
                    }
                }
            }
            return(shaderClass);
        }
예제 #2
0
        public static byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            // Always output a result into the file
            string result;

            try
            {
                var parsingResult = XenkoShaderParser.TryPreProcessAndParse(inputFileContent, inputFileName);

                if (parsingResult.HasErrors)
                {
                    result = "// Failed to parse the shader:\n" + parsingResult;
                }
                else
                {
                    // Try to generate a mixin code.
                    var shaderKeyGenerator = new ShaderMixinCodeGen(parsingResult.Shader, parsingResult);

                    shaderKeyGenerator.Run();
                    result = shaderKeyGenerator.Text ?? string.Empty;
                }
            }
            catch (Exception ex)
            {
                result = "// Unexpected exceptions occurred while generating the file\n" + ex;
            }

            // We force the UTF8 to include the BOM to match VS default
            var data = Encoding.UTF8.GetBytes(result);

            return(Encoding.UTF8.GetPreamble().Concat(data).ToArray());
        }
예제 #3
0
        public override void SaveGeneratedAsset(AssetItem assetItem)
        {
            //generate the .cs files
            // Always output a result into the file
            string result;

            try
            {
                var parsingResult = XenkoShaderParser.TryPreProcessAndParse(Text, assetItem.FullPath);

                if (parsingResult.HasErrors)
                {
                    result = "// Failed to parse the shader:\n" + parsingResult;
                }
                else
                {
                    // Try to generate a mixin code.
                    var shaderKeyGenerator = new ShaderMixinCodeGen(parsingResult.Shader, parsingResult);

                    shaderKeyGenerator.Run();
                    result = shaderKeyGenerator.Text ?? string.Empty;
                }
            }
            catch (Exception ex)
            {
                result = "// Unexpected exceptions occurred while generating the file\n" + ex;
            }

            // We force the UTF8 to include the BOM to match VS default
            var data = Encoding.UTF8.GetBytes(result);

            File.WriteAllBytes(assetItem.GetGeneratedAbsolutePath(), data);
        }
        public static byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            // Always output a result into the file
            string result;

            try
            {
                SiliconStudio.Shaders.Parser.ShaderMacro[] macros;

                // Changed some keywords to avoid ambiguities with HLSL and improve consistency
                if (inputFileName != null && Path.GetExtension(inputFileName).ToLowerInvariant() == ".xkfx")
                {
                    // XKFX
                    macros = new[]
                    {
                        new SiliconStudio.Shaders.Parser.ShaderMacro("shader", "effect")
                    };
                }
                else
                {
                    // XKSL
                    macros = new[]
                    {
                        new SiliconStudio.Shaders.Parser.ShaderMacro("class", "shader")
                    };
                }

                var parsingResult = XenkoShaderParser.TryPreProcessAndParse(inputFileContent, inputFileName, macros);

                if (parsingResult.HasErrors)
                {
                    result = "// Failed to parse the shader:\n" + parsingResult;
                }
                else
                {
                    // Try to generate a mixin code.
                    var shaderKeyGenerator = new ShaderMixinCodeGen(parsingResult.Shader, parsingResult);

                    shaderKeyGenerator.Run();
                    result = shaderKeyGenerator.Text ?? string.Empty;
                }
            }
            catch (Exception ex)
            {
                result = "// Unexpected exceptions occurred while generating the file\n" + ex;
            }

            // We force the UTF8 to include the BOM to match VS default
            var data = Encoding.UTF8.GetBytes(result);

            return(Encoding.UTF8.GetPreamble().Concat(data).ToArray());
        }
예제 #5
0
        /// <summary>
        /// Generates the csharp code from a xkfx file.
        /// </summary>
        /// <param name="xkfxShaderCode">The PDXFX shader code.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>System.String.</returns>
        /// <exception cref="System.InvalidOperationException"></exception>
        public static string GenerateCsharp(string xkfxShaderCode, string filePath)
        {
            // Compile
            var shader = XenkoShaderParser.PreProcessAndParse(xkfxShaderCode, filePath);

            // Try to generate a mixin code.
            var loggerResult       = new LoggerResult();
            var shaderKeyGenerator = new ShaderMixinCodeGen(shader, loggerResult);

            if (shaderKeyGenerator.Run())
            {
                return(shaderKeyGenerator.Text);
            }
            throw new InvalidOperationException(loggerResult.ToString());
        }
예제 #6
0
        public static ShaderClassType ParseSource(string shaderSource, LoggerResult log)
        {
            var parsingResult = XenkoShaderParser.TryParse(shaderSource, null);

            parsingResult.CopyTo(log);

            if (parsingResult.HasErrors)
            {
                return(null);
            }

            var shader      = parsingResult.Shader;
            var shaderClass = shader.Declarations.OfType <ShaderClassType>().Single();

            return(shaderClass);
        }
예제 #7
0
        public override void Save(Stream stream)
        {
            //regex the class name if it has changed
            var className = new UFile(AbsoluteSourceLocation).GetFileName();

            Text = Regex.Replace(Text, $"class {className}");

            var buffer = Encoding.UTF8.GetBytes(Text);

            stream.Write(buffer, 0, buffer.Length);

            //generate the .cs files
            // Always output a result into the file
            string result;

            try
            {
                var parsingResult = XenkoShaderParser.TryPreProcessAndParse(Text, AbsoluteSourceLocation);

                if (parsingResult.HasErrors)
                {
                    result = "// Failed to parse the shader:\n" + parsingResult;
                }
                else
                {
                    // Try to generate a mixin code.
                    var shaderKeyGenerator = new ShaderMixinCodeGen(parsingResult.Shader, parsingResult);

                    shaderKeyGenerator.Run();
                    result = shaderKeyGenerator.Text ?? string.Empty;
                }
            }
            catch (Exception ex)
            {
                result = "// Unexpected exceptions occurred while generating the file\n" + ex;
            }

            // We force the UTF8 to include the BOM to match VS default
            var data = Encoding.UTF8.GetBytes(result);

            File.WriteAllBytes(GeneratedAbsolutePath, data);
        }
예제 #8
0
        /// <summary>
        /// Generates the csharp code from a xkfx file.
        /// </summary>
        /// <param name="xkfxShaderCode">The PDXFX shader code.</param>
        /// <param name="filePath">The file path.</param>
        /// <returns>System.String.</returns>
        /// <exception cref="System.InvalidOperationException"></exception>
        public static string GenerateCsharp(string xkfxShaderCode, string filePath)
        {
            // In .xkfx, shader has been renamed to effect, in order to avoid ambiguities with HLSL and .xksl
            var macros = new []
            {
                new Xenko.Core.Shaders.Parser.ShaderMacro("shader", "effect")
            };

            // Compile
            var shader = XenkoShaderParser.PreProcessAndParse(xkfxShaderCode, filePath, macros);

            // Try to generate a mixin code.
            var loggerResult       = new LoggerResult();
            var shaderKeyGenerator = new ShaderMixinCodeGen(shader, loggerResult);

            if (shaderKeyGenerator.Run())
            {
                return(shaderKeyGenerator.Text);
            }
            throw new InvalidOperationException(loggerResult.ToString());
        }
예제 #9
0
        public static ShaderClassType ParseSource(string shaderSource, LoggerResult log)
        {
            var parsingResult = XenkoShaderParser.TryParse(shaderSource, null);

            parsingResult.CopyTo(log);

            if (parsingResult.HasErrors)
            {
                return(null);
            }

            var shader      = parsingResult.Shader;
            var shaderClass = shader.Declarations.OfType <ShaderClassType>().Single();

            shaderClass.SourcePath             = null;           // shaderSource.Path;
            shaderClass.SourceHash             = ObjectId.Empty; // shaderSource.Hash;
            shaderClass.PreprocessedSourceHash = ObjectId.Empty; // hashPreprocessSource;
            shaderClass.IsInstanciated         = false;

            return(shaderClass);
        }
예제 #10
0
        private LoadedShaderClassType LoadShaderClass(ShaderClassSource classSource, string generics, LoggerResult log, SiliconStudio.Shaders.Parser.ShaderMacro[] macros = null)
        {
            var type = classSource.ClassName;

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            var shaderSourceKey = new ShaderSourceKey(type, generics, macros);

            lock (loadedShaders)
            {
                // Already instantiated
                LoadedShaderClassType shaderClass;

                if (loadedShaders.TryGetValue(shaderSourceKey, out shaderClass))
                {
                    return(shaderClass);
                }

                // Load file
                var    shaderSource = SourceManager.LoadShaderSource(type);
                string preprocessedSource;
                try
                {
                    preprocessedSource = PreProcessor.Run(shaderSource.Source, shaderSource.Path, macros);
                }
                catch (Exception ex)
                {
                    log.Error(MessageCode.ErrorUnexpectedException, new SourceSpan(new SourceLocation(shaderSource.Path, 0, 1, 1), 1), ex);
                    return(null);
                }

                byte[] byteArray            = Encoding.UTF8.GetBytes(preprocessedSource);
                var    hashPreprocessSource = ObjectId.FromBytes(byteArray);

                // Compile
                var parsingResult = XenkoShaderParser.TryParse(preprocessedSource, shaderSource.Path);
                parsingResult.CopyTo(log);

                if (parsingResult.HasErrors)
                {
                    return(null);
                }

                var shader = parsingResult.Shader;

                // As shaders can be embedded in namespaces, get only the shader class and make sure there is only one in a xksl.
                var shaderClassTypes = XenkoShaderParser.GetShaderClassTypes(shader.Declarations).ToList();
                if (shaderClassTypes.Count != 1)
                {
                    var sourceSpan = new SourceSpan(new SourceLocation(shaderSource.Path, 0, 0, 0), 1);
                    if (shaderClassTypes.Count > 1)
                    {
                        sourceSpan = shaderClassTypes[1].Span;
                    }
                    log.Error(XenkoMessageCode.ShaderMustContainSingleClassDeclaration, sourceSpan, type);
                    return(null);
                }

                shaderClass                        = new LoadedShaderClassType();
                shaderClass.Type                   = shaderClassTypes.First();
                shaderClass.SourcePath             = shaderSource.Path;
                shaderClass.SourceHash             = shaderSource.Hash;
                shaderClass.PreprocessedSourceHash = hashPreprocessSource;
                shaderClass.IsInstanciated         = false;

                // TODO: We should not use Console. Change the way we log things here
                // Console.WriteLine("Loading Shader {0}{1}", type, macros != null && macros.Length > 0 ? String.Format("<{0}>", string.Join(", ", macros)) : string.Empty);

                // If the file name is not matching the class name, provide an error
                if (shaderClass.Type.Name.Text != type)
                {
                    log.Error(XenkoMessageCode.FileNameNotMatchingClassName, shaderClass.Type.Name.Span, type, shaderClass.Type.Name.Text);
                    return(null);
                }

                loadedShaders.Add(shaderSourceKey, shaderClass);

                return(shaderClass);
            }
        }