Example #1
0
        private void UpdateCompositionNodes <T>(ShaderClassType shader, ComputeShaderClassBase <T> node, IObjectNode ownerNode)
            where T : class, IComputeNode
        {
            var keysToRemove         = new List <object>(node.CompositionNodes.Keys);
            var compositionNodesNode = ownerNode[nameof(ComputeShaderClassBase <T> .CompositionNodes)].Target;

            if (shader != null)
            {
                // TODO: is it enough detect compositions?
                foreach (var member in shader.Members.OfType <Variable>().Where(x => x.Type is TypeName && x.Type.TypeInference?.TargetType == null))
                {
                    // ComputeColor only
                    if (member.Type.Name.Text == "ComputeColor")
                    {
                        var index = new Index(member.Name.Text);
                        if (compositionNodesNode.Indices.Any(x => Equals(x, index)))
                        {
                            // This composition node already exists, keep it in the list
                            keysToRemove.Remove(member.Name.Text);
                        }
                        else
                        {
                            // This is a new composition node, add it
                            compositionNodesNode.Add(null, index);
                        }
                    }
                }
            }

            // Remove all composition nodes that we don't have anymore
            keysToRemove.Select(x => new Index(x)).ForEach(x => compositionNodesNode.Remove(compositionNodesNode.Retrieve(x), x));
        }
        public static ShaderClassType ParseReferencedShader <T>(this ComputeShaderClassBase <T> node, IDictionary <string, string> projectShaders)
            where T : class, IComputeNode
        {
            ShaderClassType shader = null;

            string source;

            if (projectShaders.TryGetValue(node.MixinReference, out source))
            {
                var logger = new LoggerResult();
                try
                {
                    shader = ShaderLoader.ParseSource(source, logger);
                    if (logger.HasErrors)
                    {
                        return(null);
                    }
                }
                catch
                {
                    // TODO: output messages
                    return(null);
                }
            }

            return(shader);
        }
Example #3
0
        private void UpdateNode<T>(ComputeShaderClassBase<T> node, IObjectNode ownerNode) where T : class, IComputeNode
        {
            var projectShaders = new Dictionary<string, string>();
            foreach (var asset in Directory.Package.AllAssets.Where(x => x.Asset is EffectShaderAsset))
            {
                // TODO: we don't detect collision of name here
                projectShaders[asset.Name] = ((EffectShaderAsset)asset.Asset).Text;
            }

            var shader = node.ParseReferencedShader(projectShaders);

            // Process generics
            UpdateGenerics(shader, node, ownerNode);

            // Process composition nodes
            UpdateCompositionNodes(shader, node, ownerNode);
        }
