1-- Parse logs from https://github.com/freedreno/freedreno/ 2-- test-texturator.c to generate a src/freedreno/fdl/fd5_layout_test.c 3-- block. We figure out the offsets from blits, but there may be some 4-- unrelated blits. So just save all of them until we find the 5-- texture state. This gives us the base address, and the miplevel #0 6-- width/height/depth. Then work backwards from there finding the 7-- blits to the same dst buffer and deducing the miplevel from the 8-- minified dimensions 9 10local posix = require "posix" 11 12io.write("Analyzing Data...\n") 13 14local r = rnn.init("a530") 15local found_tex = 0 16 17local allblits = {} 18local nallblits = 0 19 20function get_first_blit(base, width, height) 21 local first_blit = nil 22 23 for n = 0,nallblits-1 do 24 local blit = allblits[n] 25 if blit.base == base and blit.width == width and blit.height == height then 26 if not first_blit or blit.addr < first_blit.addr then 27 first_blit = blit 28 end 29 end 30 end 31 32 return first_blit 33end 34 35function minify(val, lvls) 36 val = val >> lvls 37 if val < 1 then 38 return 1 39 end 40 return val 41end 42 43function printf(fmt, ...) 44 return io.write(string.format(fmt, ...)) 45end 46 47function start_cmdstream(name) 48 io.write("Parsing " .. name .. "\n") 49 allblits = {} 50 nallblits = 0 51end 52 53-- Record texture upload blits done through CP_EVENT_WRITE 54function CP_EVENT_WRITE(pkt, size) 55 if tostring(pkt[0].EVENT) ~= "BLIT" then 56 return 57 end 58 59 local blit = {} 60 61 blit.width = r.RB_RESOLVE_CNTL_2.X + 1 62 blit.height = r.RB_RESOLVE_CNTL_2.Y + 1 63 blit.pitch = r.RB_BLIT_DST_PITCH 64 blit.addr = r.RB_BLIT_DST_LO | (r.RB_BLIT_DST_HI << 32) 65 blit.base = bos.base(blit.addr) 66 blit.ubwc_addr = r.RB_BLIT_FLAG_DST_LO | (r.RB_BLIT_FLAG_DST_HI << 32) 67 blit.ubwc_base = bos.base(blit.ubwc_addr) 68 blit.ubwc_pitch = r.RB_BLIT_FLAG_DST_PITCH 69 blit.endaddr = 0 -- filled in later 70 printf("Found event blit: 0x%x (0x%x) %dx%d UBWC 0x%x (0x%x) tiled %s\n", blit.addr, blit.base, blit.width, blit.height, blit.ubwc_addr, blit.ubwc_base, r.RB_RESOLVE_CNTL_3.TILED) 71 72 allblits[nallblits] = blit 73 nallblits = nallblits + 1 74end 75 76function CP_BLIT(pkt, size) 77 -- Just in case, filter out anything that isn't starting 78 -- at 0,0 79 if pkt[1].SRC_X1 ~= 0 or pkt[1].SRC_Y1 ~= 0 then 80 return 81 end 82 83 local blit = {} 84 85 blit.width = pkt[2].SRC_X2 + 1 86 blit.height = pkt[2].SRC_Y2 + 1 87 blit.pitch = r.RB_2D_DST_SIZE.PITCH 88 blit.addr = r.RB_2D_DST_LO | (r.RB_2D_DST_HI << 32) 89 blit.base = bos.base(blit.addr) 90 blit.ubwc_addr = r.RB_2D_DST_FLAGS_LO | (r.RB_2D_DST_FLAGS_HI << 32) 91 blit.ubwc_base = bos.base(blit.ubwc_addr) 92 blit.ubwc_pitch = r.RB_2D_DST_FLAGS_PITCH 93 blit.endaddr = 0 -- filled in later 94 printf("Found cp blit: 0x%x (0x%x) %dx%d UBWC 0x%x (0x%x) %s\n", blit.addr, blit.base, blit.width, blit.height, blit.ubwc_addr, blit.ubwc_base, r.RB_2D_DST_INFO.TILE_MODE) 95 96 allblits[nallblits] = blit 97 nallblits = nallblits + 1 98end 99 100function A5XX_TEX_CONST(pkt, size) 101 -- ignore any texture state w/ DEPTH=1, these aren't the 3d tex state we 102 -- are looking for 103 104 local base = pkt[4].BASE_LO | (pkt[5].BASE_HI << 32) 105 -- UBWC base on a5xx seems to be at the start of each miplevel, followed by pixels 106 -- somewhere past that. 107 local ubwc_base = base 108 local width0 = pkt[1].WIDTH 109 local height0 = pkt[1].HEIGHT 110 local depth0 = pkt[5].DEPTH 111 112 if (found_tex ~= 0) then 113 return 114 end 115 found_tex = 1 116 117 printf("Found texture state:\n %ux%ux%u (%s, %s, UBWC=%s)\n", 118 width0, height0, depth0, pkt[0].FMT, pkt[0].TILE_MODE, tostring(pkt[3].FLAG)) 119 120 -- Note that in some case the texture has some extra page or so 121 -- at the beginning: 122 local basebase = bos.base(base) 123 printf("base: 0x%x (0x%x)\n", base, basebase) 124 printf("ubwcbase: 0x%x (0x%x)\n", ubwc_base, bos.base(ubwc_base)) 125 126 -- see if we can find the associated blits.. The blob always seems to 127 -- start from the lower (larger) mipmap levels and layers, so we don't 128 -- need to sort by dst address. Also, while we are at it, fill in the 129 -- end-addr (at least for everything but the last blit) 130 local blits = {} 131 local nblits = 0 132 local lastblit = nil 133 for n = 0,nallblits-1 do 134 local blit = allblits[n] 135 --printf("blit addr: 0x%x (0x%x)\n", blit.addr, blit.base) 136 if blit.base == basebase and blit.addr >= base then 137 blits[nblits] = blit 138 nblits = nblits + 1 139 if lastblit then 140 lastblit.endaddr = blit.addr 141 end 142 lastblit = blit 143 end 144 end 145 146 printf(" {\n") 147 printf(" .format = %s,\n", pkt[0].FMT) 148 if (tostring(pkt[2].TYPE) == "A5XX_TEX_3D") then 149 printf(" .is_3d = true,\n") 150 end 151 152 printf(" .layout = {\n") 153 printf(" .tile_mode = %s,\n", pkt[0].TILE_MODE) 154 printf(" .ubwc = %s,\n", tostring(pkt[3].FLAG)) 155 156 if (tostring(pkt[2].TYPE) == "A5XX_TEX_3D") then 157 printf(" .width0 = %d, .height0 = %d, .depth0 = %d,\n", width0, height0, depth0) 158 else 159 printf(" .width0 = %d, .height0 = %d,\n", width0, height0) 160 end 161 162 printf(" .slices = {\n") 163 local w = 0 164 local h = 0 165 local level = 0 166 repeat 167 local w = minify(width0, level) 168 local h = minify(height0, level) 169 local blit = get_first_blit(basebase, w, h) 170 if blit then 171 printf(" { .offset = %d, .pitch = %u },\n", 172 blit.addr - base, 173 blit.pitch); 174 end 175 level = level + 1 176 until w == 1 and h == 1 177 printf(" },\n") 178 179 if pkt[3].FLAG then 180 printf(" .ubwc_slices = {\n") 181 level = 0 182 repeat 183 local w = minify(width0, level) 184 local h = minify(height0, level) 185 local blit = get_first_blit(basebase, w, h) 186 if blit then 187 printf(" { .offset = %d, .pitch = %u },\n", 188 blit.ubwc_addr - ubwc_base, 189 blit.ubwc_pitch); 190 end 191 level = level + 1 192 until w == 1 and h == 1 193 printf(" },\n") 194 end 195 196 printf(" },\n") 197 printf(" },\n") 198 printf("\n\n") 199end 200 201