示例#1
0
 public ShaderConfig(ShaderHeader header, TranslationFlags flags, TranslatorCallbacks callbacks)
 {
     Stage             = header.Stage;
     OutputTopology    = header.OutputTopology;
     MaxOutputVertices = header.MaxOutputVertexCount;
     OmapTargets       = header.OmapTargets;
     OmapSampleMask    = header.OmapSampleMask;
     OmapDepth         = header.OmapDepth;
     Flags             = flags;
     _callbacks        = callbacks;
 }
示例#2
0
 public ShaderConfig(TranslationFlags flags, TranslatorCallbacks callbacks)
 {
     Stage             = ShaderStage.Compute;
     OutputTopology    = OutputTopology.PointList;
     MaxOutputVertices = 0;
     OmapTargets       = null;
     OmapSampleMask    = false;
     OmapDepth         = false;
     Flags             = flags;
     _callbacks        = callbacks;
 }
示例#3
0
 public ShaderConfig(ShaderHeader header, TranslationFlags flags, TranslatorCallbacks callbacks)
 {
     Stage             = header.Stage;
     OutputTopology    = header.OutputTopology;
     MaxOutputVertices = header.MaxOutputVertexCount;
     LocalMemorySize   = header.ShaderLocalMemoryLowSize + header.ShaderLocalMemoryHighSize;
     ImapTypes         = header.ImapTypes;
     OmapTargets       = header.OmapTargets;
     OmapSampleMask    = header.OmapSampleMask;
     OmapDepth         = header.OmapDepth;
     Flags             = flags;
     _callbacks        = callbacks;
 }
示例#4
0
        private static Operation[] DecodeShader(
            ReadOnlySpan <byte> code,
            TranslatorCallbacks callbacks,
            TranslationFlags flags,
            out ShaderConfig config,
            out int size)
        {
            Block[] cfg;

            if ((flags & TranslationFlags.Compute) != 0)
            {
                config = new ShaderConfig(flags, callbacks);

                cfg = Decoder.Decode(code, 0);
            }
            else
            {
                config = new ShaderConfig(new ShaderHeader(code), flags, callbacks);

                cfg = Decoder.Decode(code, HeaderSize);
            }

            if (cfg == null)
            {
                config.PrintLog("Invalid branch detected, failed to build CFG.");

                size = 0;

                return(Array.Empty <Operation>());
            }

            EmitterContext context = new EmitterContext(config);

            ulong maxEndAddress = 0;

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

                if (maxEndAddress < block.EndAddress)
                {
                    maxEndAddress = block.EndAddress;
                }

                context.CurrBlock = block;

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

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

                    if ((flags & TranslationFlags.DebugMode) != 0)
                    {
                        string instName;

                        if (op.Emitter != null)
                        {
                            instName = op.Emitter.Method.Name;
                        }
                        else
                        {
                            instName = "???";

                            config.PrintLog($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16}).");
                        }

                        string dbgComment = $"0x{op.Address:X6}: 0x{op.RawOpCode:X16} {instName}";

                        context.Add(new CommentNode(dbgComment));
                    }

                    if (op.NeverExecute)
                    {
                        continue;
                    }

                    Operand predSkipLbl = null;

                    bool skipPredicateCheck = op is OpCodeBranch opBranch && !opBranch.PushTarget;

                    if (op is OpCodeBranchPop opBranchPop)
                    {
                        // If the instruction is a SYNC or BRK 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 = opBranchPop.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?.Invoke(context);

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

            size = (int)maxEndAddress + (((flags & TranslationFlags.Compute) != 0) ? 0 : HeaderSize);

            return(context.GetOperations());
        }
示例#5
0
        public static ShaderProgram Translate(ReadOnlySpan <byte> vpACode, ReadOnlySpan <byte> vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags)
        {
            Operation[] vpAOps = DecodeShader(vpACode, callbacks, flags, out _, out _);
            Operation[] vpBOps = DecodeShader(vpBCode, callbacks, flags, out ShaderConfig config, out int sizeB);

            return(Translate(Combine(vpAOps, vpBOps), config, sizeB));
        }
示例#6
0
        public static ShaderProgram Translate(ReadOnlySpan <byte> code, TranslatorCallbacks callbacks, TranslationFlags flags)
        {
            Operation[] ops = DecodeShader(code, callbacks, flags, out ShaderConfig config, out int size);

            return(Translate(ops, config, size));
        }