Example #1
0
        public override HlslTreeNode Reduce()
        {
            switch (Operation)
            {
            case Opcode.Add:
            {
                var addend1   = Children[0].Reduce();
                var addend2   = Children[1].Reduce();
                var constant1 = addend1 as HlslConstant;
                var constant2 = addend2 as HlslConstant;
                if (constant1 != null)
                {
                    float value1 = constant1.Value;
                    if (value1 == 0)
                    {
                        Replace(addend2);
                        return(addend2);
                    }
                    if (constant2 != null)
                    {
                        return(new HlslConstant(value1 + constant2.Value));
                    }
                }
                if (constant2 != null)
                {
                    float value2 = constant2.Value;
                    if (value2 == 0)
                    {
                        return(addend1);
                    }
                    if (value2 < 0)
                    {
                        var sub = new HlslOperation(Opcode.Sub);
                        sub.AddChild(addend1);
                        sub.AddChild(new HlslConstant(-value2));
                        Replace(sub);
                        return(sub);
                    }
                }
                if (addend1 == addend2)
                {
                    var mul = new HlslOperation(Opcode.Mul);
                    mul.AddChild(new HlslConstant(2));
                    mul.AddChild(addend1);
                    Replace(mul);
                    return(mul);
                }
                break;
            }

            case Opcode.Mad:
            {
                var mul2 = new HlslOperation(Opcode.Mul);
                mul2.AddChild(Children[0]);
                mul2.AddChild(Children[1]);
                Children[0].Parents.Remove(this);
                Children[1].Parents.Remove(this);

                var add = new HlslOperation(Opcode.Add);
                add.AddChild(mul2);
                add.AddChild(Children[2]);
                Replace(add);

                return(add.Reduce());
            }

            case Opcode.Mov:
            {
                return(Children[0].Reduce());
            }

            case Opcode.Mul:
            {
                var multiplicand1 = Children[0].Reduce();
                var multiplicand2 = Children[1].Reduce();
                var constant1     = multiplicand1 as HlslConstant;
                var constant2     = multiplicand2 as HlslConstant;
                if (constant1 != null)
                {
                    float value1 = constant1.Value;
                    if (value1 == 0)
                    {
                        Replace(multiplicand1);
                        return(multiplicand1);
                    }
                    if (value1 == 1)
                    {
                        Replace(multiplicand2);
                        return(multiplicand2);
                    }
                    if (constant2 != null)
                    {
                        return(new HlslConstant(value1 * constant2.Value));
                    }
                }
                if (constant2 != null)
                {
                    float value2 = constant2.Value;
                    if (value2 == 0)
                    {
                        Replace(multiplicand2);
                        return(multiplicand2);
                    }
                    if (value2 == 1)
                    {
                        Replace(multiplicand1);
                        return(multiplicand1);
                    }
                }
                break;
            }
            }
            return(base.Reduce());
        }
        private HlslTreeNode CreateInstructionTree(Instruction instruction, RegisterKey destinationKey)
        {
            int componentIndex = destinationKey.ComponentIndex;

            switch (instruction.Opcode)
            {
            case Opcode.Dcl:
            {
                var shaderInput = new HlslShaderInput()
                {
                    InputDecl      = destinationKey,
                    ComponentIndex = componentIndex
                };
                return(shaderInput);
            }

            case Opcode.Def:
            {
                var constant = new HlslConstant(instruction.GetParamSingle(componentIndex + 1));
                return(constant);
            }

            case Opcode.Abs:
            case Opcode.Add:
            case Opcode.Mad:
            case Opcode.Mov:
            case Opcode.Mul:
            {
                int numInputs;
                switch (instruction.Opcode)
                {
                case Opcode.Abs:
                case Opcode.Mov:
                    numInputs = 1;
                    break;

                case Opcode.Add:
                case Opcode.Mul:
                    numInputs = 2;
                    break;

                case Opcode.Mad:
                    numInputs = 3;
                    break;

                default:
                    throw new NotImplementedException();
                }
                var operation = new HlslOperation(instruction.Opcode);
                for (int j = 0; j < numInputs; j++)
                {
                    var modifier = instruction.GetSourceModifier(j + 1);
                    if (modifier != SourceModifier.None)
                    {
                        // TODO
                    }
                    var inputKey = GetParamRegisterKey(instruction, j + 1, componentIndex);
                    var input    = _activeOutputs[inputKey];
                    operation.AddChild(input);
                }

                return(operation);
            }

            default:
                throw new NotImplementedException();
            }
        }