History

drm: Add UAPI for the Asahi driver

This adds the UAPI for the Asahi driver targeting the GPU in the Apple M1 and M2 series systems on chip. The UAPI design is based on other modern Vulkan-capable drivers, including Xe and Panthor. Memory management is based on explicit VM management. Synchronization is exclusively explicit sync. This UAPI is validated against our open source Mesa stack, which is fully conformant to the OpenGL 4.6, OpenGL ES 3.2, OpenCL 3.0, and Vulkan 1.4 standards. The Vulkan driver supports sparse, exercising the VM_BIND mechanism. This patch adds the standalone UAPI header. It is implemented by an open source DRM driver written in Rust. We fully intend to upstream this driver when possible. However, as a production graphics driver, it depends on a significant number of Rust abstractions that will take a long time to upstream. In the mean time, our userspace is upstream in Mesa but is not allowed to probe with upstream Mesa as the UAPI is not yet reviewed and merged in the upstream kernel. Although we ship a patched Mesa in Fedora Asahi Remix, any containers shipping upstream Mesa builds are broken for our users, including upstream Flatpak and Waydroid runtimes. Additionally, it forces us to maintain forks of Mesa and virglrenderer, which complicates bisects. The intention in sending out this patch is for this UAPI to be thoroughly reviewed. Once we as the DRM community are satisfied with the UAPI, this header lands signifying that the UAPI is stable and must only be evolved in backwards-compatible ways; it will be the UAPI implemented in the DRM driver that eventually lands upstream. That promise lets us enable upstream Mesa, solving all these issues while the upstream Rust abstractions are developed. https://github.com/alyssarosenzweig/linux/commits/agx-uapi-v7 contains the DRM driver implementing this proposed UAPI. https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33984 contains the Mesa patches to implement this proposed UAPI. That Linux and Mesa branch together give a complete graphics/compute stack on top of this UAPI.

Alyssa Rosenzweig committed 1 year ago

Commit 12a2bf61 parent 8f47efd3 files · +1200 −0Browse files

Showing the changes to include/uapi (1 of 3 files). Show all

Unified · Split

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