Ejemplo n.º 1
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;
                    }
                }
        }
Ejemplo n.º 2
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));
        }
Ejemplo n.º 3
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));
        }
Ejemplo n.º 4
0
        public ShaderHeader(IGalMemory Memory, long Position)
        {
            uint CommonWord0 = (uint)Memory.ReadInt32(Position + 0);
            uint CommonWord1 = (uint)Memory.ReadInt32(Position + 4);
            uint CommonWord2 = (uint)Memory.ReadInt32(Position + 8);
            uint CommonWord3 = (uint)Memory.ReadInt32(Position + 12);
            uint CommonWord4 = (uint)Memory.ReadInt32(Position + 16);

            SphType         = ReadBits(CommonWord0, 0, 5);
            Version         = ReadBits(CommonWord0, 5, 5);
            ShaderType      = ReadBits(CommonWord0, 10, 4);
            MrtEnable       = ReadBits(CommonWord0, 14, 1) != 0;
            KillsPixels     = ReadBits(CommonWord0, 15, 1) != 0;
            DoesGlobalStore = ReadBits(CommonWord0, 16, 1) != 0;
            SassVersion     = ReadBits(CommonWord0, 17, 4);
            DoesLoadOrStore = ReadBits(CommonWord0, 26, 1) != 0;
            DoesFp64        = ReadBits(CommonWord0, 27, 1) != 0;
            StreamOutMask   = ReadBits(CommonWord0, 28, 4);

            ShaderLocalMemoryLowSize = ReadBits(CommonWord1, 0, 24);
            PerPatchAttributeCount   = ReadBits(CommonWord1, 24, 8);

            ShaderLocalMemoryHighSize = ReadBits(CommonWord2, 0, 24);
            ThreadsPerInputPrimitive  = ReadBits(CommonWord2, 24, 8);

            ShaderLocalMemoryCrsSize = ReadBits(CommonWord3, 0, 24);
            OutputTopology           = ReadBits(CommonWord3, 24, 4);

            MaxOutputVertexCount = ReadBits(CommonWord4, 0, 12);
            StoreReqStart        = ReadBits(CommonWord4, 12, 8);
            StoreReqEnd          = ReadBits(CommonWord4, 24, 8);
        }
Ejemplo n.º 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;
                    }
                }
        }
Ejemplo n.º 6
0
        public void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type)
        {
            if (Memory == null)
            {
                throw new ArgumentNullException(nameof(Memory));
            }

            Shader.Create(Memory, Tag, Type);
        }
Ejemplo n.º 7
0
        public GlslProgram Decompile(IGalMemory Memory, long Position, GalShaderType ShaderType)
        {
            Blocks  = ShaderDecoder.Decode(Memory, Position);
            BlocksB = null;

            Decl = new GlslDecl(Blocks, ShaderType);

            return(Decompile());
        }
Ejemplo n.º 8
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));
        }
