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(); } }