Exemplo n.º 1
0
        private ShaderClassType LoadShaderClass(string type, string generics, LoggerResult log, SiliconStudio.Shaders.Parser.ShaderMacro[] macros = null, HashSet <string> modifiedShaders = null)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            var shaderSourceKey = new ShaderSourceKey(type, generics, macros);

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

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

                // Load file
                var shaderSource = SourceManager.LoadShaderSource(type, modifiedShaders);

                // TODO USE ORIGINAL SOURCE PATH and not to object database path
                var preprocessedSource = PreProcessor.Run(shaderSource.Source, shaderSource.Path, macros);

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

                // Compile
                var parsingResult = ParadoxShaderParser.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 pdxsl.
                var shaderClassTypes = GetShaderClassTypes(shader.Declarations).ToList();
                if (shaderClassTypes.Count != 1)
                {
                    throw new InvalidOperationException(string.Format("Shader [{0}] must contain only a single Shader class type intead of [{1}]", type, shaderClassTypes.Count));
                }

                shaderClass                        = 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 (shaderClass.Name.Text != type)
                {
                    throw new InvalidOperationException(string.Format("Unable to load shader [{0}] not maching class name [{1}]", type, shaderClass.Name.Text));
                }

                // Only full version are stored
                loadedShaders.Add(shaderSourceKey, shaderClass);

                return(shaderClass);
            }
        }
Exemplo n.º 2
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);
            }
        }