diff options
Diffstat (limited to 'tools/proxyclient/m1n1/agx/render.py')
| -rw-r--r-- | tools/proxyclient/m1n1/agx/render.py | 1075 |
1 files changed, 1075 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/agx/render.py b/tools/proxyclient/m1n1/agx/render.py new file mode 100644 index 0000000..b29683b --- /dev/null +++ b/tools/proxyclient/m1n1/agx/render.py @@ -0,0 +1,1075 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MIT +import sys, json, zipfile + +json.c_make_encoder = None + +from m1n1.proxy import * +from .context import * +from .event import GPUEventManager +from .uapi import * +from m1n1.constructutils import ConstructClass, Ver + +def unswizzle(agx, addr, w, h, psize, dump=None, grid=False): + iface = agx.u.iface + + tw = 64 + th = 64 + ntx = (w + tw - 1) // 64 + nty = (h + th - 1) // 64 + data = iface.readmem(addr, ntx * nty * psize * tw * th) + new_data = [] + for y in range(h): + ty = y // th + for x in range(w): + tx = x // tw + toff = tw * th * psize * (ty * ntx + tx) + j = x & (tw - 1) + i = y & (th - 1) + off = ( + ((j & 1) << 0) | ((i & 1) << 1) | + ((j & 2) << 1) | ((i & 2) << 2) | + ((j & 4) << 2) | ((i & 4) << 3) | + ((j & 8) << 3) | ((i & 8) << 4) | + ((j & 16) << 4) | ((i & 16) << 5) | + ((j & 32) << 5) | ((i & 32) << 6)) + r,g,b,a = data[toff + psize*off: toff + psize*(off+1)] + if grid: + if x % 64 == 0 or y % 64 == 0: + r,g,b,a = 255,255,255,255 + elif x % 32 == 0 or y % 32 == 0: + r,g,b,a = 128,128,128,255 + new_data.append(bytes([b, g, r, a])) + data = b"".join(new_data) + if dump: + open(dump, "wb").write(data[:w*h*psize]) + #iface.writemem(addr, data) + +class GPUFrame: + def __init__(self, context, filename=None, track=False): + self.ctx = context + self.agx = context.agx + self.objects = [] + self.cmdbuf = None + self.track = track + if filename is not None: + self.load(filename) + + def add_object(self, obj): + self.objects.append(obj) + + def save(self, filename): + cmdbuf = self.cmdbuf + with zipfile.ZipFile(filename, "w") as zf: + cmdbuf_data = json.dumps(cmdbuf, indent=4).encode("utf-8") + zf.writestr("cmdbuf.json", cmdbuf_data) + + obj_info = [] + for obj in self.objects: + if obj._data == bytes(obj._size): + filename = None + else: + filename = f"obj_{obj._addr:x}.bin" + zf.writestr(filename, obj._data) + obj_info.append({ + "file": filename, + "name": obj._name, + "addr": obj._addr, + "size": obj._size, + "map_flags": obj._map_flags, + }) + + obj_info_data = json.dumps(obj_info, indent=4).encode("utf-8") + zf.writestr("objects.json", obj_info_data) + + def load(self, filename): + with zipfile.ZipFile(filename, "r") as zf: + with zf.open("cmdbuf.json", "r") as fd: + self.cmdbuf = drm_asahi_cmdbuf_t.from_json(fd) + with zf.open("objects.json", "r") as fd: + obj_info = json.load(fd) + + self.objects = [] + for i in obj_info: + filename = i["file"] + obj = self.ctx.new_at(i["addr"], Bytes(i["size"]), name=i["name"], track=self.track, + **i["map_flags"]) + if filename is not None: + with zf.open(i["file"], "r") as fd: + data = fd.read() + obj.val = data + obj.push() + else: + obj.val = bytes(i["size"]) + obj.push() + self.objects.append(obj) + +class GPUWork: + def __init__(self, renderer): + self.objects = [] + self.renderer = renderer + + def add(self, obj): + self.objects.append(obj) + + def free(self): + for obj in self.objects: + obj.free() + self.objects = [] + +class GPURenderer: + def __init__(self, ctx, buffers=16, bm_slot=0, queue=0): + self.agx = agx = ctx.agx + self.queue = queue + + # 0..63 + self.ctx = ctx + self.ctx_id = ctx.ctx + + # 0..255 + self.buffers = buffers + self.buffer_mgr_slot = bm_slot + + ## These MUST go together + self.buffer_mgr = GPUBufferManager(agx, ctx, buffers) + self.buffer_mgr_initialized = False + self.unk_emptybuf = agx.kobj.new_buf(0x40, "unk_emptybuf") + self.tpc_size = 0 + + ##### Job group + + self.job_list = agx.kshared.new(JobList) + self.job_list.first_job = 0 + self.job_list.last_head = self.job_list._addr # Empty list has self as last_head + self.job_list.unkptr_10 = 0 + self.job_list.push() + + ##### Work Queues + + self.ts3d_1 = agx.kshared.new(Int64ul, name="3D timestamp 1") + self.ts3d_2 = agx.kshared.new(Int64ul, name="3D timestamp 2") + self.tsta_1 = agx.kshared.new(Int64ul, name="TA timestamp 1") + self.tsta_2 = agx.kshared.new(Int64ul, name="TA timestamp 2") + + self.wq_3d = GPU3DWorkQueue(agx, ctx, self.job_list) + self.wq_ta = GPUTAWorkQueue(agx, ctx, self.job_list) + + self.wq_3d.info.uuid = 0x3D0000 | bm_slot + self.wq_3d.info.push() + self.wq_ta.info.uuid = 0x7A0000 | bm_slot + self.wq_ta.info.push() + + self.stamp_value_3d = 0x3D000000 | (bm_slot << 16) + self.stamp_value_ta = 0x7A000000 | (bm_slot << 16) + + ##### TA stamps + + # start? + self.stamp_ta1 = agx.kshared.new(StampCounter, name="TA stamp 1") + self.stamp_ta1.value = self.stamp_value_ta + self.stamp_ta1.push() + + # complete? + self.stamp_ta2 = agx.kobj.new(StampCounter, name="TA stamp 2") + self.stamp_ta2.value = self.stamp_value_ta + self.stamp_ta2.push() + + ##### 3D stamps + + # start? + self.stamp_3d1 = agx.kshared.new(StampCounter, name="3D stamp 1") + self.stamp_3d1.value = self.stamp_value_3d + self.stamp_3d1.push() + + # complete? + self.stamp_3d2 = agx.kobj.new(StampCounter, name="3D stamp 2") + self.stamp_3d2.value = self.stamp_value_3d + self.stamp_3d2.push() + + + ##### Things userspace deals with for macOS + + #self.aux_fb = ctx.uobj.new_buf(0x8000, "Aux FB thing") + ##self.deflake_1 = ctx.uobj.new_buf(0x20, "Deflake 1") + ##self.deflake_2 = ctx.uobj.new_buf(0x280, "Deflake 2") + ##self.deflake_3 = ctx.uobj.new_buf(0x540, "Deflake 3") + #self.deflake = ctx.uobj.new_buf(0x7e0, "Deflake") + #self.unk_buf = ctx.uobj.new(Array(0x800, Int64ul), "Unknown Buffer") + #self.unk_buf.val = [0, *range(1, 0x400), *(0x400 * [0])] + #self.unk_buf.push() + + ##### Some kind of feedback/status buffer, GPU managed? + + self.event_control = agx.kobj.new(EventControl) + self.event_control.event_count = agx.kobj.new(Int32ul, "event_count") + self.event_control.event_count.val = 0 + self.event_control.event_count.push() + + self.event_control.generation = 0 + self.event_control.cur_count = 0 + self.event_control.unk_10 = 0x50 + self.event_control.push() + + self.frames = 0 + + self.ev_ta = ev_ta = self.agx.event_mgr.allocate_event() + self.ev_3d = ev_3d = self.agx.event_mgr.allocate_event() + + self.work = [] + + def submit(self, cmdbuf, wait_for=None): + nclusters = 8 + + work = GPUWork(self) + self.work.append(work) + + self.buffer_mgr.increment() + + aux_fb = self.ctx.uobj.new_buf(0x20000, "Aux FB thing", track=False) + work.add(aux_fb) + + # t8103 + deflake_1_size = 0x540 + deflake_2_size = 0x280 + deflake_3_size = 0x20 + + # t6002 - 9 times larger instead of 8? works with 8... + deflake_1_size *= nclusters + deflake_2_size *= nclusters + deflake_3_size *= nclusters + + deflake_1 = self.ctx.uobj.new_buf(deflake_1_size, "Deflake 1", track=True) + deflake_2 = self.ctx.uobj.new_buf(deflake_2_size, "Deflake 2", track=True) + deflake_3 = self.ctx.uobj.new_buf(deflake_3_size, "Deflake 3", track=True) + work.add(deflake_1) + work.add(deflake_2) + work.add(deflake_3) + + unk_buf = self.ctx.uobj.new(Array(0x800, Int64ul), "Unknown Buffer", track=False) + work.add(unk_buf) + + unk_buf.val = [0, *range(2, 0x401), *(0x400 * [0])] + unk_buf.push() + + work.cmdbuf = cmdbuf + + self.frames += 1 + + work.ev_ta = ev_ta = self.ev_ta + work.ev_3d = ev_3d = self.ev_3d + + self.ev_ta.rearm() + self.ev_3d.rearm() + + self.agx.log(f"ev_ta: {ev_ta.id}") + self.agx.log(f"ev_3d: {ev_3d.id}") + + #self.event_control.base_stamp = self.stamp_value >> 8 + #self.event_control.push() + + self.prev_stamp_value_3d = self.stamp_value_3d + self.prev_stamp_value_ta = self.stamp_value_ta + self.stamp_value_3d += 0x100 + self.stamp_value_ta += 0x100 + self.event_control.event_count.val += 2 + self.event_control.event_count.push() + + work.stamp_value_3d = self.stamp_value_3d + work.stamp_value_ta = self.stamp_value_ta + + agx = self.agx + ctx = self.ctx + + work.width = width = cmdbuf.fb_width + work.height = height = cmdbuf.fb_height + + ##### TVB allocations / Tiler config + + tile_width = 32 + tile_height = 32 + tiles_x = ((width + tile_width - 1) // tile_width) + tiles_y = ((height + tile_height - 1) // tile_height) + tiles = tiles_x * tiles_y + + mtiles_x = 4 + mtiles_y = 4 + + mtile_x1 = align(((tiles_x + mtiles_x - 1) // mtiles_x), 4) + mtile_x2 = 2 * mtile_x1 + mtile_x3 = 3 * mtile_x1 + mtile_y1 = align(((tiles_y + mtiles_y - 1) // mtiles_y), 4) + mtile_y2 = 2 * mtile_y1 + mtile_y3 = 3 * mtile_y1 + + mtile_stride = mtile_x1 * mtile_y1 + + ## TODO: *samples + tiles_per_mtile_x = mtile_x1 + tiles_per_mtile_y = mtile_y1 + + tile_blocks_x = (tiles_x + 15) // 16 + tile_blocks_y = (tiles_y + 15) // 16 + tile_blocks = tile_blocks_x * tile_blocks_y + + tiling_params = TilingParameters() + # rgn_header_size + rgn_entry_size = 5 + tiling_params.size1 = (rgn_entry_size * tiles_per_mtile_x * tiles_per_mtile_y + 3) // 4 + # PPP_MULTISAMPLECTL + tiling_params.unk_4 = 0x88 + # PPP_CTRL + tiling_params.unk_8 = 0x203 # bit 0: GL clip mode + # PPP_SCREEN + tiling_params.x_max = width - 1 + tiling_params.y_max = height - 1 + # TE_SCREEN + tiling_params.tile_count = ((tiles_y-1) << 12) | (tiles_x-1) + # TE_MTILE1 + tiling_params.x_blocks = mtile_x3 | (mtile_x2 << 9) | (mtile_x1 << 18) + # TE_MTILE2 + tiling_params.y_blocks = mtile_y3 | (mtile_y2 << 9) | (mtile_y1 << 18) + tiling_params.size2 = mtile_stride + tiling_params.size3 = 2 * mtile_stride + tiling_params.unk_24 = 0x100 + tiling_params.unk_28 = 0x8000 + + tilemap_size = (4 * tiling_params.size1 * mtiles_x * mtiles_y) + + tmtiles_x = tiles_per_mtile_x * mtiles_x + tmtiles_y = tiles_per_mtile_y * mtiles_y + + tpc_entry_size = 8 + tpc_size = tpc_entry_size * tmtiles_x * tmtiles_y * nclusters + + if self.tpc_size < tpc_size: + self.tpc = ctx.uobj.new_buf(tpc_size, "TPC", track=True).push() + self.tpc_size = tpc_size + + depth_aux_buffer_addr = 0 + if cmdbuf.depth_buffer: + size = align_pot(max(width, tile_width)) * align_pot(max(height, tile_width)) // 32 + depth_aux_buffer = self.ctx.uobj.new_buf(size, "Depth Aux", track=True) + work.add(depth_aux_buffer) + depth_aux_buffer_addr = depth_aux_buffer._addr + + stencil_aux_buffer_addr = 0 + if cmdbuf.stencil_buffer: + size = align_pot(max(width, tile_width)) * align_pot(max(height, tile_width)) // 32 + stencil_aux_buffer = self.ctx.uobj.new_buf(size, "Stencil Aux", track=False) + work.add(stencil_aux_buffer) + stencil_aux_buffer_addr = stencil_aux_buffer._addr + + #tvb_tilemap_size = 0x80 * mtile_stride + tvb_tilemap_size = tilemap_size + tvb_tilemap = ctx.uobj.new_buf(tvb_tilemap_size, "TVB Tilemap", track=True).push() + work.tvb_tilemap_size = tvb_tilemap_size + work.tvb_tilemap = tvb_tilemap + work.add(tvb_tilemap) + + # rogue: 0x180 * 4? + tvb_heapmeta_size = 0x200 + #tvb_heapmeta_size = 0x600 + tvb_heapmeta = ctx.uobj.new_buf(tvb_heapmeta_size, "TVB Heap Meta", track=False).push() + work.add(tvb_heapmeta) + + unk_tile_buf1 = self.ctx.uobj.new_buf(tvb_tilemap_size * nclusters, "Unk tile buf 1", track=True) + print("tvb_tilemap_size", hex(tvb_tilemap_size)) + unk_tile_buf2 = self.ctx.uobj.new_buf(0x4 * nclusters, "Unk tile buf 2", track=True) + #size = 0xc0 * nclusters + size = 0xc80 + unk_tile_buf3 = self.ctx.uobj.new_buf(size, "Unk tile buf 3", track=True) + unk_tile_buf4 = self.ctx.uobj.new_buf(0x280 * nclusters, "Unk tile buf 4", track=True) + unk_tile_buf5 = self.ctx.uobj.new_buf(0x30 * nclusters, "Unk tile buf 5", track=True) + work.add(unk_tile_buf1) + work.add(unk_tile_buf2) + work.add(unk_tile_buf3) + work.add(unk_tile_buf4) + work.add(unk_tile_buf5) + + ##### Buffer stuff? + + # buffer related? + bufferthing_buf = ctx.uobj.new_buf(0x80, "BufferThing.unkptr_18", track=True) + work.add(bufferthing_buf) + + work.buf_desc = buf_desc = agx.kobj.new(BufferThing, track=False) + work.add(buf_desc) + buf_desc.unk_0 = 0x0 + buf_desc.unk_8 = 0x0 + buf_desc.unk_10 = 0x0 + buf_desc.unkptr_18 = bufferthing_buf._addr + buf_desc.unk_20 = 0x0 + buf_desc.bm_misc_addr = self.buffer_mgr.misc_obj._addr + buf_desc.unk_2c = 0x0 + buf_desc.unk_30 = 0x0 + buf_desc.unk_38 = 0x0 + buf_desc.push() + + uuid_3d = cmdbuf.cmd_3d_id + uuid_ta = cmdbuf.cmd_ta_id + encoder_id = cmdbuf.encoder_id + + #print(barrier_cmd) + + #self.wq_ta.submit(ta_barrier_cmd) + + ##### 3D barrier command + + barrier_cmd = agx.kobj.new(WorkCommandBarrier, track=False) + work.add(barrier_cmd) + barrier_cmd.stamp = self.stamp_ta2 + barrier_cmd.wait_value = self.stamp_value_ta + barrier_cmd.stamp_self = self.stamp_value_3d + barrier_cmd.event = ev_ta.id + barrier_cmd.uuid = uuid_3d + + #print(barrier_cmd) + + self.wq_3d.submit(barrier_cmd) + + ##### 3D execution + + work.wc_3d = wc_3d = agx.kobj.new(WorkCommand3D, track=False) + work.add(work.wc_3d) + wc_3d.counter = 0 + wc_3d.context_id = self.ctx_id + wc_3d.unk_8 = 0 + wc_3d.event_control = self.event_control + wc_3d.buffer_mgr = self.buffer_mgr.info + wc_3d.buf_thing = buf_desc + wc_3d.unk_emptybuf_addr = self.unk_emptybuf._addr + wc_3d.tvb_tilemap = tvb_tilemap._addr + wc_3d.unk_40 = 0x88 + wc_3d.unk_48 = 0x1 + wc_3d.tile_blocks_y = mtile_y1 + wc_3d.tile_blocks_x = mtile_x1 + wc_3d.unk_50 = 0x0 + wc_3d.unk_58 = 0x0 + + TAN_60 = 1.732051 + wc_3d.merge_upper_x = TAN_60 / width + wc_3d.merge_upper_y = TAN_60 / height + wc_3d.unk_68 = 0x0 + wc_3d.tile_count = tiles + + wc_3d.unk_758 = Flag() + wc_3d.unk_75c = Flag() + wc_3d.unk_buf = WorkCommand1_UnkBuf() + wc_3d.busy_flag = Flag() + wc_3d.unk_buf2 = WorkCommand1_UnkBuf2() + wc_3d.unk_buf2.unk_0 = 0 + wc_3d.unk_buf2.unk_8 = 0 + wc_3d.unk_buf2.unk_10 = 1 + wc_3d.ts1 = TimeStamp(0) + wc_3d.ts2 = TimeStamp(self.ts3d_1._addr) + wc_3d.ts3 = TimeStamp(self.ts3d_2._addr) + wc_3d.unk_914 = 0 + wc_3d.unk_918 = 0 + wc_3d.unk_920 = 0 + wc_3d.unk_924 = 1 + # Ventura + wc_3d.unk_928_0 = 0 + wc_3d.unk_928_4 = 0 + wc_3d.ts_flag = TsFlag() + + # cmdbuf.ds_flags + # 0 - no depth + # 0x80000 - depth store enable + # 0x08000 - depth load enable + + # 0x00044 - compressed depth + + # 0x40000 - stencil store enable + # 0x04000 - stencil load enable + # 0x00110 - compressed stencil + + # Z store format + # 0x4000000 - Depth16Unorm + + # For Depth16Unorm: 0x40000 here also + # AFBI.[ 0. 4] unk1 = 0x4c000 + + # ASAHI_CMDBUF_SET_WHEN_RELOADING_Z_OR_S + # Actually set when loading *and* storing Z, OR loading *and* storing S + + # Structures embedded in WorkCommand3D + if True: + wc_3d.struct_1 = Start3DStruct1() + wc_3d.struct_1.store_pipeline_bind = cmdbuf.store_pipeline_bind + wc_3d.struct_1.store_pipeline_addr = cmdbuf.store_pipeline | 4 + wc_3d.struct_1.unk_8 = 0x0 + wc_3d.struct_1.unk_c = 0x0 + + TAN_60 = 1.732051 + wc_3d.struct_1.merge_upper_x = TAN_60 / width + wc_3d.struct_1.merge_upper_y = TAN_60 / height + + wc_3d.struct_1.unk_18 = 0x0 + # ISP_MTILE_SIZE + wc_3d.struct_1.tile_blocks_y = mtile_y1 + wc_3d.struct_1.tile_blocks_x = mtile_x1 + wc_3d.struct_1.unk_24 = 0x0 + wc_3d.struct_1.tile_counts = ((tiles_y-1) << 12) | (tiles_x-1) + wc_3d.struct_1.unk_2c = 0x8 + wc_3d.struct_1.depth_clear_val1 = cmdbuf.depth_clear_value + wc_3d.struct_1.stencil_clear_val1 = cmdbuf.stencil_clear_value + wc_3d.struct_1.unk_35 = 0x7 # clear flags? 2 = depth 4 = stencil? + wc_3d.struct_1.unk_36 = 0x0 + wc_3d.struct_1.unk_38 = 0x0 + wc_3d.struct_1.unk_3c = 0x1 + wc_3d.struct_1.unk_40 = 0 + wc_3d.struct_1.unk_44_padding = bytes(0xac) + wc_3d.struct_1.depth_bias_array = Start3DArrayAddr(cmdbuf.depth_bias_array) + wc_3d.struct_1.scissor_array = Start3DArrayAddr(cmdbuf.scissor_array) + wc_3d.struct_1.visibility_result_buffer = 0x0 + wc_3d.struct_1.unk_118 = 0x0 + wc_3d.struct_1.unk_120 = [0] * 37 + wc_3d.struct_1.unk_reload_pipeline = Start3DClearPipelineBinding( + cmdbuf.partial_reload_pipeline_bind, cmdbuf.partial_reload_pipeline | 4) + wc_3d.struct_1.unk_258 = 0 + wc_3d.struct_1.unk_260 = 0 + wc_3d.struct_1.unk_268 = 0 + wc_3d.struct_1.unk_270 = 0 + wc_3d.struct_1.reload_pipeline = Start3DClearPipelineBinding( + cmdbuf.partial_reload_pipeline_bind, cmdbuf.partial_reload_pipeline | 4) + wc_3d.struct_1.depth_flags = cmdbuf.ds_flags | 0x44 + wc_3d.struct_1.unk_290 = 0x0 + wc_3d.struct_1.depth_buffer_ptr1 = cmdbuf.depth_buffer + wc_3d.struct_1.unk_2a0 = 0x0 + wc_3d.struct_1.unk_2a8 = 0x0 + wc_3d.struct_1.depth_buffer_ptr2 = cmdbuf.depth_buffer + wc_3d.struct_1.depth_buffer_ptr3 = cmdbuf.depth_buffer + wc_3d.struct_1.depth_aux_buffer_ptr = depth_aux_buffer_addr + wc_3d.struct_1.stencil_buffer_ptr1 = cmdbuf.stencil_buffer + wc_3d.struct_1.unk_2d0 = 0x0 + wc_3d.struct_1.unk_2d8 = 0x0 + wc_3d.struct_1.stencil_buffer_ptr2 = cmdbuf.stencil_buffer + wc_3d.struct_1.stencil_buffer_ptr3 = cmdbuf.stencil_buffer + wc_3d.struct_1.stencil_aux_buffer_ptr = stencil_aux_buffer_addr + wc_3d.struct_1.unk_2f8 = [0x0, 0x0] + wc_3d.struct_1.aux_fb_unk0 = 4 #0x8 # sometimes 4 + wc_3d.struct_1.unk_30c = 0x0 + wc_3d.struct_1.aux_fb = AuxFBInfo(0xc000, 0, width, height) + wc_3d.struct_1.unk_320_padding = bytes(0x10) + wc_3d.struct_1.unk_partial_store_pipeline = Start3DStorePipelineBinding( + cmdbuf.partial_store_pipeline_bind, cmdbuf.partial_store_pipeline | 4) + wc_3d.struct_1.partial_store_pipeline = Start3DStorePipelineBinding( + cmdbuf.partial_store_pipeline_bind, cmdbuf.partial_store_pipeline | 4) + wc_3d.struct_1.depth_clear_val2 = cmdbuf.depth_clear_value + wc_3d.struct_1.stencil_clear_val2 = cmdbuf.stencil_clear_value + wc_3d.struct_1.unk_375 = 3 + wc_3d.struct_1.unk_376 = 0x0 + wc_3d.struct_1.unk_378 = 0x10 + wc_3d.struct_1.unk_37c = 0x0 + wc_3d.struct_1.unk_380 = 0x0 + wc_3d.struct_1.unk_388 = 0x0 + wc_3d.struct_1.unk_390_0 = 0x0 # Ventura + wc_3d.struct_1.depth_dimensions = (width - 1) | ((height - 1) << 15) + + if True: + wc_3d.struct_2 = Start3DStruct2() + wc_3d.struct_2.unk_0 = 0xa000 + wc_3d.struct_2.clear_pipeline = Start3DClearPipelineBinding( + cmdbuf.load_pipeline_bind, cmdbuf.load_pipeline | 4) + wc_3d.struct_2.unk_18 = 0x88 + wc_3d.struct_2.scissor_array = cmdbuf.scissor_array + wc_3d.struct_2.depth_bias_array = cmdbuf.depth_bias_array + wc_3d.struct_2.aux_fb = wc_3d.struct_1.aux_fb + # ISP_ZLS_PIXELS + wc_3d.struct_2.depth_dimensions = wc_3d.struct_1.depth_dimensions + wc_3d.struct_2.visibility_result_buffer = 0x0 + # ISP_ZLSCTL + wc_3d.struct_2.depth_flags = cmdbuf.ds_flags + wc_3d.struct_2.unk_58_g14_0 = 0x4040404 + wc_3d.struct_2.unk_58_g14_8 = 0 + wc_3d.struct_2.depth_buffer_ptr1 = cmdbuf.depth_buffer + wc_3d.struct_2.depth_buffer_ptr2 = cmdbuf.depth_buffer + wc_3d.struct_2.unk_68_g14_0 = 0 + wc_3d.struct_2.stencil_buffer_ptr1 = cmdbuf.stencil_buffer + wc_3d.struct_2.stencil_buffer_ptr2 = cmdbuf.stencil_buffer + wc_3d.struct_2.unk_78 = [0] * 4 + wc_3d.struct_2.depth_aux_buffer_ptr1 = depth_aux_buffer_addr + wc_3d.struct_2.unk_a0 = 0 + wc_3d.struct_2.depth_aux_buffer_ptr2 = depth_aux_buffer_addr + wc_3d.struct_2.unk_b0 = 0 + wc_3d.struct_2.stencil_aux_buffer_ptr1 = stencil_aux_buffer_addr + wc_3d.struct_2.unk_c0 = 0 + wc_3d.struct_2.stencil_aux_buffer_ptr2 = stencil_aux_buffer_addr + wc_3d.struct_2.unk_d0 = 0 + wc_3d.struct_2.tvb_tilemap = tvb_tilemap._addr + wc_3d.struct_2.tvb_heapmeta_addr = tvb_heapmeta._addr + wc_3d.struct_2.unk_e8 = tiling_params.size1 << 24 + wc_3d.struct_2.tvb_heapmeta_addr2 = tvb_heapmeta._addr + # 0x10000 - clear empty tiles + # ISP_CTL (but bits seem to have moved) + wc_3d.struct_2.unk_f8 = 0x10280 #0x10280 # TODO: varies 0, 0x280, 0x10000, 0x10280 + wc_3d.struct_2.aux_fb_ptr = aux_fb._addr + wc_3d.struct_2.unk_108 = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0] + wc_3d.struct_2.pipeline_base = self.ctx.pipeline_base + wc_3d.struct_2.unk_140 = 0x8c60 + wc_3d.struct_2.unk_148 = 0x0 + wc_3d.struct_2.unk_150 = 0x0 + wc_3d.struct_2.unk_158 = 0x1c + wc_3d.struct_2.unk_160 = 0 + wc_3d.struct_2.unk_168_padding = bytes(0x1d8) + wc_3d.struct_2.unk_198_padding = bytes(0x1a8) + + if True: + wc_3d.struct_6 = Start3DStruct6() + wc_3d.struct_6.tvb_overflow_count = 0x0 + wc_3d.struct_6.unk_8 = 0x0 # 1? + wc_3d.struct_6.unk_c = 0x0 # 1? + wc_3d.struct_6.unk_10 = 0x0 + wc_3d.struct_6.encoder_id = cmdbuf.encoder_id + wc_3d.struct_6.unk_1c = 0xffffffff + wc_3d.struct_6.unknown_buffer = unk_buf._addr + wc_3d.struct_6.unk_28 = 0x0 + wc_3d.struct_6.unk_30 = 0x0 + wc_3d.struct_6.unk_34 = 0x0 + + if True: + wc_3d.struct_7 = Start3DStruct7() + wc_3d.struct_7.unk_0 = 0x0 + wc_3d.struct_7.stamp1 = self.stamp_3d1 + wc_3d.struct_7.stamp2 = self.stamp_3d2 + wc_3d.struct_7.stamp_value = self.stamp_value_3d + wc_3d.struct_7.ev_3d = ev_3d.id + wc_3d.struct_7.evctl_index = 0x0 + wc_3d.struct_7.unk_24 = 1 + wc_3d.struct_7.uuid = uuid_3d + wc_3d.struct_7.prev_stamp_value = self.prev_stamp_value_3d >> 8 + wc_3d.struct_7.unk_30 = 0x0 + + wc_3d.set_addr() # Update inner structure addresses + #print("WC3D", hex(wc_3d._addr)) + #print(" s1", hex(wc_3d.struct_1._addr)) + #print(" s2", hex(wc_3d.struct_2._addr)) + #print(" s6", hex(wc_3d.struct_6._addr)) + #print(" s7", hex(wc_3d.struct_7._addr)) + + ms = GPUMicroSequence(agx) + + start_3d = Start3DCmd() + start_3d.struct1 = wc_3d.struct_1 # 0x44 bytes! + start_3d.struct2 = wc_3d.struct_2 # 0x168 bytes! + start_3d.buf_thing = buf_desc + start_3d.stats_ptr = agx.initdata.regionB.stats_3d.stats._addr + start_3d.busy_flag_ptr = wc_3d.busy_flag._addr + start_3d.struct6 = wc_3d.struct_6 # 4 bytes! + start_3d.struct7 = wc_3d.struct_7 # 4 bytes! + start_3d.cmdqueue_ptr = self.wq_3d.info._addr + start_3d.workitem_ptr = wc_3d._addr + start_3d.context_id = self.ctx_id + start_3d.unk_50 = 0x1 + start_3d.event_generation = self.event_control.generation + start_3d.buffer_mgr_slot = self.buffer_mgr_slot + start_3d.unk_5c = 0x0 + start_3d.prev_stamp_value = self.prev_stamp_value_3d >> 8 + start_3d.unk_68 = 0x0 + start_3d.unk_buf_ptr = wc_3d.unk_758._addr + start_3d.unk_buf2_ptr = wc_3d.unk_buf2._addr + start_3d.unk_7c = 0x0 + start_3d.unk_80 = 0x0 + start_3d.unk_84 = 0x0 + start_3d.uuid = uuid_3d + start_3d.attachments = [] + start_3d.unk_194 = 0 + start_3d.unkptr_19c = self.event_control.unk_buf._addr + + work.fb = None + work.depth = None + + for i in cmdbuf.attachments[:cmdbuf.attachment_count]: + cache_lines = align_up(i.size, 128) // 128 + order = 1 # FIXME + start_3d.attachments.append(Attachment(i.pointer, cache_lines, 0x17, order)) # FIXME check + if work.fb is None and i.type == ASAHI_ATTACHMENT_C: + work.fb = i.pointer + if work.depth is None and i.type == ASAHI_ATTACHMENT_Z: + work.depth = i.pointer + start_3d.attachments += [Attachment(0, 0, 0, 0)] * (16 - len(start_3d.attachments)) + start_3d.num_attachments = cmdbuf.attachment_count + start_3d.unk_190 = 0x0 + + start_3d_offset = ms.append(start_3d) + + ts1 = TimestampCmd() + ts1.unk_1 = 0x0 + ts1.unk_2 = 0x0 + ts1.unk_3 = 0x80 + ts1.ts0_addr = wc_3d.ts1._addr + ts1.ts1_addr = wc_3d.ts2._addr + ts1.ts2_addr = wc_3d.ts2._addr + ts1.cmdqueue_ptr = self.wq_3d.info._addr + ts1.unk_24 = 0x0 + if Ver.check("V >= V13_0B4"): + ts1.unkptr_2c_0 = wc_3d.ts_flag._addr + ts1.uuid = uuid_3d + ts1.unk_30_padding = 0x0 + ms.append(ts1) + + ms.append(WaitForInterruptCmd(0, 1, 0)) + + ts2 = TimestampCmd() + ts2.unk_1 = 0x0 + ts2.unk_2 = 0x0 + ts2.unk_3 = 0x0 + ts2.ts0_addr = wc_3d.ts1._addr + ts2.ts1_addr = wc_3d.ts2._addr + ts2.ts2_addr = wc_3d.ts3._addr + ts2.cmdqueue_ptr = self.wq_3d.info._addr + ts2.unk_24 = 0x0 + if Ver.check("V >= V13_0B4"): + ts2.unkptr_2c_0 = wc_3d.ts_flag._addr + ts2.uuid = uuid_3d + ts2.unk_30_padding = 0x0 + ms.append(ts2) + + finish_3d = Finalize3DCmd() + finish_3d.uuid = uuid_3d + finish_3d.unk_8 = 0 + finish_3d.stamp = self.stamp_3d2 + finish_3d.stamp_value = self.stamp_value_3d + finish_3d.unk_18 = 0 + finish_3d.buf_thing = buf_desc + finish_3d.buffer_mgr = self.buffer_mgr.info + finish_3d.unk_2c = 1 + finish_3d.stats_ptr = agx.initdata.regionB.stats_3d.stats._addr + finish_3d.struct7 = wc_3d.struct_7 + finish_3d.busy_flag_ptr = wc_3d.busy_flag._addr + finish_3d.cmdqueue_ptr = self.wq_3d.info._addr + finish_3d.workitem_ptr = wc_3d._addr + finish_3d.unk_5c = self.ctx_id + finish_3d.unk_buf_ptr = wc_3d.unk_758._addr + finish_3d.unk_6c = 0 + finish_3d.unk_74 = 0 + finish_3d.unk_7c = 0 + finish_3d.unk_84 = 0 + finish_3d.unk_8c = 0 + finish_3d.unk_8c_g14 = 0 + finish_3d.restart_branch_offset = start_3d_offset - ms.off + finish_3d.unk_98 = 0 + finish_3d.unk_9c = bytes(0x10) + ms.append(finish_3d) + ms.finalize() + + work.add(ms.obj) + + wc_3d.microsequence_ptr = ms.obj._addr + wc_3d.microsequence_size = ms.size + + print(wc_3d) + self.wq_3d.submit(wc_3d) + + ##### TA init + + #print(ctx_info) + if wait_for is not None: + barrier_cmd = agx.kobj.new(WorkCommandBarrier, track=False) + work.add(barrier_cmd) + if not isinstance(wait_for, tuple): + barrier_cmd.stamp = wait_for.renderer.stamp_3d2 + barrier_cmd.wait_value = wait_for.stamp_value_3d + barrier_cmd.event = wait_for.ev_3d.id + else: + barrier_cmd.stamp_addr = wait_for[0] + barrier_cmd.wait_value = wait_for[1] + barrier_cmd.event = wait_for[2] + + barrier_cmd.stamp_self = self.stamp_value_ta + barrier_cmd.uuid = uuid_ta + + self.wq_ta.submit(barrier_cmd) + + if not self.buffer_mgr_initialized: + wc_initbm = agx.kobj.new(WorkCommandInitBM, track=False) + work.add(wc_initbm) + wc_initbm.context_id = self.ctx_id + wc_initbm.buffer_mgr_slot = self.buffer_mgr_slot + wc_initbm.unk_c = 0 + wc_initbm.unk_10 = self.buffer_mgr.info.block_count + wc_initbm.buffer_mgr = self.buffer_mgr.info + wc_initbm.stamp_value = self.stamp_value_ta + + self.wq_ta.submit(wc_initbm) + + self.buffer_mgr_initialized = True + + ##### TA execution + + work.wc_ta = wc_ta = agx.kobj.new(WorkCommandTA, track=False) + work.add(work.wc_ta) + wc_ta.context_id = self.ctx_id + wc_ta.counter = 1 + wc_ta.unk_8 = 0 + wc_ta.event_control = self.event_control + wc_ta.buffer_mgr_slot = self.buffer_mgr_slot + wc_ta.buffer_mgr = self.buffer_mgr.info + wc_ta.buf_thing = buf_desc + wc_ta.unk_emptybuf_addr = wc_3d.unk_emptybuf_addr + wc_ta.unk_34 = 0x0 + + wc_ta.unk_154 = bytes(0x268) + wc_ta.unk_3e8 = bytes(0x74) + wc_ta.unk_594 = WorkCommand0_UnkBuf() + + wc_ta.ts1 = TimeStamp(0) + wc_ta.ts2 = TimeStamp(self.tsta_1._addr) + wc_ta.ts3 = TimeStamp(self.tsta_2._addr) + wc_ta.unk_5c4 = 0 + wc_ta.unk_5c8 = 0 + wc_ta.unk_5cc = 0 + wc_ta.unk_5d0 = 0 + wc_ta.unk_5d4 = 1 #0x27 #1 + # Ventura + wc_ta.unk_5e0 = 0 + wc_ta.unk_5e4 = 0 + wc_ta.ts_flag = TsFlag() + + # Structures embedded in WorkCommandTA + if True: + wc_ta.tiling_params = tiling_params + + if True: + wc_ta.struct_2 = StartTACmdStruct2() + wc_ta.struct_2.unk_0 = 0x200 + wc_ta.struct_2.unk_8 = 0x1e3ce508 # fixed + wc_ta.struct_2.unk_c = 0x1e3ce508 # fixed + wc_ta.struct_2.tvb_tilemap = tvb_tilemap._addr + wc_ta.struct_2.tvb_cluster_tilemaps = unk_tile_buf1._addr + wc_ta.struct_2.tpc = self.tpc._addr + wc_ta.struct_2.tvb_heapmeta_addr = tvb_heapmeta._addr | 0x8000_0000_0000_0000 + wc_ta.struct_2.iogpu_unk_54 = 0x6b0003 # fixed + wc_ta.struct_2.iogpu_unk_55 = 0x3a0012 # fixed + wc_ta.struct_2.iogpu_unk_56 = 0x1 # fixed + wc_ta.struct_2.tvb_cluster_meta1 = unk_tile_buf2._addr | 0x4_0000_0000_0000 + wc_ta.struct_2.unk_48 = 0xa000 + wc_ta.struct_2.unk_50 = 0x88 # fixed + wc_ta.struct_2.tvb_heapmeta_addr2 = tvb_heapmeta._addr + wc_ta.struct_2.unk_60 = 0x0 # fixed + wc_ta.struct_2.core_mask = 0xffffffffffffffff + #wc_ta.struct_2.unk_68 = 0xff << (8 * (self.buffer_mgr_slot % 8)) + wc_ta.struct_2.iogpu_deflake_1 = deflake_1._addr + wc_ta.struct_2.iogpu_deflake_2 = deflake_2._addr + wc_ta.struct_2.unk_80 = 0x1 # fixed + wc_ta.struct_2.iogpu_deflake_3 = deflake_3._addr | 0x4_0000_0000_0000 # check + wc_ta.struct_2.encoder_addr = cmdbuf.encoder_ptr + wc_ta.struct_2.tvb_cluster_meta2 = unk_tile_buf3._addr + wc_ta.struct_2.tvb_cluster_meta3 = unk_tile_buf4._addr + wc_ta.struct_2.tiling_control = 0xa040 #0xa041 # fixed + wc_ta.struct_2.unk_b0 = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0] # fixed + wc_ta.struct_2.pipeline_base = self.ctx.pipeline_base + wc_ta.struct_2.tvb_cluster_meta4 = unk_tile_buf5._addr | 0x3000_0000_0000_0000 + wc_ta.struct_2.unk_f0 = 0x20 # fixed + wc_ta.struct_2.unk_f8 = 0x8c60 # fixed + wc_ta.struct_2.unk_100 = [0x0, 0x0, 0x0] # fixed + wc_ta.struct_2.unk_118 = 0x1c # fixed + + if True: + wc_ta.struct_3 = StartTACmdStruct3() + wc_ta.struct_3.unk_480 = [0x0, 0x0, 0x0, 0x0, 0x0, 0x0] # fixed + wc_ta.struct_3.unk_498 = 0x0 # fixed + wc_ta.struct_3.unk_4a0 = 0x0 # fixed + wc_ta.struct_3.iogpu_deflake_1 = deflake_1._addr + wc_ta.struct_3.unk_4ac = 0x0 # fixed + wc_ta.struct_3.unk_4b0 = 0x0 # fixed + wc_ta.struct_3.unk_4b8 = 0x0 # fixed + wc_ta.struct_3.unk_4bc = 0x0 # fixed + wc_ta.struct_3.unk_4c4_padding = bytes(0x48) + wc_ta.struct_3.unk_50c = 0x0 # fixed + wc_ta.struct_3.unk_510 = 0x0 # fixed + wc_ta.struct_3.unk_518 = 0x0 # fixed + wc_ta.struct_3.unk_520 = 0x0 # fixed + wc_ta.struct_3.unk_528 = 0x0 # fixed + wc_ta.struct_3.unk_52c = 0x0 # fixed + wc_ta.struct_3.unk_530 = 0x0 # fixed + wc_ta.struct_3.encoder_id = cmdbuf.encoder_id + wc_ta.struct_3.unk_538 = 0x0 # fixed + wc_ta.struct_3.unk_53c = 0xffffffff + wc_ta.struct_3.unknown_buffer = wc_3d.struct_6.unknown_buffer + wc_ta.struct_3.unk_548 = 0x0 # fixed + wc_ta.struct_3.unk_550 = [ + 0x0, 0x0, # fixed + 0x0, # 1 for boot stuff? + 0x0, 0x0, 0x0] # fixed + wc_ta.struct_3.stamp1 = self.stamp_ta1 + wc_ta.struct_3.stamp2 = self.stamp_ta2 + wc_ta.struct_3.stamp_value = self.stamp_value_ta + wc_ta.struct_3.ev_ta = ev_ta.id + wc_ta.struct_3.evctl_index = 0 + wc_ta.struct_3.unk_584 = 0x0 # 1 for boot stuff? + wc_ta.struct_3.uuid2 = uuid_ta + wc_ta.struct_3.prev_stamp_value = self.prev_stamp_value_ta >> 8 + wc_ta.struct_3.unk_590 = 0 # sometimes 1? + + wc_ta.set_addr() # Update inner structure addresses + #print("wc_ta", wc_ta) + + ms = GPUMicroSequence(agx) + + start_ta = StartTACmd() + start_ta.tiling_params = wc_ta.tiling_params + start_ta.struct2 = wc_ta.struct_2 # len 0x120 + start_ta.buffer_mgr = self.buffer_mgr.info + start_ta.buf_thing = buf_desc + start_ta.stats_ptr = agx.initdata.regionB.stats_ta.stats._addr + start_ta.cmdqueue_ptr = self.wq_ta.info._addr + start_ta.context_id = self.ctx_id + start_ta.unk_38 = 1 + start_ta.event_generation = self.event_control.generation + start_ta.buffer_mgr_slot = self.buffer_mgr_slot + start_ta.unk_48 = 0#1 #0 + start_ta.unk_50 = 0 + start_ta.struct3 = wc_ta.struct_3 + + start_ta.unkptr_5c = wc_ta.unk_594._addr + start_ta.unk_64 = 0x0 # fixed + start_ta.unk_68 = 0x0 # sometimes 1? + start_ta.uuid = uuid_ta + start_ta.unk_70 = 0x0 # fixed + start_ta.unk_74 = [ # fixed + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ] + start_ta.unk_15c = 0x0 # fixed + start_ta.unk_160 = 0x0 # fixed + start_ta.unk_168 = 0x0 # fixed + start_ta.unk_16c = 0x0 # fixed + start_ta.unk_170 = 0x0 # fixed + start_ta.unk_178 = 0x0 # fixed? + start_ta.unk_17c = 0x0 + start_ta.unkptr_180 = self.event_control.unk_buf._addr + start_ta.unk_188 = 0x0 + + start_ta_offset = ms.append(start_ta) + + ts1 = TimestampCmd() + ts1.unk_1 = 0x0 + ts1.unk_2 = 0x0 + ts1.unk_3 = 0x80 + ts1.ts0_addr = wc_ta.ts1._addr + ts1.ts1_addr = wc_ta.ts2._addr + ts1.ts2_addr = wc_ta.ts2._addr + ts1.cmdqueue_ptr = self.wq_ta.info._addr + ts1.unk_24 = 0x0 + if Ver.check("V >= V13_0B4"): + ts1.unkptr_2c_0 = wc_ta.ts_flag._addr + ts1.uuid = uuid_ta + ts1.unk_30_padding = 0x0 + ms.append(ts1) + + ms.append(WaitForInterruptCmd(1, 0, 0)) + + ts2 = TimestampCmd() + ts2.unk_1 = 0x0 + ts2.unk_2 = 0x0 + ts2.unk_3 = 0x0 + ts2.ts0_addr = wc_ta.ts1._addr + ts2.ts1_addr = wc_ta.ts2._addr + ts2.ts2_addr = wc_ta.ts3._addr + ts2.cmdqueue_ptr = self.wq_ta.info._addr + ts2.unk_24 = 0x0 + if Ver.check("V >= V13_0B4"): + ts2.unkptr_2c_0 = wc_ta.ts_flag._addr + ts2.uuid = uuid_ta + ts2.unk_30_padding = 0x0 + ms.append(ts2) + + finish_ta = FinalizeTACmd() + finish_ta.buf_thing = buf_desc + finish_ta.buffer_mgr = self.buffer_mgr.info + finish_ta.stats_ptr = agx.initdata.regionB.stats_ta.stats._addr + finish_ta.cmdqueue_ptr = self.wq_ta.info._addr + finish_ta.context_id = self.ctx_id + finish_ta.unk_28 = 0x0 # fixed + finish_ta.struct3 = wc_ta.struct_3 + finish_ta.unk_34 = 0x0 # fixed + finish_ta.uuid = uuid_ta + finish_ta.stamp = self.stamp_ta2 + finish_ta.stamp_value = self.stamp_value_ta + finish_ta.unk_48 = 0x0 # fixed + finish_ta.unk_50 = 0x0 # fixed + finish_ta.unk_54 = 0x0 # fixed + finish_ta.unk_58 = 0x0 # fixed + finish_ta.unk_60 = 0x0 # fixed + finish_ta.unk_64 = 0x0 # fixed + finish_ta.unk_68 = 0x0 # fixed + finish_ta.unk_6c_g14 = 0 # fixed + finish_ta.restart_branch_offset = start_ta_offset - ms.off + finish_ta.unk_70 = 0x0 # fixed + finish_ta.unk_74 = bytes(0x10) # Ventura + ms.append(finish_ta) + + ms.finalize() + + work.add(ms.obj) + + wc_ta.unkptr_45c = self.tpc._addr + wc_ta.tvb_size = tpc_size + wc_ta.microsequence_ptr = ms.obj._addr + wc_ta.microsequence_size = ms.size + wc_ta.ev_3d = ev_3d.id + wc_ta.stamp_value = self.stamp_value_ta + + print(wc_ta) + self.wq_ta.submit(wc_ta) + + self.agx.log("Submit done") + return work + + def run(self): + ##### Run queues + self.agx.log("Run queues") + self.agx.ch.queue[self.queue].q_3D.run(self.wq_3d, self.ev_3d.id) + self.agx.ch.queue[self.queue].q_TA.run(self.wq_ta, self.ev_ta.id) + self.agx.log("Run done") + + def wait(self): + self.agx.log("Waiting...") + work = self.work[-1] + + ##### Wait for work completion + while not self.ev_3d.fired: + self.agx.wait_for_events(timeout=2.0) + + if not self.ev_3d.fired: + self.agx.log("3D event didn't fire") + + self.agx.log(f"Event {self.ev_3d.id} fired") + #print("Stamps:") + #print(self.stamp_ta1.pull()) + #print(self.stamp_ta2.pull()) + #print(self.stamp_3d1.pull()) + #print(self.stamp_3d2.pull()) + + #print("WCs:") + #print(work.wc_3d.pull()) + #print(work.wc_ta.pull()) + + #if work.fb is not None and work.width and work.height: + if work.fb is not None and work.width and work.height and work.width == 1920: + agx = self.agx + self.agx.log(f"Render {work.width}x{work.height} @ {work.fb:#x}") + base, obj = self.agx.find_object(work.fb, self.ctx_id) + + #unswizzle(agx, obj._paddr, work.width, work.height, 4, "fb.bin", grid=False) + #open("fb.bin", "wb").write(self.agx.u.iface.readmem(obj._paddr, work.width*work.height*4)) + #os.system(f"convert -size {work.width}x{work.height} -depth 8 rgba:fb.bin -alpha off frame{self.frames}.png") + self.agx.p.fb_blit(0, 0, work.width, work.height, obj._paddr, work.width, PIX_FMT.XBGR) + + if False: #work.depth is not None: + base, obj = self.agx.find_object(work.depth, self.ctx_id) + + width = align_up(work.width, 64) + height = align_up(work.height, 64) + + obj.pull() + chexdump(obj.val) + + unswizzle(self.agx, obj._paddr, work.width, work.height, 4, "depth.bin", grid=False) + os.system(f"convert -size {work.width}x{work.height} -depth 8 rgba:depth.bin -alpha off depth.png") + + for i in self.work: + i.free() + + self.work = [] |
