import sys import os SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..", "..", "..", "..")) sys.path.insert(0, os.path.join(PROJECT_ROOT, "engine", "tools")) sys.path.insert(0, os.path.join(PROJECT_ROOT, "engine", "third_party", "renderdoc")) from renderdoc_parser import ( open_capture, close_capture, get_capture_info, get_frame_overview, list_actions, set_event, get_pipeline_state, list_textures, list_buffers, get_pass_timing, ) RDC_PATH = os.path.join( PROJECT_ROOT, "build", "tests", "RHI", "OpenGL", "integration", "sphere", "Debug", "sphere_frame30_capture.rdc", ) def print_section(title): print("\n" + "=" * 60) print(f" {title}") print("=" * 60) def get_actions_list(actions_result): if "error" in actions_result: return [] if isinstance(actions_result, dict): return actions_result.get("actions", []) return [] def analyze_capture(filepath): print(f"\nOpening: {filepath}") result = open_capture(filepath) if "error" in result: print(f"Failed to open capture: {result}") return print_section("Capture Info") info = get_capture_info() if isinstance(info, dict) and "error" not in info: print(f" API: {info.get('api', 'N/A')}") print(f" GPU: {info.get('gpu', 'N/A')}") print(f" Driver: {info.get('driver', 'N/A')}") print(f" Resolution: {info.get('width', 'N/A')}x{info.get('height', 'N/A')}") print(f" Textures: {info.get('texture_count', 'N/A')}") print(f" Buffers: {info.get('buffer_count', 'N/A')}") if info.get("quirks"): print(f" GPU Quirks: {info['quirks']}") print_section("Frame Overview") overview = get_frame_overview() if isinstance(overview, dict) and "error" not in overview: print(f" Draw Calls: {overview.get('draw_calls', 'N/A')}") print(f" Clear Calls: {overview.get('clears', 'N/A')}") print(f" Dispatch Calls: {overview.get('dispatches', 'N/A')}") print(f" Memory Usage: {overview.get('memory_usage', 'N/A')}") rt = overview.get("render_targets", []) if rt: print(f" Render Targets: {len(rt)}") print_section("Actions / Draw Calls") actions_raw = list_actions(max_depth=3) actions = get_actions_list(actions_raw) if not actions: print(" No actions found (capture may only contain Present call)") for action in actions[:30]: indent = " " * action.get("depth", 0) event_id = action.get("event_id", "?") name = action.get("name", "Unknown") flags = action.get("flags", []) flags_str = ", ".join(flags) if flags else "" print(f" [{event_id}] {indent}{name} {flags_str}") if len(actions) > 30: print(f" ... and {len(actions) - 30} more actions") print_section("Textures") textures_raw = list_textures() if isinstance(textures_raw, dict) and "error" not in textures_raw: textures = textures_raw.get("textures", []) if not textures: print(" No textures found") for tex in textures: if isinstance(tex, dict): print( f" [{tex.get('id', '?')}] {tex.get('name', 'Unknown')}: " f"{tex.get('width', 0)}x{tex.get('height', 0)}, " f"format={tex.get('format', 'N/A')}, " f"mips={tex.get('mips', 'N/A')}" ) else: print(f" {tex}") print_section("Buffers") buffers_raw = list_buffers() if isinstance(buffers_raw, dict) and "error" not in buffers_raw: buffers = buffers_raw.get("buffers", []) if not buffers: print(" No buffers found") for buf in buffers: if isinstance(buf, dict): print( f" [{buf.get('id', '?')}] {buf.get('name', 'Unknown')}: " f"{buf.get('length', 'N/A')} bytes" ) else: print(f" {buf}") if actions: last_action = actions[-1] event_id = last_action.get("event_id") if event_id: print_section("Pipeline State at Last Action") set_event(event_id) pipeline = get_pipeline_state(event_id) if isinstance(pipeline, dict) and "error" not in pipeline: if "vertex_shader" in pipeline: vs = pipeline["vertex_shader"] print( f" Vertex Shader: {vs.get('name', vs) if isinstance(vs, dict) else vs}" ) if "pixel_shader" in pipeline: ps = pipeline["pixel_shader"] print( f" Pixel Shader: {ps.get('name', ps) if isinstance(ps, dict) else ps}" ) if "viewport" in pipeline: vp = pipeline["viewport"] if isinstance(vp, dict): print( f" Viewport: x={vp.get('x', 0)}, y={vp.get('y', 0)}, " f"w={vp.get('width', 0)}, h={vp.get('height', 0)}" ) else: print(f" Viewport: {vp}") print_section("Pass Timing (Top 10)") timing_raw = get_pass_timing(granularity="pass", top_n=10) if isinstance(timing_raw, dict) and "error" not in timing_raw: timing = timing_raw.get("passes", timing_raw.get("timings", [])) if not timing: print(" No timing data available") for entry in timing[:10]: if isinstance(entry, dict): print(f" {entry.get('name', 'N/A')}: {entry.get('time', 'N/A')}ms") else: print(f" {entry}") elif isinstance(timing_raw, list): for entry in timing_raw[:10]: print(f" {entry}") close_capture() print("\n") if __name__ == "__main__": analyze_capture(RDC_PATH)