master ohmu/fastfetch-openbsd / src / detection / gpu / asahi_drm.h
ohmu  ·  2026-10-15
   1/* SPDX-License-Identifier: MIT */
   2/*
   3 * Copyright (C) The Asahi Linux Contributors
   4 * Copyright (C) 2018-2023 Collabora Ltd.
   5 * Copyright (C) 2014-2018 Broadcom
   6 */
   7#ifndef _ASAHI_DRM_H_
   8#define _ASAHI_DRM_H_
   9
  10#if __has_include(<drm.h>)
  11    #include <drm.h>
  12#else
  13    #include <drm/drm.h>
  14#endif
  15
  16#if defined(__cplusplus)
  17extern "C" {
  18#endif
  19
  20/**
  21 * DOC: Introduction to the Asahi UAPI
  22 *
  23 * This documentation describes the Asahi IOCTLs.
  24 *
  25 * Just a few generic rules about the data passed to the Asahi IOCTLs (cribbed
  26 * from Panthor):
  27 *
  28 * - Structures must be aligned on 64-bit/8-byte. If the object is not
  29 *   naturally aligned, a padding field must be added.
  30 * - Fields must be explicitly aligned to their natural type alignment with
  31 *   pad[0..N] fields.
  32 * - All padding fields will be checked by the driver to make sure they are
  33 *   zeroed.
  34 * - Flags can be added, but not removed/replaced.
  35 * - New fields can be added to the main structures (the structures
  36 *   directly passed to the ioctl). Those fields can be added at the end of
  37 *   the structure, or replace existing padding fields. Any new field being
  38 *   added must preserve the behavior that existed before those fields were
  39 *   added when a value of zero is passed.
  40 * - New fields can be added to indirect objects (objects pointed by the
  41 *   main structure), iff those objects are passed a size to reflect the
  42 *   size known by the userspace driver (see
  43 *   drm_asahi_cmd_header::size).
  44 * - If the kernel driver is too old to know some fields, those will be
  45 *   ignored if zero, and otherwise rejected (and so will be zero on output).
  46 * - If userspace is too old to know some fields, those will be zeroed
  47 *   (input) before the structure is parsed by the kernel driver.
  48 * - Each new flag/field addition must come with a driver version update so
  49 *   the userspace driver doesn't have to guess which flags are supported.
  50 * - Structures should not contain unions, as this would defeat the
  51 *   extensibility of such structures.
  52 * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed
  53 *   at the end of the drm_asahi_ioctl_id enum.
  54 */
  55
  56/**
  57 * enum drm_asahi_ioctl_id - IOCTL IDs
  58 *
  59 * Place new ioctls at the end, don't re-order, don't replace or remove entries.
  60 *
  61 * These IDs are not meant to be used directly. Use the DRM_IOCTL_ASAHI_xxx
  62 * definitions instead.
  63 */
  64enum drm_asahi_ioctl_id {
  65    /** @DRM_ASAHI_GET_PARAMS: Query device properties. */
  66    DRM_ASAHI_GET_PARAMS = 0,
  67
  68    /** @DRM_ASAHI_GET_TIME: Query device time. */
  69    DRM_ASAHI_GET_TIME,
  70
  71    /** @DRM_ASAHI_VM_CREATE: Create a GPU VM address space. */
  72    DRM_ASAHI_VM_CREATE,
  73
  74    /** @DRM_ASAHI_VM_DESTROY: Destroy a VM. */
  75    DRM_ASAHI_VM_DESTROY,
  76
  77    /** @DRM_ASAHI_VM_BIND: Bind/unbind memory to a VM. */
  78    DRM_ASAHI_VM_BIND,
  79
  80    /** @DRM_ASAHI_GEM_CREATE: Create a buffer object. */
  81    DRM_ASAHI_GEM_CREATE,
  82
  83    /**
  84     * @DRM_ASAHI_GEM_MMAP_OFFSET: Get offset to pass to mmap() to map a
  85     * given GEM handle.
  86     */
  87    DRM_ASAHI_GEM_MMAP_OFFSET,
  88
  89    /** @DRM_ASAHI_GEM_BIND_OBJECT: Bind memory as a special object */
  90    DRM_ASAHI_GEM_BIND_OBJECT,
  91
  92    /** @DRM_ASAHI_QUEUE_CREATE: Create a scheduling queue. */
  93    DRM_ASAHI_QUEUE_CREATE,
  94
  95    /** @DRM_ASAHI_QUEUE_DESTROY: Destroy a scheduling queue. */
  96    DRM_ASAHI_QUEUE_DESTROY,
  97
  98    /** @DRM_ASAHI_SUBMIT: Submit commands to a queue. */
  99    DRM_ASAHI_SUBMIT,
 100};
 101
 102#define DRM_ASAHI_MAX_CLUSTERS 64
 103
 104/**
 105 * struct drm_asahi_params_global - Global parameters.
 106 *
 107 * This struct may be queried by drm_asahi_get_params.
 108 */
 109struct drm_asahi_params_global {
 110    /** @features: Feature bits from drm_asahi_feature */
 111    __u64 features;
 112
 113    /** @gpu_generation: GPU generation, e.g. 13 for G13G */
 114    __u32 gpu_generation;
 115
 116    /** @gpu_variant: GPU variant as a character, e.g. 'C' for G13C */
 117    __u32 gpu_variant;
 118
 119    /**
 120     * @gpu_revision: GPU revision in BCD, e.g. 0x00 for 'A0' or
 121     * 0x21 for 'C1'
 122     */
 123    __u32 gpu_revision;
 124
 125    /** @chip_id: Chip ID in BCD, e.g. 0x8103 for T8103 */
 126    __u32 chip_id;
 127
 128    /** @num_dies: Number of dies in the SoC */
 129    __u32 num_dies;
 130
 131    /** @num_clusters_total: Number of GPU clusters (across all dies) */
 132    __u32 num_clusters_total;
 133
 134    /**
 135     * @num_cores_per_cluster: Number of logical cores per cluster
 136     * (including inactive/nonexistent)
 137     */
 138    __u32 num_cores_per_cluster;
 139
 140    /** @max_frequency_khz: Maximum GPU core clock frequency */
 141    __u32 max_frequency_khz;
 142
 143    /** @core_masks: Bitmask of present/enabled cores per cluster */
 144    __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
 145
 146    /**
 147     * @vm_start: VM range start VMA. Together with @vm_end, this defines
 148     * the window of valid GPU VAs. Userspace is expected to subdivide VAs
 149     * out of this window.
 150     *
 151     * This window contains all virtual addresses that userspace needs to
 152     * know about. There may be kernel-internal GPU VAs outside this range,
 153     * but that detail is not relevant here.
 154     */
 155    __u64 vm_start;
 156
 157    /** @vm_end: VM range end VMA */
 158    __u64 vm_end;
 159
 160    /**
 161     * @vm_kernel_min_size: Minimum kernel VMA window size.
 162     *
 163     * When creating a VM, userspace is required to carve out a section of
 164     * virtual addresses (within the range given by @vm_start and
 165     * @vm_end). The kernel will allocate various internal structures
 166     * within the specified VA range.
 167     *
 168     * Allowing userspace to choose the VA range for the kernel, rather than
 169     * the kernel reserving VAs and requiring userspace to cope, can assist
 170     * in implementing SVM.
 171     */
 172    __u64 vm_kernel_min_size;
 173
 174    /**
 175     * @max_commands_per_submission: Maximum number of supported commands
 176     * per submission. This mirrors firmware limits. Userspace must split up
 177     * larger command buffers, which may require inserting additional
 178     * synchronization.
 179     */
 180    __u32 max_commands_per_submission;
 181
 182    /**
 183     * @max_attachments: Maximum number of drm_asahi_attachment's per
 184     * command
 185     */
 186    __u32 max_attachments;
 187
 188    /**
 189     * @command_timestamp_frequency_hz: Timebase frequency for timestamps
 190     * written during command exeuction, specified via drm_asahi_timestamp
 191     * structures. As this rate is controlled by the firmware, it is a
 192     * queryable parameter.
 193     *
 194     * Userspace must divide by this frequency to convert timestamps to
 195     * seconds, rather than hardcoding a particular firmware's rate.
 196     */
 197    __u64 command_timestamp_frequency_hz;
 198};
 199
 200/**
 201 * enum drm_asahi_feature - Feature bits
 202 *
 203 * This covers only features that userspace cannot infer from the architecture
 204 * version. Most features don't need to be here.
 205 */
 206enum drm_asahi_feature {
 207    /**
 208     * @DRM_ASAHI_FEATURE_SOFT_FAULTS: GPU has "soft fault" enabled. Shader
 209     * loads of unmapped memory will return zero. Shader stores to unmapped
 210     * memory will be silently discarded. Note that only shader load/store
 211     * is affected. Other hardware units are not affected, notably including
 212     * texture sampling.
 213     *
 214     * Soft fault is set when initializing the GPU and cannot be runtime
 215     * toggled. Therefore, it is exposed as a feature bit and not a
 216     * userspace-settable flag on the VM. When soft fault is enabled,
 217     * userspace can speculate memory accesses more aggressively.
 218     */
 219    DRM_ASAHI_FEATURE_SOFT_FAULTS = (1UL) << 0,
 220};
 221
 222/**
 223 * struct drm_asahi_get_params - Arguments passed to DRM_IOCTL_ASAHI_GET_PARAMS
 224 */
 225struct drm_asahi_get_params {
 226    /** @param_group: Parameter group to fetch (MBZ) */
 227    __u32 param_group;
 228
 229    /** @pad: MBZ */
 230    __u32 pad;
 231
 232    /** @pointer: User pointer to write parameter struct */
 233    __u64 pointer;
 234
 235    /**
 236     * @size: Size of the user buffer. In case of older userspace, this may
 237     * be less than sizeof(struct drm_asahi_params_global). The kernel will
 238     * not write past the length specified here, allowing extensibility.
 239     */
 240    __u64 size;
 241};
 242
 243/**
 244 * struct drm_asahi_vm_create - Arguments passed to DRM_IOCTL_ASAHI_VM_CREATE
 245 */
 246struct drm_asahi_vm_create {
 247    /**
 248     * @kernel_start: Start of the kernel-reserved address range. See
 249     * drm_asahi_params_global::vm_kernel_min_size.
 250     *
 251     * Both @kernel_start and @kernel_end must be within the range of
 252     * valid VAs given by drm_asahi_params_global::vm_start and
 253     * drm_asahi_params_global::vm_end. The size of the kernel range
 254     * (@kernel_end - @kernel_start) must be at least
 255     * drm_asahi_params_global::vm_kernel_min_size.
 256     *
 257     * Userspace must not bind any memory on this VM into this reserved
 258     * range, it is for kernel use only.
 259     */
 260    __u64 kernel_start;
 261
 262    /**
 263     * @kernel_end: End of the kernel-reserved address range. See
 264     * @kernel_start.
 265     */
 266    __u64 kernel_end;
 267
 268    /** @vm_id: Returned VM ID */
 269    __u32 vm_id;
 270
 271    /** @pad: MBZ */
 272    __u32 pad;
 273};
 274
 275/**
 276 * struct drm_asahi_vm_destroy - Arguments passed to DRM_IOCTL_ASAHI_VM_DESTROY
 277 */
 278struct drm_asahi_vm_destroy {
 279    /** @vm_id: VM ID to be destroyed */
 280    __u32 vm_id;
 281
 282    /** @pad: MBZ */
 283    __u32 pad;
 284};
 285
 286/**
 287 * enum drm_asahi_gem_flags - Flags for GEM creation
 288 */
 289enum drm_asahi_gem_flags {
 290    /**
 291     * @DRM_ASAHI_GEM_WRITEBACK: BO should be CPU-mapped as writeback.
 292     *
 293     * Map as writeback instead of write-combine. This optimizes for CPU
 294     * reads.
 295     */
 296    DRM_ASAHI_GEM_WRITEBACK = (1L << 0),
 297
 298    /**
 299     * @DRM_ASAHI_GEM_VM_PRIVATE: BO is private to this GPU VM (no exports).
 300     */
 301    DRM_ASAHI_GEM_VM_PRIVATE = (1L << 1),
 302};
 303
 304/**
 305 * struct drm_asahi_gem_create - Arguments passed to DRM_IOCTL_ASAHI_GEM_CREATE
 306 */
 307struct drm_asahi_gem_create {
 308    /** @size: Size of the BO */
 309    __u64 size;
 310
 311    /** @flags: Combination of drm_asahi_gem_flags flags. */
 312    __u32 flags;
 313
 314    /**
 315     * @vm_id: VM ID to assign to the BO, if DRM_ASAHI_GEM_VM_PRIVATE is set
 316     */
 317    __u32 vm_id;
 318
 319    /** @handle: Returned GEM handle for the BO */
 320    __u32 handle;
 321
 322    /** @pad: MBZ */
 323    __u32 pad;
 324};
 325
 326/**
 327 * struct drm_asahi_gem_mmap_offset - Arguments passed to
 328 * DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET
 329 */
 330struct drm_asahi_gem_mmap_offset {
 331    /** @handle: Handle for the object being mapped. */
 332    __u32 handle;
 333
 334    /** @flags: Must be zero */
 335    __u32 flags;
 336
 337    /** @offset: The fake offset to use for subsequent mmap call */
 338    __u64 offset;
 339};
 340
 341/**
 342 * enum drm_asahi_bind_flags - Flags for GEM binding
 343 */
 344enum drm_asahi_bind_flags {
 345    /**
 346     * @DRM_ASAHI_BIND_UNBIND: Instead of binding a GEM object to the range,
 347     * simply unbind the GPU VMA range.
 348     */
 349    DRM_ASAHI_BIND_UNBIND = (1L << 0),
 350
 351    /** @DRM_ASAHI_BIND_READ: Map BO with GPU read permission */
 352    DRM_ASAHI_BIND_READ = (1L << 1),
 353
 354    /** @DRM_ASAHI_BIND_WRITE: Map BO with GPU write permission */
 355    DRM_ASAHI_BIND_WRITE = (1L << 2),
 356
 357    /**
 358     * @DRM_ASAHI_BIND_SINGLE_PAGE: Map a single page of the BO repeatedly
 359     * across the VA range.
 360     *
 361     * This is useful to fill a VA range with scratch pages or zero pages.
 362     * It is intended as a mechanism to accelerate sparse.
 363     */
 364    DRM_ASAHI_BIND_SINGLE_PAGE = (1L << 3),
 365};
 366
 367/**
 368 * struct drm_asahi_gem_bind_op - Description of a single GEM bind operation.
 369 */
 370struct drm_asahi_gem_bind_op {
 371    /** @flags: Combination of drm_asahi_bind_flags flags. */
 372    __u32 flags;
 373
 374    /** @handle: GEM object to bind (except for UNBIND) */
 375    __u32 handle;
 376
 377    /**
 378     * @offset: Offset into the object (except for UNBIND).
 379     *
 380     * For a regular bind, this is the beginning of the region of the GEM
 381     * object to bind.
 382     *
 383     * For a single-page bind, this is the offset to the single page that
 384     * will be repeatedly bound.
 385     *
 386     * Must be page-size aligned.
 387     */
 388    __u64 offset;
 389
 390    /**
 391     * @range: Number of bytes to bind/unbind to @addr.
 392     *
 393     * Must be page-size aligned.
 394     */
 395    __u64 range;
 396
 397    /**
 398     * @addr: Address to bind to.
 399     *
 400     * Must be page-size aligned.
 401     */
 402    __u64 addr;
 403};
 404
 405/**
 406 * struct drm_asahi_vm_bind - Arguments passed to
 407 * DRM_IOCTL_ASAHI_VM_BIND
 408 */
 409struct drm_asahi_vm_bind {
 410    /** @vm_id: The ID of the VM to bind to */
 411    __u32 vm_id;
 412
 413    /** @num_binds: number of binds in this IOCTL. */
 414    __u32 num_binds;
 415
 416    /**
 417     * @stride: Stride in bytes between consecutive binds. This allows
 418     * extensibility of drm_asahi_gem_bind_op.
 419     */
 420    __u32 stride;
 421
 422    /** @pad: MBZ */
 423    __u32 pad;
 424
 425    /**
 426     * @userptr: User pointer to an array of @num_binds structures of type
 427     * @drm_asahi_gem_bind_op and size @stride bytes.
 428     */
 429    __u64 userptr;
 430};
 431
 432/**
 433 * enum drm_asahi_bind_object_op - Special object bind operation
 434 */
 435enum drm_asahi_bind_object_op {
 436    /** @DRM_ASAHI_BIND_OBJECT_OP_BIND: Bind a BO as a special GPU object */
 437    DRM_ASAHI_BIND_OBJECT_OP_BIND = 0,
 438
 439    /** @DRM_ASAHI_BIND_OBJECT_OP_UNBIND: Unbind a special GPU object */
 440    DRM_ASAHI_BIND_OBJECT_OP_UNBIND = 1,
 441};
 442
 443/**
 444 * enum drm_asahi_bind_object_flags - Special object bind flags
 445 */
 446enum drm_asahi_bind_object_flags {
 447    /**
 448     * @DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS: Map a BO as a timestamp
 449     * buffer.
 450     */
 451    DRM_ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS = (1L << 0),
 452};
 453
 454/**
 455 * struct drm_asahi_gem_bind_object - Arguments passed to
 456 * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT
 457 */
 458struct drm_asahi_gem_bind_object {
 459    /** @op: Bind operation (enum drm_asahi_bind_object_op) */
 460    __u32 op;
 461
 462    /** @flags: Combination of drm_asahi_bind_object_flags flags. */
 463    __u32 flags;
 464
 465    /** @handle: GEM object to bind/unbind (BIND) */
 466    __u32 handle;
 467
 468    /** @vm_id: The ID of the VM to operate on (MBZ currently) */
 469    __u32 vm_id;
 470
 471    /** @offset: Offset into the object (BIND only) */
 472    __u64 offset;
 473
 474    /** @range: Number of bytes to bind/unbind (BIND only) */
 475    __u64 range;
 476
 477    /** @object_handle: Object handle (out for BIND, in for UNBIND) */
 478    __u32 object_handle;
 479
 480    /** @pad: MBZ */
 481    __u32 pad;
 482};
 483
 484/**
 485 * enum drm_asahi_cmd_type - Command type
 486 */
 487enum drm_asahi_cmd_type {
 488    /**
 489     * @DRM_ASAHI_CMD_RENDER: Render command, executing on the render
 490     * subqueue. Combined vertex and fragment operation.
 491     *
 492     * Followed by a @drm_asahi_cmd_render payload.
 493     */
 494    DRM_ASAHI_CMD_RENDER = 0,
 495
 496    /**
 497     * @DRM_ASAHI_CMD_COMPUTE: Compute command on the compute subqueue.
 498     *
 499     * Followed by a @drm_asahi_cmd_compute payload.
 500     */
 501    DRM_ASAHI_CMD_COMPUTE = 1,
 502
 503    /**
 504     * @DRM_ASAHI_SET_VERTEX_ATTACHMENTS: Software command to set
 505     * attachments for subsequent vertex shaders in the same submit.
 506     *
 507     * Followed by (possibly multiple) @drm_asahi_attachment payloads.
 508     */
 509    DRM_ASAHI_SET_VERTEX_ATTACHMENTS = 2,
 510
 511    /**
 512     * @DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS: Software command to set
 513     * attachments for subsequent fragment shaders in the same submit.
 514     *
 515     * Followed by (possibly multiple) @drm_asahi_attachment payloads.
 516     */
 517    DRM_ASAHI_SET_FRAGMENT_ATTACHMENTS = 3,
 518
 519    /**
 520     * @DRM_ASAHI_SET_COMPUTE_ATTACHMENTS: Software command to set
 521     * attachments for subsequent compute shaders in the same submit.
 522     *
 523     * Followed by (possibly multiple) @drm_asahi_attachment payloads.
 524     */
 525    DRM_ASAHI_SET_COMPUTE_ATTACHMENTS = 4,
 526};
 527
 528/**
 529 * enum drm_asahi_priority - Scheduling queue priority.
 530 *
 531 * These priorities are forwarded to the firmware to influence firmware
 532 * scheduling. The exact policy is ultimately decided by firmware, but
 533 * these enums allow userspace to communicate the intentions.
 534 */
 535enum drm_asahi_priority {
 536    /** @DRM_ASAHI_PRIORITY_LOW: Low priority queue. */
 537    DRM_ASAHI_PRIORITY_LOW = 0,
 538
 539    /** @DRM_ASAHI_PRIORITY_MEDIUM: Medium priority queue. */
 540    DRM_ASAHI_PRIORITY_MEDIUM = 1,
 541
 542    /**
 543     * @DRM_ASAHI_PRIORITY_HIGH: High priority queue.
 544     *
 545     * Reserved for future extension.
 546     */
 547    DRM_ASAHI_PRIORITY_HIGH = 2,
 548
 549    /**
 550     * @DRM_ASAHI_PRIORITY_REALTIME: Real-time priority queue.
 551     *
 552     * Reserved for future extension.
 553     */
 554    DRM_ASAHI_PRIORITY_REALTIME = 3,
 555};
 556
 557/**
 558 * struct drm_asahi_queue_create - Arguments passed to
 559 * DRM_IOCTL_ASAHI_QUEUE_CREATE
 560 */
 561struct drm_asahi_queue_create {
 562    /** @flags: MBZ */
 563    __u32 flags;
 564
 565    /** @vm_id: The ID of the VM this queue is bound to */
 566    __u32 vm_id;
 567
 568    /** @priority: One of drm_asahi_priority */
 569    __u32 priority;
 570
 571    /** @queue_id: The returned queue ID */
 572    __u32 queue_id;
 573
 574    /**
 575     * @usc_exec_base: GPU base address for all USC binaries (shaders) on
 576     * this queue. USC addresses are 32-bit relative to this 64-bit base.
 577     *
 578     * This sets the following registers on all queue commands:
 579     *
 580     *	USC_EXEC_BASE_TA  (vertex)
 581     *	USC_EXEC_BASE_ISP (fragment)
 582     *	USC_EXEC_BASE_CP  (compute)
 583     *
 584     * While the hardware lets us configure these independently per command,
 585     * we do not have a use case for this. Instead, we expect userspace to
 586     * fix a 4GiB VA carveout for USC memory and pass its base address here.
 587     */
 588    __u64 usc_exec_base;
 589};
 590
 591/**
 592 * struct drm_asahi_queue_destroy - Arguments passed to
 593 * DRM_IOCTL_ASAHI_QUEUE_DESTROY
 594 */
 595struct drm_asahi_queue_destroy {
 596    /** @queue_id: The queue ID to be destroyed */
 597    __u32 queue_id;
 598
 599    /** @pad: MBZ */
 600    __u32 pad;
 601};
 602
 603/**
 604 * enum drm_asahi_sync_type - Sync item type
 605 */
 606enum drm_asahi_sync_type {
 607    /** @DRM_ASAHI_SYNC_SYNCOBJ: Binary sync object */
 608    DRM_ASAHI_SYNC_SYNCOBJ = 0,
 609
 610    /** @DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ: Timeline sync object */
 611    DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ = 1,
 612};
 613
 614/**
 615 * struct drm_asahi_sync - Sync item
 616 */
 617struct drm_asahi_sync {
 618    /** @sync_type: One of drm_asahi_sync_type */
 619    __u32 sync_type;
 620
 621    /** @handle: The sync object handle */
 622    __u32 handle;
 623
 624    /** @timeline_value: Timeline value for timeline sync objects */
 625    __u64 timeline_value;
 626};
 627
 628/**
 629 * define DRM_ASAHI_BARRIER_NONE - Command index for no barrier
 630 *
 631 * This special value may be passed in to drm_asahi_command::vdm_barrier or
 632 * drm_asahi_command::cdm_barrier to indicate that the respective subqueue
 633 * should not wait on any previous work.
 634 */
 635#define DRM_ASAHI_BARRIER_NONE (0xFFFFu)
 636
 637/**
 638 * struct drm_asahi_cmd_header - Top level command structure
 639 *
 640 * This struct is core to the command buffer definition and therefore is not
 641 * extensible.
 642 */
 643struct drm_asahi_cmd_header {
 644    /** @cmd_type: One of drm_asahi_cmd_type */
 645    __u16 cmd_type;
 646
 647    /**
 648     * @size: Size of this command, not including this header.
 649     *
 650     * For hardware commands, this enables extensibility of commands without
 651     * requiring extra command types. Passing a command that is shorter
 652     * than expected is explicitly allowed for backwards-compatibility.
 653     * Truncated fields will be zeroed.
 654     *
 655     * For the synthetic attachment setting commands, this implicitly
 656     * encodes the number of attachments. These commands take multiple
 657     * fixed-size @drm_asahi_attachment structures as their payload, so size
 658     * equals number of attachments * sizeof(struct drm_asahi_attachment).
 659     */
 660    __u16 size;
 661
 662    /**
 663     * @vdm_barrier: VDM (render) command index to wait on.
 664     *
 665     * Barriers are indices relative to the beginning of a given submit. A
 666     * barrier of 0 waits on commands submitted to the respective subqueue
 667     * in previous submit ioctls. A barrier of N waits on N previous
 668     * commands on the subqueue within the current submit ioctl. As a
 669     * special case, passing @DRM_ASAHI_BARRIER_NONE avoids waiting on any
 670     * commands in the subqueue.
 671     *
 672     * Examples:
 673     *
 674     *   0: This waits on all previous work.
 675     *
 676     *   NONE: This does not wait for anything on this subqueue.
 677     *
 678     *   1: This waits on the first render command in the submit.
 679     *   This is valid only if there are multiple render commands in the
 680     *   same submit.
 681     *
 682     * Barriers are valid only for hardware commands. Synthetic software
 683     * commands to set attachments must pass NONE here.
 684     */
 685    __u16 vdm_barrier;
 686
 687    /**
 688     * @cdm_barrier: CDM (compute) command index to wait on.
 689     *
 690     * See @vdm_barrier, and replace VDM/render with CDM/compute.
 691     */
 692    __u16 cdm_barrier;
 693};
 694
 695/**
 696 * struct drm_asahi_submit - Arguments passed to DRM_IOCTL_ASAHI_SUBMIT
 697 */
 698struct drm_asahi_submit {
 699    /**
 700     * @syncs: An optional pointer to an array of drm_asahi_sync. The first
 701     * @in_sync_count elements are in-syncs, then the remaining
 702     * @out_sync_count elements are out-syncs. Using a single array with
 703     * explicit partitioning simplifies handling.
 704     */
 705    __u64 syncs;
 706
 707    /**
 708     * @cmdbuf: Pointer to the command buffer to submit.
 709     *
 710     * This is a flat command buffer. By design, it contains no CPU
 711     * pointers, which makes it suitable for a virtgpu wire protocol without
 712     * requiring any serializing/deserializing step.
 713     *
 714     * It consists of a series of commands. Each command begins with a
 715     * fixed-size @drm_asahi_cmd_header header and is followed by a
 716     * variable-length payload according to the type and size in the header.
 717     *
 718     * The combined count of "real" hardware commands must be nonzero and at
 719     * most drm_asahi_params_global::max_commands_per_submission.
 720     */
 721    __u64 cmdbuf;
 722
 723    /** @flags: Flags for command submission (MBZ) */
 724    __u32 flags;
 725
 726    /** @queue_id: The queue ID to be submitted to */
 727    __u32 queue_id;
 728
 729    /**
 730     * @in_sync_count: Number of sync objects to wait on before starting
 731     * this job.
 732     */
 733    __u32 in_sync_count;
 734
 735    /**
 736     * @out_sync_count: Number of sync objects to signal upon completion of
 737     * this job.
 738     */
 739    __u32 out_sync_count;
 740
 741    /** @cmdbuf_size: Command buffer size in bytes */
 742    __u32 cmdbuf_size;
 743
 744    /** @pad: MBZ */
 745    __u32 pad;
 746};
 747
 748/**
 749 * struct drm_asahi_attachment - Describe an "attachment".
 750 *
 751 * Attachments are any memory written by shaders, notably including render
 752 * target attachments written by the end-of-tile program. This is purely a hint
 753 * about the accessed memory regions. It is optional to specify, which is
 754 * fortunate as it cannot be specified precisely with bindless access anyway.
 755 * But where possible, it's probably a good idea for userspace to include these
 756 * hints, forwarded to the firmware.
 757 *
 758 * This struct is implicitly sized and therefore is not extensible.
 759 */
 760struct drm_asahi_attachment {
 761    /** @pointer: Base address of the attachment */
 762    __u64 pointer;
 763
 764    /** @size: Size of the attachment in bytes */
 765    __u64 size;
 766
 767    /** @pad: MBZ */
 768    __u32 pad;
 769
 770    /** @flags: MBZ */
 771    __u32 flags;
 772};
 773
 774enum drm_asahi_render_flags {
 775    /**
 776     * @DRM_ASAHI_RENDER_VERTEX_SCRATCH: A vertex stage shader uses scratch
 777     * memory.
 778     */
 779    DRM_ASAHI_RENDER_VERTEX_SCRATCH = (1U << 0),
 780
 781    /**
 782     * @DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES: Process even empty tiles.
 783     * This must be set when clearing render targets.
 784     */
 785    DRM_ASAHI_RENDER_PROCESS_EMPTY_TILES = (1U << 1),
 786
 787    /**
 788     * @DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING: Run vertex stage on a single
 789     * cluster (on multi-cluster GPUs)
 790     *
 791     * This harms performance but can workaround certain sync/coherency
 792     * bugs, and therefore is useful for debugging.
 793     */
 794    DRM_ASAHI_RENDER_NO_VERTEX_CLUSTERING = (1U << 2),
 795
 796    /**
 797     * @DRM_ASAHI_RENDER_DBIAS_IS_INT: Use integer depth bias formula.
 798     *
 799     * Graphics specifications contain two alternate formulas for depth
 800     * bias, a float formula used with floating-point depth buffers and an
 801     * integer formula using with unorm depth buffers. This flag specifies
 802     * that the integer formula should be used. If omitted, the float
 803     * formula is used instead.
 804     *
 805     * This corresponds to bit 18 of the relevant hardware control register,
 806     * so we match that here for efficiency.
 807     */
 808    DRM_ASAHI_RENDER_DBIAS_IS_INT = (1U << 18),
 809};
 810
 811/**
 812 * struct drm_asahi_zls_buffer - Describe a depth or stencil buffer.
 813 *
 814 * These fields correspond to hardware registers in the ZLS (Z Load/Store) unit.
 815 * There are three hardware registers for each field respectively for loads,
 816 * stores, and partial renders. In practice, it makes sense to set all to the
 817 * same values, except in exceptional cases not yet implemented in userspace, so
 818 * we do not duplicate here for simplicity/efficiency.
 819 *
 820 * This struct is embedded in other structs and therefore is not extensible.
 821 */
 822struct drm_asahi_zls_buffer {
 823    /** @base: Base address of the buffer */
 824    __u64 base;
 825
 826    /**
 827     * @comp_base: If the load buffer is compressed, address of the
 828     * compression metadata section.
 829     */
 830    __u64 comp_base;
 831
 832    /**
 833     * @stride: If layered rendering is enabled, the number of bytes
 834     * between each layer of the buffer.
 835     */
 836    __u32 stride;
 837
 838    /**
 839     * @comp_stride: If layered rendering is enabled, the number of bytes
 840     * between each layer of the compression metadata.
 841     */
 842    __u32 comp_stride;
 843};
 844
 845/**
 846 * struct drm_asahi_timestamp - Describe a timestamp write.
 847 *
 848 * The firmware can optionally write the GPU timestamp at render pass
 849 * granularities, but it needs to be mapped specially via
 850 * DRM_IOCTL_ASAHI_GEM_BIND_OBJECT. This structure therefore describes where to
 851 * write as a handle-offset pair, rather than a GPU address like normal.
 852 *
 853 * This struct is embedded in other structs and therefore is not extensible.
 854 */
 855struct drm_asahi_timestamp {
 856    /**
 857     * @handle: Handle of the timestamp buffer, or 0 to skip this
 858     * timestamp. If nonzero, this must equal the value returned in
 859     * drm_asahi_gem_bind_object::object_handle.
 860     */
 861    __u32 handle;
 862
 863    /** @offset: Offset to write into the timestamp buffer */
 864    __u32 offset;
 865};
 866
 867/**
 868 * struct drm_asahi_timestamps - Describe timestamp writes.
 869 *
 870 * Each operation that can be timestamped, can be timestamped at the start and
 871 * end. Therefore, drm_asahi_timestamp structs always come in pairs, bundled
 872 * together into drm_asahi_timestamps.
 873 *
 874 * This struct is embedded in other structs and therefore is not extensible.
 875 */
 876struct drm_asahi_timestamps {
 877    /** @start: Timestamp recorded at the start of the operation */
 878    struct drm_asahi_timestamp start;
 879
 880    /** @end: Timestamp recorded at the end of the operation */
 881    struct drm_asahi_timestamp end;
 882};
 883
 884/**
 885 * struct drm_asahi_helper_program - Describe helper program configuration.
 886 *
 887 * The helper program is a compute-like kernel required for various hardware
 888 * functionality. Its most important role is dynamically allocating
 889 * scratch/stack memory for individual subgroups, by partitioning a static
 890 * allocation shared for the whole device. It is supplied by userspace via
 891 * drm_asahi_helper_program and internally dispatched by the hardware as needed.
 892 *
 893 * This struct is embedded in other structs and therefore is not extensible.
 894 */
 895struct drm_asahi_helper_program {
 896    /**
 897     * @binary: USC address to the helper program binary. This is a tagged
 898     * pointer with configuration in the bottom bits.
 899     */
 900    __u32 binary;
 901
 902    /** @cfg: Additional configuration bits for the helper program. */
 903    __u32 cfg;
 904
 905    /**
 906     * @data: Data passed to the helper program. This value is not
 907     * interpreted by the kernel, firmware, or hardware in any way. It is
 908     * simply a sideband for userspace, set with the submit ioctl and read
 909     * via special registers inside the helper program.
 910     *
 911     * In practice, userspace will pass a 64-bit GPU VA here pointing to the
 912     * actual arguments, which presumably don't fit in 64-bits.
 913     */
 914    __u64 data;
 915};
 916
 917/**
 918 * struct drm_asahi_bg_eot - Describe a background or end-of-tile program.
 919 *
 920 * The background and end-of-tile programs are dispatched by the hardware at the
 921 * beginning and end of rendering. As the hardware "tilebuffer" is simply local
 922 * memory, these programs are necessary to implement API-level render targets.
 923 * The fragment-like background program is responsible for loading either the
 924 * clear colour or the existing render target contents, while the compute-like
 925 * end-of-tile program stores the tilebuffer contents to memory.
 926 *
 927 * This struct is embedded in other structs and therefore is not extensible.
 928 */
 929struct drm_asahi_bg_eot {
 930    /**
 931     * @usc: USC address of the hardware USC words binding resources
 932     * (including images and uniforms) and the program itself. Note this is
 933     * an additional layer of indirection compared to the helper program,
 934     * avoiding the need for a sideband for data. This is a tagged pointer
 935     * with additional configuration in the bottom bits.
 936     */
 937    __u32 usc;
 938
 939    /**
 940     * @rsrc_spec: Resource specifier for the program. This is a packed
 941     * hardware data structure describing the required number of registers,
 942     * uniforms, bound textures, and bound samplers.
 943     */
 944    __u32 rsrc_spec;
 945};
 946
 947/**
 948 * struct drm_asahi_cmd_render - Command to submit 3D
 949 *
 950 * This command submits a single render pass. The hardware control stream may
 951 * include many draws and subpasses, but within the command, the framebuffer
 952 * dimensions and attachments are fixed.
 953 *
 954 * The hardware requires the firmware to set a large number of Control Registers
 955 * setting up state at render pass granularity before each command rendering 3D.
 956 * The firmware bundles this state into data structures. Unfortunately, we
 957 * cannot expose either any of that directly to userspace, because the
 958 * kernel-firmware ABI is not stable. Although we can guarantee the firmware
 959 * updates in tandem with the kernel, we cannot break old userspace when
 960 * upgrading the firmware and kernel. Therefore, we need to abstract well the
 961 * data structures to avoid tying our hands with future firmwares.
 962 *
 963 * The bulk of drm_asahi_cmd_render therefore consists of values of hardware
 964 * control registers, marshalled via the firmware interface.
 965 *
 966 * The framebuffer/tilebuffer dimensions are also specified here. In addition to
 967 * being passed to the firmware/hardware, the kernel requires these dimensions
 968 * to calculate various essential tiling-related data structures. It is
 969 * unfortunate that our submits are heavier than on vendors with saner
 970 * hardware-software interfaces. The upshot is all of this information is
 971 * readily available to userspace with all current APIs.
 972 *
 973 * It looks odd - but it's not overly burdensome and it ensures we can remain
 974 * compatible with old userspace.
 975 */
 976struct drm_asahi_cmd_render {
 977    /** @flags: Combination of drm_asahi_render_flags flags. */
 978    __u32 flags;
 979
 980    /**
 981     * @isp_zls_pixels: ISP_ZLS_PIXELS register value. This contains the
 982     * depth/stencil width/height, which may differ from the framebuffer
 983     * width/height.
 984     */
 985    __u32 isp_zls_pixels;
 986
 987    /**
 988     * @vdm_ctrl_stream_base: VDM_CTRL_STREAM_BASE register value. GPU
 989     * address to the beginning of the VDM control stream.
 990     */
 991    __u64 vdm_ctrl_stream_base;
 992
 993    /** @vertex_helper: Helper program used for the vertex shader */
 994    struct drm_asahi_helper_program vertex_helper;
 995
 996    /** @fragment_helper: Helper program used for the fragment shader */
 997    struct drm_asahi_helper_program fragment_helper;
 998
 999    /**
1000     * @isp_scissor_base: ISP_SCISSOR_BASE register value. GPU address of an
1001     * array of scissor descriptors indexed in the render pass.
1002     */
1003    __u64 isp_scissor_base;
1004
1005    /**
1006     * @isp_dbias_base: ISP_DBIAS_BASE register value. GPU address of an
1007     * array of depth bias values indexed in the render pass.
1008     */
1009    __u64 isp_dbias_base;
1010
1011    /**
1012     * @isp_oclqry_base: ISP_OCLQRY_BASE register value. GPU address of an
1013     * array of occlusion query results written by the render pass.
1014     */
1015    __u64 isp_oclqry_base;
1016
1017    /** @depth: Depth buffer */
1018    struct drm_asahi_zls_buffer depth;
1019
1020    /** @stencil: Stencil buffer */
1021    struct drm_asahi_zls_buffer stencil;
1022
1023    /** @zls_ctrl: ZLS_CTRL register value */
1024    __u64 zls_ctrl;
1025
1026    /** @ppp_multisamplectl: PPP_MULTISAMPLECTL register value */
1027    __u64 ppp_multisamplectl;
1028
1029    /**
1030     * @sampler_heap: Base address of the sampler heap. This heap is used
1031     * for both vertex shaders and fragment shaders. The registers are
1032     * per-stage, but there is no known use case for separate heaps.
1033     */
1034    __u64 sampler_heap;
1035
1036    /** @ppp_ctrl: PPP_CTRL register value */
1037    __u32 ppp_ctrl;
1038
1039    /** @width_px: Framebuffer width in pixels */
1040    __u16 width_px;
1041
1042    /** @height_px: Framebuffer height in pixels */
1043    __u16 height_px;
1044
1045    /** @layers: Number of layers in the framebuffer */
1046    __u16 layers;
1047
1048    /** @sampler_count: Number of samplers in the sampler heap. */
1049    __u16 sampler_count;
1050
1051    /** @utile_width_px: Width of a logical tilebuffer tile in pixels */
1052    __u8 utile_width_px;
1053
1054    /** @utile_height_px: Height of a logical tilebuffer tile in pixels */
1055    __u8 utile_height_px;
1056
1057    /** @samples: # of samples in the framebuffer. Must be 1, 2, or 4. */
1058    __u8 samples;
1059
1060    /** @sample_size_B: # of bytes in the tilebuffer required per sample. */
1061    __u8 sample_size_B;
1062
1063    /**
1064     * @isp_merge_upper_x: 32-bit float used in the hardware triangle
1065     * merging. Calculate as: tan(60 deg) * width.
1066     *
1067     * Making these values UAPI avoids requiring floating-point calculations
1068     * in the kernel in the hot path.
1069     */
1070    __u32 isp_merge_upper_x;
1071
1072    /**
1073     * @isp_merge_upper_y: 32-bit float. Calculate as: tan(60 deg) * height.
1074     * See @isp_merge_upper_x.
1075     */
1076    __u32 isp_merge_upper_y;
1077
1078    /** @bg: Background program run for each tile at the start */
1079    struct drm_asahi_bg_eot bg;
1080
1081    /** @eot: End-of-tile program ran for each tile at the end */
1082    struct drm_asahi_bg_eot eot;
1083
1084    /**
1085     * @partial_bg: Background program ran at the start of each tile when
1086     * resuming the render pass during a partial render.
1087     */
1088    struct drm_asahi_bg_eot partial_bg;
1089
1090    /**
1091     * @partial_eot: End-of-tile program ran at the end of each tile when
1092     * pausing the render pass during a partial render.
1093     */
1094    struct drm_asahi_bg_eot partial_eot;
1095
1096    /**
1097     * @isp_bgobjdepth: ISP_BGOBJDEPTH register value. This is the depth
1098     * buffer clear value, encoded in the depth buffer's format: either a
1099     * 32-bit float or a 16-bit unorm (with upper bits zeroed).
1100     */
1101    __u32 isp_bgobjdepth;
1102
1103    /**
1104     * @isp_bgobjvals: ISP_BGOBJVALS register value. The bottom 8-bits
1105     * contain the stencil buffer clear value.
1106     */
1107    __u32 isp_bgobjvals;
1108
1109    /** @ts_vtx: Timestamps for the vertex portion of the render */
1110    struct drm_asahi_timestamps ts_vtx;
1111
1112    /** @ts_frag: Timestamps for the fragment portion of the render */
1113    struct drm_asahi_timestamps ts_frag;
1114};
1115
1116/**
1117 * struct drm_asahi_cmd_compute - Command to submit compute
1118 *
1119 * This command submits a control stream consisting of compute dispatches. There
1120 * is essentially no limit on how many compute dispatches may be included in a
1121 * single compute command, although timestamps are at command granularity.
1122 */
1123struct drm_asahi_cmd_compute {
1124    /** @flags: MBZ */
1125    __u32 flags;
1126
1127    /** @sampler_count: Number of samplers in the sampler heap. */
1128    __u32 sampler_count;
1129
1130    /**
1131     * @cdm_ctrl_stream_base: CDM_CTRL_STREAM_BASE register value. GPU
1132     * address to the beginning of the CDM control stream.
1133     */
1134    __u64 cdm_ctrl_stream_base;
1135
1136    /**
1137     * @cdm_ctrl_stream_end: GPU base address to the end of the hardware
1138     * control stream. Note this only considers the first contiguous segment
1139     * of the control stream, as the stream might jump elsewhere.
1140     */
1141    __u64 cdm_ctrl_stream_end;
1142
1143    /** @sampler_heap: Base address of the sampler heap. */
1144    __u64 sampler_heap;
1145
1146    /** @helper: Helper program used for this compute command */
1147    struct drm_asahi_helper_program helper;
1148
1149    /** @ts: Timestamps for the compute command */
1150    struct drm_asahi_timestamps ts;
1151};
1152
1153/**
1154 * struct drm_asahi_get_time - Arguments passed to DRM_IOCTL_ASAHI_GET_TIME
1155 */
1156struct drm_asahi_get_time {
1157    /** @flags: MBZ. */
1158    __u64 flags;
1159
1160    /** @gpu_timestamp: On return, the GPU timestamp in nanoseconds. */
1161    __u64 gpu_timestamp;
1162};
1163
1164/**
1165 * DRM_IOCTL_ASAHI() - Build an Asahi IOCTL number
1166 * @__access: Access type. Must be R, W or RW.
1167 * @__id: One of the DRM_ASAHI_xxx id.
1168 * @__type: Suffix of the type being passed to the IOCTL.
1169 *
1170 * Don't use this macro directly, use the DRM_IOCTL_ASAHI_xxx
1171 * values instead.
1172 *
1173 * Return: An IOCTL number to be passed to ioctl() from userspace.
1174 */
1175#define DRM_IOCTL_ASAHI(__access, __id, __type)           \
1176    DRM_IO##__access(DRM_COMMAND_BASE + DRM_ASAHI_##__id, \
1177        struct drm_asahi_##__type)
1178
1179/* Note: this is an enum so that it can be resolved by Rust bindgen. */
1180enum {
1181    DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOCTL_ASAHI(W, GET_PARAMS, get_params),
1182    DRM_IOCTL_ASAHI_GET_TIME = DRM_IOCTL_ASAHI(WR, GET_TIME, get_time),
1183    DRM_IOCTL_ASAHI_VM_CREATE = DRM_IOCTL_ASAHI(WR, VM_CREATE, vm_create),
1184    DRM_IOCTL_ASAHI_VM_DESTROY = DRM_IOCTL_ASAHI(W, VM_DESTROY, vm_destroy),
1185    DRM_IOCTL_ASAHI_VM_BIND = DRM_IOCTL_ASAHI(W, VM_BIND, vm_bind),
1186    DRM_IOCTL_ASAHI_GEM_CREATE = DRM_IOCTL_ASAHI(WR, GEM_CREATE, gem_create),
1187    DRM_IOCTL_ASAHI_GEM_MMAP_OFFSET = DRM_IOCTL_ASAHI(WR, GEM_MMAP_OFFSET, gem_mmap_offset),
1188    DRM_IOCTL_ASAHI_GEM_BIND_OBJECT = DRM_IOCTL_ASAHI(WR, GEM_BIND_OBJECT, gem_bind_object),
1189    DRM_IOCTL_ASAHI_QUEUE_CREATE = DRM_IOCTL_ASAHI(WR, QUEUE_CREATE, queue_create),
1190    DRM_IOCTL_ASAHI_QUEUE_DESTROY = DRM_IOCTL_ASAHI(W, QUEUE_DESTROY, queue_destroy),
1191    DRM_IOCTL_ASAHI_SUBMIT = DRM_IOCTL_ASAHI(W, SUBMIT, submit),
1192};
1193
1194#if defined(__cplusplus)
1195}
1196#endif
1197
1198#endif /* _ASAHI_DRM_H_ */