Beispiel #1
0
        static void Main(string[] args)
        {
            if (args.Length == 2)
            {
                GlslDecompiler Decompiler = new GlslDecompiler();

                GalShaderType ShaderType = GalShaderType.Vertex;

                switch (args[0].ToLower())
                {
                case "v":  ShaderType = GalShaderType.Vertex;         break;

                case "tc": ShaderType = GalShaderType.TessControl;    break;

                case "te": ShaderType = GalShaderType.TessEvaluation; break;

                case "g":  ShaderType = GalShaderType.Geometry;       break;

                case "f":  ShaderType = GalShaderType.Fragment;       break;
                }

                byte[] Binary = File.ReadAllBytes(args[1]);

                GlslProgram Program = Decompiler.Decompile(Binary, ShaderType);

                Console.WriteLine(Program.Code);
            }
            else
            {
                Console.WriteLine("Usage: Ryujinx.ShaderTools [v|tc|te|g|f] shader.bin");
            }
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            if (args.Length == 2)
            {
                GalShaderType type = GalShaderType.Vertex;

                switch (args[0].ToLower())
                {
                case "v":  type = GalShaderType.Vertex;         break;

                case "tc": type = GalShaderType.TessControl;    break;

                case "te": type = GalShaderType.TessEvaluation; break;

                case "g":  type = GalShaderType.Geometry;       break;

                case "f":  type = GalShaderType.Fragment;       break;
                }

                using (FileStream fs = new FileStream(args[1], FileMode.Open, FileAccess.Read))
                {
                    Memory mem = new Memory(fs);

                    ShaderConfig config = new ShaderConfig(type, 65536);

                    string code = Translator.Translate(mem, 0, config).Code;

                    Console.WriteLine(code);
                }
            }
            else
            {
                Console.WriteLine("Usage: Ryujinx.ShaderTools [v|tc|te|g|f] shader.bin");
            }
        }
Beispiel #3
0
        public static void Dump(IGalMemory memory, long position, GalShaderType type, string extSuffix = "")
        {
            if (!IsDumpEnabled())
            {
                return;
            }

            string fileName = "Shader" + DumpIndex.ToString("d4") + "." + ShaderExtension(type) + extSuffix + ".bin";

            string fullPath = Path.Combine(FullDir(), fileName);
            string codePath = Path.Combine(CodeDir(), fileName);

            DumpIndex++;

            using (FileStream fullFile = File.Create(fullPath))
                using (FileStream codeFile = File.Create(codePath))
                {
                    BinaryWriter fullWriter = new BinaryWriter(fullFile);
                    BinaryWriter codeWriter = new BinaryWriter(codeFile);

                    for (long i = 0; i < 0x50; i += 4)
                    {
                        fullWriter.Write(memory.ReadInt32(position + i));
                    }

                    long offset = 0;

                    ulong instruction = 0;

                    //Dump until a NOP instruction is found
                    while ((instruction >> 48 & 0xfff8) != 0x50b0)
                    {
                        uint word0 = (uint)memory.ReadInt32(position + 0x50 + offset + 0);
                        uint word1 = (uint)memory.ReadInt32(position + 0x50 + offset + 4);

                        instruction = word0 | (ulong)word1 << 32;

                        //Zero instructions (other kind of NOP) stop immediatly,
                        //this is to avoid two rows of zeroes
                        if (instruction == 0)
                        {
                            break;
                        }

                        fullWriter.Write(instruction);
                        codeWriter.Write(instruction);

                        offset += 8;
                    }

                    //Align to meet nvdisasm requeriments
                    while (offset % 0x20 != 0)
                    {
                        fullWriter.Write(0);
                        codeWriter.Write(0);

                        offset += 4;
                    }
                }
        }
Beispiel #4
0
        public GlslProgram Decompile(int[] Code, GalShaderType ShaderType)
        {
            ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0);

            ShaderIrNode[] Nodes = Block.GetNodes();

            Decl = new GlslDecl(Nodes, ShaderType);

            SB = new StringBuilder();

            SB.AppendLine("#version 410 core");

            PrintDeclTextures();
            PrintDeclUniforms();
            PrintDeclInAttributes();
            PrintDeclOutAttributes();
            PrintDeclGprs();
            PrintDeclPreds();

            PrintBlockScope("void main()", 1, Nodes);

            string GlslCode = SB.ToString();

            return(new GlslProgram(
                       GlslCode,
                       Decl.Textures.Values,
                       Decl.Uniforms.Values));
        }
