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.
8--
9-- TODO add more checks
10-- TODO maybe some parts could be shared across
11--      different generations
12
13--local posix = require "posix"
14
15function printf(fmt, ...)
16	return io.write(string.format(fmt, ...))
17end
18
19function dbg(fmt, ...)
20	--printf(fmt, ...)
21end
22
23stages = {
24	"SB6_VS_SHADER",
25	"SB6_HS_SHADER",
26	"SB6_DS_SHADER",
27	"SB6_GS_SHADER",
28	"SB6_FS_SHADER",
29	"SB6_CS_SHADER",
30}
31
32-- maps shader stage to HLSQ_xS_CNTL register name:
33cntl_regs = {
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",
40}
41
42-- initialize constant updated ranges:
43--   constranges[stagename] -> table of offsets that have been uploaded
44constranges = {}
45function reset_constranges()
46	for i,stage in ipairs(stages) do
47		constranges[stage] = {}
48	end
49end
50
51reset_constranges()
52
53printf("Checking cmdstream...\n")
54
55local r = rnn.init("a630")
56
57function draw(primtype, nindx)
58	printf("draw!\n")
59	-- reset ranges of uploaded consts on each draw:
60	reset_constranges()
61end
62
63function CP_LOAD_STATE6(pkt, size)
64	if tostring(pkt[0].STATE_TYPE) ~= "ST6_CONSTANTS" then
65		return
66	end
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)
74	end
75
76end
77