예제 #1
0
        /*
         * There are a few token types:
         * comment_token fourCC data
         * def_token dest_param literal_param literal_param literal_param literal_param
         * dcl_token decl_param dest_param
         * inst_token dest_param [src_param ...]
         * end_token
         */
        public static ShaderModel Parse(BytecodeReader reader)
        {
            var result = new ShaderModel();

            result.MinorVersion = reader.ReadByte();
            result.MajorVersion = reader.ReadByte();
            result.Type         = (ShaderType)reader.ReadUInt16();
            //SM1 shaders do not encode instruction size which rely on for reading operands.
            //So we won't support SM1
            if (result.MajorVersion == 1)
            {
                throw new ParseException("Shader Model 1 is not supported");
            }
            while (true)
            {
                var instruction = result.ReadInstruction(reader);
                if (instruction == null)
                {
                    continue;
                }
                result.Tokens.Add(instruction);
                if (instruction.Opcode == Opcode.End)
                {
                    break;
                }
            }
            return(result);
        }
예제 #2
0
        public static string Decompile(ShaderModel shaderModel, string entryPoint = null)
        {
            if (shaderModel.Type == ShaderType.Effect)
            {
                return(EffectHLSLWriter.Decompile(shaderModel.EffectChunk));
            }
            var hlslWriter = new HlslWriter(shaderModel, false, entryPoint);

            return(hlslWriter.Decompile());
        }
예제 #3
0
        public static string Disassemble(ShaderModel shaderModel)
        {
            if (shaderModel.Type == ShaderType.Effect)
            {
                var effectWriter = new EffectAsmWriter(shaderModel.EffectChunk);
                return(effectWriter.Decompile());
            }
            var asmWriter = new AsmWriter(shaderModel);

            return(asmWriter.Decompile());
        }