Beispiel #5
0
        public static void Dump(IGalMemory Memory, long Position, GalShaderType Type, string ExtSuffix = "")
        {
            if (!IsDumpEnabled())
            {
                return;
            }

            string FileName = "Shader" + DumpIndex.ToString("d4") + "." + ShaderExtension(Type) + ExtSuffix + ".bin";

            string FullPath = Path.Combine(FullDir(), FileName);
            string CodePath = Path.Combine(CodeDir(), FileName);

            DumpIndex++;

            using (FileStream FullFile = File.Create(FullPath))
                using (FileStream CodeFile = File.Create(CodePath))
                {
                    BinaryWriter FullWriter = new BinaryWriter(FullFile);
                    BinaryWriter CodeWriter = new BinaryWriter(CodeFile);

                    for (long i = 0; i < 0x50; i += 4)
                    {
                        FullWriter.Write(Memory.ReadInt32(Position + i));
                    }

                    long Offset = 0;

                    ulong Instruction = 0;

                    //Dump until a NOP instruction is found
                    while ((Instruction >> 48 & 0xfff8) != 0x50b0)
                    {
                        uint Word0 = (uint)Memory.ReadInt32(Position + 0x50 + Offset + 0);
                        uint Word1 = (uint)Memory.ReadInt32(Position + 0x50 + Offset + 4);

                        Instruction = Word0 | (ulong)Word1 << 32;

                        //Zero instructions (other kind of NOP) stop immediatly,
                        //this is to avoid two rows of zeroes
                        if (Instruction == 0)
                        {
                            break;
                        }

                        FullWriter.Write(Instruction);
                        CodeWriter.Write(Instruction);

                        Offset += 8;
                    }

                    //Align to meet nvdisasm requeriments
                    while (Offset % 0x20 != 0)
                    {
                        FullWriter.Write(0);
                        CodeWriter.Write(0);

                        Offset += 4;
                    }
                }
        }
Beispiel #6
0
        public GlslDecl(ShaderIrNode[] Nodes, GalShaderType ShaderType)
        {
            this.ShaderType = ShaderType;

            StagePrefix = StagePrefixes[(int)ShaderType] + "_";

            m_Uniforms = new Dictionary <int, ShaderDeclInfo>();

            m_Textures = new Dictionary <int, ShaderDeclInfo>();

            m_InAttributes  = new Dictionary <int, ShaderDeclInfo>();
            m_OutAttributes = new Dictionary <int, ShaderDeclInfo>();

            m_Gprs  = new Dictionary <int, ShaderDeclInfo>();
            m_Preds = new Dictionary <int, ShaderDeclInfo>();

            if (ShaderType == GalShaderType.Fragment)
            {
                m_Gprs.Add(0, new ShaderDeclInfo(FragmentOutputName, 0, 0, 4));

                m_InAttributes.Add(7, new ShaderDeclInfo(PositionOutAttrName, -1, 0, 4));
            }
            else
            {
                m_OutAttributes.Add(7, new ShaderDeclInfo("gl_Position", -1, 0, 4));
            }

            foreach (ShaderIrNode Node in Nodes)
            {
                Traverse(null, Node);
            }
        }
Beispiel #7
0
        static void Main(string[] args)
        {
            if (args.Length == 2)
            {
                GlslDecompiler Decompiler = new GlslDecompiler(MaxUboSize);

                GalShaderType ShaderType = GalShaderType.Vertex;

                switch (args[0].ToLower())
                {
                case "v":  ShaderType = GalShaderType.Vertex;         break;

                case "tc": ShaderType = GalShaderType.TessControl;    break;

                case "te": ShaderType = GalShaderType.TessEvaluation; break;

                case "g":  ShaderType = GalShaderType.Geometry;       break;

                case "f":  ShaderType = GalShaderType.Fragment;       break;
                }

                using (FileStream FS = new FileStream(args[1], FileMode.Open, FileAccess.Read))
                {
                    Memory Mem = new Memory(FS);

                    GlslProgram Program = Decompiler.Decompile(Mem, 0, ShaderType);

                    Console.WriteLine(Program.Code);
                }
            }
            else
            {
                Console.WriteLine("Usage: Ryujinx.ShaderTools [v|tc|te|g|f] shader.bin");
            }
        }
