neon-wgpu-runtime 0.2.0

Neon3 WGPU renderer and window runtime
use std::time::{Duration, Instant};

use neon_ipc::RpcClient;
use neon_protocol::{
    ClientIdentity, ClientKind, ProtocolVersion, RequestId, Revision, RpcRequest, ServiceName,
};
use neon_ui_schema::{
    UI_FRAGMENT_SCHEMA_VERSION, UiBounds, UiCommand, UiFragment, UiFragmentId,
    UiFragmentSubmission, UiNode, UiNodeId, UiNodeKind, UiStyle,
};
use serde_json::json;

fn request(sequence: u64) -> RpcRequest {
    let fragment = UiFragment {
        fragment_id: UiFragmentId("probe.fragment".into()),
        revision: Revision(sequence),
        root: UiNode {
            node_id: UiNodeId("probe.root".into()),
            kind: UiNodeKind::Panel,
            bounds: UiBounds {
                x: 0.0,
                y: 0.0,
                width: 32.0,
                height: 32.0,
            },
            layout: None,
            visible: true,
            enabled: true,
            text_key: None,
            text: None,
            image: None,
            surface: None,
            style: UiStyle::default(),
            enter_transition: None,
            world_depth: None,
            world_scale: None,
            children: Vec::new(),
        },
        effects: Vec::new(),
    };
    RpcRequest {
        protocol: "neon3.rpc".into(),
        version: ProtocolVersion { major: 1, minor: 0 },
        request_id: RequestId(format!("latency-probe-{sequence}")),
        client: ClientIdentity {
            kind: ClientKind::Cli,
            instance_id: "interaction-latency-probe".into(),
            pid: std::process::id(),
            origin: "interaction-latency-probe".into(),
        },
        target: ServiceName("wgpu-runtime".into()),
        method: "wgpu.ui.submit_fragment".into(),
        params: json!(UiCommand::SubmitFragment {
            submission: UiFragmentSubmission {
                schema_version: UI_FRAGMENT_SCHEMA_VERSION,
                fragment,
            },
        }),
        expected_revision: None,
        idempotency_key: Some(format!("latency-probe-{sequence}")),
    }
}

fn main() {
    let endpoint = std::env::args()
        .nth(1)
        .expect("usage: interaction_latency_probe <loopback-endpoint>")
        .parse()
        .expect("endpoint must be a socket address");
    let mut failures = 0_u32;
    for sequence in 1..=3 {
        let started = Instant::now();
        let result = RpcClient::connect(endpoint)
            .and_then(|client| client.with_timeout(Duration::from_millis(500)))
            .and_then(|mut client| client.call(&request(sequence)));
        let elapsed_ms = started.elapsed().as_secs_f64() * 1000.0;
        let passed = matches!(&result, Ok(response) if response.status == neon_protocol::RpcStatus::Accepted)
            && elapsed_ms < 250.0;
        if !passed {
            failures += 1;
        }
        println!(
            "{}",
            json!({
                "probe": "interaction_latency",
                "sequence": sequence,
                "input": {"method": "wgpu.ui.submit_fragment", "fragment_revision": sequence},
                "intermediate": {"elapsed_ms": elapsed_ms},
                "response": result.as_ref().ok().map(|response| json!({
                    "request_id": response.request_id,
                    "status": response.status,
                    "revision": response.revision,
                })),
                "pass": passed,
            })
        );
    }
    if failures != 0 {
        std::process::exit(1);
    }
}