【关键节点】OpenGL RenderDoc 捕获修复完成
## 修复内容 ### OpenGL SwapChain 架构重构 - OpenGLSwapChain 现在从 OpenGLDevice 获取 HDC,统一管理 - OpenGLDevice 拥有 HDC/HGLRC 的完整生命周期 - OpenGLSwapChain::Present() 使用 device->GetPresentationDC() ### API 变更 - GetContext() → GetGLContext() - GetDC() → GetPresentationDC() - Initialize(device*, hwnd, width, height) 新签名 ### 修复的测试 - minimal: rdc 34KB - triangle: rdc 50KB - quad: rdc 3.2MB - sphere: rdc 3.2MB ### 根本原因 之前传 HDC 给 RenderDoc::SetDevice(),需要传 HGLRC 才能正确 hook OpenGL 函数
This commit is contained in:
175
tests/RHI/OpenGL/integration/sphere/parse_rdc.py
Normal file
175
tests/RHI/OpenGL/integration/sphere/parse_rdc.py
Normal file
@@ -0,0 +1,175 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user