summaryrefslogtreecommitdiff
path: root/src/freedreno/decode/scripts/analyze.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/freedreno/decode/scripts/analyze.lua')
-rw-r--r--src/freedreno/decode/scripts/analyze.lua178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/freedreno/decode/scripts/analyze.lua b/src/freedreno/decode/scripts/analyze.lua
new file mode 100644
index 00000000000..27e97ecd4a5
--- /dev/null
+++ b/src/freedreno/decode/scripts/analyze.lua
@@ -0,0 +1,178 @@
+-- A script that compares a set of equivalent cmdstream captures from
+-- various generations, looking for equivalencies between registers.
+--
+-- This would be run across a group of similar tests for various
+-- generations, for example:
+--
+-- cffdump --script scripts/analyze.lua a320/quad-flat-*.rd a420/quad-flat-*.rd
+--
+-- This is done by comparing unique register values. Ie. for each
+-- generation, find the set of registers that have different values
+-- between equivalent draw calls.
+
+local posix = require "posix"
+
+io.write("Analyzing Data...\n")
+
+-- results - table structure:
+-- * [gpuname] - gpu
+-- * tests
+-- * [testname] - current test
+-- * draws
+-- * [1..n] - the draws
+-- * primtype - the primitive type
+-- * regs - table of values for draw
+-- * [regbase] - regval
+-- * regvals - table of unique values across all draws
+-- * [regbase]
+-- * [regval] - list of test names
+-- * [1..n] - testname "." didx
+local results = {}
+
+local test = nil
+local gpuname = nil
+local testname = nil
+
+
+-- srsly, no sparse table size() op?
+function tblsz(tbl)
+ local n = 0;
+ for k,v in pairs(tbl) do
+ n = n + 1
+ end
+ return n
+end
+
+
+function start_cmdstream(name)
+ testname = posix.basename(name)
+ gpuname = posix.basename(posix.dirname(name))
+ --io.write("START: gpuname=" .. gpuname .. ", testname=" .. testname .. "\n");
+ local gpu = results[gpuname]
+ if gpu == nil then
+ gpu = {["tests"] = {}, ["regvals"] = {}}
+ results[gpuname] = gpu
+ end
+ test = {["draws"] = {}}
+ gpu["tests"][testname] = test
+end
+
+function draw(primtype, nindx)
+ -- RECTLIST is only used internally.. we want to ignore it for
+ -- now, although it could potentially be interesting to track
+ -- these separately (separating clear/restore/resolve) just to
+ -- figure out which registers are used for which..
+ if primtype == "DI_PT_RECTLIST" then
+ return
+ end
+ local regtbl = {}
+ local draw = {["primtype"] = primtype, ["regs"] = regtbl}
+ local didx = tblsz(test["draws"])
+
+ test["draws"][didx] = draw
+
+ -- populate current regs. For now just consider ones that have
+ -- been written.. maybe we need to make that configurable in
+ -- case it filters out too many registers.
+ for regbase=0,0xffff do
+ if regs.written(regbase) ~= 0 then
+ local regval = regs.val(regbase)
+
+ -- track reg vals per draw:
+ regtbl[regbase] = regval
+
+ -- also track which reg vals appear in which tests:
+ local uniq_regvals = results[gpuname]["regvals"][regbase]
+ if uniq_regvals == nil then
+ uniq_regvals = {}
+ results[gpuname]["regvals"][regbase] = uniq_regvals;
+ end
+ local drawlist = uniq_regvals[regval]
+ if drawlist == nil then
+ drawlist = {}
+ uniq_regvals[regval] = drawlist
+ end
+ table.insert(drawlist, testname .. "." .. didx)
+ end
+ end
+
+ -- TODO maybe we want to whitelist a few well known regs, for the
+ -- convenience of the code that runs at the end to analyze the data?
+ -- TODO also would be useful to somehow capture CP_SET_BIN..
+
+end
+
+function end_cmdstream()
+ test = nil
+ gpuname = nil
+ testname = nil
+end
+
+function print_draws(gpuname, gpu)
+ io.write(" " .. gpuname .. "\n")
+ for testname,test in pairs(gpu["tests"]) do
+ io.write(" " .. testname .. ", draws=" .. #test["draws"] .. "\n")
+ for didx,draw in pairs(test["draws"]) do
+ io.write(" " .. didx .. ": " .. draw["primtype"] .. "\n")
+ end
+ end
+end
+
+-- sort and concat a list of draw names to form a key which can be
+-- compared to other drawlists to check for equality
+-- TODO maybe we instead want a scheme that allows for some fuzzyness
+-- in the matching??
+function drawlistname(drawlist)
+ local name = nil
+ for idx,draw in pairs(drawlist) do
+ if name == nil then
+ name = draw
+ else
+ name = name .. ":" .. draw
+ end
+ end
+ return name
+end
+
+local rnntbl = {}
+
+function dumpmatches(name)
+ for gpuname,gpu in pairs(results) do
+ local r = rnntbl[gpuname]
+ if r == nil then
+ io.write("loading rnn database: \n" .. gpuname)
+ r = rnn.init(gpuname)
+ rnntbl[gpuname] = r
+ end
+ for regbase,regvals in pairs(gpu["regvals"]) do
+ for regval,drawlist in pairs(regvals) do
+ local name2 = drawlistname(drawlist)
+ if name == name2 then
+ io.write(string.format(" %s:%s:\t%08x %s\n",
+ gpuname, rnn.regname(r, regbase),
+ regval, rnn.regval(r, regbase, regval)))
+ end
+ end
+ end
+ end
+end
+
+function finish()
+ -- drawlistnames that we've already dumped:
+ local dumped = {}
+
+ for gpuname,gpu in pairs(results) do
+ -- print_draws(gpuname, gpu)
+ for regbase,regvals in pairs(gpu["regvals"]) do
+ for regval,drawlist in pairs(regvals) do
+ local name = drawlistname(drawlist)
+ if dumped[name] == nil then
+ io.write("\n" .. name .. ":\n")
+ dumpmatches(name)
+ dumped[name] = 1
+ end
+ end
+ end
+ end
+end
+