private static void FillBlock( IGpuAccessor gpuAccessor, Block block, ulong limitAddress, ulong startAddress) { 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.OpActivator opActivator) = OpCodeTable.GetEmitter(opCode); if (emitter == null) { // TODO: Warning, illegal encoding. block.OpCodes.Add(new OpCode(null, opAddress, opCode)); continue; } if (opActivator == null) { throw new ArgumentNullException(nameof(opActivator)); } OpCode op = (OpCode)opActivator(emitter, opAddress, opCode); block.OpCodes.Add(op); }while (!IsBranch(block.GetLastOp())); block.EndAddress = address; block.UpdatePushOps(); }
private static bool HasBlockAfter(IGpuAccessor gpuAccessor, Block currBlock, ulong startAdddress) { if (!gpuAccessor.MemoryMapped(startAdddress + currBlock.EndAddress) || !gpuAccessor.MemoryMapped(startAdddress + currBlock.EndAddress + 7)) { return(false); } ulong inst = gpuAccessor.MemoryRead <ulong>(startAdddress + currBlock.EndAddress); return(inst != 0UL && inst != ShaderEndDelimiter); }
public ShaderHeader(IGpuAccessor gpuAccessor, ulong address) { int commonWord0 = gpuAccessor.MemoryRead <int>(address + 0); int commonWord1 = gpuAccessor.MemoryRead <int>(address + 4); int commonWord2 = gpuAccessor.MemoryRead <int>(address + 8); int commonWord3 = gpuAccessor.MemoryRead <int>(address + 12); int commonWord4 = gpuAccessor.MemoryRead <int>(address + 16); SphType = commonWord0.Extract(0, 5); Version = commonWord0.Extract(5, 5); Stage = (ShaderStage)commonWord0.Extract(10, 4); // Invalid. if (Stage == ShaderStage.Compute) { Stage = ShaderStage.Vertex; } MrtEnable = commonWord0.Extract(14); KillsPixels = commonWord0.Extract(15); DoesGlobalStore = commonWord0.Extract(16); SassVersion = commonWord0.Extract(17, 4); GpPassthrough = commonWord0.Extract(24); 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 = (OutputTopology)commonWord3.Extract(24, 4); MaxOutputVertexCount = commonWord4.Extract(0, 12); StoreReqStart = commonWord4.Extract(12, 8); StoreReqEnd = commonWord4.Extract(24, 8); ImapTypes = new ImapPixelType[32]; for (ulong i = 0; i < 32; i++) { byte imap = gpuAccessor.MemoryRead <byte>(address + 0x18 + i); ImapTypes[i] = new ImapPixelType( (PixelImap)((imap >> 0) & 3), (PixelImap)((imap >> 2) & 3), (PixelImap)((imap >> 4) & 3), (PixelImap)((imap >> 6) & 3)); } int type2OmapTarget = gpuAccessor.MemoryRead <int>(address + 0x48); int type2Omap = gpuAccessor.MemoryRead <int>(address + 0x4c); OmapTargets = new OmapTarget[8]; for (int offset = 0; offset < OmapTargets.Length * 4; offset += 4) { OmapTargets[offset >> 2] = new OmapTarget( type2OmapTarget.Extract(offset + 0), type2OmapTarget.Extract(offset + 1), type2OmapTarget.Extract(offset + 2), type2OmapTarget.Extract(offset + 3)); } OmapSampleMask = type2Omap.Extract(0); OmapDepth = type2Omap.Extract(1); }
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(); }