Ejemplo n.º 9
0
        public ShaderHeader(IGalMemory Memory, long Position)
        {
            uint CommonWord0 = (uint)Memory.ReadInt32(Position + 0);
            uint CommonWord1 = (uint)Memory.ReadInt32(Position + 4);
            uint CommonWord2 = (uint)Memory.ReadInt32(Position + 8);
            uint CommonWord3 = (uint)Memory.ReadInt32(Position + 12);
            uint CommonWord4 = (uint)Memory.ReadInt32(Position + 16);

            SphType         = ReadBits(CommonWord0, 0, 5);
            Version         = ReadBits(CommonWord0, 5, 5);
            ShaderType      = ReadBits(CommonWord0, 10, 4);
            MrtEnable       = ReadBits(CommonWord0, 14, 1) != 0;
            KillsPixels     = ReadBits(CommonWord0, 15, 1) != 0;
            DoesGlobalStore = ReadBits(CommonWord0, 16, 1) != 0;
            SassVersion     = ReadBits(CommonWord0, 17, 4);
            DoesLoadOrStore = ReadBits(CommonWord0, 26, 1) != 0;
            DoesFp64        = ReadBits(CommonWord0, 27, 1) != 0;
            StreamOutMask   = ReadBits(CommonWord0, 28, 4);

            ShaderLocalMemoryLowSize = ReadBits(CommonWord1, 0, 24);
            PerPatchAttributeCount   = ReadBits(CommonWord1, 24, 8);

            ShaderLocalMemoryHighSize = ReadBits(CommonWord2, 0, 24);
            ThreadsPerInputPrimitive  = ReadBits(CommonWord2, 24, 8);

            ShaderLocalMemoryCrsSize = ReadBits(CommonWord3, 0, 24);
            OutputTopology           = ReadBits(CommonWord3, 24, 4);

            MaxOutputVertexCount = ReadBits(CommonWord4, 0, 12);
            StoreReqStart        = ReadBits(CommonWord4, 12, 8);
            StoreReqEnd          = ReadBits(CommonWord4, 24, 8);

            //Type 2 (fragment?) reading
            uint Type2OmapTarget = (uint)Memory.ReadInt32(Position + 72);
            uint Type2Omap       = (uint)Memory.ReadInt32(Position + 76);

            OmapTargets = new OmapTarget[8];

            for (int i = 0; i < OmapTargets.Length; i++)
            {
                int Offset = i * 4;

                OmapTargets[i] = new OmapTarget
                {
                    Red   = ReadBits(Type2OmapTarget, Offset + 0, 1) != 0,
                    Green = ReadBits(Type2OmapTarget, Offset + 1, 1) != 0,
                    Blue  = ReadBits(Type2OmapTarget, Offset + 2, 1) != 0,
                    Alpha = ReadBits(Type2OmapTarget, Offset + 3, 1) != 0
                };
            }

            OmapSampleMask = ReadBits(Type2Omap, 0, 1) != 0;
            OmapDepth      = ReadBits(Type2Omap, 1, 1) != 0;
        }
Ejemplo n.º 10
0
        private static void FillBlock(IGalMemory Memory, ShaderIrBlock Block, long Beginning)
        {
            long Position = Block.Position;

            do
            {
                //Ignore scheduling instructions, which are written every 32 bytes.
                if (((Position - Beginning) & 0x1f) == 0)
                {
                    Position += 8;

                    continue;
                }

                uint Word0 = (uint)Memory.ReadInt32(Position + 0);
                uint Word1 = (uint)Memory.ReadInt32(Position + 4);

                Position += 8;

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

                ShaderDecodeFunc Decode = ShaderOpCodeTable.GetDecoder(OpCode);

                if (AddDbgComments)
                {
                    string DbgOpCode = $"0x{(Position - Beginning - 8):x16}: 0x{OpCode:x16} ";

                    DbgOpCode += (Decode?.Method.Name ?? "???");

                    if (Decode == ShaderDecode.Bra)
                    {
                        int Offset = ((int)(OpCode >> 20) << 8) >> 8;

                        long Target = Position + Offset;

                        DbgOpCode += " (0x" + Target.ToString("x16") + ")";
                    }

                    Block.AddNode(new ShaderIrCmnt(DbgOpCode));
                }

                if (Decode == null)
                {
                    continue;
                }

                Decode(Block, OpCode);
            }while (!IsFlowChange(Block.GetLastNode()));

            Block.EndPosition = Position;
        }
Ejemplo n.º 11
0
        private static void FillBlock(IGalMemory memory, ShaderIrBlock block, long beginning)
        {
            int position = block.Position;

            do
            {
                //Ignore scheduling instructions, which are written every 32 bytes.
                if ((position & 0x1f) == 0)
                {
                    position += 8;

                    continue;
                }

                uint word0 = (uint)memory.ReadInt32(position + beginning + 0);
                uint word1 = (uint)memory.ReadInt32(position + beginning + 4);

                position += 8;

                long opCode = word0 | (long)word1 << 32;

                ShaderDecodeFunc decode = ShaderOpCodeTable.GetDecoder(opCode);

                if (AddDbgComments)
                {
                    string dbgOpCode = $"0x{(position - 8):x16}: 0x{opCode:x16} ";

                    dbgOpCode += (decode?.Method.Name ?? "???");

                    if (decode == ShaderDecode.Bra || decode == ShaderDecode.Ssy)
                    {
                        int offset = ((int)(opCode >> 20) << 8) >> 8;

                        long target = position + offset;

                        dbgOpCode += " (0x" + target.ToString("x16") + ")";
                    }

                    block.AddNode(new ShaderIrCmnt(dbgOpCode));
                }

                if (decode == null)
                {
                    continue;
                }

                decode(block, opCode, position);
            }while (!IsFlowChange(block.GetLastNode()));

            block.EndPosition = position;
        }