Example #4
0
        private void UpdateGenerics<T>(ShaderClassType shader, ComputeShaderClassBase<T> node, IObjectNode ownerNode)
            where T : class, IComputeNode
        {
            var genericsNode = ownerNode[nameof(ComputeShaderClassBase<T>.Generics)].Target;
            var keysToRemove = new List<string>(node.Generics.Keys);
            if (shader != null)
            {
                foreach (var generic in shader.ShaderGenerics)
                {
                    var parameterType = ComputeShaderClassHelper.GetComputeColorParameterType(generic.Type.Name.Text);
                    if (parameterType == null)
                        continue;

                    var index = new NodeIndex(generic.Name.Text);
                    if (genericsNode.Indices.Any(x => Equals(x, index)))
                    {
                        var value = genericsNode.Retrieve(index);
                        if (parameterType.IsInstanceOfType(value))
                        {
                            // This generic already exists and has the correct type, keep it in the list
                            keysToRemove.Remove(generic.Name);
                        }
                        else
                        {
                            // This generic already exists but has a different type. Just update the value.
                            var parameter = Activator.CreateInstance(parameterType);
                            genericsNode.Add(parameter, index);
                        }
                    }
                    else
                    {
                        // This is a new generic, add it
                        var parameter = Activator.CreateInstance(parameterType);
                        genericsNode.Add(parameter, index);
                    }
                }
            }

            // Remove all generics that we don't have anymore
            foreach (var k in keysToRemove)
            {
                var x = new NodeIndex(k);
                genericsNode.Remove(genericsNode.Retrieve(x), x);
            }
        }
        /// <summary>
        /// Load the shader and extract the information.
        /// </summary>
        public static void PrepareNode <T>(this ComputeShaderClassBase <T> _this, ConcurrentDictionary <string, string> projectShaders) where T : class, IComputeNode
        {
            // TODO: merge common keys between the previous dictionaries and the new one
            _this.Generics.Clear();
            _this.CompositionNodes.Clear();

            if (string.IsNullOrEmpty(_this.MixinReference))
            {
                return;
            }

            var newGenerics         = new ComputeColorParameters();
            var newCompositionNodes = new Dictionary <string, T>();
            var newMembers          = new Dictionary <ParameterKey, object>();

            var             localMixinName = _this.MixinReference;
            ShaderClassType shader         = null;

            string source;

            if (projectShaders.TryGetValue(localMixinName, out source))
            {
                var logger = new LoggerResult();
                try
                {
                    shader = ShaderLoader.ParseSource(source, logger);
                    if (logger.HasErrors)
                    {
                        logger.Messages.Clear();
                        return;
                    }
                }
                catch
                {
                    // TODO: output messages
                    return;
                }
            }

            if (shader == null)
            {
                return;
            }

            var acceptLinkedVariable = true;

            foreach (var generic in shader.ShaderGenerics)
            {
                if (generic.Type.Name.Text == "float4")
                {
                    _this.AddKey <Vector4>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "float3")
                {
                    _this.AddKey <Vector3>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "float2")
                {
                    _this.AddKey <Vector2>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "float")
                {
                    _this.AddKey <float>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "int")
                {
                    _this.AddKey <int>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "Texture2D")
                {
                    _this.AddKey <Graphics.Texture>(generic.Name.Text, newGenerics);
                }
                else if (generic.Type.Name.Text == "SamplerState")
                {
                    _this.AddKey <SamplerState>(generic.Name.Text, newGenerics);
                }
                else
                {
                    _this.AddKey <string>(generic.Name.Text, newGenerics);
                }

                if (generic.Type is LinkType)
                {
                    acceptLinkedVariable = false; // since the behavior is unpredictable, safely prevent addition of linked variable (= with Link annotation)
                }
            }

            foreach (var member in shader.Members.OfType <Variable>())
            {
                // TODO: enough detect compositions?
                if (member.Type is TypeName && (member.Type.TypeInference == null || member.Type.TypeInference.TargetType == null))
                {
                    // ComputeColor only
                    if (member.Type.Name.Text == "ComputeColor")
                    {
                        if (_this.CompositionNodes.ContainsKey(member.Name.Text))
                        {
                            newCompositionNodes.Add(member.Name.Text, _this.CompositionNodes[member.Name.Text]);
                        }
                        else
                        {
                            newCompositionNodes.Add(member.Name.Text, null);
                        }
                    }
                }
                else
                {
                    var    isColor  = false;
                    string linkName = null;
                    var    isStage  = member.Qualifiers.Contains(ParadoxStorageQualifier.Stage);
                    var    isStream = member.Qualifiers.Contains(ParadoxStorageQualifier.Stream);
                    foreach (var annotation in member.Attributes.OfType <SiliconStudio.Shaders.Ast.Hlsl.AttributeDeclaration>())
                    {
                        if (annotation.Name == "Color")
                        {
                            isColor = true;
                        }
                        if (acceptLinkedVariable && annotation.Name == "Link" && annotation.Parameters.Count > 0)
                        {
                            linkName = (string)annotation.Parameters[0].Value;
                        }
                    }

                    if (!isStream && (isStage || !string.IsNullOrEmpty(linkName)))
                    {
                        if (linkName == null)
                        {
                            linkName = localMixinName + "." + member.Name.Text;
                        }

                        var memberType = member.Type.ResolveType();
                        if (isColor)
                        {
                            _this.AddMember <Color4>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Float || memberType == ScalarType.Half)
                        {
                            _this.AddMember <float>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Double)
                        {
                            _this.AddMember <double>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Int)
                        {
                            _this.AddMember <int>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.UInt)
                        {
                            _this.AddMember <uint>(linkName, newMembers);
                        }
                        else if (memberType == ScalarType.Bool)
                        {
                            _this.AddMember <bool>(linkName, newMembers);
                        }
                        else if (memberType is VectorType)
                        {
                            switch (((VectorType)memberType).Dimension)
                            {
                            case 2:
                                _this.AddMember <Vector2>(linkName, newMembers);
                                break;

                            case 3:
                                _this.AddMember <Vector3>(linkName, newMembers);
                                break;

                            case 4:
                                _this.AddMember <Vector4>(linkName, newMembers);
                                break;
                            }
                        }
                        else if (member.Type.Name.Text == "Texture2D")
                        {
                            _this.AddMember <Graphics.Texture>(linkName, newMembers);
                        }
                        else if (member.Type.Name.Text == "SamplerState")
                        {
                            _this.AddMember <Graphics.SamplerState>(linkName, newMembers);
                        }
                    }
                }
            }

            _this.Generics         = newGenerics;
            _this.CompositionNodes = newCompositionNodes;
            _this.Members          = newMembers;
        }