Beispiel #8
0
        public static void Dump(byte[] Binary, GalShaderType Type, string ExtSuffix = "")
        {
            if (string.IsNullOrWhiteSpace(GraphicsConfig.ShadersDumpPath))
            {
                return;
            }

            string FileName = "Shader" + DumpIndex.ToString("d4") + "." + ShaderExtension(Type) + ExtSuffix + ".bin";

            string FullPath = Path.Combine(FullDir(), FileName);
            string CodePath = Path.Combine(CodeDir(), FileName);

            DumpIndex++;

            File.WriteAllBytes(FullPath, Binary);

            using (FileStream CodeFile = File.Create(CodePath))
                using (BinaryWriter Writer = new BinaryWriter(CodeFile))
                {
                    long Offset;

                    for (Offset = 0; Offset + 0x50 < Binary.LongLength; Offset++)
                    {
                        Writer.Write(Binary[Offset + 0x50]);
                    }

                    //Align to meet nvdisasm requeriments
                    while (Offset % 0x20 != 0)
                    {
                        Writer.Write(0);

                        Offset += 4;
                    }
                }
        }
Beispiel #9
0
        public GlslProgram Decompile(IGalMemory Memory, long Position, GalShaderType ShaderType)
        {
            Blocks = ShaderDecoder.Decode(Memory, Position);

            Decl = new GlslDecl(Blocks, ShaderType);

            SB = new StringBuilder();

            SB.AppendLine("#version 410 core");

            PrintDeclTextures();
            PrintDeclUniforms();
            PrintDeclInAttributes();
            PrintDeclOutAttributes();
            PrintDeclGprs();
            PrintDeclPreds();

            PrintBlockScope(Blocks[0], null, null, "void main()", IdentationStr);

            string GlslCode = SB.ToString();

            return(new GlslProgram(
                       GlslCode,
                       Decl.Textures.Values,
                       Decl.Uniforms.Values));
        }
Beispiel #10
0
        public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset, GalShaderType ShaderType)
        {
            ShaderIrBlock Block = new ShaderIrBlock();

            while (Offset + 2 <= Code.Length)
            {
                uint Word0 = (uint)Code[Offset++];
                uint Word1 = (uint)Code[Offset++];

                long OpCode = Word0 | (long)Word1 << 32;

                ShaderDecodeFunc Decode = ShaderOpCodeTable.GetDecoder(OpCode);

                if (Decode == null)
                {
                    continue;
                }

                Decode(Block, OpCode);

                if (Block.GetLastNode() is ShaderIrOp Op && IsFlowChange(Op.Inst))
                {
                    break;
                }
            }

            Block.RunOptimizationPasses(ShaderType);

            return(Block);
        }
Beispiel #11
0
        private ShaderStage ShaderStageFactory(
            IGalMemory Memory,
            long Position,
            long PositionB,
            bool IsDualVp,
            GalShaderType Type)
        {
            GlslProgram Program;

            GlslDecompiler Decompiler = new GlslDecompiler();

            if (IsDualVp)
            {
                ShaderDumper.Dump(Memory, Position, Type, "a");
                ShaderDumper.Dump(Memory, PositionB, Type, "b");

                Program = Decompiler.Decompile(
                    Memory,
                    Position,
                    PositionB,
                    Type);
            }
            else
            {
                ShaderDumper.Dump(Memory, Position, Type);

                Program = Decompiler.Decompile(Memory, Position, Type);
            }

            return(new ShaderStage(
                       Type,
                       Program.Code,
                       Program.Textures,
                       Program.Uniforms));
        }
