private void WriteAst(HlslAst ast) { var compiler = new NodeCompiler(_registers); var rootGroups = ast.Roots.GroupBy(r => r.Key.RegisterKey); if (_registers.MethodOutputRegisters.Count == 1) { var rootGroup = rootGroups.Single(); var registerKey = rootGroup.Key; var roots = rootGroup.OrderBy(r => r.Key.ComponentIndex).Select(r => r.Value).ToList(); string statement = compiler.Compile(roots, 4); WriteLine($"return {statement};"); } else { foreach (var rootGroup in rootGroups) { var registerKey = rootGroup.Key; var roots = rootGroup.OrderBy(r => r.Key.ComponentIndex).Select(r => r.Value).ToList(); RegisterDeclaration outputRegister = _registers.MethodOutputRegisters[registerKey]; string statement = compiler.Compile(roots, roots.Count); WriteLine($"o.{outputRegister.Name} = {statement};"); } WriteLine(); WriteLine($"return o;"); } }
private void WriteAst(HlslAst ast) { var compiler = new NodeCompiler(_registers); foreach (var rootGroup in ast.NoOutputInstructions) { string statement = compiler.Compile(rootGroup.Value); WriteLine($"{statement};"); } if (ast.Roots.Count == 1) { string statement = compiler.Compile(ast.Roots.Single().Value); WriteLine($"return {statement};"); } else { foreach (var rootGroup in ast.Roots) { RegisterDeclaration outputRegister = _registers.MethodOutputRegisters[rootGroup.Key]; string statement = compiler.Compile(rootGroup.Value); WriteLine($"o.{outputRegister.Name} = {statement};"); } WriteLine(); WriteLine($"return o;"); } }
public void Write(string hlslFilename) { hlslFile = new FileStream(hlslFilename, FileMode.Create, FileAccess.Write); hlslWriter = new StreamWriter(hlslFile); _registers = new RegisterState(_shader); WriteConstantDeclarations(); if (_registers.MethodInputRegisters.Count > 1) { WriteInputStructureDeclaration(); } if (_registers.MethodOutputRegisters.Count > 1) { WriteOutputStructureDeclaration(); } string methodReturnType = GetMethodReturnType(); string methodParameters = GetMethodParameters(); string methodSemantic = GetMethodSemantic(); WriteLine("{0} main({1}){2}", methodReturnType, methodParameters, methodSemantic); WriteLine("{"); indent = "\t"; if (_registers.MethodOutputRegisters.Count > 1) { var outputStructType = _shader.Type == ShaderType.Pixel ? "PS_OUT" : "VS_OUT"; WriteLine($"{outputStructType} o;"); WriteLine(); } HlslAst ast = null; if (_doAstAnalysis) { var parser = new BytecodeParser(); ast = parser.Parse(_shader); ast.ReduceTree(); WriteAst(ast); } else { WriteLine("{0} o;", methodReturnType); WriteLine(); WriteInstructionList(); } indent = ""; WriteLine("}"); hlslWriter.Dispose(); hlslFile.Dispose(); }
protected override void WriteMethodBody() { if (_registers.MethodOutputRegisters.Count > 1) { var outputStructType = _shader.Type == ShaderType.Pixel ? "PS_OUT" : "VS_OUT"; WriteLine($"{outputStructType} o;"); WriteLine(); } var parser = new BytecodeParser(); HlslAst ast = parser.Parse(_shader); ast.ReduceTree(new NodeGrouper(_registers)); WriteAst(ast); }
void WriteAst(HlslAst ast) { var roots = ast.Roots.OrderBy(r => r.Key.ComponentIndex).Select(r => r.Value).ToList(); // Check for scalar promotion from float to float4 if (roots.All(r => r is HlslConstant)) { var constants = roots.Cast <HlslConstant>(); float value = constants.First().Value; if (constants.Skip(1).All(r => r.Value == value)) { WriteLine("return {0};", value.ToString(CultureInfo.InvariantCulture)); return; } // In float4(x, float), x cannot be promoted from float to float3 // In float4(x, y), x cannot be promoted to float2 and y to float2 } var groups = GroupComponents(roots); if (groups.Count == 1) { var shaderInputs = groups.First().Cast <HlslShaderInput>(); var firstInput = shaderInputs.First(); string swizzle = GetAstSourceSwizzleName(shaderInputs, 4); var decl = RegisterDeclarations.FirstOrDefault(x => x.RegisterType == firstInput.InputDecl.RegisterType && x.RegisterNumber == firstInput.InputDecl.RegisterNumber); WriteLine($"return {decl.Name}{swizzle};"); return; } var constructorParts = groups.Select(Compile); string returnStatement = $"return float4({string.Join(", ", constructorParts)});"; WriteLine(returnStatement); }
public void Write(string hlslFilename) { hlslFile = new FileStream(hlslFilename, FileMode.Create, FileAccess.Write); hlslWriter = new StreamWriter(hlslFile); ConstantDefinitions = new List <Constant>(); ConstantIntDefinitions = new List <ConstantInt>(); // Look for dcl instructions RegisterDeclarations = new List <RegisterDeclaration>(); foreach (var declInstruction in shader.Instructions.Where(x => x.Opcode == Opcode.Dcl)) { var decl = new RegisterDeclaration(declInstruction); RegisterDeclarations.Add(decl); } // Look for and parse the constant table ConstantDeclarations = shader.ParseConstantTable(); foreach (ConstantDeclaration declaration in ConstantDeclarations) { string typeName = GetTypeName(declaration); WriteLine("{0} {1};", typeName, declaration.Name); } if (ConstantDeclarations.Count != 0) { WriteLine(); } string methodTypeName; string methodParamList = ""; string methodSemantic = ""; // Create the input structure var dclInputs = RegisterDeclarations.Where(x => x.RegisterType == RegisterType.Input || x.RegisterType == RegisterType.MiscType); numInputs = dclInputs.Count(); if (numInputs == 0) { System.Diagnostics.Debug.Assert(shader.Type == ShaderType.Pixel); } else if (numInputs == 1) { var dclInput = dclInputs.Single(); methodParamList = string.Format("{0} {1} : {2}", dclInput.TypeName, dclInput.Name, dclInput.Semantic); } else { if (shader.Type == ShaderType.Pixel) { methodParamList = "VS_OUT i"; WriteLine("struct VS_OUT"); } else { methodParamList = "VS_IN i"; WriteLine("struct VS_IN"); } WriteLine("{"); indent = "\t"; foreach (var dclInput in dclInputs) { WriteLine("{0} {1} : {2};", dclInput.TypeName, dclInput.Name, dclInput.Semantic); } indent = ""; WriteLine("};"); WriteLine(); } // Create the output structure if (shader.Type == ShaderType.Vertex) { var dclOutputs = RegisterDeclarations.Where(x => x.RegisterType == RegisterType.Output || x.RegisterType == RegisterType.ColorOut); numOutputs = dclOutputs.Count(); if (numOutputs == 1) { var dclOutput = dclOutputs.Single(); methodTypeName = dclOutput.TypeName; methodSemantic = " : " + dclOutput.Semantic; } else { methodTypeName = "VS_OUT"; WriteLine("struct VS_OUT"); WriteLine("{"); indent = "\t"; foreach (var dclOutput in dclOutputs) { WriteLine("{0} {1} : {2};", dclOutput.TypeName, dclOutput.Name, dclOutput.Semantic); } indent = ""; WriteLine("};"); WriteLine(); } } else { // Find all assignments to pixel shader color outputs. Dictionary <string, int> colorRegisters = new Dictionary <string, int>(); foreach (Instruction instruction in shader.Instructions) { if (!instruction.HasDestination) { continue; } int destIndex = instruction.GetDestinationParamIndex(); if (instruction.GetParamRegisterType(destIndex) == RegisterType.ColorOut) { string registerName = "oC" + instruction.GetParamRegisterNumber(destIndex).ToString(); if (!colorRegisters.ContainsKey(registerName)) { colorRegisters.Add(registerName, 0); } } } if (colorRegisters.Count > 1) { methodTypeName = "PS_OUT"; WriteLine("struct PS_OUT"); } else { methodTypeName = "float4"; methodSemantic = " : COLOR"; } } WriteLine("{0} main({1}){2}", methodTypeName, methodParamList, methodSemantic); WriteLine("{"); indent = "\t"; HlslAst ast = null; if (doAstAnalysis) { var parser = new BytecodeParser(); ast = parser.Parse(shader); ast.ReduceTree(); } if (ast != null) { WriteAst(ast); } else { WriteLine("{0} o;", methodTypeName); WriteLine(); // Find all assignments to temporary variables // and declare the variables. var tempRegisters = new Dictionary <string, int>(); foreach (Instruction instruction in shader.Instructions) { if (!instruction.HasDestination) { continue; } int destIndex = instruction.GetDestinationParamIndex(); if (instruction.GetParamRegisterType(destIndex) == RegisterType.Temp) { string registerName = instruction.GetParamRegisterName(destIndex); if (!tempRegisters.ContainsKey(registerName)) { tempRegisters.Add(registerName, 0); } tempRegisters[registerName] |= instruction.GetDestinationWriteMask(); } } foreach (var registerName in tempRegisters.Keys) { int writeMask = tempRegisters[registerName]; string writeMaskName; switch (writeMask) { case 0x1: writeMaskName = "float"; break; case 0x3: writeMaskName = "float2"; break; case 0x7: writeMaskName = "float3"; break; case 0xF: writeMaskName = "float4"; break; default: // TODO writeMaskName = "float4"; break; //throw new NotImplementedException(); } WriteLine("{0} {1};", writeMaskName, registerName); } foreach (Instruction instruction in shader.Instructions) { WriteInstruction(instruction); } WriteLine(); WriteLine("return o;"); } indent = ""; WriteLine("}"); hlslWriter.Dispose(); hlslFile.Dispose(); }