Ejemplo n.º 12
0
        private static void FillBlock(
            IGalMemory memory,
            Block block,
            ulong limitAddress,
            ulong startAddress)
        {
            ulong address = block.Address;

            do
            {
                if (address >= limitAddress)
                {
                    break;
                }

                //Ignore scheduling instructions, which are written every 32 bytes.
                if (((address - startAddress) & 0x1f) == 0)
                {
                    address += 8;

                    continue;
                }

                uint word0 = (uint)memory.ReadInt32((long)(address + 0));
                uint word1 = (uint)memory.ReadInt32((long)(address + 4));

                ulong opAddress = address;

                address += 8;

                long opCode = word0 | (long)word1 << 32;

                (InstEmitter emitter, Type opCodeType) = OpCodeTable.GetEmitter(opCode);

                if (emitter == null)
                {
                    //TODO: Warning, illegal encoding.
                    continue;
                }

                OpCode op = MakeOpCode(opCodeType, emitter, opAddress, opCode);

                block.OpCodes.Add(op);
            }while (!IsBranch(block.GetLastOp()));

            block.EndAddress = address;

            block.UpdateSsyOpCodes();
        }
Ejemplo n.º 13
0
        public GlslProgram Decompile(
            IGalMemory Memory,
            long VpAPosition,
            long VpBPosition,
            GalShaderType ShaderType)
        {
            Blocks  = ShaderDecoder.Decode(Memory, VpAPosition);
            BlocksB = ShaderDecoder.Decode(Memory, VpBPosition);

            GlslDecl DeclVpA = new GlslDecl(Blocks, ShaderType);
            GlslDecl DeclVpB = new GlslDecl(BlocksB, ShaderType);

            Decl = GlslDecl.Merge(DeclVpA, DeclVpB);

            return(Decompile());
        }
Ejemplo n.º 14
0
        private OglShaderStage ShaderStageFactory(
            IGalMemory memory,
            long position,
            long positionB,
            bool isDualVp,
            GalShaderType type)
        {
            GlslProgram program;

            GlslDecompiler decompiler = new GlslDecompiler(OglLimit.MaxUboSize, OglExtension.NvidiaDriver);

            int shaderDumpIndex = ShaderDumper.DumpIndex;

            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);
            }

            string code = program.Code;

            if (ShaderDumper.IsDumpEnabled())
            {
                code = "//Shader " + shaderDumpIndex + Environment.NewLine + code;
            }

            return(new OglShaderStage(type, code, program.Uniforms, program.Textures));
        }
Ejemplo n.º 15
0
        private OglShaderStage ShaderStageFactory(
            IGalMemory memory,
            long position,
            long positionB,
            bool isDualVp,
            GalShaderType type)
        {
            ShaderConfig config = new ShaderConfig(type, OglLimit.MaxUboSize);

            ShaderProgram program;

            if (isDualVp)
            {
                ShaderDumper.Dump(memory, position, type, "a");
                ShaderDumper.Dump(memory, positionB, type, "b");

                program = Translator.Translate(memory, (ulong)position, (ulong)positionB, config);
            }
            else
            {
                ShaderDumper.Dump(memory, position, type);

                program = Translator.Translate(memory, (ulong)position, config);
            }

            string code = program.Code;

            if (ShaderDumper.IsDumpEnabled())
            {
                int shaderDumpIndex = ShaderDumper.DumpIndex;

                code = "//Shader " + shaderDumpIndex + Environment.NewLine + code;
            }

            return(new OglShaderStage(type, code, program.Info.CBuffers, program.Info.Textures));
        }
Ejemplo n.º 16
0
        private OGLShaderStage ShaderStageFactory(
            IGalMemory Memory,
            long Position,
            long PositionB,
            bool IsDualVp,
            GalShaderType Type)
        {
            GlslProgram Program;

            GlslDecompiler Decompiler = new GlslDecompiler(OGLLimit.MaxUboSize);

            int ShaderDumpIndex = ShaderDumper.DumpIndex;

            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);
            }

            string Code = Program.Code;

            if (ShaderDumper.IsDumpEnabled())
            {
                Code = "//Shader " + ShaderDumpIndex + Environment.NewLine + Code;
            }

            return(new OGLShaderStage(Type, Code, Program.Uniforms, Program.Textures));
        }
