/// <summary>
        /// Get a compilation context based on the macros
        /// </summary>
        /// <param name="mixinToAnalyze">List of mixin to analyze</param>
        /// <param name="log">The log.</param>
        /// <returns>the correct compilation context</returns>
        private ShaderCompilationContext GetCompilationContext(IEnumerable<ModuleMixinInfo> mixinToAnalyze, LoggerResult log)
        {
            var mixinInfos = new HashSet<ModuleMixinInfo>();
            foreach (var mixin in mixinToAnalyze)
                mixinInfos.UnionWith(mixin.MinimalContext);

            var context = new ShaderCompilationContext(log);
            context.Preprocess(mixinInfos);
            return context;
        }
        /// <summary>
        /// create the context for each composition by cloning their dependencies
        /// </summary>
        /// <param name="shaderSource">the entry ShaderSource (root)</param>
        /// <param name="dictionary">the ouputed compositions</param>
        /// <param name="compilationContext">the compilation context</param>
        /// <param name="cloneContext">The clone context.</param>
        /// <returns>a list of all the needed mixins</returns>
        private static List<ModuleMixin> BuildCompositionsDictionary(ShaderSource shaderSource, CompositionDictionary dictionary, ShaderCompilationContext compilationContext, CloneContext cloneContext, LoggerResult log)
        {
            if (shaderSource is ShaderMixinSource)
            {
                var shaderMixinSource = shaderSource as ShaderMixinSource;

                var finalModule = compilationContext.GetModuleMixinFromShaderSource(shaderSource);

                //PerformanceLogger.Start(PerformanceStage.DeepClone);
                finalModule = finalModule.DeepClone(new CloneContext(cloneContext));
                //PerformanceLogger.Pause(PerformanceStage.DeepClone);

                foreach (var composition in shaderMixinSource.Compositions)
                {
                    //look for the key
                    var foundVars = finalModule.FindAllVariablesByName(composition.Key).Where(value => value.Variable.Qualifiers.Contains(XenkoStorageQualifier.Compose)).ToList();

                    if (foundVars.Count > 1)
                    {
                        log.Error(XenkoMessageCode.ErrorAmbiguousComposition, new SourceSpan(), composition.Key);
                    }
                    else if (foundVars.Count > 0)
                    {
                        Variable foundVar = foundVars[0].Variable;
                        var moduleMixins = BuildCompositionsDictionary(composition.Value, dictionary, compilationContext, cloneContext, log);
                        if (moduleMixins == null)
                            return null;

                        dictionary.Add(foundVar, moduleMixins);
                    }
                    else
                    {
                        // No matching variable was found
                        // TODO: log a message?
                    }
                }
                return new List<ModuleMixin> { finalModule };
            }


            if (shaderSource is ShaderClassSource)
            {
                var finalModule = compilationContext.GetModuleMixinFromShaderSource(shaderSource);

                //PerformanceLogger.Start(PerformanceStage.DeepClone);
                finalModule = finalModule.DeepClone(new CloneContext(cloneContext));
                //PerformanceLogger.Pause(PerformanceStage.DeepClone);

                return new List<ModuleMixin> { finalModule };
            }

            if (shaderSource is ShaderArraySource)
            {
                var shaderArraySource = shaderSource as ShaderArraySource;
                var compositionArray = new List<ModuleMixin>();
                foreach (var shader in shaderArraySource.Values)
                {
                    var mixin = BuildCompositionsDictionary(shader, dictionary, compilationContext, cloneContext, log);
                    if (mixin == null)
                        return null;
                    compositionArray.AddRange(mixin);
                }
                return compositionArray;
            }

            return null;
        }