STRUCT DRM_ASAHI_CMD_RENDER(9)
π struct drm_asahi_cmd_render(9) β like, the Kernel API Manual bestie β¨
okay so before we even start: this page is from the Kernel API Manual, and the whole vibe is "here's the one struct you need to submit a single 3D render pass." no cap. let's get into it π
β¨ NAME β¨
struct drm_asahi_cmd_render β the command you submit for 3D. literally that's it. that's the whole thing. π¦
πΈ SYNOPSIS πΈ
struct drm_asahi_cmd_render {
__u32 flags;
__u32 isp_zls_pixels;
__u64 vdm_ctrl_stream_base;
struct drm_asahi_helper_program vertex_helper;
struct drm_asahi_helper_program fragment_helper;
__u64 isp_scissor_base;
__u64 isp_dbias_base;
__u64 isp_oclqry_base;
struct drm_asahi_zls_buffer depth;
struct drm_asahi_zls_buffer stencil;
__u64 zls_ctrl;
__u64 ppp_multisamplectl;
__u64 sampler_heap;
__u32 ppp_ctrl;
__u16 width_px;
__u16 height_px;
__u16 layers;
__u16 sampler_count;
__u8 utile_width_px;
__u8 utile_height_px;
__u8 samples;
__u8 sample_size_B;
__u32 isp_merge_upper_x;
__u32 isp_merge_upper_y;
struct drm_asahi_bg_eot bg;
struct drm_asahi_bg_eot eot;
struct drm_asahi_bg_eot partial_bg;
struct drm_asahi_bg_eot partial_eot;
__u32 isp_bgobjdepth;
__u32 isp_bgobjvals;
struct drm_asahi_timestamps ts_vtx;
struct drm_asahi_timestamps ts_frag;
};
like, look at her. so many fields. she's got range π
π«Ά Members π«Ά
okay bestie, field by field, no skipping, i promise π
flagsβ a combo ofdrm_asahi_render_flagsflags. that's the whole tea βisp_zls_pixelsβ theISP_ZLS_PIXELSregister value. heads up tho: this holds the depth/stencil width/height, and those can legit be different from the framebuffer width/height. don't assume, iygkwyk πvdm_ctrl_stream_baseβ theVDM_CTRL_STREAM_BASEregister value. it's the GPU address pointing at the start of the VDM control stream. think "main character's home address" but for a stream πvertex_helperβ the helper program used for the vertex shader β¨fragment_helperβ the helper program used for the fragment shader β¨isp_scissor_baseβ theISP_SCISSOR_BASEregister value. GPU address of an array of scissor descriptors, indexed in the render pass. lowkey iconic βοΈisp_dbias_baseβ theISP_DBIAS_BASEregister value. GPU address of an array of depth bias values, indexed in the render pass.isp_oclqry_baseβ theISP_OCLQRY_BASEregister value. GPU address of an array of occlusion query results that the render pass writes. she writes, she doesn't just read πdepthβ the depth buffer π«§stencilβ the stencil buffer π«§zls_ctrlβ theZLS_CTRLregister valueppp_multisamplectlβ thePPP_MULTISAMPLECTLregister valuesampler_heapβ base address of the sampler heap. this heap serves both vertex shaders and fragment shaders. the registers are per-stage, but ngl there's no known use case for separate heaps. so like, one heap, two stages, we move πppp_ctrlβ thePPP_CTRLregister valuewidth_pxβ framebuffer width in pixels πheight_pxβ framebuffer height in pixels πlayersβ number of layers in the framebuffer. yes she stacks π₯sampler_countβ number of samplers in the sampler heap.utile_width_pxβ width of a logical tilebuffer tile in pixels.utile_height_pxβ height of a logical tilebuffer tile in pixels.samplesβ the # of samples in the framebuffer. must be1,2, or4. like those are the only options, don't try anything else fr fr β οΈsample_size_Bβ the # of bytes in the tilebuffer required per sample.isp_merge_upper_xβ a 32-bit float used in the hardware triangle merging. calculate it as:tan(60 deg) * width.
making these values UAPI avoids requiring floating-point calculations in the kernel in the hot path. periodt. π₯
isp_merge_upper_yβ a 32-bit float. calculate it as:tan(60 deg) * height. seeisp_merge_upper_xπbgβ the background program run for each tile at the start πeotβ the end-of-tile program ran for each tile at the end πpartial_bgβ the background program ran at the start of each tile when resuming the render pass during a partial render βΈοΈpartial_eotβ the end-of-tile program ran at the end of each tile when pausing the render pass during a partial render β―οΈisp_bgobjdepthβ theISP_BGOBJDEPTHregister value. it's the depth buffer clear value, encoded in the depth buffer's format: either a 32-bit float or a 16-bit unorm (with upper bits zeroed). she's bilingual π£οΈisp_bgobjvalsβ theISP_BGOBJVALSregister value. the bottom 8-bits contain the stencil buffer clear value. bottom bits stay winning π§ts_vtxβ timestamps for the vertex portion of the render β±οΈts_fragβ timestamps for the fragment portion of the render β±οΈ
π¦ Description π¦
so this command submits a single render pass, okay? the hardware control stream may include a whole bunch of draws and subpasses, but within the command, the framebuffer dimensions and attachments are fixed. no take-backs, no changing mid-command π
here's the situation: the hardware requires the firmware to set a large number of Control Registers β like, setting up state at render-pass granularity β before every single command that renders 3D. a lot. and so the firmware bundles all that state into data structures. iconic of her β¨
but π we cannot expose any of that directly to userspace, because the kernel-firmware ABI is not stable. we can guarantee the firmware updates in tandem with the kernel, but we can't be out here breaking old userspace when someone upgrades the firmware and kernel. so we need to abstract the data structures well β otherwise we're tying our own hands with future firmwares. not the move π«
so the bulk of drm_asahi_cmd_render? it's values of hardware control registers, marshalled via the firmware interface. that's the whole main character arc π¬
the framebuffer/tilebuffer dimensions are also specified here. and on top of being passed to the firmware/hardware, the kernel needs these dimensions to calculate various essential tiling-related data structures. unfortunate truth: our submits are heavier than on vendors with saner hardware-software interfaces π the upshot tho? all of this information is readily available to userspace with all current APIs. slay π
it looks odd β but it's not overly burdensome, and it ensures we can remain compatible with old userspace. and honestly? that's the win we care about π«Ά
π SEE ALSO π
go read these, bestie, they're all right here:
Kernel file ./include/uapi/drm/asahi_drm.h, Introduction to the Asahi UAPI(9), enum drm_asahi_ioctl_id(9), struct drm_asahi_params_global(9), enum drm_asahi_feature(9), struct drm_asahi_get_params(9), struct drm_asahi_vm_create(9), struct drm_asahi_vm_destroy(9), enum drm_asahi_gem_flags(9), struct drm_asahi_gem_create(9), struct drm_asahi_gem_mmap_offset(9), enum drm_asahi_bind_flags(9), struct drm_asahi_gem_bind_op(9), struct drm_asahi_vm_bind(9), enum drm_asahi_bind_object_op(9), enum drm_asahi_bind_object_flags(9), struct drm_asahi_gem_bind_object(9), enum drm_asahi_cmd_type(9), enum drm_asahi_priority(9), struct drm_asahi_queue_create(9), struct drm_asahi_queue_destroy(9), enum drm_asahi_sync_type(9), struct drm_asahi_sync(9), DRM_ASAHI_BARRIER_NONE(9), struct drm_asahi_cmd_header(9), struct drm_asahi_submit(9), struct drm_asahi_attachment(9), struct drm_asahi_zls_buffer(9), struct drm_asahi_timestamp(9), struct drm_asahi_timestamps(9), struct drm_asahi_helper_program(9), struct drm_asahi_bg_eot(9), struct drm_asahi_cmd_compute(9), struct drm_asahi_get_time(9), DRM_IOCTL_ASAHI(9)
and that's the page!! π this beauty lives in ./include/uapi/drm and she's dated October 2026 β so mark your calendars bestie, she's from the future and she ate π sign-off complete, go write some userspace code, i believe in you π§β¨
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms