Esempio n. 1
0
        private static void FillBlock(ShaderConfig config, Block block, ulong limitAddress, ulong startAddress)
        {
            IGpuAccessor gpuAccessor = config.GpuAccessor;

            ulong address               = block.Address;
            int   bufferOffset          = 0;
            ReadOnlySpan <ulong> buffer = ReadOnlySpan <ulong> .Empty;

            InstOp op = default;

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

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

                if (bufferOffset >= buffer.Length)
                {
                    buffer       = gpuAccessor.GetCode(startAddress + address, 8);
                    bufferOffset = 0;
                }

                ulong opCode = buffer[bufferOffset++];

                op = InstTable.GetOp(address, opCode);

                if (op.Props.HasFlag(InstProps.TexB))
                {
                    config.SetUsedFeature(FeatureFlags.Bindless);
                }

                if (op.Name == InstName.Ald || op.Name == InstName.Ast || op.Name == InstName.Ipa)
                {
                    SetUserAttributeUses(config, op.Name, opCode);
                }
                else if (op.Name == InstName.Ssy || op.Name == InstName.Pbk)
                {
                    block.AddPushOp(op);
                }

                block.OpCodes.Add(op);

                address += 8;
            }while (!op.Props.HasFlag(InstProps.Bra));

            block.EndAddress = address;
        }
Esempio n. 2
0
        private static void SetUserAttributeUses(ShaderConfig config, InstName name, ulong opCode)
        {
            int  offset;
            int  count    = 1;
            bool isStore  = false;
            bool indexed  = false;
            bool perPatch = false;

            if (name == InstName.Ast)
            {
                InstAst opAst = new InstAst(opCode);
                count    = (int)opAst.AlSize + 1;
                offset   = opAst.Imm11;
                indexed  = opAst.Phys;
                perPatch = opAst.P;
                isStore  = true;
            }
            else if (name == InstName.Ald)
            {
                InstAld opAld = new InstAld(opCode);
                count    = (int)opAld.AlSize + 1;
                offset   = opAld.Imm11;
                indexed  = opAld.Phys;
                perPatch = opAld.P;
                isStore  = opAld.O;
            }
            else /* if (name == InstName.Ipa) */
            {
                InstIpa opIpa = new InstIpa(opCode);
                offset  = opIpa.Imm10;
                indexed = opIpa.Idx;
            }

            if (indexed)
            {
                if (isStore)
                {
                    config.SetAllOutputUserAttributes();
                }
                else
                {
                    config.SetAllInputUserAttributes();
                }
            }
            else
            {
                for (int elemIndex = 0; elemIndex < count; elemIndex++)
                {
                    int attr = offset + elemIndex * 4;
                    if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
                    {
                        int index = (attr - AttributeConsts.UserAttributeBase) / 16;

                        if (isStore)
                        {
                            config.SetOutputUserAttribute(index, perPatch);
                        }
                        else
                        {
                            config.SetInputUserAttribute(index, perPatch);
                        }
                    }

                    if (!isStore &&
                        ((attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.ClipDistance0) ||
                         (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd)))
                    {
                        config.SetUsedFeature(FeatureFlags.FixedFuncAttr);
                    }
                }
            }
        }
Esempio n. 3
0
        private static void FillBlock(ShaderConfig config, Block block, ulong limitAddress, ulong startAddress)
        {
            IGpuAccessor gpuAccessor = config.GpuAccessor;

            ulong address = block.Address;

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

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

                    continue;
                }

                ulong opAddress = address;

                address += 8;

                long opCode = gpuAccessor.MemoryRead <long>(startAddress + opAddress);

                (InstEmitter emitter, OpCodeTable.MakeOp makeOp) = OpCodeTable.GetEmitter(opCode);

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

                    block.OpCodes.Add(new OpCode(null, opAddress, opCode));

                    continue;
                }

                if (makeOp == null)
                {
                    throw new ArgumentNullException(nameof(makeOp));
                }

                OpCode op = makeOp(emitter, opAddress, opCode);

                // We check these patterns to figure out the presence of bindless access
                if ((op is OpCodeImage image && image.IsBindless) ||
                    (op is OpCodeTxd txd && txd.IsBindless) ||
                    (op is OpCodeTld4B) ||
                    (emitter == InstEmit.TexB) ||
                    (emitter == InstEmit.TldB) ||
                    (emitter == InstEmit.TmmlB) ||
                    (emitter == InstEmit.TxqB))
                {
                    config.SetUsedFeature(FeatureFlags.Bindless);
                }

                // Populate used attributes.
                if (op is IOpCodeAttribute opAttr)
                {
                    SetUserAttributeUses(config, opAttr);
                }

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

            block.EndAddress = address;

            block.UpdatePushOps();
        }