17ec681f3Smrg-- A script that compares a set of equivalent cmdstream captures from 27ec681f3Smrg-- various generations, looking for equivalencies between registers. 37ec681f3Smrg-- 47ec681f3Smrg-- This would be run across a group of similar tests for various 57ec681f3Smrg-- generations, for example: 67ec681f3Smrg-- 77ec681f3Smrg-- cffdump --script scripts/analyze.lua a320/quad-flat-*.rd a420/quad-flat-*.rd 87ec681f3Smrg-- 97ec681f3Smrg-- This is done by comparing unique register values. Ie. for each 107ec681f3Smrg-- generation, find the set of registers that have different values 117ec681f3Smrg-- between equivalent draw calls. 127ec681f3Smrg 137ec681f3Smrglocal posix = require "posix" 147ec681f3Smrg 157ec681f3Smrgio.write("Analyzing Data...\n") 167ec681f3Smrg 177ec681f3Smrg-- results - table structure: 187ec681f3Smrg-- * [gpuname] - gpu 197ec681f3Smrg-- * tests 207ec681f3Smrg-- * [testname] - current test 217ec681f3Smrg-- * draws 227ec681f3Smrg-- * [1..n] - the draws 237ec681f3Smrg-- * primtype - the primitive type 247ec681f3Smrg-- * regs - table of values for draw 257ec681f3Smrg-- * [regbase] - regval 267ec681f3Smrg-- * regvals - table of unique values across all draws 277ec681f3Smrg-- * [regbase] 287ec681f3Smrg-- * [regval] - list of test names 297ec681f3Smrg-- * [1..n] - testname "." didx 307ec681f3Smrglocal results = {} 317ec681f3Smrg 327ec681f3Smrglocal test = nil 337ec681f3Smrglocal gpuname = nil 347ec681f3Smrglocal testname = nil 357ec681f3Smrg 367ec681f3Smrg 377ec681f3Smrg-- srsly, no sparse table size() op? 387ec681f3Smrgfunction tblsz(tbl) 397ec681f3Smrg local n = 0; 407ec681f3Smrg for k,v in pairs(tbl) do 417ec681f3Smrg n = n + 1 427ec681f3Smrg end 437ec681f3Smrg return n 447ec681f3Smrgend 457ec681f3Smrg 467ec681f3Smrg 477ec681f3Smrgfunction start_cmdstream(name) 487ec681f3Smrg testname = posix.basename(name) 497ec681f3Smrg gpuname = posix.basename(posix.dirname(name)) 507ec681f3Smrg --io.write("START: gpuname=" .. gpuname .. ", testname=" .. testname .. "\n"); 517ec681f3Smrg local gpu = results[gpuname] 527ec681f3Smrg if gpu == nil then 537ec681f3Smrg gpu = {["tests"] = {}, ["regvals"] = {}} 547ec681f3Smrg results[gpuname] = gpu 557ec681f3Smrg end 567ec681f3Smrg test = {["draws"] = {}} 577ec681f3Smrg gpu["tests"][testname] = test 587ec681f3Smrgend 597ec681f3Smrg 607ec681f3Smrgfunction draw(primtype, nindx) 617ec681f3Smrg -- RECTLIST is only used internally.. we want to ignore it for 627ec681f3Smrg -- now, although it could potentially be interesting to track 637ec681f3Smrg -- these separately (separating clear/restore/resolve) just to 647ec681f3Smrg -- figure out which registers are used for which.. 657ec681f3Smrg if primtype == "DI_PT_RECTLIST" then 667ec681f3Smrg return 677ec681f3Smrg end 687ec681f3Smrg local regtbl = {} 697ec681f3Smrg local draw = {["primtype"] = primtype, ["regs"] = regtbl} 707ec681f3Smrg local didx = tblsz(test["draws"]) 717ec681f3Smrg 727ec681f3Smrg test["draws"][didx] = draw 737ec681f3Smrg 747ec681f3Smrg -- populate current regs. For now just consider ones that have 757ec681f3Smrg -- been written.. maybe we need to make that configurable in 767ec681f3Smrg -- case it filters out too many registers. 777ec681f3Smrg for regbase=0,0xffff do 787ec681f3Smrg if regs.written(regbase) ~= 0 then 797ec681f3Smrg local regval = regs.val(regbase) 807ec681f3Smrg 817ec681f3Smrg -- track reg vals per draw: 827ec681f3Smrg regtbl[regbase] = regval 837ec681f3Smrg 847ec681f3Smrg -- also track which reg vals appear in which tests: 857ec681f3Smrg local uniq_regvals = results[gpuname]["regvals"][regbase] 867ec681f3Smrg if uniq_regvals == nil then 877ec681f3Smrg uniq_regvals = {} 887ec681f3Smrg results[gpuname]["regvals"][regbase] = uniq_regvals; 897ec681f3Smrg end 907ec681f3Smrg local drawlist = uniq_regvals[regval] 917ec681f3Smrg if drawlist == nil then 927ec681f3Smrg drawlist = {} 937ec681f3Smrg uniq_regvals[regval] = drawlist 947ec681f3Smrg end 957ec681f3Smrg table.insert(drawlist, testname .. "." .. didx) 967ec681f3Smrg end 977ec681f3Smrg end 987ec681f3Smrg 997ec681f3Smrg -- TODO maybe we want to whitelist a few well known regs, for the 1007ec681f3Smrg -- convenience of the code that runs at the end to analyze the data? 1017ec681f3Smrg -- TODO also would be useful to somehow capture CP_SET_BIN.. 1027ec681f3Smrg 1037ec681f3Smrgend 1047ec681f3Smrg 1057ec681f3Smrgfunction end_cmdstream() 1067ec681f3Smrg test = nil 1077ec681f3Smrg gpuname = nil 1087ec681f3Smrg testname = nil 1097ec681f3Smrgend 1107ec681f3Smrg 1117ec681f3Smrgfunction print_draws(gpuname, gpu) 1127ec681f3Smrg io.write(" " .. gpuname .. "\n") 1137ec681f3Smrg for testname,test in pairs(gpu["tests"]) do 1147ec681f3Smrg io.write(" " .. testname .. ", draws=" .. #test["draws"] .. "\n") 1157ec681f3Smrg for didx,draw in pairs(test["draws"]) do 1167ec681f3Smrg io.write(" " .. didx .. ": " .. draw["primtype"] .. "\n") 1177ec681f3Smrg end 1187ec681f3Smrg end 1197ec681f3Smrgend 1207ec681f3Smrg 1217ec681f3Smrg-- sort and concat a list of draw names to form a key which can be 1227ec681f3Smrg-- compared to other drawlists to check for equality 1237ec681f3Smrg-- TODO maybe we instead want a scheme that allows for some fuzzyness 1247ec681f3Smrg-- in the matching?? 1257ec681f3Smrgfunction drawlistname(drawlist) 1267ec681f3Smrg local name = nil 1277ec681f3Smrg for idx,draw in pairs(drawlist) do 1287ec681f3Smrg if name == nil then 1297ec681f3Smrg name = draw 1307ec681f3Smrg else 1317ec681f3Smrg name = name .. ":" .. draw 1327ec681f3Smrg end 1337ec681f3Smrg end 1347ec681f3Smrg return name 1357ec681f3Smrgend 1367ec681f3Smrg 1377ec681f3Smrglocal rnntbl = {} 1387ec681f3Smrg 1397ec681f3Smrgfunction dumpmatches(name) 1407ec681f3Smrg for gpuname,gpu in pairs(results) do 1417ec681f3Smrg local r = rnntbl[gpuname] 1427ec681f3Smrg if r == nil then 1437ec681f3Smrg io.write("loading rnn database: \n" .. gpuname) 1447ec681f3Smrg r = rnn.init(gpuname) 1457ec681f3Smrg rnntbl[gpuname] = r 1467ec681f3Smrg end 1477ec681f3Smrg for regbase,regvals in pairs(gpu["regvals"]) do 1487ec681f3Smrg for regval,drawlist in pairs(regvals) do 1497ec681f3Smrg local name2 = drawlistname(drawlist) 1507ec681f3Smrg if name == name2 then 1517ec681f3Smrg io.write(string.format(" %s:%s:\t%08x %s\n", 1527ec681f3Smrg gpuname, rnn.regname(r, regbase), 1537ec681f3Smrg regval, rnn.regval(r, regbase, regval))) 1547ec681f3Smrg end 1557ec681f3Smrg end 1567ec681f3Smrg end 1577ec681f3Smrg end 1587ec681f3Smrgend 1597ec681f3Smrg 1607ec681f3Smrgfunction finish() 1617ec681f3Smrg -- drawlistnames that we've already dumped: 1627ec681f3Smrg local dumped = {} 1637ec681f3Smrg 1647ec681f3Smrg for gpuname,gpu in pairs(results) do 1657ec681f3Smrg -- print_draws(gpuname, gpu) 1667ec681f3Smrg for regbase,regvals in pairs(gpu["regvals"]) do 1677ec681f3Smrg for regval,drawlist in pairs(regvals) do 1687ec681f3Smrg local name = drawlistname(drawlist) 1697ec681f3Smrg if dumped[name] == nil then 1707ec681f3Smrg io.write("\n" .. name .. ":\n") 1717ec681f3Smrg dumpmatches(name) 1727ec681f3Smrg dumped[name] = 1 1737ec681f3Smrg end 1747ec681f3Smrg end 1757ec681f3Smrg end 1767ec681f3Smrg end 1777ec681f3Smrgend 1787ec681f3Smrg 179