Ejemplo n.º 17
0
        public static ShaderProgram Translate(
            IGalMemory memory,
            ulong address,
            ulong addressB,
            ShaderConfig config)
        {
            Operation[] shaderOps = DecodeShader(memory, address, config.Type);

            if (addressB != 0)
            {
                // Dual vertex shader.
                Operation[] shaderOpsB = DecodeShader(memory, addressB, config.Type);

                shaderOps = Combine(shaderOps, shaderOpsB);
            }

            BasicBlock[] irBlocks = ControlFlowGraph.MakeCfg(shaderOps);

            Dominance.FindDominators(irBlocks[0], irBlocks.Length);

            Dominance.FindDominanceFrontiers(irBlocks);

            Ssa.Rename(irBlocks);

            Optimizer.Optimize(irBlocks);

            StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(irBlocks);

            GlslProgram program = GlslGenerator.Generate(sInfo, config);

            ShaderProgramInfo spInfo = new ShaderProgramInfo(
                program.CBufferDescriptors,
                program.TextureDescriptors);

            return(new ShaderProgram(spInfo, program.Code));
        }
Ejemplo n.º 18
0
        private GlslProgram GetGlslProgram(IGalMemory Memory, long Position, GalShaderType Type)
        {
            GlslDecompiler Decompiler = new GlslDecompiler();

            return(Decompiler.Decompile(Memory, Position + 0x50, Type));
        }
Ejemplo n.º 19
0
 public void Create(IGalMemory memory, long key, GalShaderType type)
 {
     _stages.GetOrAdd(key, (stage) => ShaderStageFactory(memory, key, 0, false, type));
 }
Ejemplo n.º 20
0
        public static ShaderIrBlock[] Decode(IGalMemory Memory, long Start)
        {
            Dictionary <long, ShaderIrBlock> Visited    = new Dictionary <long, ShaderIrBlock>();
            Dictionary <long, ShaderIrBlock> VisitedEnd = new Dictionary <long, ShaderIrBlock>();

            Queue <ShaderIrBlock> Blocks = new Queue <ShaderIrBlock>();

            ShaderIrBlock Enqueue(long Position, ShaderIrBlock Source = null)
            {
                if (!Visited.TryGetValue(Position, out ShaderIrBlock Output))
                {
                    Output = new ShaderIrBlock(Position);

                    Blocks.Enqueue(Output);

                    Visited.Add(Position, Output);
                }

                if (Source != null)
                {
                    Output.Sources.Add(Source);
                }

                return(Output);
            }

            ShaderIrBlock Entry = Enqueue(Start + HeaderSize);

            while (Blocks.Count > 0)
            {
                ShaderIrBlock Current = Blocks.Dequeue();

                FillBlock(Memory, Current, Start + HeaderSize);

                //Set child blocks. "Branch" is the block the branch instruction
                //points to (when taken), "Next" is the block at the next address,
                //executed when the branch is not taken. For Unconditional Branches
                //or end of shader, Next is null.
                if (Current.Nodes.Count > 0)
                {
                    ShaderIrNode LastNode = Current.GetLastNode();

                    ShaderIrOp Op = GetInnermostOp(LastNode);

                    if (Op?.Inst == ShaderIrInst.Bra)
                    {
                        int Offset = ((ShaderIrOperImm)Op.OperandA).Value;

                        long Target = Current.EndPosition + Offset;

                        Current.Branch = Enqueue(Target, Current);
                    }

                    if (NodeHasNext(LastNode))
                    {
                        Current.Next = Enqueue(Current.EndPosition);
                    }
                }

                //If we have on the graph two blocks with the same end position,
                //then we need to split the bigger block and have two small blocks,
                //the end position of the bigger "Current" block should then be == to
                //the position of the "Smaller" block.
                while (VisitedEnd.TryGetValue(Current.EndPosition, out ShaderIrBlock Smaller))
                {
                    if (Current.Position > Smaller.Position)
                    {
                        ShaderIrBlock Temp = Smaller;

                        Smaller = Current;
                        Current = Temp;
                    }

                    Current.EndPosition = Smaller.Position;
                    Current.Next        = Smaller;
                    Current.Branch      = null;

                    Current.Nodes.RemoveRange(
                        Current.Nodes.Count - Smaller.Nodes.Count,
                        Smaller.Nodes.Count);

                    VisitedEnd[Smaller.EndPosition] = Smaller;
                }

                VisitedEnd.Add(Current.EndPosition, Current);
            }

            //Make and sort Graph blocks array by position.
            ShaderIrBlock[] Graph = new ShaderIrBlock[Visited.Count];

            while (Visited.Count > 0)
            {
                ulong FirstPos = ulong.MaxValue;

                foreach (ShaderIrBlock Block in Visited.Values)
                {
                    if (FirstPos > (ulong)Block.Position)
                    {
                        FirstPos = (ulong)Block.Position;
                    }
                }

                ShaderIrBlock Current = Visited[(long)FirstPos];

                do
                {
                    Graph[Graph.Length - Visited.Count] = Current;

                    Visited.Remove(Current.Position);

                    Current = Current.Next;
                }while (Current != null);
            }

            return(Graph);
        }