Beispiel #12
0
        public static void Optimize(List <ShaderIrNode> Nodes, GalShaderType ShaderType)
        {
            Dictionary <int, RegUse> Uses = new Dictionary <int, RegUse>();

            RegUse GetUse(int Key)
            {
                RegUse Use;

                if (!Uses.TryGetValue(Key, out Use))
                {
                    Use = new RegUse();

                    Uses.Add(Key, Use);
                }

                return(Use);
            }

            int GetGprKey(int GprIndex)
            {
                return(GprIndex);
            }

            int GetPredKey(int PredIndex)
            {
                return(PredIndex | 0x10000000);
            }

            RegUse GetGprUse(int GprIndex)
            {
                return(GetUse(GetGprKey(GprIndex)));
            }

            RegUse GetPredUse(int PredIndex)
            {
                return(GetUse(GetPredKey(PredIndex)));
            }

            void FindRegUses(List <(int, UseSite)> UseList, object Parent, ShaderIrNode Node, int OperIndex = 0)
            {
                if (Node is ShaderIrAsg Asg)
                {
                    FindRegUses(UseList, Asg, Asg.Src);
                }
                else if (Node is ShaderIrCond Cond)
                {
                    FindRegUses(UseList, Cond, Cond.Pred, 0);
                    FindRegUses(UseList, Cond, Cond.Child, 1);
                }
                else if (Node is ShaderIrOp Op)
                {
                    FindRegUses(UseList, Op, Op.OperandA, 0);
                    FindRegUses(UseList, Op, Op.OperandB, 1);
                    FindRegUses(UseList, Op, Op.OperandC, 2);
                }
                else if (Node is ShaderIrOperGpr Gpr && Gpr.Index != ShaderIrOperGpr.ZRIndex)
                {
                    UseList.Add((GetGprKey(Gpr.Index), new UseSite(Parent, OperIndex)));
                }
Beispiel #13
0
        public static string GetConstantBufferName(AstOperand cbuf, GalShaderType shaderType)
        {
            string ubName = GetUbName(shaderType, cbuf.CbufSlot);

            ubName += "[" + (cbuf.CbufOffset >> 2) + "]";

            return(ubName + "." + GetSwizzleMask(cbuf.CbufOffset & 3));
        }
Beispiel #14
0
        public static string GetUbName(GalShaderType shaderType, int slot)
        {
            string ubName = GetShaderStagePrefix(shaderType);

            ubName += "_" + DefaultNames.UniformNamePrefix + slot;

            return(ubName + "_" + DefaultNames.UniformNameSuffix);
        }
Beispiel #15
0
        public GlslProgram Decompile(IGalMemory Memory, long Position, GalShaderType ShaderType)
        {
            Blocks  = ShaderDecoder.Decode(Memory, Position);
            BlocksB = null;

            Decl = new GlslDecl(Blocks, ShaderType);

            return(Decompile());
        }
Beispiel #16
0
        public EmitterContext(GalShaderType shaderType, ShaderHeader header)
        {
            _shaderType = shaderType;
            _header     = header;

            _operations = new List <Operation>();

            _labels = new Dictionary <ulong, Operand>();
        }
Beispiel #17
0
        public void CreateShader(long Tag, GalShaderType Type, byte[] Data)
        {
            if (Data == null)
            {
                throw new ArgumentNullException(nameof(Data));
            }

            Shader.Create(Tag, Type, Data);
        }
Beispiel #18
0
        public void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type)
        {
            if (Memory == null)
            {
                throw new ArgumentNullException(nameof(Memory));
            }

            Shader.Create(Memory, Tag, Type);
        }
Beispiel #19
0
        private ShaderStage ShaderStageFactory(IGalMemory Memory, long Position, GalShaderType Type)
        {
            GlslProgram Program = GetGlslProgram(Memory, Position, Type);

            return(new ShaderStage(
                       Type,
                       Program.Code,
                       Program.Textures,
                       Program.Uniforms));
        }
Beispiel #20
0
        public ShaderConfig(GalShaderType type, int maxCBufferSize)
        {
            if (maxCBufferSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxCBufferSize));
            }

            Type           = type;
            MaxCBufferSize = maxCBufferSize;
        }
Beispiel #21
0
        private ShaderStage ShaderStageFactory(GalShaderType Type, byte[] Data)
        {
            GlslProgram Program = GetGlslProgram(Data, Type);

            return(new ShaderStage(
                       Type,
                       Program.Code,
                       Program.Textures,
                       Program.Uniforms));
        }
Beispiel #22
0
 public OglShaderStage(
     GalShaderType type,
     string code,
     IEnumerable <CBufferDescriptor> constBufferUsage,
     IEnumerable <TextureDescriptor> textureUsage)
 {
     Type             = type;
     Code             = code;
     ConstBufferUsage = constBufferUsage;
     TextureUsage     = textureUsage;
 }
Beispiel #23
0
 public OglShaderStage(
     GalShaderType type,
     string code,
     IEnumerable <ShaderDeclInfo> constBufferUsage,
     IEnumerable <ShaderDeclInfo> textureUsage)
 {
     Type             = type;
     Code             = code;
     ConstBufferUsage = constBufferUsage;
     TextureUsage     = textureUsage;
 }
