예제 #1
0
 public NodeCompiler(RegisterState registers)
 {
     _registers                    = registers;
     _nodeGrouper                  = new NodeGrouper(registers);
     _constantCompiler             = new ConstantCompiler(_nodeGrouper);
     _matrixMultiplicationCompiler = new MatrixMultiplicationCompiler(this);
 }
예제 #2
0
        public void ReduceTree(NodeGrouper nodeGrouper)
        {
            var templateMatcher = new TemplateMatcher(nodeGrouper);

            Roots = Roots.ToDictionary(r => r.Key,
                                       r => templateMatcher.Reduce(r.Value));
            NoOutputInstructions = NoOutputInstructions.ToDictionary(r => r.Key,
                                                                     r => templateMatcher.Reduce(r.Value));
        }
예제 #3
0
        public HlslTreeNode[] TryGetContext(IList <HlslTreeNode> components)
        {
            var firstComponent = components[0];

            if (!(firstComponent is DivisionOperation firstDivision))
            {
                return(null);
            }

            var firstLengthContext = _nodeGrouper.LengthGrouper.TryGetLengthContext(firstDivision.Divisor);

            if (firstLengthContext == null)
            {
                return(null);
            }

            int dimension = firstLengthContext.Length;

            if (firstLengthContext.Any(c => NodeGrouper.AreNodesEquivalent(firstDivision.Dividend, c)) == false)
            {
                return(null);
            }

            for (int i = 1; i < dimension; i++)
            {
                if (i >= components.Count)
                {
                    return(null);
                }

                var nextComponent = components[i];
                if (!(nextComponent is DivisionOperation nextDivision))
                {
                    return(null);
                }

                if (NodeGrouper.AreNodesEquivalent(nextDivision.Divisor, firstDivision.Divisor) == false)
                {
                    return(null);
                }

                if (firstLengthContext.Any(c => NodeGrouper.AreNodesEquivalent(nextDivision.Dividend, c)) == false)
                {
                    return(null);
                }
            }

            return(components
                   .Take(dimension)
                   .Cast <DivisionOperation>()
                   .Select(c => c.Dividend)
                   .ToArray());
        }
예제 #4
0
        public string Compile(ConstantNode[] group)
        {
            ConstantNode first = group[0];

            int count = group.Length;

            if (count == 1)
            {
                return(CompileConstant(first));
            }

            if (group.All(c => NodeGrouper.AreNodesEquivalent(c, first)))
            {
                return(CompileConstant(first));
            }

            string components = string.Join(", ", group.Select(CompileConstant));

            return($"float{count}({components})");
        }
        public HlslTreeNode[] TryGetContext(IList <HlslTreeNode> components)
        {
            var firstComponent = components[0];

            if (!(firstComponent is DivisionOperation firstDivision) ||
                !(firstDivision.Divisor is LengthOperation firstLength))
            {
                return(null);
            }

            if (!firstLength.X.Inputs.Any(c => NodeGrouper.AreNodesEquivalent(firstDivision.Dividend, c)))
            {
                return(null);
            }

            int normalizeComponentCount = 1;

            for (int i = 1; i < components.Count; i++)
            {
                if (IsNormalizeGroupComponent(components[i], firstDivision, firstLength))
                {
                    normalizeComponentCount++;
                }
                else
                {
                    break;
                }
            }

            if (normalizeComponentCount < 2)
            {
                return(null);
            }

            return(components
                   .Take(normalizeComponentCount)
                   .Cast <DivisionOperation>()
                   .Select(c => c.Dividend)
                   .ToArray());
        }
