1 -- Parse cmdstream dump and check for common errors
2 -- 1) Check for overflowing HLSQ_xS_CNTL.CONSTLEN
3 -- 2) Check for constant uploades that overwrite each other. The
4 -- range checking is reset on each draw, since it is a valid
5 -- use-case to do partial constant upload. But if we see two
6 -- CP_LOAD_STATE* that overwrite the same range of constants
7 -- within the same draw, that is almost certainly unintentional.
9 -- TODO add more checks
10 -- TODO maybe some parts could be shared across
11 -- different generations
13 --local posix = require "posix"
15 function printf(fmt, ...)
16 return io.write(string.format(fmt, ...))
19 function dbg(fmt, ...)
32 -- maps shader stage to HLSQ_xS_CNTL register name:
34 ["SB6_VS_SHADER"] = "HLSQ_VS_CNTL",
35 ["SB6_HS_SHADER"] = "HLSQ_HS_CNTL",
36 ["SB6_DS_SHADER"] = "HLSQ_DS_CNTL",
37 ["SB6_GS_SHADER"] = "HLSQ_GS_CNTL",
38 ["SB6_FS_SHADER"] = "HLSQ_FS_CNTL",
39 ["SB6_CS_SHADER"] = "HLSQ_CS_CNTL",
42 -- initialize constant updated ranges:
43 -- constranges[stagename] -> table of offsets that have been uploaded
45 function reset_constranges()
46 for i,stage in ipairs(stages) do
47 constranges[stage] = {}
53 printf("Checking cmdstream...\n")
55 local r = rnn.init("a630")
57 function draw(primtype, nindx)
59 -- reset ranges of uploaded consts on each draw:
63 function CP_LOAD_STATE6(pkt, size)
64 if tostring(pkt[0].STATE_TYPE) ~= "ST6_CONSTANTS" then
67 dbg("got CP_LOAD_STATE6\n")
68 stage = tostring(pkt[0].STATE_BLOCK)
69 max = pkt[0].DST_OFF + pkt[0].NUM_UNIT
70 cntl_reg = cntl_regs[stage]
71 dbg("looking for %s.. max=%d vs %d\n", cntl_reg, max, r[cntl_reg].CONSTLEN)
72 if max > r[cntl_reg].CONSTLEN then
73 printf("ERROR: invalid max constant offset for stage %s: %d vs %d\n", stage, max, r[cntl_reg].CONSTLEN)