// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// AGIS - Android GPU Inspector Service
@available(added=9)
library fuchsia.gpu.agis;

using zx;

/// Client supplied id.
alias ClientId = uint64;

/// Agis internally generated id.
alias GlobalId = uint32;

/// AGIS provides FIDL services that facilitate Vulkan command tracing.
/// It acts as an intermediary between gapii, the Android GPU Inspector
/// interposing shared library and Vulkan layer, and the host Android GPU
/// Inspector (AGI) application.
///
/// Vulkan Traceable Component (vtc)
type Vtc = resource table {
    1: global_id GlobalId;
    2: process_koid zx.Koid;
    3: process_name string:zx.MAX_NAME_LEN;
};

/// Max vtcs that may be registered.
/// ZX_CHANNEL_MAX_MESSAGE_BYTES = 64KiB.  At an approximate message size
/// of 50B, rounding up to 64B, we easily fit 128 vtcs in a message
/// with ample headroom for message size growth.
///
/// The number of vtcs is determined by developers, rather than users.
/// The typical expected vtc count is 1 considering a developer
/// performing Vulkan tracing on 1 component at a time.
const MAX_VTCS uint32 = 128;

type Error = flexible enum {
    NOT_FOUND = 1;
    ALREADY_REGISTERED = 2;
    VTCS_EXCEEDED = 3;
    INTERNAL_ERROR = 4;
};

/// The AGIS ComponentRegistry protocol allows traceable Fuchsia components to register
/// as Vulkan traceable.
@discoverable
closed protocol ComponentRegistry {
    /// Register a process as traceable.
    strict Register(struct {
        /// Client assigned ID for the vtc.
        id ClientId;

        /// Process koid.
        process_koid zx.Koid;

        /// Must match ZX_PROP_NAME of the kernel object.
        process_name string:zx.MAX_NAME_LEN;
    }) -> () error Error;

    // Unregister |global_id| from the registry.
    strict Unregister(struct {
        id ClientId;
    }) -> () error Error;

    /// Hanging get to retrieve the Vulkan endpoint of the ffx/vulkan Zircon
    /// socket pair.  This get is first satisfied when the client
    /// (the AGI application) calls FfxBridge::GetSocket() on the |global_id|
    /// that matches the client id |id|.
    strict GetVulkanSocket(struct {
        id ClientId;
    }) -> (resource struct {
        socket zx.Handle:<SOCKET, optional>;
    }) error Error;
};

/// The AGIS Observer protocol provides the interface to retrieve the full list of
/// registered Vulkan Traceable Components (vtcs).
@discoverable
closed protocol Observer {
    /// Retrieve registered components.
    /// For AGI, gapis will be the only client of this Vtcs interface.
    strict Vtcs() -> (resource struct {
        vtcs vector<Vtc>:MAX_VTCS;
    }) error Error;
};

/// The AGIS Connector protocol provides the interface to retrieve the ffx socket endpoint.
@discoverable
closed protocol Connector {
    /// Retrieves the ffx socket endpoint of the ffx/vulkan socket pair.
    strict GetSocket(struct {
        global_id GlobalId;
    }) -> (resource struct {
        socket zx.Handle:SOCKET;
    }) error Error;
};
