Esempio n. 1
0
        private static ShaderProgram Translate(Operation[] ops, ShaderConfig config, int size)
        {
            BasicBlock[] blocks = ControlFlowGraph.MakeCfg(ops);

            if (blocks.Length > 0)
            {
                Dominance.FindDominators(blocks[0], blocks.Length);

                Dominance.FindDominanceFrontiers(blocks);

                Ssa.Rename(blocks);

                Optimizer.RunPass(blocks, config);

                Lowering.RunPass(blocks, config);
            }

            StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(blocks, config);

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

            ShaderProgramInfo spInfo = new ShaderProgramInfo(
                program.CBufferDescriptors,
                program.SBufferDescriptors,
                program.TextureDescriptors,
                program.ImageDescriptors,
                sInfo.UsesInstanceId);

            string glslCode = program.Code;

            return(new ShaderProgram(spInfo, config.Stage, glslCode, size));
        }
Esempio n. 2
0
 public void MergeFromtNextStage(ShaderConfig config)
 {
     NextInputAttributesComponents         = config.ThisInputAttributesComponents;
     NextInputAttributesPerPatchComponents = config.ThisInputAttributesPerPatchComponents;
     NextUsesFixedFuncAttributes           = config.UsedFeatures.HasFlag(FeatureFlags.FixedFuncAttr);
     MergeOutputUserAttributes(config.UsedInputAttributes, config.UsedInputAttributesPerPatch);
 }
Esempio n. 3
0
        public static AttributeInfo From(ShaderConfig config, int value)
        {
            value &= ~3;

            if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
            {
                int location = (value - AttributeConsts.UserAttributeBase) / 16;
                var elemType = config.GpuAccessor.QueryAttributeType(location) switch
                {
                    AttributeType.Sint => AggregateType.S32,
                    AttributeType.Uint => AggregateType.U32,
                    _ => AggregateType.FP32
                };

                return(new AttributeInfo(value, 4, AggregateType.Vector | elemType, false));
            }
            else if (value >= AttributeConsts.FragmentOutputColorBase && value < AttributeConsts.FragmentOutputColorEnd)
            {
                return(new AttributeInfo(value, 4, AggregateType.Vector | AggregateType.FP32, false));
            }
            else if (BuiltInAttributes.TryGetValue(value, out AttributeInfo info))
            {
                return(info);
            }

            return(new AttributeInfo(value, 0, AggregateType.Invalid));
        }
Esempio n. 4
0
 public EmitterContext(DecodedProgram program, ShaderConfig config, bool isNonMain)
 {
     Program     = program;
     Config      = config;
     IsNonMain   = isNonMain;
     _operations = new List <Operation>();
     _labels     = new Dictionary <ulong, Operand>();
 }
Esempio n. 5
0
        private static Block[][] DecodeShader(
            ulong address,
            IGpuAccessor gpuAccessor,
            TranslationOptions options,
            TranslationCounts counts,
            out ShaderConfig config)
        {
            Block[][] cfg;
            ulong     maxEndAddress = 0;

            bool hasBindless;

            if ((options.Flags & TranslationFlags.Compute) != 0)
            {
                config = new ShaderConfig(gpuAccessor, options, counts);

                cfg = Decoder.Decode(gpuAccessor, address, out hasBindless);
            }
            else
            {
                config = new ShaderConfig(new ShaderHeader(gpuAccessor, address), gpuAccessor, options, counts);

                cfg = Decoder.Decode(gpuAccessor, address + HeaderSize, out hasBindless);
            }

            if (hasBindless)
            {
                config.SetUsedFeature(FeatureFlags.Bindless);
            }

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

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

                    if (!hasBindless)
                    {
                        for (int index = 0; index < block.OpCodes.Count; index++)
                        {
                            if (block.OpCodes[index] is OpCodeTextureBase texture)
                            {
                                config.TextureHandlesForCache.Add(texture.HandleOffset);
                            }
                        }
                    }
                }
            }

            config.SizeAdd((int)maxEndAddress + (options.Flags.HasFlag(TranslationFlags.Compute) ? 0 : HeaderSize));

            return(cfg);
        }
Esempio n. 6
0
 internal TranslatorContext(ulong addressA, ulong addressB, Block[][] cfgA, Block[][] cfgB, ShaderConfig configA, ShaderConfig configB)
 {
     Address  = addressB;
     AddressA = addressA;
     _config  = configB;
     _configA = configA;
     _cfg     = cfgB;
     _cfgA    = cfgA;
 }
Esempio n. 7
0
 internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config)
 {
     Address  = address;
     AddressA = 0;
     _config  = config;
     _configA = null;
     _cfg     = cfg;
     _cfgA    = null;
 }
Esempio n. 8
0
        public void MergeFromtNextStage(ShaderConfig config)
        {
            NextInputAttributesComponents         = config.ThisInputAttributesComponents;
            NextInputAttributesPerPatchComponents = config.ThisInputAttributesPerPatchComponents;
            NextUsesFixedFuncAttributes           = config.UsedFeatures.HasFlag(FeatureFlags.FixedFuncAttr);
            MergeOutputUserAttributes(config.UsedInputAttributes, config.UsedInputAttributesPerPatch);

            if (config.Stage != ShaderStage.Fragment)
            {
                LastInVertexPipeline = false;
            }
        }
Esempio n. 9
0
 private static void ScanForBindless(BasicBlock[] blocks, ShaderConfig config)
 {
     for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
     {
         // Right now the guest shader cache cannot handle bindless textures correctly.
         for (LinkedListNode <INode> node = blocks[blkIndex].Operations.First; node != null; node = node.Next)
         {
             if (node.Value is TextureOperation texOp && (texOp.Flags & TextureFlags.Bindless) != 0)
             {
                 config.SetUsedFeature(FeatureFlags.Bindless);
                 break;
             }
         }
     }
 }
Esempio n. 10
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());
        }
Esempio n. 11
0
 internal TranslatorContext(ulong address, DecodedProgram program, ShaderConfig config)
 {
     Address  = address;
     _program = program;
     _config  = config;
 }