private HlslTreeNode[] TryGetMatrixRow(DotProductContext firstDotProductNode)
        {
            if (firstDotProductNode.Value1[0] is RegisterInputNode value1)
            {
                ConstantDeclaration constant = _registers.FindConstant(value1);
                if (constant != null && constant.Rows > 1)
                {
                    return(firstDotProductNode.Value1);
                }
            }

            if (firstDotProductNode.Value2[0] is RegisterInputNode value2)
            {
                ConstantDeclaration constant = _registers.FindConstant(value2);
                if (constant != null && constant.Rows > 1)
                {
                    return(firstDotProductNode.Value2);
                }
            }

            return(null);
        }
        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 string GetRegisterName(RegisterKey registerKey)
        {
            var decl = _registerDeclarations[registerKey];

            switch (registerKey.Type)
            {
            case RegisterType.Texture:
                return(decl.Name);

            case RegisterType.Input:
                return((MethodInputRegisters.Count == 1) ? decl.Name : ("i." + decl.Name));

            case RegisterType.RastOut:
            case RegisterType.Output:
            case RegisterType.AttrOut:
            case RegisterType.ColorOut:
                return((MethodOutputRegisters.Count == 1) ? decl.Name : ("o." + decl.Name));

            case RegisterType.Const:
                var constDecl = FindConstant(ParameterType.Float, registerKey.Number);
                if (ColumnMajorOrder)
                {
                    if (constDecl.Rows == 1)
                    {
                        return(constDecl.Name);
                    }
                    string col = (registerKey.Number - constDecl.RegisterIndex).ToString();
                    return($"transpose({constDecl.Name})[{col}]");
                }
                if (constDecl.Rows == 1)
                {
                    return(constDecl.Name);
                }
                string row = (registerKey.Number - constDecl.RegisterIndex).ToString();
                return(constDecl.Name + $"[{row}]");

            case RegisterType.Sampler:
                ConstantDeclaration samplerDecl = FindConstant(RegisterSet.Sampler, registerKey.Number);
                if (samplerDecl != null)
                {
                    return(samplerDecl.Name);
                }
                else
                {
                    throw new NotImplementedException();
                }

            case RegisterType.MiscType:
                switch (registerKey.Number)
                {
                case 0:
                    return("vFace");

                case 1:
                    return("vPos");

                default:
                    throw new NotImplementedException();
                }

            case RegisterType.Temp:
                return(registerKey.ToString());

            default:
                throw new NotImplementedException();
            }
        }
        public string GetSourceName(Token instruction, int srcIndex)
        {
            string      sourceRegisterName;
            RegisterKey registerKey  = instruction.GetParamRegisterKey(srcIndex);
            var         registerType = instruction.GetParamRegisterType(srcIndex);

            switch (registerType)
            {
            case RegisterType.Const:
            case RegisterType.Const2:
            case RegisterType.Const3:
            case RegisterType.Const4:
            case RegisterType.ConstBool:
            case RegisterType.ConstInt:
                sourceRegisterName = GetSourceConstantName(instruction, srcIndex);
                if (sourceRegisterName != null)
                {
                    return(sourceRegisterName);
                }

                ParameterType parameterType;
                switch (registerType)
                {
                case RegisterType.Const:
                case RegisterType.Const2:
                case RegisterType.Const3:
                case RegisterType.Const4:
                    parameterType = ParameterType.Float;
                    break;

                case RegisterType.ConstBool:
                    parameterType = ParameterType.Bool;
                    break;

                case RegisterType.ConstInt:
                    parameterType = ParameterType.Int;
                    break;

                default:
                    throw new NotImplementedException();
                }
                int registerNumber       = instruction.GetParamRegisterNumber(srcIndex);
                ConstantDeclaration decl = FindConstant(registerNumber);
                if (decl == null)
                {
                    // Constant register not found in def statements nor the constant table
                    throw new NotImplementedException();
                }

                if (decl.ParameterClass == ParameterClass.MatrixRows)
                {
                    sourceRegisterName = string.Format("{0}[{1}]", decl.Name, registerNumber - decl.RegisterIndex);
                }
                else
                {
                    sourceRegisterName = decl.Name;
                }
                break;

            default:
                sourceRegisterName = GetRegisterName(registerKey);
                break;
            }

            sourceRegisterName = sourceRegisterName ?? instruction.GetParamRegisterName(srcIndex);

            sourceRegisterName += instruction.GetSourceSwizzleName(srcIndex, true);
            return(ApplyModifier(instruction.GetSourceModifier(srcIndex), sourceRegisterName));
        }