예제 #6
0
 public NormalizeGrouper(NodeGrouper nodeGrouper)
 {
     _nodeGrouper = nodeGrouper;
 }
 private static bool IsNormalizeGroupComponent(HlslTreeNode nextComponent, DivisionOperation firstDivision, LengthOperation firstLength)
 {
     return(nextComponent is DivisionOperation nextDivision &&
            NodeGrouper.AreNodesEquivalent(nextDivision.Divisor, firstDivision.Divisor) &&
            firstLength.X.Inputs.Any(c => NodeGrouper.AreNodesEquivalent(nextDivision.Dividend, c)));
 }
        public MatrixMultiplicationContext TryGetMultiplicationGroup(IList <HlslTreeNode> components)
        {
            const bool allowMatrix = true;

            var first = components[0];
            var firstDotProductNode = _nodeGrouper.DotProductGrouper.TryGetDotProductGroup(first, allowMatrix);

            if (firstDotProductNode == null)
            {
                return(null);
            }

            int dimension = firstDotProductNode.Dimension;

            if (components.Count < dimension)
            {
                return(null);
            }

            HlslTreeNode[] firstMatrixRow = TryGetMatrixRow(firstDotProductNode);
            if (firstMatrixRow == null)
            {
                return(null);
            }

            HlslTreeNode[] vector = firstDotProductNode.Value1 == firstMatrixRow
                    ? firstDotProductNode.Value2
                    : firstDotProductNode.Value1;

            var matrixRows = new HlslTreeNode[dimension][];

            matrixRows[0] = firstMatrixRow;
            for (int i = 1; i < dimension; i++)
            {
                var next           = components[i];
                var dotProductNode = _nodeGrouper.DotProductGrouper.TryGetDotProductGroup(next, dimension, allowMatrix);
                if (dotProductNode == null)
                {
                    return(null);
                }

                HlslTreeNode[] matrixRow = TryGetMatrixRow(dotProductNode);
                if (matrixRow == null)
                {
                    return(null);
                }
                matrixRows[i] = matrixRow;

                HlslTreeNode[] nextVector = dotProductNode.Value1 == matrixRow
                    ? dotProductNode.Value2
                    : dotProductNode.Value1;
                if (NodeGrouper.IsVectorEquivalent(vector, nextVector) == false)
                {
                    return(null);
                }
            }

            ConstantDeclaration matrix = TryGetMatrixDeclaration(matrixRows);

            if (matrix == null)
            {
                return(null);
            }

            bool matrixByVector = firstMatrixRow
                                  .Cast <RegisterInputNode>()
                                  .All(row => row.ComponentIndex == 0);

            SwizzleVector(vector, firstMatrixRow, matrixByVector);

            return(new MatrixMultiplicationContext(vector, matrix, matrixByVector));
        }
 public MatrixMultiplicationGrouper(NodeGrouper nodeGrouper, RegisterState registers)
 {
     _nodeGrouper = nodeGrouper;
     _registers   = registers;
 }
예제 #10
0
 public ConstantCompiler(NodeGrouper nodeGrouper)
 {
     _nodeGrouper = nodeGrouper;
 }
        // Vector by matrix multiplication has a pattern of:
        // float2(dot(m_row1, v), dot(m_row2, v))
        // float3(dot(m_row1, v), dot(m_row2, v), dot(m_row3, v))
        // float4(dot(m_row1, v), dot(m_row2, v), dot(m_row3, v), dot(m_row4, v))
        public MatrixMultiplicationContext TryGetMultiplicationGroup(IList <HlslTreeNode> components)
        {
            const bool allowMatrix = true;

            if (!(components[0] is DotProductOperation firstDot))
            {
                return(null);
            }

            int dimension = firstDot.X.Length;

            if (components.Count < dimension)
            {
                return(null);
            }

            GroupNode firstMatrixRow = TryGetMatrixRow(firstDot, firstDot, 0);

            if (firstMatrixRow == null)
            {
                return(null);
            }

            GroupNode vector = firstDot.X == firstMatrixRow
                    ? firstDot.Y
                    : firstDot.X;

            var matrixRows = new List <GroupNode>();

            matrixRows.Add(firstMatrixRow);
            for (int i = 1; i < components.Count; i++)
            {
                if (!(components[i] is DotProductOperation nextDot))
                {
                    break;
                }

                GroupNode matrixRow = TryGetMatrixRow(nextDot, firstDot, i);
                if (matrixRow == null)
                {
                    break;
                }

                GroupNode nextVector = nextDot.X == matrixRow
                    ? nextDot.Y
                    : nextDot.X;
                if (!NodeGrouper.AreNodesEquivalent(vector, nextVector))
                {
                    break;
                }

                matrixRows.Add(matrixRow);
            }

            if (matrixRows.Count < 2)
            {
                return(null);
            }

            ConstantDeclaration matrix = TryGetMatrixDeclaration(matrixRows);

            if (matrix == null)
            {
                return(null);
            }

            bool matrixByVector = firstMatrixRow.Inputs
                                  .Cast <RegisterInputNode>()
                                  .All(row => row.ComponentIndex == 0);

            vector = SwizzleVector(vector, firstMatrixRow, matrixByVector);

            return(new MatrixMultiplicationContext(vector, matrix, matrixByVector, matrixRows.Count));
        }
예제 #12
0
 public DotProductGrouper(NodeGrouper nodeGrouper)
 {
     _nodeGrouper = nodeGrouper;
 }