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;");
            }
        }
Beispiel #2
0
        public uint GetRegisterFullLength(RegisterKey registerKey)
        {
            if (registerKey.Type == RegisterType.Const)
            {
                var constant = FindConstant(ParameterType.Float, registerKey.Number);
                return(constant.Columns);
            }

            RegisterDeclaration decl = _registerDeclarations[registerKey];

            switch (decl.TypeName)
            {
            case "float":
                return(1);

            case "float2":
                return(2);

            case "float3":
                return(3);

            case "float4":
                return(4);

            default:
                throw new InvalidOperationException();
            }
        }
        public uint GetRegisterFullLength(RegisterKey registerKey)
        {
            if (registerKey.Type == RegisterType.Const)
            {
                var constant = FindConstant(registerKey.Number);
                var data     = constant.GetRegisterTypeByOffset(registerKey.Number - constant.RegisterIndex);
                if (data.Type.ParameterType != ParameterType.Float)
                {
                    throw new NotImplementedException();
                }
                if (data.Type.ParameterClass == ParameterClass.MatrixColumns)
                {
                    return(data.Type.Rows);
                }
                return(data.Type.Columns);
            }

            RegisterDeclaration decl = _registerDeclarations[registerKey];

            switch (decl.TypeName)
            {
            case "float":
                return(1);

            case "float2":
                return(2);

            case "float3":
                return(3);

            case "float4":
                return(4);

            default:
                throw new InvalidOperationException();
            }
        }
        void WriteTemps()
        {
            Dictionary <RegisterKey, int> tempRegisters = new Dictionary <RegisterKey, int>();

            foreach (var inst in _shader.Instructions)
            {
                foreach (var operand in inst.Operands)
                {
                    if (operand is DestinationOperand dest)
                    {
                        if (dest.RegisterType == RegisterType.Temp)
                        {
                            var registerKey = new RegisterKey(dest.RegisterType, dest.RegisterNumber);
                            if (!tempRegisters.ContainsKey(registerKey))
                            {
                                var reg = new RegisterDeclaration(registerKey);
                                _registers._registerDeclarations[registerKey] = reg;
                                tempRegisters[registerKey] = (int)inst.GetDestinationWriteMask();
                            }
                            else
                            {
                                tempRegisters[registerKey] |= (int)inst.GetDestinationWriteMask();
                            }
                        }
                    }
                }
            }
            if (tempRegisters.Count == 0)
            {
                return;
            }
            foreach (IGrouping <int, RegisterKey> group in tempRegisters.GroupBy(
                         kv => kv.Value,
                         kv => kv.Key))
            {
                int    writeMask = group.Key;
                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();
                }
                WriteIndent();
                WriteLine("{0} {1};", writeMaskName, string.Join(", ", group));
            }
        }
        private void Load(ShaderModel shader)
        {
            ConstantDeclarations = shader.ConstantTable.ConstantDeclarations;
            foreach (var constantDeclaration in ConstantDeclarations)
            {
                RegisterType registerType;
                switch (constantDeclaration.RegisterSet)
                {
                case RegisterSet.Bool:
                    registerType = RegisterType.ConstBool;
                    break;

                case RegisterSet.Float4:
                    registerType = RegisterType.Const;
                    break;

                case RegisterSet.Int4:
                    registerType = RegisterType.ConstInt;
                    break;

                case RegisterSet.Sampler:
                    registerType = RegisterType.Sampler;
                    break;

                default:
                    throw new InvalidOperationException();
                }
                if (registerType == RegisterType.Sampler)
                {
                    // Use declaration from declaration instruction instead
                    continue;
                }
                for (uint r = 0; r < constantDeclaration.RegisterCount; r++)
                {
                    var registerKey         = new RegisterKey(registerType, constantDeclaration.RegisterIndex + r);
                    var registerDeclaration = new RegisterDeclaration(registerKey);
                    _registerDeclarations.Add(registerKey, registerDeclaration);
                }
            }

            foreach (var instruction in shader.Tokens.OfType <InstructionToken>().Where(i => i.HasDestination))
            {
                if (instruction.Opcode == Opcode.Dcl)
                {
                    var         registerDeclaration = new RegisterDeclaration(instruction);
                    RegisterKey registerKey         = registerDeclaration.RegisterKey;

                    _registerDeclarations.Add(registerKey, registerDeclaration);

                    switch (registerKey.Type)
                    {
                    case RegisterType.Input:
                    case RegisterType.MiscType:
                    case RegisterType.Texture when shader.Type == ShaderType.Pixel:
                        MethodInputRegisters.Add(registerKey, registerDeclaration);
                        break;

                    case RegisterType.Output:
                    case RegisterType.ColorOut:
                    case RegisterType.AttrOut when shader.MajorVersion == 3 && shader.Type == ShaderType.Vertex:
                        MethodOutputRegisters.Add(registerKey, registerDeclaration);
                        break;

                    case RegisterType.Sampler:
                    case RegisterType.Addr:
                        break;

                    default:
                        throw new Exception($"Unexpected dcl {registerKey.Type}");
                    }
                }
                else if (instruction.Opcode == Opcode.Def)
                {
                    var constant = new Constant(
                        instruction.GetParamRegisterNumber(0),
                        instruction.GetParamSingle(1),
                        instruction.GetParamSingle(2),
                        instruction.GetParamSingle(3),
                        instruction.GetParamSingle(4));
                    _constantDefinitions.Add(constant);
                }
                else if (instruction.Opcode == Opcode.DefI)
                {
                    var constantInt = new ConstantInt(instruction.GetParamRegisterNumber(0),
                                                      instruction.Data[1],
                                                      instruction.Data[2],
                                                      instruction.Data[3],
                                                      instruction.Data[4]);
                    _constantIntDefinitions.Add(constantInt);
                }
                else
                {
                    // Find all assignments to color outputs, because pixel shader outputs are not declared.
                    int          destIndex      = instruction.GetDestinationParamIndex();
                    RegisterType registerType   = instruction.GetParamRegisterType(destIndex);
                    var          registerNumber = instruction.GetParamRegisterNumber(destIndex);
                    var          registerKey    = new RegisterKey(registerType, registerNumber);
                    if (_registerDeclarations.ContainsKey(registerKey) == false)
                    {
                        var reg = new RegisterDeclaration(registerKey);
                        _registerDeclarations[registerKey] = reg;
                        switch (registerType)
                        {
                        case RegisterType.AttrOut:
                        case RegisterType.ColorOut:
                        case RegisterType.DepthOut:
                        case RegisterType.Output:
                        case RegisterType.RastOut:
                            MethodOutputRegisters[registerKey] = reg;
                            break;
                        }
                    }
                }
            }
        }