Ejemplo n.º 21
0
 public void Create(IGalMemory memory, long vpAPos, long key, GalShaderType type)
 {
     _stages.GetOrAdd(key, (stage) => ShaderStageFactory(memory, vpAPos, key, true, type));
 }
Ejemplo n.º 22
0
        public static Block[] Decode(IGalMemory memory, ulong address)
        {
            List <Block> blocks = new List <Block>();

            Queue <Block> workQueue = new Queue <Block>();

            Dictionary <ulong, Block> visited = new Dictionary <ulong, Block>();

            Block GetBlock(ulong blkAddress)
            {
                if (!visited.TryGetValue(blkAddress, out Block block))
                {
                    block = new Block(blkAddress);

                    workQueue.Enqueue(block);

                    visited.Add(blkAddress, block);
                }

                return(block);
            }

            ulong startAddress = address + HeaderSize;

            GetBlock(startAddress);

            while (workQueue.TryDequeue(out Block currBlock))
            {
                //Check if the current block is inside another block.
                if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex))
                {
                    Block nBlock = blocks[nBlkIndex];

                    if (nBlock.Address == currBlock.Address)
                    {
                        throw new InvalidOperationException("Found duplicate block address on the list.");
                    }

                    nBlock.Split(currBlock);

                    blocks.Insert(nBlkIndex + 1, currBlock);

                    continue;
                }

                //If we have a block after the current one, set the limit address.
                ulong limitAddress = ulong.MaxValue;

                if (nBlkIndex != blocks.Count)
                {
                    Block nBlock = blocks[nBlkIndex];

                    int nextIndex = nBlkIndex + 1;

                    if (nBlock.Address < currBlock.Address && nextIndex < blocks.Count)
                    {
                        limitAddress = blocks[nextIndex].Address;
                    }
                    else if (nBlock.Address > currBlock.Address)
                    {
                        limitAddress = blocks[nBlkIndex].Address;
                    }
                }

                FillBlock(memory, currBlock, limitAddress, startAddress);

                if (currBlock.OpCodes.Count != 0)
                {
                    foreach (OpCodeSsy ssyOp in currBlock.SsyOpCodes)
                    {
                        GetBlock(ssyOp.GetAbsoluteAddress());
                    }

                    //Set child blocks. "Branch" is the block the branch instruction
                    //points to (when taken), "Next" is the block at the next address,
                    //executed when the branch is not taken. For Unconditional Branches
                    //or end of program, Next is null.
                    OpCode lastOp = currBlock.GetLastOp();

                    if (lastOp is OpCodeBranch op)
                    {
                        currBlock.Branch = GetBlock(op.GetAbsoluteAddress());
                    }

                    if (!IsUnconditionalBranch(lastOp))
                    {
                        currBlock.Next = GetBlock(currBlock.EndAddress);
                    }
                }

                //Insert the new block on the list (sorted by address).
                if (blocks.Count != 0)
                {
                    Block nBlock = blocks[nBlkIndex];

                    blocks.Insert(nBlkIndex + (nBlock.Address < currBlock.Address ? 1 : 0), currBlock);
                }
                else
                {
                    blocks.Add(currBlock);
                }
            }

            foreach (Block ssyBlock in blocks.Where(x => x.SsyOpCodes.Count != 0))
            {
                for (int ssyIndex = 0; ssyIndex < ssyBlock.SsyOpCodes.Count; ssyIndex++)
                {
                    PropagateSsy(visited, ssyBlock, ssyIndex);
                }
            }

            return(blocks.ToArray());
        }
Ejemplo n.º 23
0
 public void Create(IGalMemory Memory, long Tag, GalShaderType Type)
 {
     Stages.GetOrAdd(Tag, (Key) => ShaderStageFactory(Memory, Tag, Type));
 }
