private static void SetUserAttributeUses(ShaderConfig config, IOpCodeAttribute opAttr) { if (opAttr.Indexed) { if (opAttr.Emitter == InstEmit.Ast) { config.SetAllOutputUserAttributes(); } else { config.SetAllInputUserAttributes(); } } else { for (int elemIndex = 0; elemIndex < opAttr.Count; elemIndex++) { int attr = opAttr.AttributeOffset + elemIndex * 4; if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd) { int index = (attr - AttributeConsts.UserAttributeBase) / 16; if (opAttr.Emitter == InstEmit.Ast) { config.SetOutputUserAttribute(index); } else { config.SetInputUserAttribute(index); } } } } }
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); } } } }
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) { for (int elemIndex = 0; elemIndex < opAttr.Count; elemIndex++) { int attr = opAttr.AttributeOffset + elemIndex * 4; if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd) { int index = (attr - AttributeConsts.UserAttributeBase) / 16; if (op.Emitter == InstEmit.Ast) { config.SetOutputUserAttribute(index); } else { config.SetInputUserAttribute(index); } } } } block.OpCodes.Add(op); }while (!IsControlFlowChange(block.GetLastOp())); block.EndAddress = address; block.UpdatePushOps(); }