Beispiel #24
0
 public OGLShaderStage(
     GalShaderType Type,
     string Code,
     IEnumerable <ShaderDeclInfo> ConstBufferUsage,
     IEnumerable <ShaderDeclInfo> TextureUsage)
 {
     this.Type             = Type;
     this.Code             = Code;
     this.ConstBufferUsage = ConstBufferUsage;
     this.TextureUsage     = TextureUsage;
 }
Beispiel #25
0
 public ShaderStage(
     GalShaderType Type,
     string Code,
     IEnumerable <ShaderDeclInfo> TextureUsage,
     IEnumerable <ShaderDeclInfo> UniformUsage)
 {
     this.Type         = Type;
     this.Code         = Code;
     this.TextureUsage = TextureUsage;
     this.UniformUsage = UniformUsage;
 }
Beispiel #26
0
        public GlslProgram Decompile(byte[] Binary, GalShaderType ShaderType)
        {
            Header  = new ShaderHeader(Binary);
            HeaderB = null;

            Blocks  = ShaderDecoder.Decode(Binary);
            BlocksB = null;

            Decl = new GlslDecl(Blocks, ShaderType, Header);

            return(Decompile());
        }
Beispiel #27
0
        public static string GetConstantBufferName(IAstNode slot, string offsetExpr, GalShaderType shaderType)
        {
            // Non-constant slots are not supported.
            // It is expected that upstream stages are never going to generate non-constant
            // slot access.
            AstOperand operand = (AstOperand)slot;

            string ubName = GetUbName(shaderType, operand.Value);

            string index0 = "[" + offsetExpr + " >> 4]";
            string index1 = "[" + offsetExpr + " >> 2 & 3]";

            return(ubName + index0 + index1);
        }
Beispiel #28
0
        private GlslDecl(GalShaderType ShaderType)
        {
            this.ShaderType = ShaderType;

            m_Uniforms = new Dictionary <int, ShaderDeclInfo>();
            m_Textures = new Dictionary <int, ShaderDeclInfo>();

            m_Attributes    = new Dictionary <int, ShaderDeclInfo>();
            m_InAttributes  = new Dictionary <int, ShaderDeclInfo>();
            m_OutAttributes = new Dictionary <int, ShaderDeclInfo>();

            m_Gprs  = new Dictionary <int, ShaderDeclInfo>();
            m_Preds = new Dictionary <int, ShaderDeclInfo>();
        }
        private long[] UploadShaders(AMemory Memory)
        {
            long[] Tags = new long[5];

            long BasePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);

            for (int Index = 0; Index < 6; Index++)
            {
                int Control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + Index * 0x10);
                int Offset  = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + Index * 0x10);

                //Note: Vertex Program (B) is always enabled.
                bool Enable = (Control & 1) != 0 || Index == 1;

                if (!Enable)
                {
                    continue;
                }

                long Tag = BasePosition + (uint)Offset;

                long Position = Gpu.GetCpuAddr(Tag);

                //TODO: Find a better way to calculate the size.
                int Size = 0x20000;

                byte[] Code = AMemoryHelper.ReadBytes(Memory, Position, (uint)Size);

                GalShaderType ShaderType = GetTypeFromProgram(Index);

                Tags[(int)ShaderType] = Tag;

                Gpu.Renderer.CreateShader(Tag, ShaderType, Code);
                Gpu.Renderer.BindShader(Tag);
            }

            int RawSX = ReadRegister(NvGpuEngine3dReg.ViewportScaleX);
            int RawSY = ReadRegister(NvGpuEngine3dReg.ViewportScaleY);

            float SX = BitConverter.Int32BitsToSingle(RawSX);
            float SY = BitConverter.Int32BitsToSingle(RawSY);

            float SignX = MathF.Sign(SX);
            float SignY = MathF.Sign(SY);

            Gpu.Renderer.SetUniform2F(GalConsts.FlipUniformName, SignX, SignY);

            return(Tags);
        }
Beispiel #30
0
        public void Unbind(GalShaderType Type)
        {
            switch (Type)
            {
            case GalShaderType.Vertex:         Current.Vertex = null; break;

            case GalShaderType.TessControl:    Current.TessControl = null; break;

            case GalShaderType.TessEvaluation: Current.TessEvaluation = null; break;

            case GalShaderType.Geometry:       Current.Geometry = null; break;

            case GalShaderType.Fragment:       Current.Fragment = null; break;
            }
        }