예제 #4
0
        private void LoadConstantOutputs(ShaderModel shader)
        {
            IList <ConstantDeclaration> constantTable = shader.ConstantTable.ConstantDeclarations;

            _activeOutputs = new Dictionary <RegisterComponentKey, HlslTreeNode>();
            _samplers      = new Dictionary <RegisterKey, HlslTreeNode>();

            foreach (var constant in constantTable)
            {
                if (constant.RegisterSet == RegisterSet.Sampler)
                {
                    var registerKey    = new RegisterKey(RegisterType.Sampler, constant.RegisterIndex);
                    var destinationKey = new RegisterComponentKey(registerKey, 0);
                    int samplerTextureDimension;
                    switch (constant.ParameterType)
                    {
                    case ParameterType.Sampler1D:
                        samplerTextureDimension = 1;
                        break;

                    case ParameterType.Sampler2D:
                        samplerTextureDimension = 2;
                        break;

                    case ParameterType.Sampler3D:
                    case ParameterType.SamplerCube:
                        samplerTextureDimension = 3;
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                    var shaderInput = new RegisterInputNode(destinationKey, samplerTextureDimension);
                    _samplers.Add(registerKey, shaderInput);
                }
                else
                {
                    for (uint r = 0; r < constant.RegisterCount; r++)
                    {
                        if (constant.ParameterType != ParameterType.Float)
                        {
                            throw new NotImplementedException();
                        }
                        var registerKey = new RegisterKey(RegisterType.Const, constant.RegisterIndex + r);
                        for (int i = 0; i < 4; i++)
                        {
                            var destinationKey = new RegisterComponentKey(registerKey, i);
                            var shaderInput    = new RegisterInputNode(destinationKey);
                            _activeOutputs.Add(destinationKey, shaderInput);
                        }
                    }
                }
            }
        }
예제 #5
0
        private void LoadConstantOutputs(ShaderModel shader)
        {
            IList <ConstantDeclaration> constantTable = shader.ConstantTable.ConstantDeclarations;

            _activeOutputs = new Dictionary <RegisterComponentKey, HlslTreeNode>();
            _samplers      = new Dictionary <RegisterKey, HlslTreeNode>();

            foreach (var constant in constantTable)
            {
                for (uint r = 0; r < constant.RegisterCount; r++)
                {
                    var data = constant.GetRegisterTypeByOffset(r);
                    int samplerTextureDimension;
                    switch (data.Type.ParameterType)
                    {
                    case ParameterType.Sampler1D:
                        samplerTextureDimension = 1;
                        goto SamplerCommon;

                    case ParameterType.Sampler2D:
                        samplerTextureDimension = 2;
                        goto SamplerCommon;

                    case ParameterType.Sampler3D:
                    case ParameterType.SamplerCube:
                        samplerTextureDimension = 3;
                        goto SamplerCommon;
SamplerCommon:
                        {
                            var registerKey    = new RegisterKey(RegisterType.Sampler, constant.RegisterIndex + r);
                            var destinationKey = new RegisterComponentKey(registerKey, 0);
                            var shaderInput    = new RegisterInputNode(destinationKey, samplerTextureDimension);
                            _samplers.Add(registerKey, shaderInput);
                        }
                        break;

                    case ParameterType.Float:
                    {
                        var registerKey = new RegisterKey(RegisterType.Const, constant.RegisterIndex + r);
                        for (int i = 0; i < 4; i++)
                        {
                            var destinationKey = new RegisterComponentKey(registerKey, i);
                            var shaderInput    = new RegisterInputNode(destinationKey);
                            _activeOutputs.Add(destinationKey, shaderInput);
                        }
                    }
                    break;

                    default:
                        throw new NotImplementedException();
                    }
                }
            }
        }
예제 #6
0
 public HlslWriter(ShaderModel shader, bool doAstAnalysis = false, string entryPoint = null)
 {
     _shader        = shader;
     _doAstAnalysis = doAstAnalysis;
     if (string.IsNullOrEmpty(entryPoint))
     {
         _entryPoint = $"{_shader.Type}Main";
     }
     else
     {
         _entryPoint = entryPoint;
     }
 }
예제 #7
0
        public HlslAst Parse(ShaderModel shader)
        {
            LoadConstantOutputs(shader);

            int  instructionPointer = 0;
            bool ifBlock            = false;

            while (instructionPointer < shader.Tokens.Count)
            {
                var instruction = shader.Tokens[instructionPointer] as InstructionToken;
                if (instruction == null)
                {
                    continue;
                }
                if (ifBlock)
                {
                    if (instruction.Opcode == Opcode.Else)
                    {
                        ifBlock = false;
                    }
                }
                else
                {
                    if (instruction.Opcode == Opcode.IfC)
                    {
                        ifBlock = true;
                    }
                    ParseInstruction(instruction);
                }
                instructionPointer++;
            }

            Dictionary <RegisterComponentKey, HlslTreeNode> roots;

            if (shader.Type == ShaderType.Pixel)
            {
                roots = _activeOutputs
                        .Where(o => o.Key.Type == RegisterType.ColorOut)
                        .ToDictionary(o => o.Key, o => o.Value);
            }
            else
            {
                roots = _activeOutputs
                        .Where(o => o.Key.Type == RegisterType.Output)
                        .ToDictionary(o => o.Key, o => o.Value);
            }
            return(new HlslAst(roots));
        }
예제 #8
0
 private void WriteExpression(ShaderModel shader)
 {
     WriteLine("void {0}Preshader(){{", _entryPoint);
     Indent++;
     WriteLine($"// {shader.Type}_{shader.MajorVersion}_{shader.MinorVersion}");
     foreach (var token in shader.Fxlc.Tokens)
     {
         WriteLine($"// {token.ToString(shader.ConstantTable, shader.Cli)}");
     }
     if (shader.Prsi != null)
     {
         WriteLine(shader.Prsi.Dump());
     }
     Indent--;
     WriteLine("}");
 }
예제 #9
0
        void WriteShader(string shaderName, ShaderModel shader)
        {
            WriteLine($"// {shaderName} {shader.Type}_{shader.MajorVersion}_{shader.MinorVersion} Has PRES {shader.Preshader != null}");
            var funcName = shaderName;
            var text     = "";

            if (shader.Type == ShaderType.Expression)
            {
                text = ExpressionHLSLWriter.Decompile(shader, funcName);
            }
            else
            {
                text = HlslWriter.Decompile(shader, funcName);
                // text = text.Replace("main(", $"{funcName}(");
            }
            WriteLine(text);
        }
예제 #10
0
        static public ShaderModel ReadShader(byte[] data)
        {
            byte       minorVersion = data[0];
            byte       majorVersion = data[1];
            ShaderType shaderType   = (ShaderType)BitConverter.ToUInt16(data, 2);

            if (shaderType == ShaderType.Effect)
            {
                var _shader        = new ShaderModel(majorVersion, minorVersion, shaderType);
                var bytecodeReader = new BytecodeReader(data, 4, data.Length - 4);
                _shader.EffectChunk = FX9.EffectContainer.Parse(bytecodeReader, (uint)(data.Length - 4));
                return(_shader);
            }
            var reader = new BytecodeReader(data, 0, data.Length);

            return(ShaderModel.Parse(reader));
        }
예제 #11
0
 public AsmWriter(ShaderModel shader)
 {
     this.shader = shader;
 }
예제 #12
0
        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;
                        }
                    }
                }
            }
        }
