| // 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. |
| |
| /// Magma is the GPU driver design for Fuchsia. |
| /// |
| /// Magma has two driver components: a hardware-specific library loaded into each application’s |
| /// address space ("client driver", sometimes known as "Installable client driver" or "ICD"); |
| /// and the Magma system driver that interfaces with the hardware. |
| /// The communication protocols between the two driver pieces are defined here. |
| /// |
| /// Some names have a numeric suffix (eg, Query2); the number is a detail of how the protocols |
| /// have evolved, and can be ignored. |
| library fuchsia.gpu.magma; |
| |
| using fuchsia.url; |
| using zx; |
| using fuchsia.memorypressure; |
| |
| /// Types of information about the hardware and driver that can be queried from the Magma system |
| /// driver. Vendor-specific ID numbers may be used, but those IDs will be listed elsewhere. |
| type QueryId = flexible enum : uint64 { |
| /// Returns the hardware vendor ID (simple result) - should be the PCI ID of the GPU vendor |
| /// if possible, or the Khronos vendor ID otherwise. |
| VENDOR_ID = 0; |
| |
| /// Returns the hardware device ID (simple result) |
| DEVICE_ID = 1; |
| |
| /// Returns true if MAGMA_QUERY_TOTAL_TIME is supported (simple result) |
| IS_TOTAL_TIME_SUPPORTED = 3; |
| |
| /// Upper 32bits: max inflight messages, lower 32bits: max inflight memory (MB) (simple result) |
| MAXIMUM_INFLIGHT_PARAMS = 5; |
| |
| /// Returns a struct magma_total_time_query_result (buffer result); see: |
| /// src/graphics/lib/magma/include/magma/magma_common_defs.h |
| MAGMA_QUERY_TOTAL_TIME = 500; |
| |
| /// Vendor specific query IDs start here |
| VENDOR_QUERY_0 = 10000; |
| }; |
| |
| /// The maximum number of ICDs supported by a Magma system driver. |
| const MAX_ICD_COUNT uint64 = 8; |
| |
| type IcdFlags = flexible bits : uint32 { |
| SUPPORTS_VULKAN = 1; |
| SUPPORTS_OPENCL = 2; |
| // Exposes the fuchsia.mediacodec.CodecFactory FIDL interface. |
| SUPPORTS_MEDIA_CODEC_FACTORY = 4; |
| }; |
| |
| /// Information about an ICD implementation that can be used with a Magma device. |
| type IcdInfo = table { |
| /// URL of the component implementation that provides the ICD. |
| 1: component_url fuchsia.url.Url; |
| |
| /// Flags describing the basic capabilities of the ICD, including what APIs it supports. |
| 2: flags IcdFlags; |
| }; |
| |
| /// The Magma Device protocol allow clients to learn about the hardware by making queries, such as |
| /// device and vendor IDs, and which client drivers are supported by the device's system driver. |
| /// To engage further with the device, clients may establish connections formed of channel pairs: |
| /// a primary channel for making requests (see Primary protocol below), and a secondary channel |
| /// for receiving notification messages. |
| protocol Device { |
| /// DEPRECATED |
| Query2(struct { |
| query_id uint64; |
| }) -> (struct { |
| result uint64; |
| }) error zx.status; |
| |
| /// DEPRECATED |
| QueryReturnsBuffer(struct { |
| query_id uint64; |
| }) -> (resource struct { |
| buffer zx.handle:VMO; |
| }) error zx.status; |
| |
| /// On success, returns a result either in a buffer or a simple value. |
| Query(struct { |
| query_id QueryId; |
| }) -> (strict resource union { |
| 1: simple_result uint64; |
| 2: buffer_result zx.handle:VMO; |
| }) error zx.status; |
| |
| /// DEPRECATED |
| Connect(struct { |
| client_id uint64; |
| }) -> (resource struct { |
| primary_channel client_end:Primary; |
| notification_channel zx.handle:CHANNEL; |
| }); |
| |
| /// Creates a connection to the device comprised of two IPC channels. |
| /// The primary channel is for the Primary protocol (see below). The notification channel is |
| /// used for vendor-specific messages which are sent only in the reverse (server-client) |
| /// direction, typically in response to client command completion. |
| Connect2(resource struct { |
| client_id uint64; |
| primary_channel server_end:Primary; |
| notification_channel zx.handle:CHANNEL; |
| }); |
| }; |
| |
| /// Methods used to expose diagnostics from the Magma device. |
| protocol DiagnosticDevice { |
| /// Dumps driver and hardware state to the log. |
| DumpState(struct { |
| dump_type uint32; |
| }); |
| }; |
| |
| /// Methods implemented by an MSD and exposed for use of an ICD loader. |
| protocol IcdLoaderDevice { |
| /// Returns a list of ICDs that can be used with this Magma device. The list is sorted in |
| /// descending order of preference. |
| GetIcdList() -> (struct { |
| icd_list vector<IcdInfo>:MAX_ICD_COUNT; |
| }); |
| }; |
| |
| /// A combination of all the production |Device| protocols. This protocol is implemented on the |
| /// Magma service side and should not be used by clients. |
| protocol CombinedDevice { |
| compose Device; |
| compose DiagnosticDevice; |
| compose IcdLoaderDevice; |
| }; |
| |
| /// Additional device methods for the purposes of testing the MSD and should not be used by ICDs. |
| protocol TestDevice { |
| compose CombinedDevice; |
| |
| GetUnitTestStatus() -> (struct { |
| status zx.status; |
| }); |
| }; |
| |
| type ObjectType = flexible enum : uint32 { |
| /// A sync object backed by a Zircon event. |
| EVENT = 10; |
| /// A memory object backeed by a Zircon VMO. |
| BUFFER = 11; |
| }; |
| |
| type BufferOp = flexible enum : uint32 { |
| /// Populate the GPU page tables with the pages mapping in this range, committing pages as |
| /// needed. This is not needed for allocations mapped GROWABLE, 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; |
| }; |
| |
| /// The batch size used to send multiple immediate commands in a single message. |
| const MAX_IMMEDIATE_COMMANDS_DATA_SIZE uint32 = 2048; |
| |
| type MapFlags = flexible bits : uint64 { |
| READ = 0x1; |
| WRITE = 0x2; |
| EXECUTE = 0x4; |
| /// Uncommitted pages may be comitted on fault by the GPU. If this flag is not set, access |
| /// faults should cause an error. |
| GROWABLE = 0x8; |
| |
| /// Vendor specific definitions start here |
| VENDOR_FLAG_0 = 0x10000; |
| }; |
| |
| type CommandBufferFlags = flexible bits : uint64 { |
| /// Vendor specific definitions start here |
| VENDOR_FLAG_0 = 0x10000; |
| }; |
| |
| /// A command buffer may be used to pass GPU instructions in a shared buffer (VMO). |
| /// DEPRECATED - TODO(fxb/86670) remove prior to SDK release |
| type CommandBuffer2 = struct { |
| /// Index of the resource containing instructions to start the command buffer. |
| resource_index uint32; |
| |
| /// Starting offset within the resource. |
| start_offset uint64; |
| |
| /// Flags. |
| flags CommandBufferFlags; |
| }; |
| |
| /// A command buffer may be used to pass GPU instructions in a shared buffer (VMO). |
| type CommandBuffer = struct { |
| /// Index of the resource containing instructions to start the command buffer. |
| resource_index uint32; |
| |
| /// Starting offset within the resource. |
| start_offset uint64; |
| }; |
| |
| /// 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 PerformanceCounterPoolId = uint64; |
| |
| type ResultFlags = flexible bits { |
| /// 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; |
| }; |
| |
| alias ObjectId = uint64; |
| |
| type BufferRange = struct { |
| buffer_id ObjectId; |
| offset uint64; |
| size uint64; |
| }; |
| |
| alias ContextId = uint32; |
| |
| alias PerformanceCounterTriggerId = uint32; |
| |
| /// Describes a set of performance counters. The exact meaning depends on the GPU driver, but will |
| /// often be a bitvector representing whether each performance counter is enabled or disabled. |
| alias PerformanceCounterSet = vector<uint64>:64; |
| |
| /// If a system driver error occurs, or if the client sends a message that the client should have |
| /// known is invalid, the connection will be closed and a zx.status sent via epitaph. |
| protocol Primary { |
| /// DEPRECATED. |
| ImportObject(resource struct { |
| object zx.handle; |
| object_type ObjectType; |
| }); |
| |
| /// Imports an object for use in the system driver. |
| ImportObject2(resource struct { |
| object zx.handle; |
| object_type ObjectType; |
| object_id ObjectId; |
| }); |
| |
| /// Destroys the object with `object_id` within this connection. |
| ReleaseObject(struct { |
| object_id ObjectId; |
| object_type ObjectType; |
| }); |
| |
| /// Creates context `context_id` for use in command execution. A context may be associated |
| /// with hardware state. |
| CreateContext(struct { |
| context_id ContextId; |
| }); |
| |
| /// Destroys context `context_id`. |
| DestroyContext(struct { |
| context_id ContextId; |
| }); |
| |
| /// DEPRECATED - TODO(fxb/86670) remove prior to SDK release |
| /// Submits a command buffer for execution on the GPU, with associated `resources`. |
| /// `resources` must refer to buffers that have been imported. |
| /// `wait_semaphores` and `signal_semaphores` must refer to events that have been imported. |
| /// `wait_semaphores` must all be signaled before execution begins, then are reset. |
| /// `signal_semaphores` will be signaled after the command buffer is completed. |
| ExecuteCommandBufferWithResources2(struct { |
| context_id uint32; |
| command_buffer CommandBuffer2; |
| resources vector<BufferRange>:MAX; |
| wait_semaphores vector<ObjectId>:MAX; |
| signal_semaphores vector<ObjectId>:MAX; |
| }); |
| |
| /// Submits command buffers for execution on the GPU, with associated `resources`. |
| /// `resources` must refer to buffers that have been imported. |
| /// `wait_semaphores` and `signal_semaphores` must refer to events that have been imported. |
| /// `wait_semaphores` must all be signaled before execution begins, then are reset. |
| /// `signal_semaphores` will be signaled after the command buffer is completed. |
| ExecuteCommand(struct { |
| context_id ContextId; |
| resources vector<BufferRange>:MAX; |
| command_buffers vector<CommandBuffer>:MAX; |
| wait_semaphores vector<ObjectId>:MAX; |
| signal_semaphores vector<ObjectId>:MAX; |
| flags CommandBufferFlags; |
| }); |
| |
| /// Submits a series of commands for execution on the GPU without using a command buffer. |
| /// `semaphores` must refer to events that have been imported, and will be signaled after |
| /// the commands are completed. |
| ExecuteImmediateCommands(struct { |
| context_id ContextId; |
| command_data bytes:MAX_IMMEDIATE_COMMANDS_DATA_SIZE; |
| semaphores vector<ObjectId>:MAX; |
| }); |
| |
| /// Incurs a round-trip to the system driver, used to ensure all previous messages have been |
| /// observed, but not necessarily completed. |
| Flush() -> (); |
| |
| /// 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 MapFlags that specify how the |
| /// GPU can access the buffer. |
| MapBufferGpu(struct { |
| buffer_id ObjectId; |
| gpu_va uint64; |
| page_offset uint64; |
| page_count uint64; |
| flags MapFlags; |
| }); |
| |
| /// Releases the mapping at `gpu_va` from the GPU for the given `buffer_id`. |
| /// Buffers will also be implicitly unmapped when released. |
| UnmapBufferGpu(struct { |
| buffer_id ObjectId; |
| gpu_va uint64; |
| }); |
| |
| /// Perform an operation on a range of the buffer, starting at `offset` and `length` bytes |
| /// long. |
| BufferRangeOp(struct { |
| buffer_id ObjectId; |
| op BufferOp; |
| offset uint64; |
| length uint64; |
| }); |
| |
| /// 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) <= MaxMessages (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(struct { |
| count uint64; |
| }); |
| |
| /// 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) <= MaxBytes (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(struct { |
| bytes uint64; |
| }); |
| |
| /// Tries to enable performance counter FIDL messages. To be successful, |access_token| must |
| /// have been returned by PerformanceCounterAccess.GetPerformanceCountToken() from the matching |
| /// device. |
| EnablePerformanceCounterAccess(resource struct { |
| access_token zx.handle:EVENT; |
| }); |
| |
| /// Returns true if any EnablePerformanceCounterAccess message has succeeded. |
| IsPerformanceCounterAccessAllowed() -> (struct { |
| enabled bool; |
| }); |
| |
| /// Enables a set of performance counters. 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 |
| /// EnablePerformanceCounterAccess before calling this method. |
| EnablePerformanceCounters(struct { |
| counters PerformanceCounterSet; |
| }); |
| |
| /// Creates a pool of buffers that performance counters can be dumped into. Performance counter |
| /// access must have been enabled using EnablePerformanceCounterAccess before calling this |
| /// method. |
| CreatePerformanceCounterBufferPool(resource struct { |
| pool_id PerformanceCounterPoolId; |
| event_channel server_end:PerformanceCounterEvents; |
| }); |
| |
| /// Releases a pool of performance counter buffers. Performance counter access must have been |
| /// enabled using EnablePerformanceCounterAccess before calling this method. |
| ReleasePerformanceCounterBufferPool(struct { |
| pool_id PerformanceCounterPoolId; |
| }); |
| |
| /// Adds a set of offsets into buffers to the pool. |offsets[n].buffer_id| is the id 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 |
| /// |offsets[n].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 |
| /// EnablePerformanceCounterAccess before calling this method. |
| AddPerformanceCounterBufferOffsetsToPool(struct { |
| pool_id PerformanceCounterPoolId; |
| offsets vector<BufferRange>:64; |
| }); |
| |
| /// Removes every offset of a buffer from the pool. Once this 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 |
| /// EnablePerformanceCounterAccess before calling this method. |
| RemovePerformanceCounterBufferFromPool(struct { |
| pool_id PerformanceCounterPoolId; |
| buffer_id ObjectId; |
| }); |
| |
| /// 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 EnablePerformanceCounterAccess before calling this method. |
| DumpPerformanceCounters(struct { |
| pool_id PerformanceCounterPoolId; |
| trigger_id PerformanceCounterTriggerId; |
| }); |
| |
| /// 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 |
| /// EnablePerformanceCounterAccess before calling this method. |
| ClearPerformanceCounters(struct { |
| counters PerformanceCounterSet; |
| }); |
| }; |
| |
| /// 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() -> (resource struct { |
| access_token zx.handle:EVENT; |
| }); |
| }; |
| |
| protocol PerformanceCounterEvents { |
| /// Signals that a performance counter buffer has data. These will be output in the order of |
| /// when the reads are completed. |
| -> OnPerformanceCounterReadCompleted(table { |
| /// Required. |
| 1: trigger_id PerformanceCounterTriggerId; |
| |
| /// Required. |
| 2: buffer_id ObjectId; |
| |
| /// Required. |
| 3: buffer_offset uint32; |
| |
| /// Required. |
| 4: timestamp zx.time; |
| |
| /// Required. |
| 5: flags ResultFlags; |
| }); |
| }; |
| |
| /// This protocol is implemented by ZX_PROTOCOL_GPU_DEPENDENCY_INJECTION devices. It's used |
| /// to inject dependencies on other services into the MSD. It can be used |
| /// only by a privileged process. |
| protocol DependencyInjection { |
| /// Provides a `fuchsia.memorypressure.Provider` implementation to the MSD. |
| SetMemoryPressureProvider(resource struct { |
| provider client_end:fuchsia.memorypressure.Provider; |
| }); |
| }; |