Esempio n. 1
0
 private EffectPool(GraphicsDevice device, string name = null) : base(name)
 {
     dataGroup = new EffectData();
     mapNameToEffect = new Dictionary<string, EffectData.Effect>();
     mapNameToConstantBuffer = new Dictionary<GraphicsDevice, Dictionary<string, Dictionary<EffectConstantBufferKey, EffectConstantBuffer>>>();
     compiledShaders = new List<DeviceChild>();
     registered = new Dictionary<EffectData, bool>(new IdentityEqualityComparer<EffectData>());
     effects = new List<Effect>();
     this.graphicsDevice = device.MainDevice;
     constantBufferAllocator = DefaultConstantBufferAllocator;
 }
Esempio n. 2
0
        public void Write(EffectData effectData, TextWriter writer)
        {
            const string codeTemplate = @"//------------------------------------------------------------------------------
// <auto-generated>
//     SharpDX Toolkit Compiler File Generated:
{0}//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace {1} 
{{
    {2} class {3}
    {{
        {4} static readonly SharpDX.Toolkit.Graphics.EffectData {5} = SharpDX.Toolkit.Graphics.EffectData.Load(new byte[] {{
{6}
        }});
    }}
}}
";

        var effectToGenerateText = new StringBuilder();
            foreach(var effect in effectData.Effects)
            {
                effectToGenerateText.AppendFormat("//     Effect [{0}]\r\n", effect.Name);
            }

            var buffer = new MemoryStream();
            effectData.Save(buffer);

            var bufferAsText = new StringBuilder();
            var bufferArray = buffer.ToArray();
            for(int i = 0; i < bufferArray.Length; i++)
            {
                bufferAsText.Append(bufferArray[i]).Append(", ");
                if (i > 0 && (i % 64) == 0)
                {
                    bufferAsText.AppendLine();
                }
            }

            writer.Write(codeTemplate,
                         effectToGenerateText, // {0} 
                         Namespace,            // {1} 
                         ClassDeclaration,     // {2} 
                         ClassName,            // {3} 
                         FieldDeclaration,     // {4} 
                         FieldName,            // {5} 
                         bufferAsText);        // {6} 

            writer.Flush();
        }
Esempio n. 3
0
        internal void CreateInstanceFrom(GraphicsDevice device, EffectData effectData, EffectPool effectPool)
        {
            GraphicsDevice  = device;
            ConstantBuffers = new EffectConstantBufferCollection();
            Parameters      = new EffectParameterCollection();
            Techniques      = new EffectTechniqueCollection();

            Pool = effectPool ?? device.DefaultEffectPool;

            // Sets the effect name
            Name = effectData.Description.Name;

            // Register the bytecode to the pool
            var effect = Pool.RegisterBytecode(effectData);

            // Initialize from effect
            InitializeFrom(effect, null);

            // If everything was fine, then we can register it into the pool
            Pool.AddEffect(this);
        }
Esempio n. 4
0
        /// <summary>
        /// Registers a EffectData to this pool.
        /// </summary>
        /// <param name="data">The effect data to register.</param>
        /// <param name="allowOverride">if set to <c>true</c> [allow override].</param>
        public void RegisterBytecode(EffectData data, bool allowOverride = false)
        {
            // Lock the whole EffectPool in case multiple threads would add EffectData at the same time.
            lock (sync)
            {
                bool hasNewBytecode = false;
                if (!registered.ContainsKey(data))
                {
                    // Pre-cache all input signatures
                    CacheInputSignature(data);

                    dataGroup.MergeFrom(data, allowOverride);
                    registered.Add(data, true);
                    hasNewBytecode = true;
                }

                if (hasNewBytecode)
                {
                    // Create all mapping
                    mapNameToEffect.Clear();
                    foreach (var effect in dataGroup.Effects)
                        mapNameToEffect.Add(effect.Name, effect);

                    // Just alocate the compiled shaders array according to the currennt size of shader datas
                    for (int i = compiledShaders.Count; i < dataGroup.Shaders.Count; i++)
                    {
                        compiledShaders.Add(null);
                    }
                }
            }
        }
