Example #1
0
        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();
        }