예제 #13
0
 public RegisterState(ShaderModel shader)
 {
     Load(shader);
 }
예제 #14
0
 public InstructionToken(Opcode opcode, int length, ShaderModel shaderModel) : base(opcode, length, shaderModel)
 {
     Operands = new List <Operand>();
 }
예제 #15
0
        private Token ReadInstruction(ShaderModel shaderModel)
        {
            uint   instructionToken = ReadUInt32();
            Opcode opcode           = (Opcode)(instructionToken & 0xffff);

            Debug.Assert(opcode <= Opcode.Breakp || (opcode >= Opcode.Phase && opcode <= Opcode.End), $"Invalid opcode {opcode}");
            int size;

            if (opcode == Opcode.Comment)
            {
                size = (int)((instructionToken >> 16) & 0x7FFF);
            }
            else
            {
                size = (int)((instructionToken >> 24) & 0x0f);
            }
            Token token = null;

            if (opcode == Opcode.Comment)
            {
                token = new CommentToken(opcode, size, shaderModel);
                for (int i = 0; i < size; i++)
                {
                    token.Data[i] = ReadUInt32();
                }
            }
            else
            {
                token = new InstructionToken(opcode, size, shaderModel);
                var inst = token as InstructionToken;
                for (int i = 0; i < size; i++)
                {
                    token.Data[i] = ReadUInt32();
                    if (opcode == Opcode.Def || opcode == Opcode.DefB || opcode == Opcode.DefI)
                    {
                    }
                    else if (opcode == Opcode.Dcl)
                    {
                        if (i == 0)
                        {
                            inst.Operands.Add(new DeclarationOperand(token.Data[i]));
                        }
                        else
                        {
                            inst.Operands.Add(new DestinationOperand(token.Data[i]));
                        }
                    }
                    else if (i == 0 && opcode != Opcode.BreakC && opcode != Opcode.IfC && opcode != Opcode.If)
                    {
                        inst.Operands.Add(new DestinationOperand(token.Data[i]));
                    }
                    else if ((token.Data[i] & (1 << 13)) != 0)
                    {
                        //Relative Address mode
                        token.Data[i + 1] = ReadUInt32();
                        inst.Operands.Add(new SourceOperand(token.Data[i], token.Data[i + 1]));
                        i++;
                    }
                    else
                    {
                        inst.Operands.Add(new SourceOperand(token.Data[i]));
                    }
                }
            }

            if (opcode != Opcode.Comment)
            {
                token.Modifier   = (int)((instructionToken >> 16) & 0xff);
                token.Predicated = (instructionToken & 0x10000000) != 0;
                token.CoIssue    = (instructionToken & 0x40000000) != 0;
                Debug.Assert((instructionToken & 0xA0000000) == 0, $"Instruction has unexpected bits set {instructionToken & 0xE0000000}");
            }

            return(token);
        }