unit pm4_pfp; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses sysutils, mqueue, bittype, pm4_ring, pm4defs, pm4_stream, time, md_sleep, si_ci_vi_merged_offset, si_ci_vi_merged_enum, si_ci_vi_merged_registers, si_ci_vi_merged_groups; type p_pfp_ctx=^t_pfp_ctx; t_pm4_parse_cb=function(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; p_pm4_ibuffer=^t_pm4_ibuffer; t_pm4_ibuffer=record next:TAILQ_ENTRY; base:Pointer; buff:Pointer; size:Ptruint; bpos:Ptruint; picb:t_pm4_parse_cb; buft:t_pm4_stream_type; c_id:Byte; end; t_flush_stream=procedure(var stream:t_pm4_stream) of object; t_pfp_ctx=object freen:TAILQ_HEAD; stall:array[t_pm4_stream_type] of TAILQ_HEAD; // stream:array[t_pm4_stream_type] of t_pm4_stream; // on_flush_stream:t_flush_stream; // SG_REG:TSH_REG_GFX_GROUP; // 0x2C00 SC_REG:TSH_REG_COMPUTE_GROUP; // 0x2E00 CX_REG:TCONTEXT_REG_GROUP; // 0xA000 UC_REG:TUSERCONFIG_REG_SHORT; // 0xC000 // ASC_COMPUTE:array[0..63] of TSH_REG_COMPUTE_GROUP; // curr_ibuf :p_pm4_ibuffer; // LastSetReg:Word; event:PRTLEvent; // function stream_type:t_pm4_stream_type; procedure init; procedure add_stall(ibuf:p_pm4_ibuffer); procedure free; // Procedure Flush_stream(t:t_pm4_stream_type); // procedure set_esgs_gsvs_ring_size(esgsRingSize,gsvsRingSize:DWORD); // procedure set_reg(i:word;data:DWORD); procedure set_sh_reg(i:word;data:DWORD); procedure set_sh_reg_compute(i:word;data:DWORD); procedure set_ctx_reg(i:word;data:DWORD); function get_reg(i:word):DWORD; procedure clear_state; end; function pm4_ibuf_init(ibuf:p_pm4_ibuffer; buff:Pointer; size:Ptruint; icb:t_pm4_parse_cb; buft:t_pm4_stream_type; c_id:Byte=0):Boolean; function pm4_ibuf_init(ibuf:p_pm4_ibuffer; buf:PPM4CMDINDIRECTBUFFER; icb:t_pm4_parse_cb; buft:t_pm4_stream_type):Boolean; function pm4_ibuf_parse(pctx:p_pfp_ctx;ibuf:p_pm4_ibuffer):Integer; function pm4_parse_ccb(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; function pm4_parse_dcb(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; function pm4_parse_compute_ring(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; implementation uses sys_bootparam, kern_dmem, kern_proc, vm_map, vm_tracking_map; function PM4_TYPE(token:DWORD):Byte; inline; begin Result:=(token shr 30) and 3; end; function PM4_LENGTH(token:DWORD):DWORD; inline; begin Result:=((token shr 14) and $FFFC) + 8; end; function pm4_ibuf_init(ibuf:p_pm4_ibuffer; buff:Pointer; size:Ptruint; icb:t_pm4_parse_cb; buft:t_pm4_stream_type; c_id:Byte=0):Boolean; begin Result:=True; ibuf^.next:=Default(TAILQ_ENTRY); ibuf^.base:=nil; ibuf^.buff:=buff; ibuf^.size:=size; ibuf^.bpos:=0; ibuf^.picb:=icb; ibuf^.buft:=buft; ibuf^.c_id:=c_id; end; function pm4_ibuf_init(ibuf:p_pm4_ibuffer; buf:PPM4CMDINDIRECTBUFFER; icb:t_pm4_parse_cb; buft:t_pm4_stream_type):Boolean; var ib_base:QWORD; ib_size:QWORD; addr:Pointer; begin Result:=False; case buf^.header.opcode of IT_INDIRECT_BUFFER_CNST:; IT_INDIRECT_BUFFER :; else begin Writeln('init not indirect buffer:0x',HexStr(DWORD(buf^.header),8)); Assert(false,'init not indirect buffer'); end; end; ib_base:=QWORD(buf^.ibBase); ib_size:=QWORD(buf^.ibSize)*sizeof(DWORD); addr:=get_dmem_ptr(Pointer(ib_base)); //Writeln(' addr:0x'+HexStr(ib_base,16)+' '+HexStr(ib_size,16)); ibuf^.next:=Default(TAILQ_ENTRY); ibuf^.base:=Pointer(ib_base); //adjust guest addr ibuf^.buff:=addr; ibuf^.size:=ib_size; ibuf^.bpos:=0; ibuf^.picb:=icb; ibuf^.buft:=buft; ibuf^.c_id:=0; Result:=True; end; function pm4_ibuf_parse(pctx:p_pfp_ctx;ibuf:p_pm4_ibuffer):Integer; var buff:Pointer; i,token,len:DWORD; begin Result:=0; pctx^.curr_ibuf :=ibuf; case pctx^.stream_type of stGfxDcb, stGfxCcb:pctx^.LastSetReg:=0; else; end; i:=ibuf^.bpos; buff:=ibuf^.buff+i; i:=ibuf^.size-i; while (i<>0) do begin token:=PDWORD(buff)^; if (PM4_TYPE(token)=2) then begin len:=sizeof(DWORD); end else begin len:=PM4_LENGTH(token); end; if (len>i) then begin i:=0; Break; end; Result:=ibuf^.picb(pctx,token,buff); if (Result<>0) then begin Break; end; Inc(buff,len); Dec(i,len); end; ibuf^.bpos:=ibuf^.size-i; pctx^.curr_ibuf:=nil; end; function t_pfp_ctx.stream_type:t_pm4_stream_type; begin Result:=curr_ibuf^.buft; end; procedure t_pfp_ctx.init; var i:t_pm4_stream_type; begin for i:=Low(t_pm4_stream_type) to High(t_pm4_stream_type) do begin stream[i]:=Default(t_pm4_stream); stream[i].buft:=i; end; end; procedure t_pfp_ctx.add_stall(ibuf:p_pm4_ibuffer); var node:p_pm4_ibuffer; buft:t_pm4_stream_type; begin node:=TAILQ_FIRST(@freen); if (node<>nil) then begin TAILQ_REMOVE(@freen,node,@node^.next); end else begin node:=AllocMem(SizeOf(t_pm4_ibuffer)); end; node^:=ibuf^; buft:=node^.buft; if (stall[buft].tqh_last=nil) then begin TAILQ_INIT(@stall[buft]); end; TAILQ_INSERT_TAIL(@stall[buft],node,@node^.next); end; procedure free_nodes(head:P_TAILQ_HEAD); var node:p_pm4_ibuffer; begin node:=TAILQ_FIRST(head); while (node<>nil) do begin TAILQ_REMOVE(head,node,@node^.next); FreeMem(node); node:=TAILQ_FIRST(head); end; end; procedure t_pfp_ctx.free; var i:t_pm4_stream_type; begin free_nodes(@freen); for i:=Low(t_pm4_stream_type) to High(t_pm4_stream_type) do begin free_nodes(@stall[i]); end; end; Procedure t_pfp_ctx.Flush_stream(t:t_pm4_stream_type); begin Assert(on_flush_stream<>nil,'on_flush_stream'); on_flush_stream(stream[t]); end; procedure t_pfp_ctx.set_esgs_gsvs_ring_size(esgsRingSize,gsvsRingSize:DWORD); begin UC_REG.VGT_ESGS_RING_SIZE:=esgsRingSize; UC_REG.VGT_GSVS_RING_SIZE:=gsvsRingSize; end; procedure t_pfp_ctx.set_reg(i:word;data:DWORD); begin case i of $2C00..$2D8C:PDWORD(@SG_REG)[i-$2C00]:=data; $2E00..$2E7F:PDWORD(@SC_REG)[i-$2E00]:=data; $A000..$A38F:PDWORD(@CX_REG)[i-$A000]:=data; $C079:PDWORD(@UC_REG.CP_COHER_BASE_HI )^:=data; $C07C:PDWORD(@UC_REG.CP_COHER_CNTL )^:=data; $C07D:PDWORD(@UC_REG.CP_COHER_SIZE )^:=data; $C07E:PDWORD(@UC_REG.CP_COHER_BASE )^:=data; $C08C:PDWORD(@UC_REG.CP_COHER_SIZE_HI )^:=data; $C200:PDWORD(@UC_REG.GRBM_GFX_INDEX )^:=data; $C240:PDWORD(@UC_REG.VGT_ESGS_RING_SIZE)^:=data; $C241:PDWORD(@UC_REG.VGT_GSVS_RING_SIZE)^:=data; $C242:PDWORD(@UC_REG.VGT_PRIMITIVE_TYPE)^:=data; $C243:PDWORD(@UC_REG.VGT_INDEX_TYPE )^:=data; $C24C:PDWORD(@UC_REG.VGT_NUM_INDICES )^:=data; $C24D:PDWORD(@UC_REG.VGT_NUM_INSTANCES )^:=data; $C258:PDWORD(@CX_REG.IA_MULTI_VGT_PARAM)^:=data; else if p_print_gpu_ops then begin Writeln(stderr,'Unknow:',getRegName(i),':=0x',HexStr(data,8)); end; end; end; procedure t_pfp_ctx.set_sh_reg(i:word;data:DWORD); begin case i of $000..$18C:PDWORD(@SG_REG)[i]:=data; $200..$27F:PDWORD(@SC_REG)[i-$200]:=data; else if p_print_gpu_ops then begin Writeln(stderr,'Unknow:',getRegName(i+$2C00),':=0x',HexStr(data,8)); end; end; end; procedure t_pfp_ctx.set_sh_reg_compute(i:word;data:DWORD); var c_id:Byte; begin c_id:=curr_ibuf^.c_id; case i of $200..$27F:PDWORD(@ASC_COMPUTE[c_id])[i-$200]:=data; else if p_print_gpu_ops then begin Writeln(stderr,'Unknow:',getRegName(i+$2C00),':=0x',HexStr(data,8)); end; end; end; procedure t_pfp_ctx.set_ctx_reg(i:word;data:DWORD); begin if (i<=$38F) then begin PDWORD(@CX_REG)[i]:=data; end else if p_print_gpu_ops then begin Writeln(stderr,'Unknow:',getRegName(i+$A000),':=0x',HexStr(data,8)); end; end; function t_pfp_ctx.get_reg(i:word):DWORD; begin case i of $2C00..$2D8C:Result:=PDWORD(@SG_REG)[i-$2C00]; $2E00..$2E7F:Result:=PDWORD(@SC_REG)[i-$2E00]; $A000..$A38F:Result:=PDWORD(@CX_REG)[i-$A000]; $C079:Result:=PDWORD(@UC_REG.CP_COHER_BASE_HI )^; $C07C:Result:=PDWORD(@UC_REG.CP_COHER_CNTL )^; $C07D:Result:=PDWORD(@UC_REG.CP_COHER_SIZE )^; $C07E:Result:=PDWORD(@UC_REG.CP_COHER_BASE )^; $C08C:Result:=PDWORD(@UC_REG.CP_COHER_SIZE_HI )^; $C200:Result:=PDWORD(@UC_REG.GRBM_GFX_INDEX )^; $C240:Result:=PDWORD(@UC_REG.VGT_ESGS_RING_SIZE)^; $C241:Result:=PDWORD(@UC_REG.VGT_GSVS_RING_SIZE)^; $C242:Result:=PDWORD(@UC_REG.VGT_PRIMITIVE_TYPE)^; $C243:Result:=PDWORD(@UC_REG.VGT_INDEX_TYPE )^; $C24C:Result:=PDWORD(@UC_REG.VGT_NUM_INDICES )^; $C24D:Result:=PDWORD(@UC_REG.VGT_NUM_INSTANCES )^; $C258:Result:=PDWORD(@CX_REG.IA_MULTI_VGT_PARAM)^; else Result:=0; end; end; procedure t_pfp_ctx.clear_state; begin PDWORD(@CX_REG)[$000]:=$00000000; PDWORD(@CX_REG)[$001]:=$00000000; PDWORD(@CX_REG)[$002]:=$00000000; PDWORD(@CX_REG)[$003]:=$00000000; PDWORD(@CX_REG)[$004]:=$00000000; PDWORD(@CX_REG)[$005]:=$00000000; PDWORD(@CX_REG)[$008]:=$00000000; PDWORD(@CX_REG)[$009]:=$00000000; PDWORD(@CX_REG)[$00a]:=$00000000; PDWORD(@CX_REG)[$00b]:=$00000000; PDWORD(@CX_REG)[$00c]:=$00000000; PDWORD(@CX_REG)[$00d]:=$40004000; PDWORD(@CX_REG)[$00f]:=$00000000; PDWORD(@CX_REG)[$010]:=$00000000; PDWORD(@CX_REG)[$011]:=$00000000; PDWORD(@CX_REG)[$012]:=$00000000; PDWORD(@CX_REG)[$013]:=$00000000; PDWORD(@CX_REG)[$014]:=$00000000; PDWORD(@CX_REG)[$015]:=$00000000; PDWORD(@CX_REG)[$016]:=$00000000; PDWORD(@CX_REG)[$017]:=$00000000; PDWORD(@CX_REG)[$020]:=$00000000; PDWORD(@CX_REG)[$021]:=$00000000; PDWORD(@CX_REG)[$07a]:=$00000000; PDWORD(@CX_REG)[$07b]:=$00000000; PDWORD(@CX_REG)[$07c]:=$00000000; PDWORD(@CX_REG)[$07d]:=$00000000; PDWORD(@CX_REG)[$07e]:=$00000000; PDWORD(@CX_REG)[$07f]:=$00000000; PDWORD(@CX_REG)[$080]:=$00000000; PDWORD(@CX_REG)[$081]:=$80000000; PDWORD(@CX_REG)[$082]:=$40004000; PDWORD(@CX_REG)[$084]:=$00000000; PDWORD(@CX_REG)[$085]:=$40004000; PDWORD(@CX_REG)[$086]:=$00000000; PDWORD(@CX_REG)[$087]:=$40004000; PDWORD(@CX_REG)[$088]:=$00000000; PDWORD(@CX_REG)[$089]:=$40004000; PDWORD(@CX_REG)[$08a]:=$00000000; PDWORD(@CX_REG)[$08b]:=$40004000; PDWORD(@CX_REG)[$08c]:=$aa99aaaa; PDWORD(@CX_REG)[$08d]:=$00000000; PDWORD(@CX_REG)[$090]:=$80000000; PDWORD(@CX_REG)[$091]:=$40004000; PDWORD(@CX_REG)[$092]:=$00000000; PDWORD(@CX_REG)[$093]:=$00000000; PDWORD(@CX_REG)[$094]:=$80000000; PDWORD(@CX_REG)[$095]:=$40004000; PDWORD(@CX_REG)[$096]:=$80000000; PDWORD(@CX_REG)[$097]:=$40004000; PDWORD(@CX_REG)[$098]:=$80000000; PDWORD(@CX_REG)[$099]:=$40004000; PDWORD(@CX_REG)[$09a]:=$80000000; PDWORD(@CX_REG)[$09b]:=$40004000; PDWORD(@CX_REG)[$09c]:=$80000000; PDWORD(@CX_REG)[$09d]:=$40004000; PDWORD(@CX_REG)[$09e]:=$80000000; PDWORD(@CX_REG)[$09f]:=$40004000; PDWORD(@CX_REG)[$0a0]:=$80000000; PDWORD(@CX_REG)[$0a1]:=$40004000; PDWORD(@CX_REG)[$0a2]:=$80000000; PDWORD(@CX_REG)[$0a3]:=$40004000; PDWORD(@CX_REG)[$0a4]:=$80000000; PDWORD(@CX_REG)[$0a5]:=$40004000; PDWORD(@CX_REG)[$0a6]:=$80000000; PDWORD(@CX_REG)[$0a7]:=$40004000; PDWORD(@CX_REG)[$0a8]:=$80000000; PDWORD(@CX_REG)[$0a9]:=$40004000; PDWORD(@CX_REG)[$0aa]:=$80000000; PDWORD(@CX_REG)[$0ab]:=$40004000; PDWORD(@CX_REG)[$0ac]:=$80000000; PDWORD(@CX_REG)[$0ad]:=$40004000; PDWORD(@CX_REG)[$0ae]:=$80000000; PDWORD(@CX_REG)[$0af]:=$40004000; PDWORD(@CX_REG)[$0b0]:=$80000000; PDWORD(@CX_REG)[$0b1]:=$40004000; PDWORD(@CX_REG)[$0b2]:=$80000000; PDWORD(@CX_REG)[$0b3]:=$40004000; PDWORD(@CX_REG)[$0b4]:=$00000000; PDWORD(@CX_REG)[$0b5]:=$3f800000; PDWORD(@CX_REG)[$0b6]:=$00000000; PDWORD(@CX_REG)[$0b7]:=$3f800000; PDWORD(@CX_REG)[$0b8]:=$00000000; PDWORD(@CX_REG)[$0b9]:=$3f800000; PDWORD(@CX_REG)[$0ba]:=$00000000; PDWORD(@CX_REG)[$0bb]:=$3f800000; PDWORD(@CX_REG)[$0bc]:=$00000000; PDWORD(@CX_REG)[$0bd]:=$3f800000; PDWORD(@CX_REG)[$0be]:=$00000000; PDWORD(@CX_REG)[$0bf]:=$3f800000; PDWORD(@CX_REG)[$0c0]:=$00000000; PDWORD(@CX_REG)[$0c1]:=$3f800000; PDWORD(@CX_REG)[$0c2]:=$00000000; PDWORD(@CX_REG)[$0c3]:=$3f800000; PDWORD(@CX_REG)[$0c4]:=$00000000; PDWORD(@CX_REG)[$0c5]:=$3f800000; PDWORD(@CX_REG)[$0c6]:=$00000000; PDWORD(@CX_REG)[$0c7]:=$3f800000; PDWORD(@CX_REG)[$0c8]:=$00000000; PDWORD(@CX_REG)[$0c9]:=$3f800000; PDWORD(@CX_REG)[$0ca]:=$00000000; PDWORD(@CX_REG)[$0cb]:=$3f800000; PDWORD(@CX_REG)[$0cc]:=$00000000; PDWORD(@CX_REG)[$0cd]:=$3f800000; PDWORD(@CX_REG)[$0ce]:=$00000000; PDWORD(@CX_REG)[$0cf]:=$3f800000; PDWORD(@CX_REG)[$0d0]:=$00000000; PDWORD(@CX_REG)[$0d1]:=$3f800000; PDWORD(@CX_REG)[$0d2]:=$00000000; PDWORD(@CX_REG)[$0d3]:=$3f800000; PDWORD(@CX_REG)[$0d4]:=$2a00161a; PDWORD(@CX_REG)[$0d5]:=$00000000; PDWORD(@CX_REG)[$0d6]:=$00000000; PDWORD(@CX_REG)[$0d8]:=$00000000; PDWORD(@CX_REG)[$103]:=$00000000; PDWORD(@CX_REG)[$105]:=$00000000; PDWORD(@CX_REG)[$106]:=$00000000; PDWORD(@CX_REG)[$107]:=$00000000; PDWORD(@CX_REG)[$108]:=$00000000; PDWORD(@CX_REG)[$10b]:=$00000000; PDWORD(@CX_REG)[$10c]:=$00000000; PDWORD(@CX_REG)[$10d]:=$00000000; PDWORD(@CX_REG)[$10f]:=$00000000; PDWORD(@CX_REG)[$110]:=$00000000; PDWORD(@CX_REG)[$111]:=$00000000; PDWORD(@CX_REG)[$112]:=$00000000; PDWORD(@CX_REG)[$113]:=$00000000; PDWORD(@CX_REG)[$114]:=$00000000; PDWORD(@CX_REG)[$115]:=$00000000; PDWORD(@CX_REG)[$116]:=$00000000; PDWORD(@CX_REG)[$117]:=$00000000; PDWORD(@CX_REG)[$118]:=$00000000; PDWORD(@CX_REG)[$119]:=$00000000; PDWORD(@CX_REG)[$11a]:=$00000000; PDWORD(@CX_REG)[$11b]:=$00000000; PDWORD(@CX_REG)[$11c]:=$00000000; PDWORD(@CX_REG)[$11d]:=$00000000; PDWORD(@CX_REG)[$11e]:=$00000000; PDWORD(@CX_REG)[$11f]:=$00000000; PDWORD(@CX_REG)[$120]:=$00000000; PDWORD(@CX_REG)[$121]:=$00000000; PDWORD(@CX_REG)[$122]:=$00000000; PDWORD(@CX_REG)[$123]:=$00000000; PDWORD(@CX_REG)[$124]:=$00000000; PDWORD(@CX_REG)[$125]:=$00000000; PDWORD(@CX_REG)[$126]:=$00000000; PDWORD(@CX_REG)[$127]:=$00000000; PDWORD(@CX_REG)[$128]:=$00000000; PDWORD(@CX_REG)[$129]:=$00000000; PDWORD(@CX_REG)[$12a]:=$00000000; PDWORD(@CX_REG)[$12b]:=$00000000; PDWORD(@CX_REG)[$12c]:=$00000000; PDWORD(@CX_REG)[$12d]:=$00000000; PDWORD(@CX_REG)[$12e]:=$00000000; PDWORD(@CX_REG)[$12f]:=$00000000; PDWORD(@CX_REG)[$130]:=$00000000; PDWORD(@CX_REG)[$131]:=$00000000; PDWORD(@CX_REG)[$132]:=$00000000; PDWORD(@CX_REG)[$133]:=$00000000; PDWORD(@CX_REG)[$134]:=$00000000; PDWORD(@CX_REG)[$135]:=$00000000; PDWORD(@CX_REG)[$136]:=$00000000; PDWORD(@CX_REG)[$137]:=$00000000; PDWORD(@CX_REG)[$138]:=$00000000; PDWORD(@CX_REG)[$139]:=$00000000; PDWORD(@CX_REG)[$13a]:=$00000000; PDWORD(@CX_REG)[$13b]:=$00000000; PDWORD(@CX_REG)[$13c]:=$00000000; PDWORD(@CX_REG)[$13d]:=$00000000; PDWORD(@CX_REG)[$13e]:=$00000000; PDWORD(@CX_REG)[$13f]:=$00000000; PDWORD(@CX_REG)[$140]:=$00000000; PDWORD(@CX_REG)[$141]:=$00000000; PDWORD(@CX_REG)[$142]:=$00000000; PDWORD(@CX_REG)[$143]:=$00000000; PDWORD(@CX_REG)[$144]:=$00000000; PDWORD(@CX_REG)[$145]:=$00000000; PDWORD(@CX_REG)[$146]:=$00000000; PDWORD(@CX_REG)[$147]:=$00000000; PDWORD(@CX_REG)[$148]:=$00000000; PDWORD(@CX_REG)[$149]:=$00000000; PDWORD(@CX_REG)[$14a]:=$00000000; PDWORD(@CX_REG)[$14b]:=$00000000; PDWORD(@CX_REG)[$14c]:=$00000000; PDWORD(@CX_REG)[$14d]:=$00000000; PDWORD(@CX_REG)[$14e]:=$00000000; PDWORD(@CX_REG)[$14f]:=$00000000; PDWORD(@CX_REG)[$150]:=$00000000; PDWORD(@CX_REG)[$151]:=$00000000; PDWORD(@CX_REG)[$152]:=$00000000; PDWORD(@CX_REG)[$153]:=$00000000; PDWORD(@CX_REG)[$154]:=$00000000; PDWORD(@CX_REG)[$155]:=$00000000; PDWORD(@CX_REG)[$156]:=$00000000; PDWORD(@CX_REG)[$157]:=$00000000; PDWORD(@CX_REG)[$158]:=$00000000; PDWORD(@CX_REG)[$159]:=$00000000; PDWORD(@CX_REG)[$15a]:=$00000000; PDWORD(@CX_REG)[$15b]:=$00000000; PDWORD(@CX_REG)[$15c]:=$00000000; PDWORD(@CX_REG)[$15d]:=$00000000; PDWORD(@CX_REG)[$15e]:=$00000000; PDWORD(@CX_REG)[$15f]:=$00000000; PDWORD(@CX_REG)[$160]:=$00000000; PDWORD(@CX_REG)[$161]:=$00000000; PDWORD(@CX_REG)[$162]:=$00000000; PDWORD(@CX_REG)[$163]:=$00000000; PDWORD(@CX_REG)[$164]:=$00000000; PDWORD(@CX_REG)[$165]:=$00000000; PDWORD(@CX_REG)[$166]:=$00000000; PDWORD(@CX_REG)[$167]:=$00000000; PDWORD(@CX_REG)[$168]:=$00000000; PDWORD(@CX_REG)[$169]:=$00000000; PDWORD(@CX_REG)[$16a]:=$00000000; PDWORD(@CX_REG)[$16b]:=$00000000; PDWORD(@CX_REG)[$16c]:=$00000000; PDWORD(@CX_REG)[$16d]:=$00000000; PDWORD(@CX_REG)[$16e]:=$00000000; PDWORD(@CX_REG)[$16f]:=$00000000; PDWORD(@CX_REG)[$170]:=$00000000; PDWORD(@CX_REG)[$171]:=$00000000; PDWORD(@CX_REG)[$172]:=$00000000; PDWORD(@CX_REG)[$173]:=$00000000; PDWORD(@CX_REG)[$174]:=$00000000; PDWORD(@CX_REG)[$175]:=$00000000; PDWORD(@CX_REG)[$176]:=$00000000; PDWORD(@CX_REG)[$177]:=$00000000; PDWORD(@CX_REG)[$178]:=$00000000; PDWORD(@CX_REG)[$179]:=$00000000; PDWORD(@CX_REG)[$17a]:=$00000000; PDWORD(@CX_REG)[$17b]:=$00000000; PDWORD(@CX_REG)[$17c]:=$00000000; PDWORD(@CX_REG)[$17d]:=$00000000; PDWORD(@CX_REG)[$17e]:=$00000000; PDWORD(@CX_REG)[$17f]:=$00000000; PDWORD(@CX_REG)[$180]:=$00000000; PDWORD(@CX_REG)[$181]:=$00000000; PDWORD(@CX_REG)[$182]:=$00000000; PDWORD(@CX_REG)[$183]:=$00000000; PDWORD(@CX_REG)[$184]:=$00000000; PDWORD(@CX_REG)[$185]:=$00000000; PDWORD(@CX_REG)[$186]:=$00000000; PDWORD(@CX_REG)[$191]:=$00000000; PDWORD(@CX_REG)[$192]:=$00000000; PDWORD(@CX_REG)[$193]:=$00000000; PDWORD(@CX_REG)[$194]:=$00000000; PDWORD(@CX_REG)[$195]:=$00000000; PDWORD(@CX_REG)[$196]:=$00000000; PDWORD(@CX_REG)[$197]:=$00000000; PDWORD(@CX_REG)[$198]:=$00000000; PDWORD(@CX_REG)[$199]:=$00000000; PDWORD(@CX_REG)[$19a]:=$00000000; PDWORD(@CX_REG)[$19b]:=$00000000; PDWORD(@CX_REG)[$19c]:=$00000000; PDWORD(@CX_REG)[$19d]:=$00000000; PDWORD(@CX_REG)[$19e]:=$00000000; PDWORD(@CX_REG)[$19f]:=$00000000; PDWORD(@CX_REG)[$1a0]:=$00000000; PDWORD(@CX_REG)[$1a1]:=$00000000; PDWORD(@CX_REG)[$1a2]:=$00000000; PDWORD(@CX_REG)[$1a3]:=$00000000; PDWORD(@CX_REG)[$1a4]:=$00000000; PDWORD(@CX_REG)[$1a5]:=$00000000; PDWORD(@CX_REG)[$1a6]:=$00000000; PDWORD(@CX_REG)[$1a7]:=$00000000; PDWORD(@CX_REG)[$1a8]:=$00000000; PDWORD(@CX_REG)[$1a9]:=$00000000; PDWORD(@CX_REG)[$1aa]:=$00000000; PDWORD(@CX_REG)[$1ab]:=$00000000; PDWORD(@CX_REG)[$1ac]:=$00000000; PDWORD(@CX_REG)[$1ad]:=$00000000; PDWORD(@CX_REG)[$1ae]:=$00000000; PDWORD(@CX_REG)[$1af]:=$00000000; PDWORD(@CX_REG)[$1b0]:=$00000000; PDWORD(@CX_REG)[$1b1]:=$00000000; PDWORD(@CX_REG)[$1b3]:=$00000000; PDWORD(@CX_REG)[$1b4]:=$00000000; PDWORD(@CX_REG)[$1b5]:=$00000000; PDWORD(@CX_REG)[$1b6]:=$00000002; PDWORD(@CX_REG)[$1b8]:=$00000000; PDWORD(@CX_REG)[$1ba]:=$00000000; PDWORD(@CX_REG)[$1c3]:=$00000000; PDWORD(@CX_REG)[$1c4]:=$00000000; PDWORD(@CX_REG)[$1c5]:=$00000000; PDWORD(@CX_REG)[$1e0]:=$00000000; PDWORD(@CX_REG)[$1e1]:=$00000000; PDWORD(@CX_REG)[$1e2]:=$00000000; PDWORD(@CX_REG)[$1e3]:=$00000000; PDWORD(@CX_REG)[$1e4]:=$00000000; PDWORD(@CX_REG)[$1e5]:=$00000000; PDWORD(@CX_REG)[$1e6]:=$00000000; PDWORD(@CX_REG)[$1e7]:=$00000000; PDWORD(@CX_REG)[$1f5]:=$00000000; PDWORD(@CX_REG)[$1f6]:=$00000000; PDWORD(@CX_REG)[$1f7]:=$00000000; PDWORD(@CX_REG)[$1f8]:=$00000000; PDWORD(@CX_REG)[$200]:=$00000000; PDWORD(@CX_REG)[$201]:=$00000000; PDWORD(@CX_REG)[$202]:=$00000000; PDWORD(@CX_REG)[$203]:=$00000000; PDWORD(@CX_REG)[$204]:=$00090000; PDWORD(@CX_REG)[$205]:=$00000004; PDWORD(@CX_REG)[$206]:=$00000000; PDWORD(@CX_REG)[$207]:=$00000000; PDWORD(@CX_REG)[$208]:=$00000000; PDWORD(@CX_REG)[$209]:=$00000000; PDWORD(@CX_REG)[$20a]:=$00000000; PDWORD(@CX_REG)[$20b]:=$00000000; PDWORD(@CX_REG)[$280]:=$00000000; PDWORD(@CX_REG)[$281]:=$00000000; PDWORD(@CX_REG)[$282]:=$00000000; PDWORD(@CX_REG)[$283]:=$00000000; PDWORD(@CX_REG)[$284]:=$00000000; PDWORD(@CX_REG)[$285]:=$00000000; PDWORD(@CX_REG)[$286]:=$00000000; PDWORD(@CX_REG)[$287]:=$00000000; PDWORD(@CX_REG)[$288]:=$00000000; PDWORD(@CX_REG)[$289]:=$00000000; PDWORD(@CX_REG)[$28a]:=$00000000; PDWORD(@CX_REG)[$28b]:=$00000000; PDWORD(@CX_REG)[$28c]:=$00000000; PDWORD(@CX_REG)[$28d]:=$00000000; PDWORD(@CX_REG)[$28e]:=$00000000; PDWORD(@CX_REG)[$28f]:=$00000000; PDWORD(@CX_REG)[$290]:=$00000000; PDWORD(@CX_REG)[$291]:=$00000000; PDWORD(@CX_REG)[$292]:=$00000000; PDWORD(@CX_REG)[$293]:=$00000000; PDWORD(@CX_REG)[$294]:=$00000000; PDWORD(@CX_REG)[$295]:=$00000100; PDWORD(@CX_REG)[$296]:=$00000080; PDWORD(@CX_REG)[$297]:=$00000002; PDWORD(@CX_REG)[$298]:=$00000000; PDWORD(@CX_REG)[$299]:=$00000000; PDWORD(@CX_REG)[$29a]:=$00000000; PDWORD(@CX_REG)[$29b]:=$00000000; PDWORD(@CX_REG)[$29c]:=$00000000; PDWORD(@CX_REG)[$2a0]:=$00000000; PDWORD(@CX_REG)[$2a1]:=$00000000; PDWORD(@CX_REG)[$2a3]:=$00000000; PDWORD(@CX_REG)[$2a5]:=$00000000; PDWORD(@CX_REG)[$2a8]:=$00000000; PDWORD(@CX_REG)[$2a9]:=$00000000; PDWORD(@CX_REG)[$2aa]:=$000000ff; PDWORD(@CX_REG)[$2ab]:=$00000000; PDWORD(@CX_REG)[$2ac]:=$00000000; PDWORD(@CX_REG)[$2ad]:=$00000000; PDWORD(@CX_REG)[$2ae]:=$00000000; PDWORD(@CX_REG)[$2af]:=$00000000; PDWORD(@CX_REG)[$2b0]:=$00000000; PDWORD(@CX_REG)[$2b1]:=$00000000; PDWORD(@CX_REG)[$2b2]:=$00000000; PDWORD(@CX_REG)[$2b4]:=$00000000; PDWORD(@CX_REG)[$2b5]:=$00000000; PDWORD(@CX_REG)[$2b7]:=$00000000; PDWORD(@CX_REG)[$2b8]:=$00000000; PDWORD(@CX_REG)[$2b9]:=$00000000; PDWORD(@CX_REG)[$2bb]:=$00000000; PDWORD(@CX_REG)[$2bc]:=$00000000; PDWORD(@CX_REG)[$2bd]:=$00000000; PDWORD(@CX_REG)[$2bf]:=$00000000; PDWORD(@CX_REG)[$2c0]:=$00000000; PDWORD(@CX_REG)[$2c1]:=$00000000; PDWORD(@CX_REG)[$2c3]:=$00000000; PDWORD(@CX_REG)[$2ca]:=$00000000; PDWORD(@CX_REG)[$2cb]:=$00000000; PDWORD(@CX_REG)[$2cc]:=$00000000; PDWORD(@CX_REG)[$2ce]:=$00000000; PDWORD(@CX_REG)[$2d5]:=$00000000; PDWORD(@CX_REG)[$2d6]:=$00000000; PDWORD(@CX_REG)[$2d7]:=$00000000; PDWORD(@CX_REG)[$2d8]:=$00000000; PDWORD(@CX_REG)[$2d9]:=$00000000; PDWORD(@CX_REG)[$2da]:=$00000000; PDWORD(@CX_REG)[$2db]:=$00000000; PDWORD(@CX_REG)[$2dc]:=$00000000; PDWORD(@CX_REG)[$2dd]:=$00000000; PDWORD(@CX_REG)[$2de]:=$00000000; PDWORD(@CX_REG)[$2df]:=$00000000; PDWORD(@CX_REG)[$2e0]:=$00000000; PDWORD(@CX_REG)[$2e1]:=$00000000; PDWORD(@CX_REG)[$2e2]:=$00000000; PDWORD(@CX_REG)[$2e3]:=$00000000; PDWORD(@CX_REG)[$2e4]:=$00000000; PDWORD(@CX_REG)[$2e5]:=$00000000; PDWORD(@CX_REG)[$2e6]:=$00000000; PDWORD(@CX_REG)[$2f5]:=$00000000; PDWORD(@CX_REG)[$2f6]:=$00000000; PDWORD(@CX_REG)[$2f7]:=$00001000; PDWORD(@CX_REG)[$2f8]:=$00000000; PDWORD(@CX_REG)[$2f9]:=$00000005; PDWORD(@CX_REG)[$2fa]:=$3f800000; PDWORD(@CX_REG)[$2fb]:=$3f800000; PDWORD(@CX_REG)[$2fc]:=$3f800000; PDWORD(@CX_REG)[$2fd]:=$3f800000; PDWORD(@CX_REG)[$2fe]:=$00000000; PDWORD(@CX_REG)[$2ff]:=$00000000; PDWORD(@CX_REG)[$300]:=$00000000; PDWORD(@CX_REG)[$301]:=$00000000; PDWORD(@CX_REG)[$302]:=$00000000; PDWORD(@CX_REG)[$303]:=$00000000; PDWORD(@CX_REG)[$304]:=$00000000; PDWORD(@CX_REG)[$305]:=$00000000; PDWORD(@CX_REG)[$306]:=$00000000; PDWORD(@CX_REG)[$307]:=$00000000; PDWORD(@CX_REG)[$308]:=$00000000; PDWORD(@CX_REG)[$309]:=$00000000; PDWORD(@CX_REG)[$30a]:=$00000000; PDWORD(@CX_REG)[$30b]:=$00000000; PDWORD(@CX_REG)[$30c]:=$00000000; PDWORD(@CX_REG)[$30d]:=$00000000; PDWORD(@CX_REG)[$316]:=$0000000e; PDWORD(@CX_REG)[$317]:=$00000010; PDWORD(@CX_REG)[$318]:=$00000000; PDWORD(@CX_REG)[$319]:=$00000000; PDWORD(@CX_REG)[$31a]:=$00000000; PDWORD(@CX_REG)[$31b]:=$00000000; PDWORD(@CX_REG)[$31c]:=$00000000; PDWORD(@CX_REG)[$31d]:=$00000000; PDWORD(@CX_REG)[$31f]:=$00000000; PDWORD(@CX_REG)[$320]:=$00000000; PDWORD(@CX_REG)[$321]:=$00000000; PDWORD(@CX_REG)[$322]:=$00000000; PDWORD(@CX_REG)[$323]:=$00000000; PDWORD(@CX_REG)[$324]:=$00000000; PDWORD(@CX_REG)[$327]:=$00000000; PDWORD(@CX_REG)[$328]:=$00000000; PDWORD(@CX_REG)[$329]:=$00000000; PDWORD(@CX_REG)[$32a]:=$00000000; PDWORD(@CX_REG)[$32b]:=$00000000; PDWORD(@CX_REG)[$32c]:=$00000000; PDWORD(@CX_REG)[$32e]:=$00000000; PDWORD(@CX_REG)[$32f]:=$00000000; PDWORD(@CX_REG)[$330]:=$00000000; PDWORD(@CX_REG)[$331]:=$00000000; PDWORD(@CX_REG)[$332]:=$00000000; PDWORD(@CX_REG)[$333]:=$00000000; PDWORD(@CX_REG)[$336]:=$00000000; PDWORD(@CX_REG)[$337]:=$00000000; PDWORD(@CX_REG)[$338]:=$00000000; PDWORD(@CX_REG)[$339]:=$00000000; PDWORD(@CX_REG)[$33a]:=$00000000; PDWORD(@CX_REG)[$33b]:=$00000000; PDWORD(@CX_REG)[$33d]:=$00000000; PDWORD(@CX_REG)[$33e]:=$00000000; PDWORD(@CX_REG)[$33f]:=$00000000; PDWORD(@CX_REG)[$340]:=$00000000; PDWORD(@CX_REG)[$341]:=$00000000; PDWORD(@CX_REG)[$342]:=$00000000; PDWORD(@CX_REG)[$345]:=$00000000; PDWORD(@CX_REG)[$346]:=$00000000; PDWORD(@CX_REG)[$347]:=$00000000; PDWORD(@CX_REG)[$348]:=$00000000; PDWORD(@CX_REG)[$349]:=$00000000; PDWORD(@CX_REG)[$34a]:=$00000000; PDWORD(@CX_REG)[$34c]:=$00000000; PDWORD(@CX_REG)[$34d]:=$00000000; PDWORD(@CX_REG)[$34e]:=$00000000; PDWORD(@CX_REG)[$34f]:=$00000000; PDWORD(@CX_REG)[$350]:=$00000000; PDWORD(@CX_REG)[$351]:=$00000000; PDWORD(@CX_REG)[$354]:=$00000000; PDWORD(@CX_REG)[$355]:=$00000000; PDWORD(@CX_REG)[$356]:=$00000000; PDWORD(@CX_REG)[$357]:=$00000000; PDWORD(@CX_REG)[$358]:=$00000000; PDWORD(@CX_REG)[$359]:=$00000000; PDWORD(@CX_REG)[$35b]:=$00000000; PDWORD(@CX_REG)[$35c]:=$00000000; PDWORD(@CX_REG)[$35d]:=$00000000; PDWORD(@CX_REG)[$35e]:=$00000000; PDWORD(@CX_REG)[$35f]:=$00000000; PDWORD(@CX_REG)[$360]:=$00000000; PDWORD(@CX_REG)[$363]:=$00000000; PDWORD(@CX_REG)[$364]:=$00000000; PDWORD(@CX_REG)[$365]:=$00000000; PDWORD(@CX_REG)[$366]:=$00000000; PDWORD(@CX_REG)[$367]:=$00000000; PDWORD(@CX_REG)[$368]:=$00000000; PDWORD(@CX_REG)[$36a]:=$00000000; PDWORD(@CX_REG)[$36b]:=$00000000; PDWORD(@CX_REG)[$36c]:=$00000000; PDWORD(@CX_REG)[$36d]:=$00000000; PDWORD(@CX_REG)[$36e]:=$00000000; PDWORD(@CX_REG)[$36f]:=$00000000; PDWORD(@CX_REG)[$372]:=$00000000; PDWORD(@CX_REG)[$373]:=$00000000; PDWORD(@CX_REG)[$374]:=$00000000; PDWORD(@CX_REG)[$375]:=$00000000; PDWORD(@CX_REG)[$376]:=$00000000; PDWORD(@CX_REG)[$377]:=$00000000; PDWORD(@CX_REG)[$379]:=$00000000; PDWORD(@CX_REG)[$37a]:=$00000000; PDWORD(@CX_REG)[$37b]:=$00000000; PDWORD(@CX_REG)[$37c]:=$00000000; PDWORD(@CX_REG)[$37d]:=$00000000; PDWORD(@CX_REG)[$37e]:=$00000000; PDWORD(@CX_REG)[$381]:=$00000000; PDWORD(@CX_REG)[$382]:=$00000000; PDWORD(@CX_REG)[$383]:=$00000000; PDWORD(@CX_REG)[$384]:=$00000000; PDWORD(@CX_REG)[$385]:=$00000000; PDWORD(@CX_REG)[$386]:=$00000000; PDWORD(@CX_REG)[$388]:=$00000000; PDWORD(@CX_REG)[$389]:=$00000000; PDWORD(@CX_REG)[$38a]:=$00000000; PDWORD(@CX_REG)[$38b]:=$00000000; PDWORD(@CX_REG)[$38c]:=$00000000; PDWORD(@CX_REG)[$38d]:=$00000000; end; /// procedure onLoadConstRam(pctx:p_pfp_ctx;Body:PPM4CMDCONSTRAMLOAD); begin Assert(pctx^.stream_type=stGfxCcb); { Writeln(' adr=0x',HexStr(Body^.addr,16)); Writeln(' len=0x',HexStr(Body^.numDwords*4,4)); Writeln(' ofs=0x',HexStr(Body^.offset,4)); } pctx^.stream[stGfxCcb].LoadConstRam(Pointer(Body^.addr and (not QWORD(31))), Body^.numDwords and (not 7), Body^.offset and (not 31)); end; function PM4_BODY_LENGTH_DW(header:PM4_TYPE_3_HEADER;sizeof:WORD):WORD; inline; begin Result:=header.count + 2; sizeof:=sizeof div 4; if (Result>sizeof) then begin Result:=Result-sizeof; end else begin Result:=0; end; end; procedure onWriteConstRam(pctx:p_pfp_ctx;Body:PPM4CMDCONSTRAMWRITE); var count:Word; src:PDWORD; src_dmem:PDWORD; begin Assert(pctx^.stream_type=stGfxCcb); count:=PM4_BODY_LENGTH_DW(Body^.header,SizeOf(PM4CMDCONSTRAMWRITE)); if (count=0) then Exit; src_dmem:=@Body^.data; //convert src_dmem -> src with pctx^.curr_ibuf^ do begin src:=base+(Int64(src_dmem)-Int64(buff)); end; pctx^.stream[stGfxCcb].LoadConstRam(src,count,Body^.offset and (not 3)); end; procedure onDumpConstRam(pctx:p_pfp_ctx;Body:PPM4CMDCONSTRAMDUMP); begin Assert(pctx^.stream_type=stGfxCcb); Assert(Body^.incrementCs=0); Assert(Body^.incrementCe=0); pctx^.stream[stGfxCcb].DumpConstRam(Pointer(Body^.addr and (not QWORD(3))), Body^.numDwords, Body^.offset and (not 3)); end; procedure onIncrementCECounter(pctx:p_pfp_ctx;Body:Pointer); begin Assert(pctx^.stream_type=stGfxCcb); pctx^.stream[stGfxCcb].IncrementCE(); end; procedure onIncrementDECounter(pctx:p_pfp_ctx;Body:Pointer); begin Assert(pctx^.stream_type=stGfxDcb); pctx^.stream[stGfxDcb].IncrementDE(); end; procedure onWaitOnCECounter(pctx:p_pfp_ctx;Body:PPM4CMDWAITONCECOUNTER); begin Assert(pctx^.stream_type=stGfxDcb); pctx^.stream[stGfxDcb].WaitOnCECounter(); end; procedure onWaitOnDECounterDiff(pctx:p_pfp_ctx;Body:PPM4CMDWAITONDECOUNTERDIFF); begin Assert(pctx^.stream_type=stGfxCcb); //(DE_COUNT - CE_COMPARE_COUNT) < DIFF pctx^.stream[stGfxCcb].WaitOnDECounterDiff(Body^.counterDiff); end; const ShdrType:array[0..1] of Pchar=('(GX)','(CS)'); function pm4_parse_ccb(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; begin Result:=0; case PM4_TYPE(token) of 0:begin //PM4_TYPE_0 if p_print_gpu_ops then Writeln('PM4_TYPE_0'); end; 2:begin //PM4_TYPE_2 if p_print_gpu_ops then Writeln('PM4_TYPE_2'); //no body end; 3:begin //PM4_TYPE_3 if p_print_gpu_ops then if (PM4_TYPE_3_HEADER(token).opcode<>IT_NOP) or (not p_print_gpu_hint) then begin Writeln('IT_',get_op_name(PM4_TYPE_3_HEADER(token).opcode), ' ',ShdrType[PM4_TYPE_3_HEADER(token).shaderType], ' len:',PM4_LENGTH(token)); end; case PM4_TYPE_3_HEADER(token).opcode of IT_NOP:; IT_LOAD_CONST_RAM :onLoadConstRam (pctx,buff); IT_WRITE_CONST_RAM :onWriteConstRam (pctx,buff); IT_DUMP_CONST_RAM :onDumpConstRam (pctx,buff); IT_INCREMENT_CE_COUNTER :onIncrementCECounter (pctx,buff); IT_WAIT_ON_DE_COUNTER_DIFF:onWaitOnDECounterDiff(pctx,buff); else begin Writeln(stderr,'PM4_TYPE_3.opcode:',get_op_name(PM4_TYPE_3_HEADER(token).opcode)); Assert(False); end; end; end; else begin Writeln(stderr,'PM4_TYPE_',PM4_TYPE(token)); Assert(False); end; end; end; procedure FlushAndWaitMe(pctx:p_pfp_ctx); var event:PRTLEvent; begin if (pctx^.stream_type=stGfxDcb) then begin if (pctx^.event=nil) then begin pctx^.event:=RTLEventCreate; end; event:=pctx^.event; pctx^.stream[stGfxDcb].PfpSyncMe(event); pctx^.Flush_stream(stGfxDcb); RTLEventWaitFor(event); end; end; procedure onEventWrite(pctx:p_pfp_ctx;Body:PTPM4CMDEVENTWRITE); begin Assert(pctx^.stream_type=stGfxDcb); DWORD(pctx^.CX_REG.VGT_EVENT_INITIATOR):=Body^.eventType; if p_print_gpu_ops then Case Body^.eventType of CS_PARTIAL_FLUSH :Writeln(' eventType=CS_PARTIAL_FLUSH'); CACHE_FLUSH_AND_INV_EVENT :Writeln(' eventType=FLUSH_AND_INV_EVENT'); DB_CACHE_FLUSH_AND_INV :Writeln(' eventType=DB_CACHE_FLUSH_AND_INV'); FLUSH_AND_INV_DB_DATA_TS :Writeln(' eventType=FLUSH_AND_INV_DB_DATA_TS'); FLUSH_AND_INV_DB_META :Writeln(' eventType=FLUSH_AND_INV_DB_META'); FLUSH_AND_INV_CB_DATA_TS :Writeln(' eventType=FLUSH_AND_INV_CB_DATA_TS'); FLUSH_AND_INV_CB_META :Writeln(' eventType=FLUSH_AND_INV_CB_META'); FLUSH_AND_INV_CB_PIXEL_DATA:Writeln(' eventType=FLUSH_AND_INV_CB_PIXEL_DATA'); THREAD_TRACE_MARKER :Writeln(' eventType=THREAD_TRACE_MARKER'); PIXEL_PIPE_STAT_CONTROL :Writeln(' eventType=PIXEL_PIPE_STAT_CONTROL'); PIXEL_PIPE_STAT_DUMP :Writeln(' eventType=PIXEL_PIPE_STAT_DUMP'); PIXEL_PIPE_STAT_RESET :Writeln(' eventType=PIXEL_PIPE_STAT_RESET'); PIPELINESTAT_STOP :Writeln(' eventType=PIPELINESTAT_STOP'); PERFCOUNTER_START :Writeln(' eventType=PERFCOUNTER_START'); PERFCOUNTER_STOP :Writeln(' eventType=PERFCOUNTER_STOP'); PERFCOUNTER_SAMPLE :Writeln(' eventType=PERFCOUNTER_SAMPLE'); else Writeln(' eventType=0x',HexStr(Body^.eventType,2)); end; pctx^.stream[stGfxDcb].EventWrite(Body^.eventType); end; procedure onEventWriteEop(pctx:p_pfp_ctx;Body:PPM4CMDEVENTWRITEEOP); begin Assert(pctx^.stream_type=stGfxDcb); //FlushAndWaitMe(pctx); Case Body^.eventType of CACHE_FLUSH_TS, //FlushCbDbCaches CACHE_FLUSH_AND_INV_TS_EVENT, //FlushAndInvalidateCbDbCaches BOTTOM_OF_PIPE_TS:; //CbDbReadsDone else Assert(False,'EventWriteEop: eventType=0x'+HexStr(Body^.eventType,1)); end; if (Body^.eventIndex<>EVENT_WRITE_INDEX_ANY_EOP_TIMESTAMP) then begin Assert(False,'EventWriteEop: eventIndex=0x'+HexStr(Body^.eventIndex,1)); end; DWORD(pctx^.CX_REG.VGT_EVENT_INITIATOR):=Body^.eventType; if p_print_gpu_ops then begin Case Body^.eventType of CACHE_FLUSH_TS :Writeln(' eventType =','FlushCbDbCaches'); CACHE_FLUSH_AND_INV_TS_EVENT:Writeln(' eventType =','FlushAndInvalidateCbDbCaches'); BOTTOM_OF_PIPE_TS :Writeln(' eventType =','CbDbReadsDone'); else; end; Writeln(' interrupt =0x',HexStr(Body^.intSel,2)); Writeln(' srcSelector=0x',HexStr(Body^.dataSel,2)); Writeln(' dstGpuAddr =0x',HexStr(Body^.address,10)); Writeln(' immValue =0x',HexStr(Body^.DATA,16)); end; //if (Body^.destTcL2<>0) then Exit; //write to L2 pctx^.stream[stGfxDcb].EventWriteEop(Pointer(Body^.address),Body^.DATA,Body^.eventType,Body^.dataSel,Body^.intSel); pctx^.Flush_stream(stGfxDcb); end; procedure onEventWriteEos(pctx:p_pfp_ctx;Body:PPM4CMDEVENTWRITEEOS); begin Assert(pctx^.stream_type=stGfxDcb); //shaderType is any? //Assert(Body^.header.shaderType=1,'shaderType<>CS'); Case Body^.eventType of CS_DONE:; PS_DONE:; else Assert(False,'EventWriteEos: eventType=0x'+HexStr(Body^.eventType,1)); //Writeln(stderr,'EventWriteEos: eventType=0x'+HexStr(Body^.eventType,1)); end; if p_print_gpu_ops then Case Body^.eventType of CS_DONE:Writeln(' CS_DONE'); PS_DONE:Writeln(' PS_DONE'); else; end; if (Body^.eventIndex<>EVENT_WRITE_INDEX_ANY_EOS_TIMESTAMP) then begin Assert(False,'EventWriteEos: eventIndex=0x'+HexStr(Body^.eventIndex,1)); //Writeln(stderr,'EventWriteEos: eventIndex=0x'+HexStr(Body^.eventIndex,1)); end; DWORD(pctx^.CX_REG.VGT_EVENT_INITIATOR):=Body^.eventType; pctx^.stream[stGfxDcb].EventWriteEos(Pointer(Body^.address),Body^.data,Body^.eventType,Body^.command); //FlushAndWaitMe(pctx); end; const engine_str:array[0..3] of RawByteString=('ME','PFP','CE','3'); procedure onDmaData(pctx:p_pfp_ctx;Body:PPM4DMADATA); var adrSrc:QWORD; adrDst:QWORD; adrSrc_dmem:Pointer; adrDst_dmem:Pointer; byteCount:DWORD; srcSel,dstSel:Byte; begin //Assert(pctx^.stream_type=stGfxDcb); if (Body^.Flags2.saic=CPDMA_ADDR_SPACE_REG) then begin Assert(Body^.Flags2.saic<>0,'DmaData: read from fifo reg'); end; if (Body^.Flags2.das=CPDMA_ADDR_SPACE_REG) then begin Assert(Body^.Flags2.daic<>0,'DmaData: send to fifo reg'); end; srcSel:=((PDWORD(Body)[1] shr $1d) and 3) or ((PDWORD(Body)[6] shr $19) and 8) or ((PDWORD(Body)[6] shr $18) and 4); dstSel:=((PDWORD(Body)[1] shr $14) and 1) or ((PDWORD(Body)[6] shr $1a) and 8) or ((PDWORD(Body)[6] shr $19) and 4); adrSrc:=Body^.srcAddr; adrDst:=Body^.dstAddr; byteCount:=Body^.Flags2.byteCount; case dstSel of kDmaDataDstRegister, kDmaDataDstRegisterNoIncrement: if (DWORD(adrDst)=$3022C) then begin //prefetchIntoL2 Exit; end; else; end; Case Body^.Flags1.engine of CP_DMA_ENGINE_ME: begin if p_print_gpu_ops then begin Writeln('[1]DmaData:0x',HexStr(adrSrc,10),'->',HexStr(adrDst,10),':size=0x',HexStr(byteCount,6)); end; pctx^.stream[stGfxDcb].DmaData(dstSel,adrDst,srcSel,adrSrc,byteCount,Body^.Flags1.cpSync); end; CP_DMA_ENGINE_PFP: begin //Execute on the parser side //FlushAndWaitMe(pctx); if p_print_gpu_ops then begin Writeln('[2]DmaData:0x',HexStr(adrSrc,10),'->',HexStr(adrDst,10),':size=0x',HexStr(byteCount,6)); end; adrDst_dmem:=get_dmem_ptr(Pointer(adrDst)); case (srcSel or (dstSel shl 4)) of (kDmaDataSrcMemory or (kDmaDataDstMemory shl 4)), (kDmaDataSrcMemoryUsingL2 or (kDmaDataDstMemory shl 4)), (kDmaDataSrcMemory or (kDmaDataDstMemoryUsingL2 shl 4)), (kDmaDataSrcMemoryUsingL2 or (kDmaDataDstMemoryUsingL2 shl 4)): begin adrSrc_dmem:=get_dmem_ptr(Pointer(adrSrc)); Move(adrSrc_dmem^,adrDst_dmem^,byteCount); vm_map_track_trigger(p_proc.p_vmspace,QWORD(adrDst),QWORD(adrDst)+byteCount,nil,M_DMEM_WRITE); end; (kDmaDataSrcData or (kDmaDataDstMemory shl 4)), (kDmaDataSrcData or (kDmaDataDstMemoryUsingL2 shl 4)): begin FillDWORD(adrDst_dmem^,(byteCount div 4),DWORD(adrSrc)); vm_map_track_trigger(p_proc.p_vmspace,QWORD(adrDst),QWORD(adrDst)+byteCount,nil,M_DMEM_WRITE); end; else Assert(false,'DmaData: srcSel=0x'+HexStr(srcSel,1)+' dstSel=0x'+HexStr(dstSel,1)); end; end; else Assert(false,'DmaData: engine='+engine_str[Body^.Flags1.engine]); end; end; procedure onWriteData(pctx:p_pfp_ctx;Body:PPM4CMDWRITEDATA); var src:PDWORD; dst:PDWORD; src_dmem:PDWORD; dst_dmem:PDWORD; count:Word; engineSel:Byte; dstSel:Byte; begin if (Body^.CONTROL.dstSel=WRITE_DATA_DST_SEL_REGISTER) then begin Assert(Body^.CONTROL.wrOneAddr=0,'WriteData: send to fifo reg'); end; count:=PM4_BODY_LENGTH_DW(Body^.header,SizeOf(PM4CMDWRITEDATA)); if p_print_gpu_ops then begin Writeln(' engine =',engine_str[Body^.CONTROL.engineSel]); Writeln(' dstSel =',Body^.CONTROL.dstSel,' ',Body^.CONTROL.wrConfirm); Writeln(' dstAddr =0x',HexStr(Body^.dstAddr,10)); Writeln(' length =',count*4); case count of 1:Writeln(' data =0x',HexStr(PDWORD(@Body^.DATA)^,8 )); 2:Writeln(' data =0x',HexStr(PQWORD(@Body^.DATA)^,16)); else; end; end; if (count=0) then Exit; dst:=Pointer(Body^.dstAddr); src_dmem:=@Body^.DATA; engineSel:=Body^.CONTROL.engineSel; dstSel :=Body^.CONTROL.dstSel; Case engineSel of WRITE_DATA_ENGINE_ME: begin //convert src_dmem -> src with pctx^.curr_ibuf^ do begin src:=base+(Int64(src_dmem)-Int64(buff)); end; pctx^.stream[pctx^.stream_type].WriteData(dstSel,dst,src,count,Body^.CONTROL.wrConfirm); end; WRITE_DATA_ENGINE_PFP: begin //FlushAndWaitMe(pctx); case dstSel of WRITE_DATA_DST_SEL_MEMORY_SYNC, //writeDataInline WRITE_DATA_DST_SEL_TCL2, //writeDataInlineThroughL2 WRITE_DATA_DST_SEL_MEMORY_ASYNC: begin dst_dmem:=get_dmem_ptr(dst); Move(src_dmem^,dst_dmem^,count*SizeOf(DWORD)); vm_map_track_trigger(p_proc.p_vmspace,QWORD(dst),QWORD(dst)+count*SizeOf(DWORD),nil,M_DMEM_WRITE); end; else Assert(false,'WriteData: dstSel=0x'+HexStr(dstSel,1)); end; end; else Assert(false,'WriteData: engineSel='+engine_str[engineSel]); end; end; Function me_test_mem(pollAddr:Pointer;ref,mask:DWORD;compareFunc:Byte):Boolean; var val:DWORD; begin val:=PQWORD(pollAddr)^ and mask; Case compareFunc of WAIT_REG_MEM_FUNC_ALWAYS :Result:=True; WAIT_REG_MEM_FUNC_LESS :Result:=(valref); WAIT_REG_MEM_FUNC_GREATER_EQUAL:Result:=(val>=ref); WAIT_REG_MEM_FUNC_GREATER :Result:=(val>ref); else Assert(false,'me_test_mem'); end; end; procedure onWaitRegMem(pctx:p_pfp_ctx;Body:PPM4CMDWAITREGMEM); begin if p_print_gpu_ops then begin Writeln(' engine =',engine_str[Body^.engine]); Writeln(' memSpace =',Body^.memSpace); Writeln(' operation =',Body^.operation); Writeln(' pollAddress=0x',HexStr(Body^.pollAddress,10)); Writeln(' reference =0x',HexStr(Body^.reference,8)); Writeln(' mask =0x',HexStr(Body^.mask,8)); Writeln(' compareFunc=0x',HexStr(Body^.compareFunc,1)); end; Assert(Body^.operation=0,'WaitRegMem: operation=0x'+HexStr(Body^.operation,1)); Case Body^.memSpace of WAIT_REG_MEM_SPACE_MEMORY:; else Assert(False,'WaitRegMem: memSpace=0x'+HexStr(Body^.memSpace,1)); end; Case Body^.engine of WAIT_REG_MEM_ENGINE_ME: begin pctx^.stream[pctx^.stream_type].WaitRegMem(Pointer(Body^.pollAddress),Body^.reference,Body^.mask,Body^.compareFunc); end; WAIT_REG_MEM_ENGINE_PFP: begin pctx^.Flush_stream(pctx^.stream_type); while not me_test_mem(Pointer(Body^.pollAddress),Body^.reference,Body^.mask,Body^.compareFunc) do begin msleep_td(hz div 10000); end; end; else Assert(false,'WaitRegMem: engine='+engine_str[Body^.engine]); end; end; function revbinstr(val:int64;cnt:byte):shortstring; var i:Integer; begin Result[0]:=AnsiChar(cnt); for i:=1 to cnt do begin Result[i]:=AnsiChar(48+val and 1); val:=val shr 1; end; end; function coherCntl_str(CNTL:TCP_COHER_CNTL):shortstring; begin Result:=''; if (CNTL.DEST_BASE_0_ENA <>0) then Result:=Result+'DS_B0 '; if (CNTL.DEST_BASE_1_ENA <>0) then Result:=Result+'DS_B1 '; if (CNTL.CB0_DEST_BASE_ENA <>0) then Result:=Result+'CB0_D '; if (CNTL.CB1_DEST_BASE_ENA <>0) then Result:=Result+'CB1_D '; if (CNTL.CB2_DEST_BASE_ENA <>0) then Result:=Result+'CB2_D '; if (CNTL.CB3_DEST_BASE_ENA <>0) then Result:=Result+'CB3_D '; if (CNTL.CB4_DEST_BASE_ENA <>0) then Result:=Result+'CB4_D '; if (CNTL.CB5_DEST_BASE_ENA <>0) then Result:=Result+'CB5_D '; if (CNTL.CB6_DEST_BASE_ENA <>0) then Result:=Result+'CB6_D '; if (CNTL.CB7_DEST_BASE_ENA <>0) then Result:=Result+'CB7_D '; if (CNTL.DB_DEST_BASE_ENA <>0) then Result:=Result+'DB_DS '; if (CNTL.TCL1_VOL_ACTION_ENA <>0) then Result:=Result+'TCL1V '; if (CNTL.TC_VOL_ACTION_ENA <>0) then Result:=Result+'TC_VA '; if (CNTL.TC_WB_ACTION_ENA <>0) then Result:=Result+'TC_WB '; if (CNTL.DEST_BASE_2_ENA <>0) then Result:=Result+'DS_B2 '; if (CNTL.DEST_BASE_3_ENA <>0) then Result:=Result+'DS_B3 '; if (CNTL.TCL1_ACTION_ENA <>0) then Result:=Result+'TCL1A '; if (CNTL.TC_ACTION_ENA <>0) then Result:=Result+'TC_AC '; if (CNTL.CB_ACTION_ENA <>0) then Result:=Result+'CB_AC '; if (CNTL.DB_ACTION_ENA <>0) then Result:=Result+'DB_AC '; if (CNTL.SH_KCACHE_ACTION_ENA <>0) then Result:=Result+'SH_KA '; if (CNTL.SH_KCACHE_VOL_ACTION_ENA<>0) then Result:=Result+'SH_KV '; if (CNTL.SH_ICACHE_ACTION_ENA <>0) then Result:=Result+'SH_IA '; end; procedure onAcquireMem(pctx:p_pfp_ctx;Body:PPM4ACQUIREMEM); var addr,size:QWORD; begin //Assert(pctx^.stream_type=stGfxDcb); pctx^.UC_REG.CP_COHER_BASE_HI.COHER_BASE_HI_256B:=Body^.coherBaseHi; DWORD(pctx^.UC_REG.CP_COHER_CNTL) :=Body^.coherCntl; pctx^.UC_REG.CP_COHER_SIZE :=Body^.coherSizeLo; pctx^.UC_REG.CP_COHER_BASE :=Body^.coherBaseLo; pctx^.UC_REG.CP_COHER_SIZE_HI.COHER_SIZE_HI_256B:=Body^.coherSizeHi; if p_print_gpu_ops then begin addr:=(QWORD(Body^.coherBaseLo) shl 8) or (QWORD(Body^.coherBaseHi) shl 40); size:=(QWORD(Body^.coherSizeLo) shl 8) or (QWORD(Body^.coherSizeHi) shl 40); Writeln('onAcquireMem:'); Writeln(' Cntl=',coherCntl_str(pctx^.UC_REG.CP_COHER_CNTL)); Writeln(' addr=0x',HexStr(addr,10)); Writeln(' size=0x',HexStr(size,10)); end; //FlushAndWaitMe(pctx); end; procedure onContextControl(pctx:p_pfp_ctx;Body:PPM4CMDCONTEXTCONTROL); begin Assert(pctx^.stream_type=stGfxDcb); if (DWORD(Body^.loadControl )<>$80000000) or (DWORD(Body^.shadowEnable)<>$80000000) then if p_print_gpu_ops then begin Writeln(stderr,' loadControl =b',revbinstr(DWORD(Body^.loadControl ),32)); Writeln(stderr,' shadowEnable=b',revbinstr(DWORD(Body^.shadowEnable),32)); end; end; procedure onSetBase(pctx:p_pfp_ctx;Body:PPM4CMDDRAWSETBASE); var addr:QWORD; begin Assert(pctx^.stream_type=stGfxDcb); addr:=QWORD(Body^.address); if (addr<>0) then if p_print_gpu_ops then begin Writeln(' baseIndex=0x',HexStr(Body^.baseIndex,4)); Writeln(' address =0x',HexStr(addr,16)); end; end; procedure onSetPredication(pctx:p_pfp_ctx;Body:PPM4CMDSETPREDICATION); var addr:QWORD; begin Assert(pctx^.stream_type=stGfxDcb); addr:=QWORD(Body^.startAddress); if (addr<>0) then if p_print_gpu_ops then begin Writeln(' startAddress=0x',HexStr(addr,16)); Writeln(' pred =',Body^.predicationBoolean); Writeln(' hint =',Body^.hint); Writeln(' predOp =',Body^.predOp); Writeln(' continueBit =',Body^.continueBit); end; end; procedure onDrawPreamble(pctx:p_pfp_ctx;Body:PPM4CMDDRAWPREAMBLE); begin Assert(pctx^.stream_type=stGfxDcb); pctx^.UC_REG.VGT_PRIMITIVE_TYPE:=Body^.control1; pctx^.CX_REG.IA_MULTI_VGT_PARAM:=Body^.control2; pctx^.CX_REG.VGT_LS_HS_CONFIG :=Body^.control3; end; procedure onClearState(pctx:p_pfp_ctx;Body:Pointer); begin Assert(pctx^.stream_type=stGfxDcb); pctx^.clear_state; end; const CONFIG_SPACE_START=$2000; procedure onSetConfigReg(pctx:p_pfp_ctx;Body:PPM4CMDSETDATA); var i,c,r:WORD; v:DWORD; begin Assert(pctx^.stream_type=stGfxDcb); c:=Body^.header.count; if (c<>0) then begin For i:=0 to c-1 do begin r:=CONFIG_SPACE_START+Body^.REG_OFFSET+i; v:=PDWORD(@Body^.REG_DATA)[i]; // if p_print_gpu_ops then begin Writeln(' SET:',getRegName(r),':=0x',HexStr(v,8)); end; // pctx^.set_reg(r,v); end; // pctx^.LastSetReg:=CONFIG_SPACE_START+Body^.REG_OFFSET+c-1; end; end; const CONTEXT_REG_BASE=$A000; procedure onSetContextReg(pctx:p_pfp_ctx;Body:PPM4CMDSETDATA); var i,c,r:WORD; v:DWORD; begin Assert(pctx^.stream_type=stGfxDcb); c:=Body^.header.count; if (c<>0) then begin For i:=0 to c-1 do begin r:=Body^.REG_OFFSET+i; v:=PDWORD(@Body^.REG_DATA)[i]; // if p_print_gpu_ops then begin Writeln(' SET:',getRegName(r+CONTEXT_REG_BASE),':=0x',HexStr(v,8)); end; // pctx^.set_ctx_reg(r,v); end; // pctx^.LastSetReg:=CONTEXT_REG_BASE+Body^.REG_OFFSET+c-1; end; end; const SH_REG_BASE=$2C00; procedure onSetShReg(pctx:p_pfp_ctx;Body:PPM4CMDSETDATA); var i,c,r:WORD; v:DWORD; begin Assert(pctx^.stream_type=stGfxDcb); c:=Body^.header.count; if (c<>0) then begin For i:=0 to c-1 do begin r:=Body^.REG_OFFSET+i; v:=PDWORD(@Body^.REG_DATA)[i]; // if p_print_gpu_ops then begin Writeln(' SET:',getRegName(r+SH_REG_BASE),':=0x',HexStr(v,8)); end; // pctx^.set_sh_reg(r,v); end; // pctx^.LastSetReg:=SH_REG_BASE+Body^.REG_OFFSET+c-1; end; end; Const USERCONFIG_REG_BASE=$C000; procedure onSetUConfigReg(pctx:p_pfp_ctx;Body:PPM4CMDSETDATA); var i,c,r:WORD; v:DWORD; begin Assert(pctx^.stream_type=stGfxDcb); c:=Body^.header.count; if (c<>0) then begin For i:=0 to c-1 do begin r:=USERCONFIG_REG_BASE+Body^.REG_OFFSET+i; v:=PDWORD(@Body^.REG_DATA)[i]; // if p_print_gpu_ops then begin Writeln(' SET:',getRegName(r),':=0x',HexStr(v,8)); end; // pctx^.set_reg(r,v); end; // pctx^.LastSetReg:=USERCONFIG_REG_BASE+Body^.REG_OFFSET+c-1; end; end; procedure onPm40(pctx:p_pfp_ctx;Body:PPM4_TYPE_0_HEADER); var i,c,r:WORD; v:DWORD; begin c:=Body^.count; if (c<>0) then For i:=0 to c-1 do begin r:=Body^.baseIndex+i; v:=PDWORD(@Body[1])[i]; pctx^.set_reg(r,v); end; end; procedure onIndexBufferSize(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEXBUFFERSIZE); begin Assert(pctx^.stream_type=stGfxDcb); pctx^.UC_REG.VGT_NUM_INDICES:=Body^.numIndices; end; procedure onIndexType(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEXTYPE); begin Assert(pctx^.stream_type=stGfxDcb); pctx^.CX_REG.VGT_DMA_INDEX_TYPE:=Body^.data; pctx^.UC_REG.VGT_INDEX_TYPE.INDEX_TYPE:=pctx^.CX_REG.VGT_DMA_INDEX_TYPE.INDEX_TYPE; end; procedure onIndexBase(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEXBASE); begin Assert(pctx^.stream_type=stGfxDcb); Assert(Body^.baseSelect=0); if p_print_gpu_ops then begin Writeln(' indexBase=',HexStr(PQWORD(@Body^.indexBaseLo)^,10)); end; pctx^.CX_REG.VGT_DMA_BASE :=Body^.indexBaseLo and (not 1); pctx^.CX_REG.VGT_DMA_BASE_HI.BASE_ADDR:=Body^.indexBaseHi; end; procedure onNumInstances(pctx:p_pfp_ctx;Body:PPM4CMDDRAWNUMINSTANCES); begin Assert(pctx^.stream_type=stGfxDcb); if p_print_gpu_ops then begin Writeln(' numInstances=',Body^.numInstances); end; pctx^.CX_REG.VGT_DMA_NUM_INSTANCES:=Body^.numInstances; pctx^.UC_REG.VGT_NUM_INSTANCES :=Body^.numInstances; end; procedure onDrawIndex2(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEX2); begin Assert(pctx^.stream_type=stGfxDcb); if (DWORD(Body^.drawInitiator)<>0) then if p_print_gpu_ops then begin Writeln(stderr,' drawInitiator=b',revbinstr(DWORD(Body^.drawInitiator),32)); end; if p_print_gpu_ops then begin Writeln(' indexBase =',HexStr(PQWORD(@Body^.indexBaseLo)^,10)); Writeln(' indexCount=',Body^.indexCount); end; pctx^.CX_REG.VGT_DMA_MAX_SIZE :=Body^.maxSize; pctx^.CX_REG.VGT_DMA_BASE :=Body^.indexBaseLo and (not 1); pctx^.CX_REG.VGT_DMA_BASE_HI.BASE_ADDR:=Body^.indexBaseHi; pctx^.CX_REG.VGT_DMA_SIZE :=Body^.indexCount; pctx^.UC_REG.VGT_NUM_INDICES :=Body^.indexCount; pctx^.CX_REG.VGT_DRAW_INITIATOR :=Body^.drawInitiator; pctx^.stream[stGfxDcb].DrawIndex2(pctx^.SG_REG, pctx^.CX_REG, pctx^.UC_REG); //FlushAndWaitMe(pctx); end; procedure onDrawIndexOffset2(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEXOFFSET2); begin Assert(pctx^.stream_type=stGfxDcb); if (DWORD(Body^.drawInitiator)<>0) then if p_print_gpu_ops then begin Writeln(stderr,' drawInitiator=b',revbinstr(DWORD(Body^.drawInitiator),32)); end; pctx^.CX_REG.VGT_DMA_MAX_SIZE :=Body^.maxSize; pctx^.CX_REG.VGT_DMA_SIZE :=Body^.indexCount; pctx^.UC_REG.VGT_NUM_INDICES :=Body^.indexCount; pctx^.CX_REG.VGT_DRAW_INITIATOR :=Body^.drawInitiator; pctx^.stream[stGfxDcb].DrawIndexOffset2(pctx^.SG_REG, pctx^.CX_REG, pctx^.UC_REG, Body^.indexOffset); //FlushAndWaitMe(pctx); end; procedure onDrawIndexAuto(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEXAUTO); begin Assert(pctx^.stream_type=stGfxDcb); if (DWORD(Body^.drawInitiator)<>2) then if p_print_gpu_ops then begin Writeln(stderr,' drawInitiator=b',revbinstr(DWORD(Body^.drawInitiator),32)); end; if p_print_gpu_ops then begin Writeln(' indexCount=',Body^.indexCount); end; pctx^.CX_REG.VGT_DMA_SIZE :=Body^.indexCount; pctx^.UC_REG.VGT_NUM_INDICES :=Body^.indexCount; pctx^.CX_REG.VGT_DRAW_INITIATOR:=Body^.drawInitiator; pctx^.stream[stGfxDcb].DrawIndexAuto(pctx^.SG_REG, pctx^.CX_REG, pctx^.UC_REG); //FlushAndWaitMe(pctx); end; procedure onDrawIndexIndirectCountMulti(pctx:p_pfp_ctx;Body:PPM4CMDDRAWINDEXINDIRECTMULTI); begin Assert(pctx^.stream_type=stGfxDcb); Assert(false,'IT_DRAW_INDEX_INDIRECT_COUNT_MULTI') end; procedure onDispatchDirect(pctx:p_pfp_ctx;Body:PPM4CMDDISPATCHDIRECT); begin Assert(pctx^.stream_type=stGfxDcb); Assert(Body^.header.shaderType=1,'shaderType<>CS'); if (DWORD(Body^.dispatchInitiator)<>1) then if p_print_gpu_ops then begin Writeln(stderr,' dispatchInitiator=b',revbinstr(DWORD(Body^.dispatchInitiator),32)); end; if p_print_gpu_ops then begin Writeln(' dim=',Body^.dimX,' ',Body^.dimY,' ',Body^.dimZ); end; pctx^.SC_REG.COMPUTE_DIM_X:=Body^.dimX; pctx^.SC_REG.COMPUTE_DIM_Y:=Body^.dimY; pctx^.SC_REG.COMPUTE_DIM_Z:=Body^.dimZ; pctx^.SC_REG.COMPUTE_DISPATCH_INITIATOR:=Body^.dispatchInitiator; pctx^.stream[stGfxDcb].DispatchDirect(pctx^.SC_REG); end; procedure onPfpSyncMe(pctx:p_pfp_ctx;Body:Pointer); begin Assert(pctx^.stream_type=stGfxDcb); //stallCommandBufferParser //PFP waits until the ME completes all preceding commands before allowing the next batch to proceed. FlushAndWaitMe(pctx); end; procedure onPushMarker(pctx:p_pfp_ctx;Body:PChar;size:Integer); begin if p_print_gpu_hint then begin Writeln('\HINT_PUSH_MARKER:',Body); end; pctx^.stream[pctx^.stream_type].Hint('\HINT_PUSH_MARKER:',Body,size); end; procedure onPopMarker(pctx:p_pfp_ctx); begin if p_print_gpu_hint then begin Writeln('\HINT_POP_MARKER'); end; pctx^.stream[pctx^.stream_type].Hint('\HINT_POP_MARKER','',0); end; procedure onSetMarker(pctx:p_pfp_ctx;Body:PChar;size:Integer); begin if p_print_gpu_hint then begin Writeln('\HINT_SET_MARKER:',Body); end; pctx^.stream[pctx^.stream_type].Hint('\HINT_SET_MARKER:',Body,size); end; procedure onMarker(pctx:p_pfp_ctx;Body:PChar;size:Integer); begin if p_print_gpu_hint then begin Writeln('\HINT_MARKER'); end; pctx^.stream[pctx^.stream_type].Hint('\HINT_MARKER','',0); end; procedure onWidthHeight(Body:PWORD); begin if p_print_gpu_hint then begin Writeln('\HINT_',Body[0],'_',Body[1]); end; end; procedure onPrepareFlipLabel(Body:PPM4PrepareFlip); begin if p_print_gpu_hint then begin Writeln('\HINT_PREPARE_FLIP_LABEL:0x',HexStr(Body^.ADDRES,16),':',HexStr(Body^.DATA,8)); end; end; procedure onPrepareFlipWithEopInterrupt(Body:PPM4PrepareFlipWithEopInterrupt); begin if p_print_gpu_hint then begin Writeln('\HINT_PREPARE_FLIP_WITH_EOP_INTERRUPT:0x',HexStr(Body^.ADDRES,16),':',HexStr(Body^.DATA,8)); end; end; procedure onPrepareFlipWithEopInterruptLabel(Body:PPM4PrepareFlipWithEopInterrupt); begin if p_print_gpu_hint then begin Writeln('\HINT_PREPARE_FLIP_WITH_EOP_INTERRUPT_LABEL:0x',HexStr(Body^.ADDRES,16),':',HexStr(Body^.DATA,8)); end; end; procedure onNop(pctx:p_pfp_ctx;Body:PDWORD); begin case pctx^.stream_type of stGfxDcb, stGfxCcb: begin Case pctx^.LastSetReg of mmPA_SC_SCREEN_SCISSOR_BR, mmCB_COLOR0_FMASK_SLICE, mmCB_COLOR1_FMASK_SLICE, mmCB_COLOR2_FMASK_SLICE, mmCB_COLOR3_FMASK_SLICE, mmCB_COLOR4_FMASK_SLICE, mmCB_COLOR5_FMASK_SLICE, mmCB_COLOR6_FMASK_SLICE, mmCB_COLOR7_FMASK_SLICE, mmCB_COLOR0_DCC_BASE, mmCB_COLOR1_DCC_BASE, mmCB_COLOR2_DCC_BASE, mmCB_COLOR3_DCC_BASE, mmCB_COLOR4_DCC_BASE, mmCB_COLOR5_DCC_BASE, mmCB_COLOR6_DCC_BASE, mmCB_COLOR7_DCC_BASE, mmDB_STENCIL_CLEAR, //mmDB_RENDER_CONTROL, mmDB_HTILE_SURFACE: begin onWidthHeight(@Body[1]); Exit; end; else; end; end; else; end; case Body[1] of OP_HINT_PUSH_MARKER: begin onPushMarker(pctx,@Body[2],PM4_LENGTH(Body[0]) - 8); end; OP_HINT_POP_MARKER: begin onPopMarker(pctx); end; OP_HINT_SET_MARKER: begin onSetMarker(pctx,@Body[2],PM4_LENGTH(Body[0]) - 8); end; OP_HINT_MARKER: begin onMarker(pctx,@Body[2],PM4_LENGTH(Body[0]) - 8); end; OP_HINT_PREPARE_FLIP_LABEL: begin onPrepareFlipLabel(@Body[2]); end; OP_HINT_PREPARE_FLIP_WITH_EOP_INTERRUPT_VOID: begin onPrepareFlipWithEopInterrupt(@Body[2]); end; OP_HINT_PREPARE_FLIP_WITH_EOP_INTERRUPT_LABEL: begin onPrepareFlipWithEopInterruptLabel(@Body[2]); end; else if p_print_gpu_hint then begin Writeln('\HINT_',get_hint_name(Body[1])); end; end; end; function pm4_parse_dcb(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; begin Result:=0; case PM4_TYPE(token) of 0:begin //PM4_TYPE_0 if p_print_gpu_ops then Writeln('PM4_TYPE_0 len:',PM4_LENGTH(token)); onPm40(pctx,buff); end; 2:begin //PM4_TYPE_2 if p_print_gpu_ops then Writeln('PM4_TYPE_2'); //no body end; 3:begin //PM4_TYPE_3 if p_print_gpu_ops then if (PM4_TYPE_3_HEADER(token).opcode<>IT_NOP) or (not p_print_gpu_hint) then begin Writeln('IT_',get_op_name(PM4_TYPE_3_HEADER(token).opcode), ' ',ShdrType[PM4_TYPE_3_HEADER(token).shaderType], ' len:',PM4_LENGTH(token)); end; case PM4_TYPE_3_HEADER(token).opcode of IT_NOP :onNop (pctx,buff); IT_WRITE_DATA :onWriteData (pctx,buff); IT_EVENT_WRITE :onEventWrite (pctx,buff); IT_EVENT_WRITE_EOP :onEventWriteEop (pctx,buff); IT_EVENT_WRITE_EOS :onEventWriteEos (pctx,buff); IT_DMA_DATA :onDmaData (pctx,buff); IT_WAIT_REG_MEM :onWaitRegMem (pctx,buff); IT_ACQUIRE_MEM :onAcquireMem (pctx,buff); IT_CONTEXT_CONTROL :onContextControl (pctx,buff); IT_DRAW_PREAMBLE :onDrawPreamble (pctx,buff); IT_CLEAR_STATE :onClearState (pctx,buff); IT_SET_CONFIG_REG :onSetConfigReg (pctx,buff); IT_SET_CONTEXT_REG :onSetContextReg (pctx,buff); IT_SET_SH_REG :onSetShReg (pctx,buff); IT_SET_UCONFIG_REG :onSetUConfigReg (pctx,buff); IT_INDEX_BUFFER_SIZE :onIndexBufferSize (pctx,buff); IT_INDEX_TYPE :onIndexType (pctx,buff); IT_INDEX_BASE :onIndexBase (pctx,buff); IT_NUM_INSTANCES :onNumInstances (pctx,buff); IT_DRAW_INDEX_2 :onDrawIndex2 (pctx,buff); IT_DRAW_INDEX_OFFSET_2 :onDrawIndexOffset2 (pctx,buff); IT_DRAW_INDEX_AUTO :onDrawIndexAuto (pctx,buff); IT_DRAW_INDEX_INDIRECT_COUNT_MULTI:onDrawIndexIndirectCountMulti(pctx,buff); IT_DISPATCH_DIRECT :onDispatchDirect (pctx,buff); IT_PFP_SYNC_ME :onPfpSyncMe (pctx,buff); IT_SET_BASE :onSetBase (pctx,buff); IT_SET_PREDICATION :onSetPredication (pctx,buff); IT_INCREMENT_DE_COUNTER :onIncrementDECounter (pctx,buff); IT_WAIT_ON_CE_COUNTER :onWaitOnCECounter (pctx,buff); else begin Writeln(stderr,'PM4_TYPE_3.opcode:',get_op_name(PM4_TYPE_3_HEADER(token).opcode)); Assert(False); end; end; case PM4_TYPE_3_HEADER(token).opcode of IT_SET_CONFIG_REG :; IT_SET_CONTEXT_REG:; IT_SET_SH_REG :; IT_SET_UCONFIG_REG:; else pctx^.LastSetReg:=0; end; end; else begin Writeln(stderr,'PM4_TYPE_',PM4_TYPE(token)); Assert(False); end; end; end; procedure onSetShRegCompute(pctx:p_pfp_ctx;Body:PPM4CMDSETDATA); var i,c,r:WORD; v:DWORD; begin c:=Body^.header.count; if (c<>0) then begin For i:=0 to c-1 do begin r:=Body^.REG_OFFSET+i; v:=PDWORD(@Body^.REG_DATA)[i]; // if p_print_gpu_ops then begin Writeln(' [ASC]SET:',getRegName(r+$2C00),':=0x',HexStr(v,8)); end; // pctx^.set_sh_reg_compute(r,v); end; // end; end; procedure onDispatchDirectCompute(pctx:p_pfp_ctx;Body:PPM4CMDDISPATCHDIRECT); var c_id:Byte; begin Assert(Body^.header.shaderType=1,'shaderType<>CS'); if (DWORD(Body^.dispatchInitiator)<>1) then if p_print_gpu_ops then begin Writeln(stderr,' dispatchInitiator=b',revbinstr(DWORD(Body^.dispatchInitiator),32)); end; c_id:=pctx^.curr_ibuf^.c_id; pctx^.ASC_COMPUTE[c_id].COMPUTE_DIM_X:=Body^.dimX; pctx^.ASC_COMPUTE[c_id].COMPUTE_DIM_Y:=Body^.dimY; pctx^.ASC_COMPUTE[c_id].COMPUTE_DIM_Z:=Body^.dimZ; pctx^.ASC_COMPUTE[c_id].COMPUTE_DISPATCH_INITIATOR:=Body^.dispatchInitiator; pctx^.stream[pctx^.stream_type].DispatchDirect(pctx^.ASC_COMPUTE[c_id]); end; procedure onReleaseMemCompute(pctx:p_pfp_ctx;Body:PPM4CMDRELEASEMEM); begin Case Body^.eventType of CS_DONE, CACHE_FLUSH_TS, //FlushCbDbCache CACHE_FLUSH_AND_INV_TS_EVENT, //FlushAndInvalidateCbDbCaches BOTTOM_OF_PIPE_TS, //CbDbReadsDone FLUSH_AND_INV_DB_DATA_TS, //FlushAndInvalidateDbCache FLUSH_AND_INV_CB_DATA_TS:; //FlushAndInvalidateCbCache else Assert(False,'ReleaseMem: eventType=0x'+HexStr(Body^.eventType,1)); end; case Body^.eventIndex of EVENT_WRITE_INDEX_ANY_EOP_TIMESTAMP:; EVENT_WRITE_INDEX_ANY_EOS_TIMESTAMP:; else Assert(False,'ReleaseMem: eventIndex=0x'+HexStr(Body^.eventIndex,1)); end; DWORD(pctx^.CX_REG.VGT_EVENT_INITIATOR):=Body^.eventType; if p_print_gpu_ops then begin Case Body^.eventType of CS_DONE, CACHE_FLUSH_TS :Writeln(' eventType =','FlushCbDbCache'); CACHE_FLUSH_AND_INV_TS_EVENT:Writeln(' eventType =','FlushAndInvalidateCbDbCaches'); BOTTOM_OF_PIPE_TS :Writeln(' eventType =','CbDbReadsDone'); FLUSH_AND_INV_DB_DATA_TS :Writeln(' eventType =','FlushAndInvalidateDbCache'); FLUSH_AND_INV_CB_DATA_TS :Writeln(' eventType =','FlushAndInvalidateCbCache'); else; end; Writeln(' interrupt =0x',HexStr(Body^.intSel,2)); Writeln(' srcSelector=0x',HexStr(Body^.dataSel,2)); Writeln(' dstSelector=0x',HexStr(Body^.dstSel,2)); Writeln(' dstGpuAddr =0x',HexStr(Body^.address,10)); Writeln(' immValue =0x',HexStr(Body^.data,16)); end; pctx^.stream[pctx^.stream_type].ReleaseMem(Pointer(Body^.address),Body^.data,Body^.eventType,Body^.dataSel,Body^.dstSel,Body^.intSel); pctx^.Flush_stream(pctx^.stream_type); end; procedure onIndirectBufferCompute(pctx:p_pfp_ctx;Body:PPM4CMDINDIRECTBUFFER); var curr_ibuf:p_pm4_ibuffer; ibuf:t_pm4_ibuffer; i:Integer; begin if p_print_gpu_ops then begin Writeln('[ASC]INDIRECT_BUFFER (CS) 0x',HexStr(Body^.ibBase,10)); end; if pm4_ibuf_init(@ibuf,Body,@pm4_parse_compute_ring,pctx^.stream_type) then begin curr_ibuf:=pctx^.curr_ibuf; i:=pm4_ibuf_parse(pctx,@ibuf); if (i<>0) then begin pctx^.add_stall(@ibuf); end; pctx^.curr_ibuf:=curr_ibuf; end; end; function pm4_parse_compute_ring(pctx:p_pfp_ctx;token:DWORD;buff:Pointer):Integer; var ibuf:t_pm4_ibuffer; i:Integer; begin Result:=0; case PM4_TYPE(token) of 0:begin //PM4_TYPE_0 if p_print_gpu_ops then Writeln('[ASC]PM4_TYPE_0 len:',PM4_LENGTH(token)); onPm40(pctx,buff); end; 2:begin //PM4_TYPE_2 if p_print_gpu_ops then Writeln('[ASC]PM4_TYPE_2'); //no body end; 3:begin //PM4_TYPE_3 if p_print_gpu_ops then if (PM4_TYPE_3_HEADER(token).opcode<>IT_NOP) or (not p_print_gpu_hint) then begin Writeln('[ASC]IT_',get_op_name(PM4_TYPE_3_HEADER(token).opcode), ' ',ShdrType[PM4_TYPE_3_HEADER(token).shaderType], ' len:',PM4_LENGTH(token)); end; case PM4_TYPE_3_HEADER(token).opcode of IT_NOP :onNop (pctx,buff); IT_WRITE_DATA :onWriteData (pctx,buff); IT_DMA_DATA :onDmaData (pctx,buff); IT_SET_SH_REG :onSetShRegCompute (pctx,buff); IT_DISPATCH_DIRECT :onDispatchDirectCompute(pctx,buff); IT_RELEASE_MEM :onReleaseMemCompute (pctx,buff); IT_WAIT_REG_MEM :onWaitRegMem (pctx,buff); IT_ACQUIRE_MEM :onAcquireMem (pctx,buff); IT_INDIRECT_BUFFER :onIndirectBufferCompute(pctx,buff); else begin Writeln(stderr,'[ASC]PM4_TYPE_3.opcode:',get_op_name(PM4_TYPE_3_HEADER(token).opcode)); Assert (False ,'[ASC]PM4_TYPE_3.opcode:'+get_op_name(PM4_TYPE_3_HEADER(token).opcode)); end; end; end; else begin Writeln(stderr,'[ASC]PM4_TYPE_',PM4_TYPE(token)); Assert (False ,'[ASC]PM4_TYPE_'+IntToStr(PM4_TYPE(token))); end; end; end; end.