// Copyright 2018 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.

library fuchsia.gpu.magma;

using zx;

enum QueryId {
    VENDOR_ID = 0;
    DEVICE_ID = 1;
    IS_TEST_RESTART_SUPPORTED = 2;
    IS_TOTAL_TIME_SUPPORTED = 3;
    MINIMUM_MAPPABLE_ADDRESS = 4;
    /// Upper 32bits: max inflight messages, lower 32bits: max inflight memory (MB)
    MAXIMUM_INFLIGHT_PARAMS = 5;
};

enum Status {
    INTERNAL_ERROR = 1;
    INVALID_ARGS = 2;
    ACCESS_DENIED = 3;
    MEMORY_ERROR = 4;
    CONTEXT_KILLED = 5;
    CONNECTION_LOST = 6;
    TIMED_OUT = 7;
    UNIMPLEMENTED = 8;
    /// An object was not in the right state for an operation on it.
    BAD_STATE = 9;
};

enum BufferOp {
    /// Eagerly populate GPU page tables with the pages mapping in this range, committing pages as
    /// needed. This is not needed for MAGMA_GPU_MAP_FLAG_GROWABLE allocations, since the page
    /// tables will be populated on demand.
    POPULATE_TABLES = 1;
    /// Depopulate GPU page table mappings for this range. This prevents the GPU from accessing
    /// pages in that range, but the pages retain their contents.
    DEPOPULATE_TABLES = 2;
};

protocol Device {
    /// Deprecated(fxbug.dev/54105)
    Query(uint64 query_id) -> (uint64 result);

    /// Returns a parameter, or an error.
    Query2(uint64 query_id) -> (uint64 result) error Status;

    /// Returns a buffer, or an error.
    QueryReturnsBuffer(uint64 query_id) -> (zx.handle:VMO buffer) error Status;

    /// Get the magma ipc channels.
    Connect(uint64 client_id) -> (zx.handle:CHANNEL primary_channel, zx.handle:CHANNEL notification_channel);

    /// Dumps driver and hardware state.
    DumpState(uint32 dump_type);

    /// For testing only.
    TestRestart();

    /// For testing only - on non-test drivers this will close the channel.
    GetUnitTestStatus() -> (zx.status status);
};

/// Primary declarations.
const uint32 kReceiveBufferSize = 2048;

struct Resource {
    zx.koid buffer;
    uint64 offset;
    uint64 length;
};

struct CommandBuffer {
    /// Index of the resource containing instructions to start the command buffer.
    uint32 batch_buffer_resource_index;
    /// Starting offset within the resource.
    uint64 batch_start_offset;
};

/// Performance counter pools contain byte ranges of buffers. Whenever a performance counter dump is
/// triggered, the driver removes a range from the pool, writes the performance counter values from
/// the hardware into it, then signals the client using OnPerformanceCounterReadCompleted. Pool IDs
/// are arbitrary uint64 values that are allocated by the client.
alias PerfCountPoolId = uint64;

bits ResultFlags {
    /// This bit is set in result_flags if the performance counters missed some samples, e.g. due to
    /// the GPU being in protected mode for part of the time.
    DISCONTINUITY = 1;
};

struct BufferOffset {
    zx.koid buffer_id;
    uint64 offset;
    uint64 size;
};

protocol Primary {
    /// Imports a buffer for use in the system driver.
    ImportBuffer(zx.handle:VMO buffer);

    /// Destroys the buffer with `buffer_id` within this connection.
    ReleaseBuffer(zx.koid buffer_id);

    /// Imports an object for use in the system driver.
    ImportObject(handle object, uint32 object_type);

    /// Destroys the object with `object_id` within this connection.
    ReleaseObject(zx.koid object_id, uint32 object_type);

    /// Creates context `context_id`.
    CreateContext(uint32 context_id);

    /// Destroys context `context_id`.
    DestroyContext(uint32 context_id);

    /// Submits a command buffer for execution on the GPU, with associated resources.
    ExecuteCommandBufferWithResources(
        uint32 context_id,
        CommandBuffer command_buffer,
        vector<Resource> resources,
        vector<zx.koid> wait_semaphores,
        vector<zx.koid> signal_semaphores);

    /// Submits a series of commands for execution on the GPU without using a command buffer.
    ExecuteImmediateCommands(uint32 context_id,
                             bytes:kReceiveBufferSize command_data,
                             vector<zx.koid> semaphores);

    /// Retrieve the current magma error status.
    GetError() -> (int32 magma_status);

    /// Maps `page_count` pages of `buffer` from `page_offset` onto the GPU in the connection's
    /// address space at `gpu_va`.  `flags` is a set of flags from `MAGMA_GPU_MAP_FLAGS` that
    /// specify how the GPU can access the buffer.
    MapBufferGpu(zx.koid buffer_id, uint64 gpu_va, uint64 page_offset,
                 uint64 page_count, uint64 flags);

    /// Releases the mapping at `gpu_va` from the GPU.
    /// Buffers will also be implicitly unmapped when released.
    UnmapBufferGpu(zx.koid buffer_id, uint64 gpu_va);

    /// DEPRECATED and replaced by BufferOp.POPULATE_TABLES. Ensures that `page_count` pages
    /// starting at `page_offset` from the beginning of the buffer are backed by physical memory.
    [Deprecated]
    CommitBuffer(zx.koid buffer_id, uint64 page_offset, uint64 page_count);

