summaryrefslogtreecommitdiff
path: root/src/freedreno/decode/scripts/parse-submits.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno/decode/scripts/parse-submits.lua')
-rw-r--r--src/freedreno/decode/scripts/parse-submits.lua413
1 files changed, 413 insertions, 0 deletions
diff --git a/src/freedreno/decode/scripts/parse-submits.lua b/src/freedreno/decode/scripts/parse-submits.lua
new file mode 100644
index 00000000000..1d21716503d
--- /dev/null
+++ b/src/freedreno/decode/scripts/parse-submits.lua
@@ -0,0 +1,413 @@
+-- Parse cmdstream dump and analyse blits and batches
+
+--local posix = require "posix"
+
+function printf(fmt, ...)
+ return io.write(string.format(fmt, ...))
+end
+
+function dbg(fmt, ...)
+ --printf(fmt, ...)
+end
+
+printf("Analyzing Data...\n")
+
+local r = rnn.init("a630")
+
+-- Each submit, all draws will target the same N MRTs:
+local mrts = {}
+local allmrts = {} -- includes historical render targets
+function push_mrt(fmt, w, h, samples, base, flag, gmem)
+ dbg("MRT: %s %ux%u 0x%x\n", fmt, w, h, base)
+
+ local mrt = {}
+ mrt.format = fmt
+ mrt.w = w
+ mrt.h = h
+ mrt.samples = samples
+ mrt.base = base
+ mrt.flag = flag
+ mrt.gmem = gmem
+
+ mrts[base] = mrt
+ allmrts[base] = mrt
+end
+
+-- And each each draw will read from M sources/textures:
+local sources = {}
+function push_source(fmt, w, h, samples, base, flag)
+ dbg("SRC: %s %ux%u 0x%x\n", fmt, w, h, base)
+
+ local source = {}
+ source.format = fmt
+ source.w = w
+ source.h = h
+ source.samples = samples
+ source.base = base
+ source.flag = flag
+
+ sources[base] = source
+end
+
+local binw
+local binh
+local nbins
+local blits = 0
+local draws = 0
+local drawmode
+local cleared
+local restored
+local resolved
+local nullbatch
+local depthtest
+local depthwrite
+local stenciltest
+local stencilwrite
+
+function start_cmdstream(name)
+ printf("Parsing %s\n", name)
+end
+
+function reset()
+ dbg("reset\n")
+ mrts = {}
+ sources = {}
+ draws = 0
+ blits = 0
+ cleared = {}
+ restored = {}
+ resolved = {}
+ depthtest = false
+ depthwrite = false
+ stenciltest = false
+ stencilwrite = false
+ drawmode = Nil
+end
+
+function start_submit()
+ dbg("start_submit\n")
+ reset()
+ nullbatch = true
+end
+
+function finish()
+ dbg("finish\n")
+
+ printf("\n")
+
+ -- TODO we get false-positives for 'NULL BATCH!' because we don't have
+ -- a really good way to differentiate between submits and cmds. Ie.
+ -- with growable cmdstream, and a large # of tiles, IB1 can get split
+ -- across multiple buffers. Since we ignore GMEM draws for window-
+ -- offset != 0,0, the later cmds will appear as null batches
+ if draws == 0 and blits == 0 then
+ if nullbatch then
+ printf("NULL BATCH!\n");
+ end
+ return
+ end
+
+ if draws > 0 then
+ printf("Batch:\n")
+ printf("-------\n")
+ printf(" # of draws: %u\n", draws)
+ printf(" mode: %s\n", drawmode)
+ if drawmode == "RM6_GMEM" then
+ printf(" bin size: %ux%u (%u bins)\n", binw, binh, nbins)
+ end
+ if depthtest or depthwrite then
+ printf(" ")
+ if depthtest then
+ printf("DEPTHTEST ")
+ end
+ if depthwrite then
+ printf("DEPTHWRITE")
+ end
+ printf("\n")
+ end
+ if stenciltest or stencilwrite then
+ printf(" ")
+ if stenciltest then
+ printf("STENCILTEST ")
+ end
+ if stencilwrite then
+ printf("STENCILWRITE")
+ end
+ printf("\n")
+ end
+ else
+ printf("Blit:\n")
+ printf("-----\n")
+ end
+
+ for base,mrt in pairs(mrts) do
+ printf(" MRT[0x%x:0x%x]:\t%ux%u\t\t%s (%s)", base, mrt.flag, mrt.w, mrt.h, mrt.format, mrt.samples)
+ if drawmode == "RM6_GMEM" then
+ if cleared[mrt.gmem] then
+ printf("\tCLEARED")
+ end
+ if restored[mrt.gmem] then
+ printf("\tRESTORED")
+ end
+ if resolved[mrt.gmem] then
+ printf("\tRESOLVED")
+ end
+ else
+ if cleared[mrt.base] then
+ printf("\tCLEARED")
+ end
+ end
+ printf("\n")
+ end
+
+ function print_source(source)
+ printf(" SRC[0x%x:0x%x]:\t%ux%u\t\t%s (%s)\n", source.base, source.flag, source.w, source.h, source.format, source.samples)
+ end
+
+ for base,source in pairs(sources) do
+ -- only show sources that have been previously rendered to, other
+ -- textures are less interesting. Possibly this should be an
+ -- option somehow
+ if draws < 10 then
+ print_source(source)
+ elseif allmrts[base] or draws == 0 then
+ print_source(source)
+ elseif source.flag and allmrts[source.flag] then
+ print_source(source)
+ end
+ end
+ reset()
+end
+
+function end_submit()
+ dbg("end_submit\n")
+ finish()
+end
+
+-- Track the current mode:
+local mode = ""
+function CP_SET_MARKER(pkt, size)
+ mode = pkt[0].MARKER
+ dbg("mode: %s\n", mode)
+end
+
+function CP_EVENT_WRITE(pkt, size)
+ if tostring(pkt[0].EVENT) ~= "BLIT" then
+ return
+ end
+ nullbatch = false
+ local m = tostring(mode)
+ if m == "RM6_GMEM" then
+ -- either clear or restore:
+ if r.RB_BLIT_INFO.CLEAR_MASK == 0 then
+ restored[r.RB_BLIT_BASE_GMEM] = 1
+ else
+ cleared[r.RB_BLIT_BASE_GMEM] = 1
+ end
+ -- push_mrt() because we could have GMEM
+ -- passes with only a clear and no draws:
+ local flag = 0
+ local sysmem = 0;
+ -- try to match up the GMEM addr with the MRT/DEPTH state,
+ -- to avoid relying on RB_BLIT_DST also getting written:
+ for n = 0,r.RB_FS_OUTPUT_CNTL1.MRT-1 do
+ if r.RB_MRT[n].BASE_GMEM == r.RB_BLIT_BASE_GMEM then
+ sysmem = r.RB_MRT[n].BASE_LO | (r.RB_MRT[n].BASE_HI << 32)
+ flag = r.RB_MRT_FLAG_BUFFER[n].ADDR_LO | (r.RB_MRT_FLAG_BUFFER[n].ADDR_HI << 32)
+ break
+ end
+ end
+ if sysmem == 0 and r.RB_BLIT_BASE_GMEM == r.RB_DEPTH_BUFFER_BASE_GMEM then
+ sysmem = r.RB_DEPTH_BUFFER_BASE_LO | (r.RB_DEPTH_BUFFER_BASE_HI << 32)
+ flag = r.RB_DEPTH_FLAG_BUFFER_BASE_LO | (r.RB_DEPTH_FLAG_BUFFER_BASE_HI << 32)
+
+ end
+ --NOTE this can get confused by previous blits:
+ --if sysmem == 0 then
+ -- -- fallback:
+ -- sysmem = r.RB_BLIT_DST_LO | (r.RB_BLIT_DST_HI << 32)
+ -- flag = r.RB_BLIT_FLAG_DST_LO | (r.RB_BLIT_FLAG_DST_HI << 32)
+ --end
+ if not r.RB_BLIT_DST_INFO.FLAGS then
+ flag = 0
+ end
+ -- TODO maybe just emit RB_BLIT_DST_LO/HI for clears.. otherwise
+ -- we get confused by stale values in registers.. not sure
+ -- if this is a problem w/ blob
+ push_mrt(r.RB_BLIT_DST_INFO.COLOR_FORMAT,
+ r.RB_BLIT_SCISSOR_BR.X + 1,
+ r.RB_BLIT_SCISSOR_BR.Y + 1,
+ r.RB_BLIT_DST_INFO.SAMPLES,
+ sysmem,
+ flag,
+ r.RB_BLIT_BASE_GMEM)
+ elseif m == "RM6_RESOLVE" then
+ resolved[r.RB_BLIT_BASE_GMEM] = 1
+ else
+ printf("I am confused!!!\n")
+ end
+end
+
+function A6XX_TEX_CONST(pkt, size)
+ push_source(pkt[0].FMT,
+ pkt[1].WIDTH, pkt[1].HEIGHT,
+ pkt[0].SAMPLES,
+ pkt[4].BASE_LO | (pkt[5].BASE_HI << 32),
+ pkt[7].FLAG_LO | (pkt[8].FLAG_HI << 32))
+end
+
+function handle_blit()
+ -- blob sometimes uses CP_BLIT for resolves, so filter those out:
+ -- TODO it would be nice to not hard-code GMEM addr:
+ -- TODO I guess the src can be an offset from GMEM addr..
+ if r.SP_PS_2D_SRC_LO == 0x100000 and not r.RB_2D_BLIT_CNTL.SOLID_COLOR then
+ resolved[0] = 1
+ return
+ end
+ if draws > 0 then
+ finish()
+ end
+ reset()
+ drawmode = "BLIT"
+ -- This kinda assumes that we are doing full img blits, which is maybe
+ -- Not completely legit. We could perhaps instead just track pitch and
+ -- size/pitch?? Or maybe the size doesn't matter much
+ push_mrt(r.RB_2D_DST_INFO.COLOR_FORMAT,
+ r.GRAS_2D_DST_BR.X + 1,
+ r.GRAS_2D_DST_BR.Y + 1,
+ "MSAA_ONE",
+ r.RB_2D_DST_LO | (r.RB_2D_DST_HI << 32),
+ r.RB_2D_DST_FLAGS_LO | (r.RB_2D_DST_FLAGS_HI << 32),
+ -1)
+ if r.RB_2D_BLIT_CNTL.SOLID_COLOR then
+ dbg("CLEAR=%x\n", r.RB_2D_DST_LO | (r.RB_2D_DST_HI << 32))
+ cleared[r.RB_2D_DST_LO | (r.RB_2D_DST_HI << 32)] = 1
+ else
+ push_source(r.SP_2D_SRC_FORMAT.COLOR_FORMAT,
+ r.GRAS_2D_SRC_BR_X.X + 1,
+ r.GRAS_2D_SRC_BR_Y.Y + 1,
+ "MSAA_ONE",
+ r.SP_PS_2D_SRC_LO | (r.SP_PS_2D_SRC_HI << 32),
+ r.SP_PS_2D_SRC_FLAGS_LO | (r.SP_PS_2D_SRC_FLAGS_HI << 32))
+ end
+ blits = blits + 1
+ finish()
+end
+
+function valid_transition(curmode, newmode)
+ if curmode == "RM6_BINNING" and newmode == "RM6_GMEM" then
+ return true
+ end
+ if curmode == "RM6_GMEM" and newmode == "RM6_RESOLVE" then
+ return true
+ end
+ return false
+end
+
+function draw(primtype, nindx)
+ dbg("draw: %s (%s)\n", primtype, mode)
+ nullbatch = false
+ if primtype == "BLIT_OP_SCALE" then
+ handle_blit()
+ return
+ elseif primtype == "EVENT:BLIT" then
+ return
+ end
+
+ local m = tostring(mode)
+
+ -- detect changes in drawmode which indicate a different
+ -- pass.. BINNING->GMEM means same pass, but other
+ -- transitions mean different pass:
+ if drawmode and m ~= drawmode then
+ dbg("%s -> %s transition\n", drawmode, m)
+ if not valid_transition(drawmode, m) then
+ dbg("invalid transition, new render pass!\n")
+ finish()
+ reset()
+ end
+ end
+
+ if m ~= "RM6_GMEM" and m ~= "RM6_BYPASS" then
+ if m == "RM6_BINNING" then
+ drawmode = m
+ return
+ end
+ if m == "RM6_RESOLVE" and primtype == "EVENT:BLIT" then
+ return
+ end
+ printf("unknown MODE %s for primtype %s\n", m, primtype)
+ return
+ end
+
+ -- Only count the first tile for GMEM mode to avoid counting
+ -- each draw for each tile
+ if m == "RM6_GMEM" then
+ if r.RB_WINDOW_OFFSET.X ~= 0 or r.RB_WINDOW_OFFSET.Y ~= 0 then
+ return
+ end
+ end
+
+ drawmode = m
+ local render_components = {}
+ render_components[0] = r.RB_RENDER_COMPONENTS.RT0;
+ render_components[1] = r.RB_RENDER_COMPONENTS.RT1;
+ render_components[2] = r.RB_RENDER_COMPONENTS.RT2;
+ render_components[3] = r.RB_RENDER_COMPONENTS.RT3;
+ render_components[4] = r.RB_RENDER_COMPONENTS.RT4;
+ render_components[5] = r.RB_RENDER_COMPONENTS.RT5;
+ render_components[6] = r.RB_RENDER_COMPONENTS.RT6;
+ render_components[7] = r.RB_RENDER_COMPONENTS.RT7;
+ for n = 0,r.RB_FS_OUTPUT_CNTL1.MRT-1 do
+ if render_components[n] ~= 0 then
+ push_mrt(r.RB_MRT[n].BUF_INFO.COLOR_FORMAT,
+ r.GRAS_SC_SCREEN_SCISSOR[0].BR.X + 1,
+ r.GRAS_SC_SCREEN_SCISSOR[0].BR.Y + 1,
+ r.RB_MSAA_CNTL.SAMPLES,
+ r.RB_MRT[n].BASE_LO | (r.RB_MRT[n].BASE_HI << 32),
+ r.RB_MRT_FLAG_BUFFER[n].ADDR_LO | (r.RB_MRT_FLAG_BUFFER[n].ADDR_HI << 32),
+ r.RB_MRT[n].BASE_GMEM)
+ end
+ end
+
+ local depthbase = r.RB_DEPTH_BUFFER_BASE_LO |
+ (r.RB_DEPTH_BUFFER_BASE_HI << 32)
+
+ if depthbase ~= 0 then
+ push_mrt(r.RB_DEPTH_BUFFER_INFO.DEPTH_FORMAT,
+ r.GRAS_SC_SCREEN_SCISSOR[0].BR.X + 1,
+ r.GRAS_SC_SCREEN_SCISSOR[0].BR.Y + 1,
+ r.RB_MSAA_CNTL.SAMPLES,
+ depthbase,
+ r.RB_DEPTH_FLAG_BUFFER_BASE_LO | (r.RB_DEPTH_FLAG_BUFFER_BASE_HI << 32),
+ r.RB_DEPTH_BUFFER_BASE_GMEM)
+ end
+
+ if r.RB_DEPTH_CNTL.Z_WRITE_ENABLE then
+ depthwrite = true
+ end
+
+ if r.RB_DEPTH_CNTL.Z_ENABLE then
+ depthtest = true
+ end
+
+ -- clearly 0 != false.. :-/
+ if r.RB_STENCILWRMASK.WRMASK ~= 0 then
+ stencilwrite = true
+ end
+
+ if r.RB_STENCIL_CONTROL.STENCIL_ENABLE then
+ stenciltest = true
+ end
+
+ -- TODO should also check for stencil buffer for z32+s8 case
+
+ if m == "RM6_GMEM" then
+ binw = r.VSC_BIN_SIZE.WIDTH
+ binh = r.VSC_BIN_SIZE.HEIGHT
+ nbins = r.VSC_BIN_COUNT.NX * r.VSC_BIN_COUNT.NY
+ end
+
+ draws = draws + 1
+end
+