Ejemplo n.º 24
0
 public void Create(IGalMemory Memory, long VpAPos, long Key, GalShaderType Type)
 {
     Stages.GetOrAdd(Key, (Stage) => ShaderStageFactory(Memory, VpAPos, Key, true, Type));
 }
Ejemplo n.º 25
0
 public void Create(IGalMemory Memory, long Key, GalShaderType Type)
 {
     Stages.GetOrAdd(Key, (Stage) => ShaderStageFactory(Memory, Key, 0, false, Type));
 }
Ejemplo n.º 26
0
        private static Operation[] DecodeShader(IGalMemory memory, ulong address, GalShaderType shaderType)
        {
            ShaderHeader header = new ShaderHeader(memory, address);

            Block[] cfg = Decoder.Decode(memory, address);

            EmitterContext context = new EmitterContext(shaderType, header);

            for (int blkIndex = 0; blkIndex < cfg.Length; blkIndex++)
            {
                Block block = cfg[blkIndex];

                context.CurrBlock = block;

                context.MarkLabel(context.GetLabel(block.Address));

                for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
                {
                    OpCode op = block.OpCodes[opIndex];

                    if (op.NeverExecute)
                    {
                        continue;
                    }

                    Operand predSkipLbl = null;

                    bool skipPredicateCheck = op.Emitter == InstEmit.Bra;

                    if (op is OpCodeSync opSync)
                    {
                        // If the instruction is a SYNC instruction with only one
                        // possible target address, then the instruction is basically
                        // just a simple branch, we can generate code similar to branch
                        // instructions, with the condition check on the branch itself.
                        skipPredicateCheck |= opSync.Targets.Count < 2;
                    }

                    if (!(op.Predicate.IsPT || skipPredicateCheck))
                    {
                        Operand label;

                        if (opIndex == block.OpCodes.Count - 1 && block.Next != null)
                        {
                            label = context.GetLabel(block.Next.Address);
                        }
                        else
                        {
                            label = Label();

                            predSkipLbl = label;
                        }

                        Operand pred = Register(op.Predicate);

                        if (op.InvertPredicate)
                        {
                            context.BranchIfTrue(label, pred);
                        }
                        else
                        {
                            context.BranchIfFalse(label, pred);
                        }
                    }

                    context.CurrOp = op;

                    op.Emitter(context);

                    if (predSkipLbl != null)
                    {
                        context.MarkLabel(predSkipLbl);
                    }
                }
            }

            return(context.GetOperations());
        }
Ejemplo n.º 27
0
 public static ShaderProgram Translate(IGalMemory memory, ulong address, ShaderConfig config)
 {
     return(Translate(memory, address, 0, config));
 }
Ejemplo n.º 28
0
        public ShaderHeader(IGalMemory memory, ulong address)
        {
            int commonWord0 = memory.ReadInt32((long)address + 0);
            int commonWord1 = memory.ReadInt32((long)address + 4);
            int commonWord2 = memory.ReadInt32((long)address + 8);
            int commonWord3 = memory.ReadInt32((long)address + 12);
            int commonWord4 = memory.ReadInt32((long)address + 16);

            SphType = commonWord0.Extract(0, 5);

            Version = commonWord0.Extract(5, 5);

            ShaderType = commonWord0.Extract(10, 4);

            MrtEnable = commonWord0.Extract(14);

            KillsPixels = commonWord0.Extract(15);

            DoesGlobalStore = commonWord0.Extract(16);

            SassVersion = commonWord0.Extract(17, 4);

            DoesLoadOrStore = commonWord0.Extract(26);

            DoesFp64 = commonWord0.Extract(27);

            StreamOutMask = commonWord0.Extract(28, 4);

            ShaderLocalMemoryLowSize = commonWord1.Extract(0, 24);

            PerPatchAttributeCount = commonWord1.Extract(24, 8);

            ShaderLocalMemoryHighSize = commonWord2.Extract(0, 24);

            ThreadsPerInputPrimitive = commonWord2.Extract(24, 8);

            ShaderLocalMemoryCrsSize = commonWord3.Extract(0, 24);

            OutputTopology = commonWord3.Extract(24, 4);

            MaxOutputVertexCount = commonWord4.Extract(0, 12);

            StoreReqStart = commonWord4.Extract(12, 8);
            StoreReqEnd   = commonWord4.Extract(24, 8);

            int type2OmapTarget = memory.ReadInt32((long)address + 72);
            int type2Omap       = memory.ReadInt32((long)address + 76);

            OmapTargets = new OutputMapTarget[8];

            for (int offset = 0; offset < OmapTargets.Length * 4; offset += 4)
            {
                OmapTargets[offset >> 2] = new OutputMapTarget(
                    type2OmapTarget.Extract(offset + 0),
                    type2OmapTarget.Extract(offset + 1),
                    type2OmapTarget.Extract(offset + 2),
                    type2OmapTarget.Extract(offset + 3));
            }

            OmapSampleMask = type2Omap.Extract(0);
            OmapDepth      = type2Omap.Extract(1);
        }