    /// Perform an operation on a range of the buffer, starting at `start_bytes` and `length` bytes
    /// long.
    BufferRangeOp(zx.koid buffer_id, BufferOp op, uint64 start_bytes, uint64 length);

    /// Tries to enable performance counter FIDL messages. To be successful, |access_token| must
    /// have been returned by PerformanceCounterAccess.GetPerformanceCountToken() from the matching
    /// device.
    AccessPerformanceCounters(zx.handle:EVENT access_token);

    /// Returns true if any AccessPerformanceCounters message has succeeded.
    IsPerformanceCounterAccessEnabled() -> (bool enabled);

    /// Enables the events OnNotifyMessagesConsumed and OnNotifyMemoryImported.
    EnableFlowControl();

    /// Indicates the given number of messages were consumed by the server.
    /// The caller should limit the number of inflight messages:
    /// (messages sent - server consumed) <= Max (see QueryId::MAXIMUM_INFLIGHT_PARAMS).
    /// Messages are actually consumed by the server as quickly as possible, however this event
    /// is sent by the server only when the consumed count reaches half the maximum.
    -> OnNotifyMessagesConsumed(uint64 count);

    /// Indicates the given number of buffer memory bytes were imported by the server.
    /// The caller should limit the amount of memory from inflight ImportBuffer messages:
    /// (bytes sent - server imported) <= Max (see QueryId::MAXIMUM_INFLIGHT_PARAMS).
    /// This is a soft limit designed to prevent excessive memory consumption, but for large
    /// messages the client may exceed the limit.
    /// Memory is imported by the server as quickly as possible, however this event
    /// is sent only when the consumed byte count reaches half the maximum; therefore,
    /// if the client's count of inflight bytes is less than max/2, the client should send the
    /// ImportBuffer message regardless of its size.
    -> OnNotifyMemoryImported(uint64 bytes);

    /// Enables a set of performance counters (the precise definition depends on the GPU driver).
    /// Disables enabled performance counters that are not in the new set. Performance counters will
    /// also be automatically disabled on connection close. Performance counter access must have
    /// been enabled using AccessPerformanceCounters before calling this method.
    EnablePerformanceCounters(vector<uint64>:64 counters);

    /// Creates a pool of buffers that performance counters can be dumped into. |pool| can be an
    /// arbitrary integer that's currently not in use. Performance counter access must have been
    /// enabled using AccessPerformanceCounters before calling this method.
    CreatePerformanceCounterBufferPool(
        PerfCountPoolId pool, request<PerformanceCounterEvents> event_channel);

    /// Releases a pool of performance counter buffers. Performance counter access must have been
    /// enabled using AccessPerformanceCounters before calling this method.
    ReleasePerformanceCounterBufferPool(PerfCountPoolId pool);

    /// Adds set of a offsets into buffers to the pool. |offsets[n].buffer_id| is the koid of a
    /// buffer that was previously imported using ImportBuffer(). The same buffer may be added to
    /// multiple pools. The pool will hold on to a reference to the buffer even after ReleaseBuffer
    /// is called.  When dumped into this entry, counters will be written starting at
    /// |buffer_offset| bytes into the buffer, and up to |offsets[n].buffer_offset| +
    /// |offsets[n].buffer_size|. |offsets[n].buffer_size| must be large enough to fit all enabled
    /// counters. Performance counter access must have been enabled using AccessPerformanceCounters
    /// before calling this method.
    AddPerformanceCounterBufferOffsetsToPool(
        PerfCountPoolId pool, vector<BufferOffset>:64 offsets);

    /// Removes every offset of a buffer from the pool. Once this is method is finished being
    /// handled on the server, no more dumps will be processed into this buffer. In-flight dumps
    /// into this buffer may be lost.  Performance counter access must have been enabled using
    /// AccessPerformanceCounters before calling this method.
    RemovePerformanceCounterBufferFromPool(PerfCountPoolId pool, zx.koid buffer_id);

    /// Triggers dumping of the performance counters into a buffer pool. May fail silently if there
    /// are no buffers in the pool. |trigger_id| is an arbitrary ID assigned by the client that can
    /// be returned in OnPerformanceCounterReadCompleted. Performance counter access must have been
    /// enabled using AccessPerformanceCounters before calling this method.
    DumpPerformanceCounters(PerfCountPoolId pool, uint32 trigger_id);

    /// Sets the values of all listed performance counters to 0. May not be supported by some
    /// hardware. Performance counter access must have been enabled using AccessPerformanceCounters
    /// before calling this method.
    ClearPerformanceCounters(vector<uint64>:64 counters);
};

/// This protocol is implemented by ZX_PROTOCOL_GPU_PERFORMANCE_COUNTERS devices.
protocol PerformanceCounterAccess {
    /// This access token is not used as an event, but is instead passed to
    /// Primary.EnablePerformanceCounterAccess.
    GetPerformanceCountToken() -> (zx.handle:EVENT access_token);
};

protocol PerformanceCounterEvents {
    /// Signals that a performance counter buffer has data. These will be output in the order of
    /// when the reads are completed.
    -> OnPerformanceCounterReadCompleted(uint32 trigger_id, zx.koid buffer_id, uint32 buffer_offset,
                                         zx.time timestamp, ResultFlags flags);
};
