mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58:31 +09:00
[Refactor] (TraceReplay): reorganize trace skills into uniform packages with bundled scripts
This commit is contained in:
+146
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Queue an exact RenderDoc frame through an Android TargetControl socket."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
from rdc.discover import find_renderdoc
|
||||
|
||||
|
||||
MESSAGE_DISCONNECTED = 1
|
||||
MESSAGE_NOOP = 3
|
||||
MESSAGE_NEW_CAPTURE = 4
|
||||
|
||||
|
||||
def _drain_pending_messages(target: Any) -> None:
|
||||
"""Consume asynchronous registration messages before queueing a capture."""
|
||||
for _ in range(20):
|
||||
message = target.ReceiveMessage(None)
|
||||
message_type = int(message.type)
|
||||
if message_type == MESSAGE_NOOP:
|
||||
return
|
||||
if message_type == MESSAGE_DISCONNECTED:
|
||||
raise RuntimeError("RenderDoc target disconnected during initial message drain")
|
||||
|
||||
|
||||
def _connect(rd: Any, host: str, ident: int, timeout: float) -> Any:
|
||||
deadline = time.monotonic() + timeout
|
||||
last_error = "target is not listening"
|
||||
while time.monotonic() < deadline:
|
||||
target = None
|
||||
try:
|
||||
target = rd.CreateTargetControl(host, ident, "renderdoc-trace-capture", True)
|
||||
if target is not None and target.Connected():
|
||||
return target
|
||||
last_error = "CreateTargetControl returned a disconnected target"
|
||||
except Exception as exc: # noqa: BLE001 - RenderDoc raises SWIG exceptions
|
||||
last_error = str(exc)
|
||||
if target is not None:
|
||||
target.Shutdown()
|
||||
time.sleep(0.05)
|
||||
raise RuntimeError(
|
||||
f"failed to connect to RenderDoc target {host}:{ident} within {timeout:g}s: "
|
||||
f"{last_error}"
|
||||
)
|
||||
|
||||
|
||||
def queue_capture(
|
||||
*,
|
||||
host: str,
|
||||
ident: int,
|
||||
frame: int,
|
||||
count: int,
|
||||
connect_timeout: float,
|
||||
capture_timeout: float,
|
||||
) -> dict[str, object]:
|
||||
rd = find_renderdoc()
|
||||
if rd is None:
|
||||
raise RuntimeError("RenderDoc Python module not found; run 'rdc setup-renderdoc'")
|
||||
|
||||
target = _connect(rd, host, ident, connect_timeout)
|
||||
started = time.monotonic()
|
||||
try:
|
||||
_drain_pending_messages(target)
|
||||
target.QueueCapture(frame, count)
|
||||
deadline = time.monotonic() + capture_timeout
|
||||
while time.monotonic() < deadline:
|
||||
if not target.Connected():
|
||||
raise RuntimeError("RenderDoc target disconnected before capture completed")
|
||||
message = target.ReceiveMessage(None)
|
||||
message_type = int(message.type)
|
||||
if message_type == MESSAGE_NEW_CAPTURE and message.newCapture is not None:
|
||||
capture = message.newCapture
|
||||
return {
|
||||
"queued": True,
|
||||
"host": host,
|
||||
"ident": ident,
|
||||
"frame": frame,
|
||||
"count": count,
|
||||
"elapsedSeconds": round(time.monotonic() - started, 3),
|
||||
"capture": {
|
||||
"captureId": capture.captureId,
|
||||
"path": capture.path,
|
||||
"frame": capture.frameNumber,
|
||||
"byteSize": capture.byteSize,
|
||||
"api": capture.api,
|
||||
"local": capture.local,
|
||||
},
|
||||
}
|
||||
if message_type == MESSAGE_DISCONNECTED:
|
||||
raise RuntimeError("RenderDoc target disconnected before capture completed")
|
||||
time.sleep(0.01)
|
||||
raise RuntimeError(
|
||||
f"timed out after {capture_timeout:g}s waiting for frame {frame} capture"
|
||||
)
|
||||
finally:
|
||||
target.Shutdown()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Wait for an Android RenderDoc TargetControl socket, queue an exact frame, "
|
||||
"and keep the connection alive until the RDC is complete."
|
||||
)
|
||||
)
|
||||
parser.add_argument("--host", default="127.0.0.1")
|
||||
parser.add_argument("--ident", type=int, default=38920)
|
||||
parser.add_argument("--frame", type=int, required=True)
|
||||
parser.add_argument("--count", type=int, default=1)
|
||||
parser.add_argument("--connect-timeout", type=float, default=20.0)
|
||||
parser.add_argument("--capture-timeout", type=float, default=90.0)
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
result = queue_capture(
|
||||
host=args.host,
|
||||
ident=args.ident,
|
||||
frame=args.frame,
|
||||
count=args.count,
|
||||
connect_timeout=args.connect_timeout,
|
||||
capture_timeout=args.capture_timeout,
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001 - convert tool failures to stable CLI output
|
||||
if args.json:
|
||||
print(json.dumps({"success": False, "error": str(exc)}))
|
||||
else:
|
||||
print(f"error: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
if args.json:
|
||||
print(json.dumps({"success": True, **result}))
|
||||
else:
|
||||
capture = result["capture"]
|
||||
assert isinstance(capture, dict)
|
||||
print(capture["path"])
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user