Esempio n. 5
0
        private void DumpBytecode(EffectCompiler compiler, EffectData effectData)
        {
            Console.WriteLine();

            for (int i = 0; i < effectData.Shaders.Count; i++)
            {
                var shader = effectData.Shaders[i];

                Color(ConsoleColor.White);
                Console.WriteLine("--------------------------------------------------------------------------------");
                Console.WriteLine("Shader[{0}] {1}Type: {2} Level: {3} Visibility: {4} ByteCode Size: {5}", i, shader.Name == null ? string.Empty : string.Format("{0} ", shader.Name), shader.Type, shader.Level, shader.Name != null ? "public" : "private", shader.Bytecode.Length);
                Console.WriteLine("--------------------------------------------------------------------------------");
                Console.WriteLine();
                ResetColor();

                DumpHtmlToConsole(compiler.DisassembleShader(shader));
                Console.WriteLine();
            }

            Color(ConsoleColor.White);
            Console.WriteLine("--------------------------------------------------------------------------------");
            Console.WriteLine("effect {0}", effectData.Description.Name);
            Console.WriteLine("--------------------------------------------------------------------------------");
            Console.WriteLine();
            ResetColor();

            const string tab = "    ";

            var effect = effectData.Description;
            {
                Console.WriteLine("{");
                foreach (var technique in effect.Techniques)
                {
                    Console.Write(tab + "technique");
                    Color(ConsoleColor.LightGreen);
                    Console.WriteLine(" {0}", technique.Name);
                    ResetColor();

                    Console.WriteLine(tab + "{");
                    for (int passIndex = 0; passIndex < technique.Passes.Count; passIndex++)
                    {
                        var pass    = technique.Passes[passIndex];
                        var passtab = pass.IsSubPass ? tab + tab + tab : tab + tab;

                        Console.Write("{0}{1} #{2}", passtab, ((pass.IsSubPass) ? "subpass" : "pass"), passIndex);
                        Color(ConsoleColor.LightGreen);
                        Console.WriteLine(" {0}", pass.Name);
                        ResetColor();

                        Console.WriteLine(passtab + "{");

                        for (int i = 0; i < pass.Pipeline.Links.Length; i++)
                        {
                            var shaderType = (EffectShaderType)i;
                            var link       = pass.Pipeline.Links[i];
                            if (link == null)
                            {
                                continue;
                            }

                            Color(ConsoleColor.LightYellow);
                            Console.Write(passtab + tab + "{0}", shaderType);
                            ResetColor();
                            Console.Write(" = ");
                            Color(ConsoleColor.White);
                            Console.WriteLine("{0}",
                                              link.IsImport ? link.ImportName : link.IsNullShader ? "null" : string.Format("Shader[{0}] => {1}", link.Index, effectData.Shaders[link.Index].Name == null ? "private" : "public " + effectData.Shaders[link.Index].Name));
                            ResetColor();
                        }

                        if (pass.Properties.Count > 0)
                        {
                            Console.WriteLine();

                            foreach (var attribute in pass.Properties)
                            {
                                var typeName = attribute.Value != null?attribute.Value.GetType().FullName.StartsWith("SharpDX") ? attribute.Value.GetType().FullName : null : null;

                                Console.WriteLine(passtab + tab + "{0} = {1}", attribute.Key, typeName == null ? attribute.Value : string.Format("{0}({1})", typeName, attribute.Value));
                            }
                        }
                        Console.WriteLine(passtab + "}");
                    }
                    Console.WriteLine(tab + "}");
                }
                Console.WriteLine("}");
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Disassembles a shader HLSL bytecode to asm code.
 /// </summary>
 /// <param name="shader">The shader.</param>
 /// <returns>A string containing asm code decoded from HLSL bytecode.</returns>
 public string DisassembleShader(EffectData.Shader shader)
 {
     var compiler = new EffectCompilerInternal();
     return compiler.DisassembleShader(shader);
 }
Esempio n. 7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Effect"/> class with the specified bytecode effect. See remarks.
 /// </summary>
 /// <param name="device">The device.</param>
 /// <param name="bytecode">The bytecode to add to <see cref="GraphicsDevice.DefaultEffectPool"/>. This bytecode must contain only one effect.</param>
 /// <exception cref="ArgumentException">If the bytecode doesn't contain a single effect.</exception>
 /// <remarks>
 /// The effect bytecode must contain only a single effect and will be registered into the <see cref="GraphicsDevice.DefaultEffectPool"/>.
 /// </remarks>
 public Effect(GraphicsDevice device, byte[] bytecode)
     : this(device, EffectData.Load(bytecode))
 {
 }
Esempio n. 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Effect" /> class with the specified bytecode effect. See remarks.
 /// </summary>
 /// <param name="device">The device.</param>
 /// <param name="effectData">The bytecode to add to the Effect Pool. This bytecode must contain only one effect.</param>
 /// <param name="effectPool">The effect pool used to register the bytecode. Default is <see cref="GraphicsDevice.DefaultEffectPool"/>.</param>
 /// <exception cref="ArgumentException">If the bytecode doesn't contain a single effect.</exception>
 /// <remarks>The effect bytecode must contain only a single effect and will be registered into the <see cref="GraphicsDevice.DefaultEffectPool"/>.</remarks>
 public Effect(GraphicsDevice device, EffectData effectData, EffectPool effectPool = null)
     : base(device)
 {
     CreateInstanceFrom(device, effectData, effectPool);
 }
Esempio n. 9
0
        /// <summary>
        /// Merges an existing <see cref="EffectData" /> into this instance.
        /// </summary>
        /// <param name="source">The EffectData to merge.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        /// <remarks>This method is useful to build an archive of several effects.</remarks>
        private EffectData.Effect RegisterInternal(EffectData source)
        {
            var effect = source.Description;

            var effectRuntime = new EffectData.Effect()
                                    {
                                        Name = effect.Name,
                                        Arguments = effect.Arguments,
                                        ShareConstantBuffers = effect.ShareConstantBuffers,
                                        Techniques = new List<EffectData.Technique>(effect.Techniques.Count)
                                    };

            Logger logger = null;

            foreach (var techniqueOriginal in effect.Techniques)
            {
                var technique = techniqueOriginal.Clone();
                effectRuntime.Techniques.Add(technique);

                foreach (var pass in technique.Passes)
                {
                    foreach (var shaderLink in pass.Pipeline)
                    {
                        // No shader set for this stage
                        if (shaderLink == null) continue;

                        // If the shader is an import, we try first to resolve it directly
                        if (shaderLink.IsImport)
                        {
                            var index = FindShaderByName(shaderLink.ImportName);
                            if (index >= 0)
                            {
                                shaderLink.ImportName = null;
                                shaderLink.Index = index;
                            }
                            else
                            {
                                if (logger == null)
                                {
                                    logger = new Logger();
                                }

                                logger.Error("Cannot find shader import by name [{0}]", shaderLink.ImportName);
                            }
                        }
                        else if (!shaderLink.IsNullShader)
                        {
                            var shader = source.Shaders[shaderLink.Index];

                            // Find a similar shader
                            var shaderIndex = FindSimilarShader(shader);

                            if (shaderIndex >= 0)
                            {
                                var previousShader = RegisteredShaders[shaderIndex];

                                // If the previous shader is 
                                if (shader.Name != null)
                                {
                                    // if shader from this instance is local and shader from source is global => transform current shader to global
                                    if (previousShader.Name == null)
                                    {
                                        previousShader.Name = shader.Name;
                                    }
                                    else if (shader.Name != previousShader.Name)
                                    {
                                        if (logger == null)
                                        {
                                            logger = new Logger();
                                        }
                                        // If shader from this instance is global and shader from source is global => check names. If exported names are different, this is an error
                                        logger.Error("Cannot merge shader [{0}] into this instance, as there is already a global shader with a different name [{1}]", shader.Name, previousShader.Name);
                                    }
                                }

                                shaderLink.Index = shaderIndex;
                            }
                            else
                            {
                                shaderLink.Index = RegisteredShaders.Count;
                                RegisteredShaders.Add(shader);
                            }
                        }
                    }
                }
            }

            if (logger != null && logger.HasErrors)
                throw new InvalidOperationException(Utilities.Join("\r\n", logger.Messages));

            return effectRuntime;
        }
Esempio n. 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EffectCompilerResult" /> class.
 /// </summary>
 /// <param name="dependencyFilePath">The path to dependency file (may be null).</param>
 /// <param name="effectData">The EffectData.</param>
 /// <param name="logger">The logger.</param>
 public EffectCompilerResult(string dependencyFilePath, EffectData effectData, Logger logger)
 {
     DependencyFilePath = dependencyFilePath;
     EffectData = effectData;
     Logger = logger;
 }
Esempio n. 11
0
        /// <summary>
        /// Initializes the specified effect bytecode.
        /// </summary>
        /// <param name="effectDataArg">The effect bytecode.</param>
        /// <exception cref="System.InvalidOperationException"></exception>
        private void Initialize(EffectData.Effect effectDataArg)
        {
            if (effectDataArg == null)
                throw new ArgumentException(string.Format("Unable to find effect [{0}] from the EffectPool", Name), "effectName");

            rawEffect = effectDataArg;

            ShareConstantBuffers = effectDataArg.ShareConstantBuffers;

            // Create the local effect constant buffers cache
            if (!ShareConstantBuffers)
                effectConstantBuffersCache = new Dictionary<EffectConstantBufferKey, EffectConstantBuffer>();

            if (effectDataArg.Techniques.Count == 0)
                throw new InvalidOperationException("No techniques found in this effect");

            var logger = new Logger();
            int techniqueIndex = 0;
            int totalPassCount = 0;
            EffectPass parentPass = null;
            foreach (var techniqueRaw in effectDataArg.Techniques)
            {
                var name = techniqueRaw.Name;
                if (string.IsNullOrEmpty(name))
                    name = string.Format("${0}", techniqueIndex++);

                var technique = new EffectTechnique(this, name);
                Techniques.Add(technique);

                int passIndex = 0;
                foreach (var passRaw in techniqueRaw.Passes)
                {
                    name = passRaw.Name;
                    if (string.IsNullOrEmpty(name))
                        name = string.Format("${0}", passIndex++);

                    var pass = new EffectPass(logger, this, technique, passRaw, name);

                    pass.Initialize(logger);

                    // If this is a subpass, add it to the parent pass
                    if (passRaw.IsSubPass)
                    {
                        if (parentPass == null)
                        {
                            logger.Error("Pass [{0}] is declared as a subpass but has no parent");
                        }
                        else
                        {
                            parentPass.SubPasses.Add(pass);
                        }
                    }
                    else
                    {
                        technique.Passes.Add(pass);
                        parentPass = pass;
                    }
                }

                // Count the number of passes
                totalPassCount += technique.Passes.Count;
            }

            if (totalPassCount == 0)
                throw new InvalidOperationException("No passes found in this effect");

            // Log all the exception in a single throw
            if (logger.HasErrors)
                throw new InvalidOperationException(Utilities.Join("\n", logger.Messages));

            // Initialize the resource linker when we are done with all pass/parameters
            ResourceLinker.Initialize();

            //// Sort all parameters by their resource types
            //// in order to achieve better local cache coherency in resource linker
            Parameters.Items.Sort((left, right) =>
                {
                    // First, order first all value types, then resource type
                    var comparison = left.IsValueType != right.IsValueType ? left.IsValueType ? -1 : 1 : 0;

                    // If same type
                    if (comparison == 0)
                    {
                        // Order by resource type
                        comparison = ((int)left.ResourceType).CompareTo((int)right.ResourceType);

                        // If same, order by resource index
                        if (comparison == 0)
                        {
                            comparison = left.Offset.CompareTo(right.Offset);
                        }
                    }
                    return comparison;
                });

            // Prelink constant buffers
            int resourceIndex = 0;
            foreach (var parameter in Parameters)
            {
                // Recalculate parameter resource index
                if (!parameter.IsValueType)
                {
                    parameter.Offset = resourceIndex++;
                }

                // Set the default values 
                parameter.SetDefaultValue();

                if (parameter.ResourceType == EffectResourceType.ConstantBuffer)
                    parameter.SetResource(0, ConstantBuffers[parameter.Name]);
            }

            // Compute slot links
            foreach (var technique in Techniques)
            {
                foreach (var pass in technique.Passes)
                {
                    foreach (var subPass in pass.SubPasses)
                    {
                        subPass.ComputeSlotLinks();
                    }
                    pass.ComputeSlotLinks();
                }
            }

            // Setup the first Current Technique.
            CurrentTechnique = this.Techniques[0];
        }
Esempio n. 12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EffectCompilerResult" /> class.
 /// </summary>
 /// <param name="effectData">The EffectData.</param>
 /// <param name="logger">The logger.</param>
 internal EffectCompilerResult(EffectData effectData, Logger logger)
 {
     EffectData = effectData;
     Logger = logger;
 }
Esempio n. 13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EffectCompilerResult" /> class.
 /// </summary>
 /// <param name="dependencyFilePath">The path to dependency file (may be null).</param>
 /// <param name="effectData">The EffectData.</param>
 /// <param name="logger">The logger.</param>
 public EffectCompilerResult(string dependencyFilePath, EffectData effectData, Logger logger)
 {
     DependencyFilePath = dependencyFilePath;
     EffectData         = effectData;
     Logger             = logger;
 }
 public TerrainRendererEffect(GraphicsDevice device, EffectData effectData)
     : base(device, effectData)
 {
 }
 protected TerrainEffectBase(GraphicsDevice device, EffectData effectData)
     : base(device, effectData, null)
 {
 }
Esempio n. 16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Effect" /> class with the specified bytecode effect. See remarks.
        /// </summary>
        /// <param name="device">The device.</param>
        /// <param name="effectData">The bytecode to add to the Effect Pool. This bytecode must contain only one effect.</param>
        /// <param name="effectPool">The effect pool used to register the bytecode. Default is <see cref="GraphicsDevice.DefaultEffectPool"/>.</param>
        /// <exception cref="ArgumentException">If the bytecode doesn't contain a single effect.</exception>
        /// <remarks>The effect bytecode must contain only a single effect and will be registered into the <see cref="GraphicsDevice.DefaultEffectPool"/>.</remarks>
        public Effect(GraphicsDevice device, EffectData effectData, EffectPool effectPool = null) : base(device)
        {
            if (effectData.Effects.Count != 1)
                throw new ArgumentException(string.Format("Expecting only one effect in the effect bytecode instead of [{0}].", Utilities.Join(",", effectData.Effects)), "effectData");

            ConstantBuffers = new EffectConstantBufferCollection();
            Parameters = new EffectParameterCollection();
            Techniques = new EffectTechniqueCollection();

            Pool = effectPool ?? device.DefaultEffectPool;

            // Sets the effect name
            Name = effectData.Effects[0].Name;

            // Register the bytecode to the pool
            Pool.RegisterBytecode(effectData);

            // Initialize from effect
            InitializeFrom(Pool.Find(Name));
            // If everything was fine, then we can register it into the pool
            Pool.AddEffect(this);
        }
Esempio n. 17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EffectCompilerResult" /> class.
 /// </summary>
 /// <param name="effectData">The EffectData.</param>
 /// <param name="logger">The logger.</param>
 internal EffectCompilerResult(bool isUpToDate, EffectData effectData, Logger logger)
 {
     IsUpToDate = isUpToDate;
     EffectData = effectData;
     Logger = logger;
 }
Esempio n. 18
0
        private void DumpBytecode(EffectData effectData)
        {
            Console.WriteLine();

            for (int i = 0; i < effectData.Shaders.Count; i++)
            {
                var shader = effectData.Shaders[i];

                Color(ConsoleColor.White);
                Console.WriteLine("--------------------------------------------------------------------------------");
                Console.WriteLine("Shader[{0}] {1}Type: {2} Level: {3} Visibility: {4} ByteCode Size: {5}", i, shader.Name == null ? string.Empty : string.Format("{0} ", shader.Name), shader.Type, shader.Level, shader.Name != null ? "public" : "private", shader.Bytecode.Length);
                Console.WriteLine("--------------------------------------------------------------------------------");
                Console.WriteLine();
                ResetColor();

                DumpHtmlToConsole(EffectCompiler.DisassembleShader(shader));
                Console.WriteLine();
            }

            Color(ConsoleColor.White);
            Console.WriteLine("--------------------------------------------------------------------------------");
            Console.WriteLine("Effects");
            Console.WriteLine("--------------------------------------------------------------------------------");
            Console.WriteLine();
            ResetColor();

            const string tab = "    ";

            foreach (var effect in effectData.Effects)
            {
                Console.Write("effect");
                Color(ConsoleColor.LightGreen);
                Console.WriteLine(" {0}", effect.Name);
                ResetColor();

                Console.WriteLine("{");
                foreach (var technique in effect.Techniques)
                {
                    Console.Write(tab + "technique");
                    Color(ConsoleColor.LightGreen);
                    Console.WriteLine(" {0}", technique.Name);
                    ResetColor();

                    Console.WriteLine(tab + "{");
                    for (int passIndex = 0; passIndex < technique.Passes.Count; passIndex++)
                    {
                        var pass = technique.Passes[passIndex];
                        var passtab = pass.IsSubPass ? tab + tab + tab : tab + tab;

                        Console.Write("{0}{1} #{2}", passtab, ((pass.IsSubPass) ? "subpass" : "pass"), passIndex);
                        Color(ConsoleColor.LightGreen);
                        Console.WriteLine(" {0}", pass.Name);
                        ResetColor();

                        Console.WriteLine(passtab + "{");

                        for (int i = 0; i < pass.Pipeline.Links.Length; i++)
                        {
                            var shaderType = (EffectShaderType) i;
                            var link = pass.Pipeline.Links[i];
                            if (link == null)
                                continue;

                            Color(ConsoleColor.LightYellow);
                            Console.Write(passtab + tab + "{0}", shaderType);
                            ResetColor();
                            Console.Write(" = ");
                            Color(ConsoleColor.White);
                            Console.WriteLine("{0}",
                                link.IsImport ? link.ImportName : link.IsNullShader ? "null" : string.Format("Shader[{0}] => {1}", link.Index, effectData.Shaders[link.Index].Name == null ? "private" : "public " + effectData.Shaders[link.Index].Name));
                            ResetColor();
                        }

                        if (pass.Attributes.Count > 0)
                        {
                            Console.WriteLine();

                            foreach (var attribute in pass.Attributes)
                            {
                                var typeName = attribute.Value != null ? attribute.Value.GetType().FullName.StartsWith("SharpDX") ? attribute.Value.GetType().FullName : null : null;
                                Console.WriteLine(passtab + tab + "{0} = {1}", attribute.Name, typeName == null ? attribute.Value : string.Format("{0}({1})", typeName, attribute.Value));
                            }
                        }
                        Console.WriteLine(passtab + "}");
                    }
                    Console.WriteLine(tab + "}");
                }
                Console.WriteLine("}");
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Effect" /> class with the specified bytecode effect. See remarks.
        /// </summary>
        /// <param name="device">The device.</param>
        /// <param name="effectData">The bytecode to add to <see cref="GraphicsDevice.DefaultEffectPool"/>. This bytecode must contain only one effect.</param>
        /// <exception cref="ArgumentException">If the bytecode doesn't contain a single effect.</exception>
        /// <remarks>
        /// The effect bytecode must contain only a single effect and will be registered into the <see cref="GraphicsDevice.DefaultEffectPool"/>.
        /// </remarks>
        public Effect(GraphicsDevice device, EffectData effectData) : base(device)
        {
            if (effectData.Effects.Count != 1)
                throw new ArgumentException(string.Format("Expecting only one effect in the effect bytecode instead of [{0}]. Use GraphicsDevice.DefaultEffectPool.RegisterBytecode instead", Utilities.Join(",", effectData.Effects)), "bytecode");

            ConstantBuffers = new EffectConstantBufferCollection();
            Parameters = new EffectParameterCollection();
            Techniques = new EffectTechniqueCollection();
            ResourceLinker = ToDispose(new EffectResourceLinker());
            Pool = device.DefaultEffectPool;

            // Sets the effect name
            Name = effectData.Effects[0].Name;

            // Register the bytecode to the pool
            Pool.RegisterBytecode(effectData);

            Initialize();
        }
Esempio n. 20
0
        internal EffectConstantBuffer GetOrCreateConstantBuffer(GraphicsDevice context, EffectData.ConstantBuffer bufferRaw)
        {
            // Only lock the constant buffer object
            lock (mapNameToConstantBuffer)
            {
                Dictionary<string, Dictionary<EffectConstantBufferKey, EffectConstantBuffer>> nameToConstantBufferList;

                // ----------------------------------------------------------------------------
                // 1) Get the cache of constant buffers for a particular GraphicsDevice
                // ----------------------------------------------------------------------------
                // TODO cache is not clear if a GraphicsDevice context is disposed
                // To simplify, we assume that a GraphicsDevice is alive during the whole life of the application.
                if (!mapNameToConstantBuffer.TryGetValue(context, out nameToConstantBufferList))
                {
                    nameToConstantBufferList = new Dictionary<string, Dictionary<EffectConstantBufferKey, EffectConstantBuffer>>();
                    mapNameToConstantBuffer[context] = nameToConstantBufferList;
                }

                // ----------------------------------------------------------------------------
                // 2) Get a set of constant buffers for a particular constant buffer name
                // ----------------------------------------------------------------------------
                Dictionary<EffectConstantBufferKey, EffectConstantBuffer> bufferSet;
                if (!nameToConstantBufferList.TryGetValue(bufferRaw.Name, out bufferSet))
                {
                    bufferSet = new Dictionary<EffectConstantBufferKey, EffectConstantBuffer>();
                    nameToConstantBufferList[bufferRaw.Name] = bufferSet;
                }

                // ----------------------------------------------------------------------------
                // 3) Get an existing constant buffer having the same name/size/layout/parameters
                // ----------------------------------------------------------------------------
                var bufferKey = new EffectConstantBufferKey(bufferRaw);
                EffectConstantBuffer buffer;
                if (!bufferSet.TryGetValue(bufferKey, out buffer))
                {
                    // 4) If this buffer doesn't exist, create a new one and register it.
                    buffer = new EffectConstantBuffer(graphicsDevice, bufferRaw);
                    bufferSet[bufferKey] = ToDispose(buffer);
                }

                return buffer;
            }
        }
Esempio n. 21
0
        internal void CreateInstanceFrom(GraphicsDevice device, EffectData effectData, EffectPool effectPool)
        {
            GraphicsDevice = device;
            ConstantBuffers = new EffectConstantBufferCollection();
            Parameters = new EffectParameterCollection();
            Techniques = new EffectTechniqueCollection();

            Pool = effectPool ?? device.DefaultEffectPool;

            // Sets the effect name
            Name = effectData.Description.Name;

            // Register the bytecode to the pool
            var effect = Pool.RegisterBytecode(effectData);

            // Initialize from effect
            InitializeFrom(effect, null);

            // If everything was fine, then we can register it into the pool
            Pool.AddEffect(this);
        }
Esempio n. 22
0
 private int FindSimilarShader(EffectData.Shader shader)
 {
     for (int i = 0; i < RegisteredShaders.Count; i++)
     {
         if (RegisteredShaders[i].IsSimilar(shader))
             return i;
     }
     return -1;
 }
Esempio n. 23
0
        /// <summary>
        /// Binds the specified effect data to this instance.
        /// </summary>
        /// <param name="effectDataArg">The effect data arg.</param>
        /// <param name="cloneFromEffect">The clone from effect.</param>
        /// <exception cref="System.InvalidOperationException">If no techniques found in this effect.</exception>
        /// <exception cref="System.ArgumentException">If unable to find effect [effectName] from the EffectPool.</exception>
        internal void InitializeFrom(EffectData.Effect effectDataArg, Effect cloneFromEffect)
        {
            RawEffectData = effectDataArg;

            // Clean any previously allocated resources
            if (DisposeCollector != null)
            {
                DisposeCollector.DisposeAndClear();
            }
            ConstantBuffers.Clear();
            Parameters.Clear();
            Techniques.Clear();
            ResourceLinker = ToDispose(new EffectResourceLinker());
            if (effectConstantBuffersCache != null)
            {
                effectConstantBuffersCache.Clear();
            }

            // Copy data
            IsSupportingDynamicCompilation = RawEffectData.Arguments != null;
            ShareConstantBuffers = RawEffectData.ShareConstantBuffers;

            // Create the local effect constant buffers cache
            if (!ShareConstantBuffers)
                effectConstantBuffersCache = new Dictionary<EffectConstantBufferKey, EffectConstantBuffer>();

            var logger = new Logger();
            int techniqueIndex = 0;
            int totalPassCount = 0;
            EffectPass parentPass = null;
            foreach (var techniqueRaw in RawEffectData.Techniques)
            {
                var name = techniqueRaw.Name;
                if (string.IsNullOrEmpty(name))
                    name = string.Format("${0}", techniqueIndex++);

                var technique = new EffectTechnique(this, name);
                Techniques.Add(technique);

                int passIndex = 0;
                foreach (var passRaw in techniqueRaw.Passes)
                {
                    name = passRaw.Name;
                    if (string.IsNullOrEmpty(name))
                        name = string.Format("${0}", passIndex++);

                    var pass = new EffectPass(logger, this, technique, passRaw, name);

                    pass.Initialize(logger);

                    // If this is a subpass, add it to the parent pass
                    if (passRaw.IsSubPass)
                    {
                        if (parentPass == null)
                        {
                            logger.Error("Pass [{0}] is declared as a subpass but has no parent.");
                        }
                        else
                        {
                            parentPass.SubPasses.Add(pass);
                        }
                    }
                    else
                    {
                        technique.Passes.Add(pass);
                        parentPass = pass;
                    }
                }

                // Count the number of passes
                totalPassCount += technique.Passes.Count;
            }

            if (totalPassCount == 0)
                throw new InvalidOperationException("No passes found in this effect.");

            // Log all the exception in a single throw
            if (logger.HasErrors)
                throw new InvalidOperationException(Utilities.Join("\n", logger.Messages));

            // Initialize the resource linker when we are done with all pass/parameters
            ResourceLinker.Initialize();

            //// Sort all parameters by their resource types
            //// in order to achieve better local cache coherency in resource linker
            Parameters.Items.Sort((left, right) =>
                {
                    // First, order first all value types, then resource type
                    var comparison = left.IsValueType != right.IsValueType ? left.IsValueType ? -1 : 1 : 0;

                    // If same type
                    if (comparison == 0)
                    {
                        // Order by resource type
                        comparison = ((int)left.ResourceType).CompareTo((int)right.ResourceType);

                        // If same, order by resource index
                        if (comparison == 0)
                        {
                            comparison = left.Offset.CompareTo(right.Offset);
                        }
                    }
                    return comparison;
                });

            // Prelink constant buffers
            int resourceIndex = 0;
            foreach (var parameter in Parameters)
            {
                // Recalculate parameter resource index
                if (!parameter.IsValueType)
                {
                    parameter.Offset = resourceIndex++;
                }

                // Set the default values 
                parameter.SetDefaultValue();

                if (parameter.ResourceType == EffectResourceType.ConstantBuffer)
                    parameter.SetResource(ConstantBuffers[parameter.Name]);
            }

            // Compute slot links
            foreach (var technique in Techniques)
            {
                foreach (var pass in technique.Passes)
                {
                    foreach (var subPass in pass.SubPasses)
                    {
                        subPass.ComputeSlotLinks();
                    }
                    pass.ComputeSlotLinks();
                }
            }

            // Setup the first Current Technique.
            CurrentTechnique = this.Techniques[0];

            // Initialize predefined parameters used by Model.Draw (to speedup things internally)
            DefaultParameters = new EffectDefaultParameters(this);

            // If this is a clone, we need to 
            if (cloneFromEffect != null)
            {
                // Copy the content of the constant buffers to the new instance.
                for (int i = 0; i < ConstantBuffers.Count; i++)
                {
                    cloneFromEffect.ConstantBuffers[i].CopyTo(ConstantBuffers[i]);
                }

                // Copy back all bound resources except constant buffers
                // that are already initialized with InitializeFrom method.
                for (int i = 0; i < cloneFromEffect.ResourceLinker.Count; i++)
                {
                    if (cloneFromEffect.ResourceLinker.BoundResources[i] is EffectConstantBuffer)
                        continue;

                    ResourceLinker.BoundResources[i] = cloneFromEffect.ResourceLinker.BoundResources[i];
                    unsafe
                    {
                        ResourceLinker.Pointers[i] = cloneFromEffect.ResourceLinker.Pointers[i];
                    }
                }

                // If everything was fine, then we can register it into the pool
                Pool.AddEffect(this);
            }

            // Allow subclasses to complete initialization.
            Initialize();
        }
Esempio n. 24
0
        internal EffectConstantBuffer GetOrCreateConstantBuffer(GraphicsDevice context, EffectData.ConstantBuffer bufferRaw)
        {
            EffectConstantBuffer constantBuffer;
            // Is the effect is using shared constant buffers via the EffectPool?
            if (ShareConstantBuffers)
            {
                // Use the pool to share constant buffers
                constantBuffer = Pool.GetOrCreateConstantBuffer(context, bufferRaw);
            }
            else
            {
                // ----------------------------------------------------------------------------
                // Get an existing constant buffer having the same name/sizel/ayout/parameters
                // ----------------------------------------------------------------------------
                var bufferKey = new EffectConstantBufferKey(bufferRaw);
                if (!effectConstantBuffersCache.TryGetValue(bufferKey, out constantBuffer))
                {
                    // 4) If this buffer doesn't exist, create a new one and register it.
                    constantBuffer = new EffectConstantBuffer(context, bufferRaw);
                    effectConstantBuffersCache.Add(bufferKey, constantBuffer);
                    DisposeCollector.Collect(constantBuffer);
                }
            }

            return constantBuffer;
        }
Esempio n. 25
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Effect" /> class with the specified bytecode effect. See remarks.
        /// </summary>
        /// <param name="device">The device.</param>
        /// <param name="effectData">The bytecode to add to the Effect Pool. This bytecode must contain only one effect.</param>
        /// <param name="effectPool">The effect pool used to register the bytecode. Default is <see cref="GraphicsDevice.DefaultEffectPool"/>.</param>
        /// <exception cref="ArgumentException">If the bytecode doesn't contain a single effect.</exception>
        /// <remarks>The effect bytecode must contain only a single effect and will be registered into the <see cref="GraphicsDevice.DefaultEffectPool"/>.</remarks>
        public Effect(GraphicsDevice device, EffectData effectData, EffectPool effectPool = null)
            : base(device)
        {
            CreateInstanceFrom(device, effectData, effectPool);

        }
Esempio n. 26
0
        /// <summary>
        /// Merges an existing <see cref="EffectData" /> into this instance.
        /// </summary>
        /// <param name="source">The EffectData to merge.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        /// <remarks>This method is useful to build an archive of several effects.</remarks>
        private EffectData.Effect RegisterInternal(EffectData source)
        {
            var effect = source.Description;

            var effectRuntime = new EffectData.Effect()
            {
                Name                 = effect.Name,
                Arguments            = effect.Arguments,
                ShareConstantBuffers = effect.ShareConstantBuffers,
                Techniques           = new List <EffectData.Technique>(effect.Techniques.Count)
            };

            Logger logger = null;

            foreach (var techniqueOriginal in effect.Techniques)
            {
                var technique = techniqueOriginal.Clone();
                effectRuntime.Techniques.Add(technique);

                foreach (var pass in technique.Passes)
                {
                    foreach (var shaderLink in pass.Pipeline)
                    {
                        // No shader set for this stage
                        if (shaderLink == null)
                        {
                            continue;
                        }

                        // If the shader is an import, we try first to resolve it directly
                        if (shaderLink.IsImport)
                        {
                            var index = FindShaderByName(shaderLink.ImportName);
                            if (index >= 0)
                            {
                                shaderLink.ImportName = null;
                                shaderLink.Index      = index;
                            }
                            else
                            {
                                if (logger == null)
                                {
                                    logger = new Logger();
                                }

                                logger.Error("Cannot find shader import by name [{0}]", shaderLink.ImportName);
                            }
                        }
                        else if (!shaderLink.IsNullShader)
                        {
                            var shader = source.Shaders[shaderLink.Index];

                            // Find a similar shader
                            var shaderIndex = FindSimilarShader(shader);

                            if (shaderIndex >= 0)
                            {
                                var previousShader = RegisteredShaders[shaderIndex];

                                // If the previous shader is
                                if (shader.Name != null)
                                {
                                    // if shader from this instance is local and shader from source is global => transform current shader to global
                                    if (previousShader.Name == null)
                                    {
                                        previousShader.Name = shader.Name;
                                    }
                                    else if (shader.Name != previousShader.Name)
                                    {
                                        if (logger == null)
                                        {
                                            logger = new Logger();
                                        }
                                        // If shader from this instance is global and shader from source is global => check names. If exported names are different, this is an error
                                        logger.Error("Cannot merge shader [{0}] into this instance, as there is already a global shader with a different name [{1}]", shader.Name, previousShader.Name);
                                    }
                                }

                                shaderLink.Index = shaderIndex;
                            }
                            else
                            {
                                shaderLink.Index = RegisteredShaders.Count;
                                RegisteredShaders.Add(shader);
                            }
                        }
                    }
                }
            }

            if (logger != null && logger.HasErrors)
            {
                throw new InvalidOperationException(Utilities.Join("\r\n", logger.Messages));
            }

            return(effectRuntime);
        }
Esempio n. 27
0
 /// <summary>
 /// Merges an existing <see cref="EffectData" /> into this instance.
 /// </summary>
 /// <param name="source">The EffectData to merge.</param>
 /// <param name="allowOverride">if set to <c>true</c> [allow override].</param>
 /// <exception cref="System.InvalidOperationException"></exception>
 /// <exception cref="InvalidOperationException">If the merge failed.</exception>
 /// <remarks>This method is useful to build an archive of several effects.</remarks>
 public void MergeFrom(EffectData source, bool allowOverride = false)
 {
     var logger = new Logger();
     if (!MergeFrom(source, logger, allowOverride))
         throw new InvalidOperationException(Utilities.Join("\r\n",logger.Messages));
 }
Esempio n. 28
0
        void Run(string[] args)
        {
            var assemblyUri  = new Uri(Assembly.GetEntryAssembly().CodeBase);
            var assemblyPath = Path.GetDirectoryName(assemblyUri.LocalPath);

            var newPath = Path.GetFullPath(Path.Combine(assemblyPath, @"..\Redist\D3D\" + (IntPtr.Size == 4 ? "x86" : "x64"))) + ";" + Environment.GetEnvironmentVariable("PATH");

            Environment.SetEnvironmentVariable("PATH", newPath);

            // Print the exe header
            PrintHeader();

            // Parse the command line
            if (!ParseCommandLine(args))
            {
                Environment.Exit(-1);
            }

            var options = this;

            // ----------------------------------------------------------------
            // Process macros
            // ----------------------------------------------------------------
            var macros = new List <EffectData.ShaderMacro>();

            foreach (var define in options.Defines)
            {
                var    nameValue = define.Split('=');
                string name      = nameValue[0];
                string value     = null;
                if (nameValue.Length > 1)
                {
                    value = nameValue[1];
                }
                macros.Add(new EffectData.ShaderMacro(name, value));
            }

            // ----------------------------------------------------------------
            // Setup compiler flags
            // ----------------------------------------------------------------
            var flags = EffectCompilerFlags.None;

            if (options.Debug)
            {
                flags |= EffectCompilerFlags.Debug;
            }

            switch (options.OptimizationLevel)
            {
            case 0:
                flags |= EffectCompilerFlags.OptimizationLevel0;
                break;

            case 1:
                flags |= EffectCompilerFlags.OptimizationLevel1;
                break;

            case 2:
                flags |= EffectCompilerFlags.OptimizationLevel2;
                break;

            case 3:
                flags |= EffectCompilerFlags.OptimizationLevel3;
                break;
            }

            if (options.PackRowMajor)
            {
                flags |= EffectCompilerFlags.PackMatrixRowMajor;
            }

            if (options.PackColumnMajor)
            {
                flags |= EffectCompilerFlags.PackMatrixColumnMajor;
            }

            if (options.AvoidFlowControl)
            {
                flags |= EffectCompilerFlags.AvoidFlowControl;
            }

            if (options.PreferFlowControl)
            {
                flags |= EffectCompilerFlags.PreferFlowControl;
            }

            if (options.EnableStrictness)
            {
                flags |= EffectCompilerFlags.EnableStrictness;
            }

            if (options.EnableBackwardsCompatibility)
            {
                flags |= EffectCompilerFlags.EnableBackwardsCompatibility;
            }

            if (options.IeeeStrictness)
            {
                flags |= EffectCompilerFlags.IeeeStrictness;
            }

            hasErrors = false;

            // ----------------------------------------------------------------
            // Process each fx files / tkfxo files
            // ----------------------------------------------------------------
            var fxFile   = options.FxFile;
            var filePath = Path.Combine(Environment.CurrentDirectory, fxFile);

            // Check that input file exists
            if (!File.Exists(filePath))
            {
                ErrorColor();
                Console.Error.WriteLine("File [{0}] does not exist", fxFile);
                ResetColor();
                Abort();
            }

            // ----------------------------------------------------------------
            // Pre check files
            // ----------------------------------------------------------------
            if (options.OutputClassFile == null && options.OutputFile == null)
            {
                options.OutputFile = Path.GetFileNameWithoutExtension(options.FxFile) + ".tkb";
            }

            // Check for output files
            bool outputFileExist = options.OutputClassFile != null && File.Exists(options.OutputClassFile);

            if (options.OutputFile != null && !File.Exists(options.OutputFile))
            {
                outputFileExist = false;
            }

            // New Compiler
            var compiler = new EffectCompiler();

            string outputDependencyDirPath  = Path.Combine(Environment.CurrentDirectory, OutputDependencyDirectory);
            string outputDependencyFilePath = Path.Combine(outputDependencyDirPath, compiler.GetDependencyFileNameFromSourcePath(options.FxFile));

            if (AllowDynamicCompiling)
            {
                CompileOnlyIfNewer = true;
            }

            if (CompileOnlyIfNewer)
            {
                if (!compiler.CheckForChanges(outputDependencyFilePath) && outputFileExist)
                {
                    Console.Error.WriteLine("Nothing to compile. Output file [{0}] is up-to-date", options.OutputFile);
                    Environment.Exit(0);
                }
            }

            var viewOnly = false;
            // Try to load this file as a precompiled file
            var effectData = EffectData.Load(fxFile);
            EffectCompilerResult compilerResult = null;

            if (effectData != null)
            {
                Console.WriteLine("Load Compiled File [{0}]", fxFile);
                viewOnly = true;
            }
            else
            {
                // Compile the fx file
                Console.WriteLine("Compile Effect File [{0}]", filePath);
                compilerResult = compiler.Compile(File.ReadAllText(filePath), filePath, flags, macros, options.IncludeDirs, AllowDynamicCompiling, CompileOnlyIfNewer ? outputDependencyFilePath : null);

                // If there is any warning, errors, turn Error color on
                if (compilerResult.Logger.Messages.Count > 0)
                {
                    ErrorColor();
                }

                // Show a message error for the current file
                if (compilerResult.HasErrors)
                {
                    Console.Error.WriteLine("Error when compiling file [{0}]:", fxFile);
                    hasErrors = true;
                }

                // Print all messages (warning and errors)
                foreach (var logMessage in compilerResult.Logger.Messages)
                {
                    Console.WriteLine(logMessage);
                }

                // If we have some messages, reset the color back
                if (compilerResult.Logger.Messages.Count > 0)
                {
                    ResetColor();
                }

                effectData = compilerResult.EffectData;
            }

            if (!NoDisassembly && effectData != null)
            {
                DumpBytecode(compiler, effectData);
            }

            if (hasErrors)
            {
                Abort();
            }

            if (!viewOnly)
            {
                Console.WriteLine();

                if (CompileOnlyIfNewer && compilerResult.DependencyFilePath != null)
                {
                    // Dependency file save to
                    Console.WriteLine("Save dependency list to [{0}]", outputDependencyFilePath);
                }

                if (OutputClassFile != null)
                {
                    var codeWriter = new EffectDataCodeWriter
                    {
                        Namespace = OutputNamespace,
                        ClassName = OutputClassname ?? Path.GetFileNameWithoutExtension(OutputClassFile),
                        FieldName = OutputFieldName,
                    };

                    Console.WriteLine("Save C# code output to [{0}]", OutputClassFile);
                    using (var stream = new NativeFileStream(OutputClassFile, NativeFileMode.Create, NativeFileAccess.Write, NativeFileShare.Write)) codeWriter.Write(effectData, new StreamWriter(stream, Encoding.UTF8));
                }

                if (options.OutputFile != null)
                {
                    Console.WriteLine("Save binary output to [{0}]", options.OutputFile);
                    // Save the result
                    effectData.Save(options.OutputFile);
                }
            }
        }
Esempio n. 29
0
 private bool CompareResourceParameter(EffectData.ResourceParameter left, EffectData.ResourceParameter right)
 {
     return (left.Class != right.Class || left.Type != right.Type || left.Count != right.Count);
 }
 public EffectToRebind(Effect effect, EffectData effectData)
 {
     Effect = effect;
     EffectData = effectData;
 }
 protected ViewerEffectBase(GraphicsDevice device, EffectData effectData)
     : base(device, effectData, null)
 {
 }
Esempio n. 32
0
        /// <summary>
        /// Merges an existing <see cref="EffectData" /> into this instance.
        /// </summary>
        /// <param name="source">The EffectData to merge.</param>
        /// <param name="logger">Logger used to report merging errors.</param>
        /// <param name="allowOverride">if set to <c>true</c> [allow override].</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        /// <remarks>This method is useful to build an archive of several effects.</remarks>
        public bool MergeFrom(EffectData source, Logger logger, bool allowOverride = false)
        {
            bool isMergeOk = true;

            foreach (var effect in source.Effects)
            {
                bool effectAlreadyRegistered = false;

                // Add effect that is not already in the archive with this same name.
                int previousEffectIndex = 0;
                for (; previousEffectIndex < Effects.Count; previousEffectIndex++)
                {
                    var effect2 = Effects[previousEffectIndex];
                    if (effect2.Name == effect.Name)
                    {
                        effectAlreadyRegistered = true;
                        break;
                    }
                }

                if (effectAlreadyRegistered)
                {
                    if (allowOverride)
                    {
                        Effects[previousEffectIndex] = effect;
                    }
                    else
                    {
                        // Skip the effect it it is already registered
                        continue;
                    }
                }
                else
                {
                    Effects.Add(effect);
                }

                foreach (var technique in effect.Techniques)
                {
                    foreach (var pass in technique.Passes)
                    {
                        foreach (var shaderLink in pass.Pipeline)
                        {
                            if (shaderLink == null)
                                continue;

                            if (shaderLink.IsImport)
                            {
                                // If this is an import, we try first to resolve it directly
                                // Else we keep the name as-is
                                var index = FindShaderByName(shaderLink.ImportName);
                                if (index >= 0)
                                {
                                    shaderLink.ImportName = null;
                                    shaderLink.Index = index;
                                }
                            }
                            else if (!shaderLink.IsNullShader)
                            {
                                var shader = source.Shaders[shaderLink.Index];
                                var index = FindShader(shader);
                                if (index >= 0)
                                {
                                    var previousShader = Shaders[index];

                                    if (shader.Name != null)
                                    {
                                        // if shader from this instance is local and shader from source is global => transform current shader to global
                                        if (previousShader.Name == null)
                                        {
                                            previousShader.Name = shader.Name;
                                        }
                                        else if (shader.Name != previousShader.Name)
                                        {
                                            // If shader from this instance is global and shader from source is global => check names. If exported names are different, this is an error
                                            logger.Error("Cannot merge shader [{0}] into this instance, as there is already a global shader with a different name [{1}]", shader.Name, previousShader.Name);
                                            isMergeOk = false;
                                        }
                                    }

                                    shaderLink.Index = index;
                                }
                                else
                                {
                                    shaderLink.Index = Shaders.Count;
                                    Shaders.Add(shader);
                                }
                            }
                        }
                    }
                }
            }

            return isMergeOk;
        }
Esempio n. 33
0
 public object ReadContent(IContentManager readerManager, ref ContentReaderParameters parameters)
 {
     parameters.KeepStreamOpen = false;
     return(EffectData.Load(parameters.Stream));
 }
Esempio n. 34
0
        /// <summary>
        ///   Initializes a new instance of the <see cref="EffectPass" /> class.
        /// </summary>
        /// <param name="logger">The logger used to log errors.</param>
        /// <param name="effect"> The effect. </param>
        /// <param name="pass"> The pass. </param>
        /// <param name="name"> The name. </param>
        internal EffectPass(Logger logger, Effect effect, EffectTechnique technique, EffectData.Pass pass, string name)
            : base(name)
        {
            this.Technique = technique;
            this.pass = pass;
            this.Effect = effect;
            this.graphicsDevice = effect.GraphicsDevice;
            pipeline = new PipelineBlock()
                           {
                               Stages = new StageBlock[EffectPass.StageCount],
                           };

            Attributes = PrepareAttributes(logger, pass.Attributes);
            IsSubPass = pass.IsSubPass;
            // Don't create SubPasses collection for subpass.
            if (!IsSubPass)
                SubPasses = new EffectPassCollection();
        }
Esempio n. 35
0
        /// <summary>
        /// Registers a EffectData to this pool.
        /// </summary>
        /// <param name="data">The effect data to register.</param>
        /// <returns>The effect description.</returns>
        public EffectData.Effect RegisterBytecode(EffectData data)
        {
            // Lock the whole EffectPool in case multiple threads would add EffectData at the same time.
            lock (sync)
            {
                EffectData.Effect effect;

                if (!registered.TryGetValue(data, out effect))
                {
                    // Pre-cache all input signatures
                    CacheInputSignature(data);

                    effect = RegisterInternal(data);
                    registered.Add(data, effect);

                    // Just allocate the compiled shaders array according to the current size of shader data
                    foreach (var compiledShaders in compiledShadersGroup)
                    {
                        for (int i = compiledShaders.Count; i < RegisteredShaders.Count; i++)
                        {
                            compiledShaders.Add(null);
                        }
                    }
                }

                return effect;
            }
        }
Esempio n. 36
0
        private bool ProcessBytecode(EffectData input, EffectData merged)
        {
            var hasErrors = false;
            if (!NoDisassembly)
                DumpBytecode(input);

            var logger = new Logger();
            merged.MergeFrom(input, logger);

            // If there is any errors from 
            if (logger.HasErrors)
            {
                hasErrors = true;
                ErrorColor();
                foreach (var message in logger.Messages)
                    Console.Error.WriteLine(message);
                ResetColor();
            }

            return hasErrors;
        }
Esempio n. 37
0
 private void CacheInputSignature(EffectData effectData)
 {
     // Iterate on all vertex shaders and make unique the bytecode
     // for faster comparison when creating input layout.
     foreach (var shader in effectData.Shaders)
     {
         if (shader.Type == EffectShaderType.Vertex && shader.InputSignature.Bytecode != null)
         {
             var inputSignature = graphicsDevice.GetOrCreateInputSignatureManager(shader.InputSignature.Bytecode, shader.InputSignature.Hashcode);
             shader.InputSignature.Bytecode = inputSignature.Bytecode;
         }
     }
 }
Esempio n. 38
0
        void Run(string[] args)
        {
            var assemblyUri = new Uri(Assembly.GetEntryAssembly().CodeBase);
            var assemblyPath = Path.GetDirectoryName(assemblyUri.LocalPath);

            var newPath = Path.GetFullPath(Path.Combine(assemblyPath, @"..\Redist\D3D\" + (IntPtr.Size == 4 ? "x86" : "x64"))) + ";" + Environment.GetEnvironmentVariable("PATH");
            Environment.SetEnvironmentVariable("PATH", newPath);

            // Print the exe header
            PrintHeader();

            // Parse the command line
            if (!ParseCommandLine(args))
                Environment.Exit(-1);

            var options = this;

            // ----------------------------------------------------------------
            // Process macros
            // ----------------------------------------------------------------
            var macros = new List<ShaderMacro>();
            foreach (var define in options.Defines)
            {
                var nameValue = define.Split('=');
                string name = nameValue[0];
                string value = null;
                if (nameValue.Length > 1)
                {
                    value = nameValue[1];
                }
                macros.Add(new ShaderMacro(name, value));
            }

            // ----------------------------------------------------------------
            // Setup compiler flags
            // ----------------------------------------------------------------
            var flags = EffectCompilerFlags.None;
            if (options.Debug)
                flags |= EffectCompilerFlags.Debug;

            switch (options.OptimizationLevel)
            {
                case 0:
                    flags |= EffectCompilerFlags.OptimizationLevel0;
                    break;
                case 1:
                    flags |= EffectCompilerFlags.OptimizationLevel1;
                    break;
                case 2:
                    flags |= EffectCompilerFlags.OptimizationLevel2;
                    break;
                case 3:
                    flags |= EffectCompilerFlags.OptimizationLevel3;
                    break;
            }

            if (options.PackRowMajor)
                flags |= EffectCompilerFlags.PackMatrixRowMajor;

            if (options.PackColumnMajor)
                flags |= EffectCompilerFlags.PackMatrixColumnMajor;

            var archiveBytecode = new EffectData();
            bool hasErrors = false;
            bool isFileUpToDate = CompileOnlyIfNewer;

            // ----------------------------------------------------------------
            // Pre check files
            // ----------------------------------------------------------------
            var outputTime = new DateTime();
            var outputFileName = OutputClassFile ?? OutputFile;
            if (!ViewOnly && CompileOnlyIfNewer)
            {
                if (OutputClassFile != null)
                {
                    if (File.Exists(OutputClassFile))
                        outputTime = File.GetLastWriteTime(OutputClassFile);
                }
                else if (OutputFile != null)
                {
                    if (File.Exists(OutputFile))
                        outputTime = File.GetLastWriteTime(OutputFile);
                }
                else
                {
                    ErrorColor();
                    Console.WriteLine("Missing /Fo OutputFile or /Fc OutputClassFile");
                    ResetColor();
                    Environment.Exit(-1);
                }


                // If the assembly is more recent than the ouput file, then regenerate it
                var assemblyTime = File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location);
                if (assemblyTime > outputTime)
                {
                    isFileUpToDate = false;
                }
                else
                {
                    // Else check that all files are not more recent.
                    foreach (var fxFile in options.FxFiles)
                    {
                        var filePath = Path.Combine(Environment.CurrentDirectory, fxFile);

                        if (!File.Exists(filePath))
                        {
                            isFileUpToDate = false;
                            break;
                        }

                        if (File.GetLastWriteTime(filePath) > outputTime)
                        {
                            isFileUpToDate = false;
                            break;
                        }
                    }
                }            
            }

            if (!ViewOnly && isFileUpToDate)
            {
                Console.WriteLine("Nothing to compile, output file is up to date [{0}]", outputFileName);
                Environment.Exit(0);
            }

            // ----------------------------------------------------------------
            // Process each fx files / tkfxo files
            // ----------------------------------------------------------------
            foreach (var fxFile in options.FxFiles)
            {
                var filePath = Path.Combine(Environment.CurrentDirectory, fxFile);

                if (!File.Exists(filePath))
                {
                    ErrorColor();
                    Console.Error.WriteLine("File [{0}] does not exist", fxFile);
                    ResetColor();
                    hasErrors = true;
                    continue;
                }

                EffectData effectData = null;

                // Try to load this file as a precompiled file
                effectData = EffectData.Load(fxFile);
                if (effectData != null)
                {
                    Console.WriteLine("Load Compiled File [{0}]", fxFile);                    
                }
                else
                {
                    // Compile the fx file
                    Console.WriteLine("Compile Effect File [{0}]", filePath);
                    var effectBytecode = EffectCompiler.Compile(File.ReadAllText(filePath), filePath, flags, macros, options.IncludeDirs);

                    // If there is any warning, errors, turn Error color on
                    if (effectBytecode.Logger.Messages.Count > 0)
                    {
                        ErrorColor();
                    }

                    // Show a message error for the current file
                    if (effectBytecode.HasErrors)
                    {
                        Console.Error.WriteLine("Error when compiling file [{0}]:", fxFile);
                        hasErrors = true;
                    }

                    // Print all messages (warning and errors)
                    foreach (var logMessage in effectBytecode.Logger.Messages)
                    {
                        Console.WriteLine(logMessage);
                    }

                    // If we have some messages, reset the color back
                    if (effectBytecode.Logger.Messages.Count > 0)
                    {
                        ResetColor();
                    }

                    effectData = effectBytecode.EffectData;
                }

                // If there is no errors, merge the result to the final archive
                if (!hasErrors)
                {
                    if (ProcessBytecode(effectData, archiveBytecode))
                        hasErrors = true;
                }
            }

            if (hasErrors)
            {
                ErrorColor();
                Console.Error.WriteLine("Compilation has errors. Process aborted.");
                ResetColor();
                Environment.Exit(-1);
            }
            else if (!ViewOnly)
            {
                Console.WriteLine();

                if (OutputClassFile != null)
                {
                    var codeWriter = new EffectDataCodeWriter
                                         {
                                             Namespace = OutputNamespace, 
                                             ClassName = OutputClassname ?? Path.GetFileNameWithoutExtension(OutputClassFile),
                                             FieldName = OutputFieldName,
                                         };

                    Console.WriteLine("Save C# code output to [{0}]", OutputClassFile);
                    using (var stream = new NativeFileStream(OutputClassFile, NativeFileMode.Create, NativeFileAccess.Write, NativeFileShare.Write))
                        codeWriter.Write(archiveBytecode, new StreamWriter(stream, Encoding.UTF8));
                }
                else
                {
                    Console.WriteLine("Save output to [{0}]", options.OutputFile);
                    // Save the result
                    archiveBytecode.Save(options.OutputFile);
                }
            }
        }
Esempio n. 39
0
 public object ReadContent(IContentManager readerManager, string assetName, Stream stream, out bool keepStreamOpen, object options)
 {
     keepStreamOpen = false;
     return(EffectData.Load(stream));
 }