Ejemplo n.º 29
0
        public static ShaderIrBlock[] Decode(IGalMemory memory, long start)
        {
            Dictionary <int, ShaderIrBlock> visited    = new Dictionary <int, ShaderIrBlock>();
            Dictionary <int, ShaderIrBlock> visitedEnd = new Dictionary <int, ShaderIrBlock>();

            Queue <ShaderIrBlock> blocks = new Queue <ShaderIrBlock>();

            long beginning = start + HeaderSize;

            ShaderIrBlock Enqueue(int position, ShaderIrBlock source = null)
            {
                if (!visited.TryGetValue(position, out ShaderIrBlock output))
                {
                    output = new ShaderIrBlock(position);

                    blocks.Enqueue(output);

                    visited.Add(position, output);
                }

                if (source != null)
                {
                    output.Sources.Add(source);
                }

                return(output);
            }

            ShaderIrBlock entry = Enqueue(0);

            while (blocks.Count > 0)
            {
                ShaderIrBlock current = blocks.Dequeue();

                FillBlock(memory, current, beginning);

                //Set child blocks. "Branch" is the block the branch instruction
                //points to (when taken), "Next" is the block at the next address,
                //executed when the branch is not taken. For Unconditional Branches
                //or end of shader, Next is null.
                if (current.Nodes.Count > 0)
                {
                    ShaderIrNode lastNode = current.GetLastNode();

                    ShaderIrOp innerOp = GetInnermostOp(lastNode);

                    if (innerOp?.Inst == ShaderIrInst.Bra)
                    {
                        int target = ((ShaderIrOperImm)innerOp.OperandA).Value;

                        current.Branch = Enqueue(target, current);
                    }

                    foreach (ShaderIrNode node in current.Nodes)
                    {
                        innerOp = GetInnermostOp(node);

                        if (innerOp is ShaderIrOp currOp && currOp.Inst == ShaderIrInst.Ssy)
                        {
                            int target = ((ShaderIrOperImm)currOp.OperandA).Value;

                            Enqueue(target, current);
                        }
                    }

                    if (NodeHasNext(lastNode))
                    {
                        current.Next = Enqueue(current.EndPosition);
                    }
                }

                //If we have on the graph two blocks with the same end position,
                //then we need to split the bigger block and have two small blocks,
                //the end position of the bigger "Current" block should then be == to
                //the position of the "Smaller" block.
                while (visitedEnd.TryGetValue(current.EndPosition, out ShaderIrBlock smaller))
                {
                    if (current.Position > smaller.Position)
                    {
                        ShaderIrBlock temp = smaller;

                        smaller = current;
                        current = temp;
                    }

                    current.EndPosition = smaller.Position;
                    current.Next        = smaller;
                    current.Branch      = null;

                    current.Nodes.RemoveRange(
                        current.Nodes.Count - smaller.Nodes.Count,
                        smaller.Nodes.Count);

                    visitedEnd[smaller.EndPosition] = smaller;
                }

                visitedEnd.Add(current.EndPosition, current);
            }

            //Make and sort Graph blocks array by position.
            ShaderIrBlock[] graph = new ShaderIrBlock[visited.Count];

            while (visited.Count > 0)
            {
                uint firstPos = uint.MaxValue;

                foreach (ShaderIrBlock block in visited.Values)
                {
                    if (firstPos > (uint)block.Position)
                    {
                        firstPos = (uint)block.Position;
                    }
                }

                ShaderIrBlock current = visited[(int)firstPos];

                do
                {
                    graph[graph.Length - visited.Count] = current;

                    visited.Remove(current.Position);

                    current = current.Next;
                }while (current != null);
            }

            return(graph);
        }