All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Stone <daniels@collabora.com>
To: igt-dev@lists.freedesktop.org
Cc: boris.brezillon@collabora.com, laura.nao@collabora.com,
	adrian.larumbe@collabora.com, daniel.almeida@collabora.com,
	liviu.dudau@arm.com
Subject: [PATCH 4/4] panthor: Add simple compute-shader test
Date: Thu, 15 Oct 2026 14:05:49 +0100	[thread overview]
Message-ID: <20261015130837.710795-5-daniels@collabora.com> (raw)
In-Reply-To: <20261015130837.710795-1-daniels@collabora.com>

This test launches a compute shader which performs RMW on a memory
array, to check that we can actually launch jobs and see the results.

Signed-off-by: Daniel Stone <daniels@collabora.com>
---
 lib/igt_panthor.h             | 204 +++++++++++++++++++++++++++++
 tests/panthor/panthor_group.c | 240 ++++++++++++++++++++++++++++++++++
 2 files changed, 444 insertions(+)

diff --git a/lib/igt_panthor.h b/lib/igt_panthor.h
index dfeb0ac60..35882fad7 100644
--- a/lib/igt_panthor.h
+++ b/lib/igt_panthor.h
@@ -363,4 +363,208 @@ cs_error_barrier(void)
 	return instr.raw;
 }
 
+struct gpu_src_reg {
+	uint8_t reg;
+	bool last;
+	uint8_t rep;
+};
+
+struct gpu_dst_reg {
+	uint8_t reg;
+};
+
+enum gpu_flow_ctrl {
+	FLOW_NONE = 0,
+	FLOW_WAIT0 = 0x1,
+	FLOW_WAIT1 = 0x2,
+	FLOW_WAIT01 = 0x3,
+	FLOW_WAIT2 = 0x4,
+	FLOW_WAIT02 = 0x5,
+	FLOW_WAIT12 = 0x6,
+	FLOW_WAIT012 = 0x7,
+	FLOW_WAIT0126 = 0x8,
+	FLOW_WAIT = 0x9,
+	FLOW_RECONVERGE = 0xa,
+	FLOW_WAIT_RESOURCE = 0xc,
+	FLOW_DISCARD = 0xd,
+	FLOW_END = 0xf,
+};
+
+enum gpu_reg_width {
+	REG_WIDTH_LO16 = 0x1,
+	REG_WIDTH_HI16 = 0x2,
+	REG_WIDTH_32 = 0x3,
+};
+
+static inline struct gpu_dst_reg
+gpu_dst_reg(uint8_t reg)
+{
+	struct gpu_dst_reg ret = {
+		.reg = reg
+	};
+	return ret;
+}
+
+static inline struct gpu_src_reg
+gpu_src_zero(void)
+{
+	struct gpu_src_reg ret = {
+		.reg = 255, /* architecturally invalid */
+		.last = false,
+		.rep = (0x3 << 6),
+	};
+	return ret;
+}
+
+static inline struct gpu_src_reg
+gpu_src_reg(uint8_t reg)
+{
+	struct gpu_src_reg ret = {
+		.reg = reg,
+		.last = false,
+		.rep = reg,
+	};
+	return ret;
+}
+
+static inline struct gpu_src_reg
+gpu_src_reg_last(uint8_t reg)
+{
+	struct gpu_src_reg ret = {
+		.reg = reg,
+		.last = true,
+		.rep = (reg | (1 << 6)),
+	};
+	return ret;
+}
+
+#define ins(x, v, s) x |= ((uint64_t) v << s)
+
+static inline uint64_t
+gpu_mov_imm_i32(struct gpu_dst_reg dst, int32_t imm, enum gpu_flow_ctrl flow)
+{
+	uint64_t ret = 0;
+	ins(ret, gpu_src_zero().rep, 0);
+	ins(ret, imm, 8);
+	ins(ret, dst.reg, 40);
+	ins(ret, REG_WIDTH_32, 46);
+	ins(ret, 0x0, 48); /* opcode */
+	ins(ret, 0x11, 52); /* class */
+	ins(ret, 0x0, 57); /* FAU */
+	ins(ret, flow, 59);
+	return ret;
+}
+
+static inline uint64_t
+gpu_lshift_or_i32(struct gpu_dst_reg dst, struct gpu_src_reg src,
+		  struct gpu_src_reg shift, struct gpu_src_reg or,
+		  enum gpu_flow_ctrl flow)
+{
+	uint64_t ret = 0;
+	ins(ret, src.rep, 0);
+	ins(ret, shift.rep, 8);
+	ins(ret, or.rep, 16);
+	ins(ret, 0x1, 24); /* logicop = or */
+	ins(ret, 0x4, 26); /* lanes = b0 */
+	ins(ret, 0x0, 30); /* dst.not = false */
+	ins(ret, 0x1, 32); /* shift = left */
+	ins(ret, 0x0, 35); /* src2.not = false */
+	ins(ret, 0x0, 36); /* widen = false */
+	ins(ret, dst.reg, 40);
+	ins(ret, REG_WIDTH_32, 46);
+	ins(ret, 0x4, 48); /* opcode */
+	ins(ret, 0xb, 52); /* class */
+	ins(ret, 0x0, 57); /* FAU */
+	ins(ret, flow, 59);
+	return ret;
+}
+
+static inline uint64_t
+gpu_iadd_u32(struct gpu_dst_reg dst, struct gpu_src_reg left,
+	     struct gpu_src_reg right, enum gpu_flow_ctrl flow)
+{
+	uint64_t ret = 0;
+	ins(ret, left.rep, 0);
+	ins(ret, right.rep, 8);
+	ins(ret, 0x0, 16); /* opcode */
+	ins(ret, 0x0, 26); /* widen1 */
+	ins(ret, 0x0, 30); /* saturate */
+	ins(ret, 0x0, 36); /* widen0 */
+	ins(ret, dst.reg, 40);
+	ins(ret, REG_WIDTH_32, 46);
+	ins(ret, 0x0, 48); /* data type */
+	ins(ret, 0xa, 52); /* class */
+	ins(ret, 0x0, 57); /* FAU */
+	ins(ret, flow, 59);
+	return ret;
+}
+
+static inline uint64_t
+gpu_imul_u32(struct gpu_dst_reg dst, struct gpu_src_reg left,
+	     struct gpu_src_reg right, enum gpu_flow_ctrl flow)
+{
+	uint64_t ret = 0;
+	ins(ret, left.rep, 0);
+	ins(ret, right.rep, 8);
+	ins(ret, 0xa, 16); /* opcode */
+	ins(ret, 0x0, 26); /* widen1 */
+	ins(ret, 0x0, 30); /* saturate */
+	ins(ret, 0x0, 36); /* widen0 */
+	ins(ret, dst.reg, 40);
+	ins(ret, REG_WIDTH_32, 46);
+	ins(ret, 0x0, 48); /* data type */
+	ins(ret, 0xa, 52); /* class */
+	ins(ret, 0x0, 57); /* FAU */
+	ins(ret, flow, 59);
+	return ret;
+}
+
+static inline uint64_t
+gpu_load_i32(struct gpu_dst_reg dst, struct gpu_src_reg addr_lo,
+	     struct gpu_src_reg addr_hi, uint16_t offset,
+	     uint8_t sb_slot, enum gpu_flow_ctrl flow)
+{
+	uint64_t ret = 0;
+	igt_assert_eq(addr_hi.reg, addr_lo.reg + 1);
+	ins(ret, addr_lo.rep, 0);
+	ins(ret, offset, 8);
+	ins(ret, 0x0, 24); /* access mode */
+	ins(ret, REG_WIDTH_32, 27);
+	ins(ret, sb_slot, 30);
+	ins(ret, 0x1, 33); /* staging register count */
+	ins(ret, 0x0, 36); /* load 32 */
+	ins(ret, 0x1, 39); /* no sign extension */
+	ins(ret, dst.reg, 40); /* base staging register */
+	ins(ret, 0x2, 46); /* write staging registers */
+	ins(ret, 0x0, 48); /* opcode */
+	ins(ret, 0x6, 52); /* class */
+	ins(ret, 0x0, 57); /* FAU */
+	ins(ret, flow, 59);
+	return ret;
+}
+
+static inline uint64_t
+gpu_store_i32(struct gpu_src_reg addr_lo, struct gpu_src_reg addr_hi,
+	      struct gpu_src_reg val, uint16_t offset,
+	      uint8_t sb_slot, enum gpu_flow_ctrl flow)
+{
+	uint64_t ret = 0;
+	igt_assert_eq(addr_hi.reg, addr_lo.reg + 1);
+	ins(ret, addr_lo.rep, 0);
+	ins(ret, offset, 8);
+	ins(ret, 0x0, 24); /* access mode */
+	ins(ret, REG_WIDTH_32, 27);
+	ins(ret, sb_slot, 30);
+	ins(ret, 0x1, 33); /* staging register count */
+	ins(ret, val.reg, 40); /* base staging register */
+	ins(ret, 0x1, 46); /* read staging registers */
+	ins(ret, 0x1, 48); /* opcode */
+	ins(ret, 0x6, 52); /* class */
+	ins(ret, 0x0, 57); /* FAU */
+	ins(ret, flow, 59);
+	return ret;
+}
+
+#undef ins
+
 #endif /* IGT_PANTHOR_H */
diff --git a/tests/panthor/panthor_group.c b/tests/panthor/panthor_group.c
index c79f8d629..feca42482 100644
--- a/tests/panthor/panthor_group.c
+++ b/tests/panthor/panthor_group.c
@@ -10,6 +10,133 @@
 #include "igt_syncobj.h"
 #include "panthor_drm.h"
 
+/*
+ * Record a simple compute program:
+ * {
+ *     extern uint32_t shared_buf[num_invocations];
+ *     extern const uint32_t my_invocation_id;
+ *     shared_buf[my_invocation_id] *= my_invocation_id;
+ * }
+ */
+static void
+record_compute_prog(uint8_t *csf_cmdbuf, unsigned int *csf_cmdbuf_size,
+		    uint8_t *gpu_cmdbuf, unsigned int *gpu_cmdbuf_size,
+		    uint32_t srt_gpuva, uint32_t fau_gpuva, uint32_t spd_gpuva,
+		    uint32_t tsd_gpuva, uint32_t data_gpuva)
+{
+	const uint8_t reg_id_global_x = 60; /* preloaded */
+	const uint8_t reg_addr_lo = 0;
+	const uint8_t reg_addr_hi = 1;
+	const uint8_t reg_val = 2;
+	const uint8_t reg_offset = 3;
+	const uint8_t reg_shift = 4;
+	const uint8_t compute_sr_base = 0;
+	const uint8_t zero_reg = 40;
+
+	uint64_t gpu_instrs[] = {
+		/* MOV_IMM.i32 rADDRLO, 0x10000 */
+		gpu_mov_imm_i32(gpu_dst_reg(reg_addr_lo), data_gpuva, FLOW_NONE),
+		/* MOV_IMM.i32 rADDRHI, 0x0 */
+		gpu_mov_imm_i32(gpu_dst_reg(reg_addr_hi), 0x0, FLOW_NONE),
+		/* MOV_IMM.i32 rSHIFT, 0x2 */
+		gpu_mov_imm_i32(gpu_dst_reg(reg_shift), 0x2, FLOW_NONE),
+		/* LSHIFT_OR.i32 rOFFSET, rGLOBALID, rSHIFT^, 0x0 */
+		gpu_lshift_or_i32(gpu_dst_reg(reg_offset),
+				  gpu_src_reg(reg_id_global_x),
+				  gpu_src_reg_last(reg_shift),
+				  gpu_src_zero(),
+				  FLOW_NONE),
+		/* IADD.u32 rADDRLO, rADDRLO^, rOFFSET^ */
+		gpu_iadd_u32(gpu_dst_reg(reg_addr_lo),
+			     gpu_src_reg_last(reg_addr_lo),
+			     gpu_src_reg_last(reg_offset),
+			     FLOW_NONE),
+		/* LOAD.i32.slot0.wait0 @rVAL, [rADDRLO:rADDRHI], offset:0 */
+		gpu_load_i32(gpu_dst_reg(reg_val),
+			     gpu_src_reg(reg_addr_lo),
+			     gpu_src_reg(reg_addr_hi),
+			     0x0,
+			     0, FLOW_WAIT0),
+		/* IMUL_u32 rVAL, rVAL^, rGLOBALID^ */
+		gpu_imul_u32(gpu_dst_reg(reg_val),
+			     gpu_src_reg_last(reg_val),
+			     gpu_src_reg_last(reg_id_global_x),
+			     FLOW_NONE),
+		/* STORE.i32.slot1.end @rVAL, [rADDRLO^:rADDRHI^], offset:0 */
+		gpu_store_i32(gpu_src_reg_last(reg_addr_lo),
+			      gpu_src_reg_last(reg_addr_hi),
+			      gpu_src_reg(reg_val),
+			      0x0,
+			      1, FLOW_END),
+	};
+
+	uint64_t csf_instrs[] = {
+		/* REQ_RESOURCE.compute */
+		cs_req_resource(true, false, false, false),
+		/* MOV32 r40, 0 (always force cache flush/invalidate) */
+		cs_mov32(zero_reg, 0),
+		/* FLUSH_CACHE.clean_invalidate_l2.clean_invalidate_lsc.invalidate_other.sb0 */
+		cs_flush(CS_FLUSH_MODE_CLEAN_AND_INVALIDATE,
+			 CS_FLUSH_MODE_CLEAN_AND_INVALIDATE,
+			 CS_FLUSH_MODE_INVALIDATE,
+			 0, zero_reg, 1),
+		/* WAIT (flush) */
+		cs_wait(0xff, false),
+		/* ShaderResourceTable 0-3 pointers */
+		cs_mov48(compute_sr_base +  0, srt_gpuva),
+		cs_mov48(compute_sr_base +  2, 0x222222222222),
+		cs_mov48(compute_sr_base +  4, 0x333333333333),
+		cs_mov48(compute_sr_base +  6, 0x444444444444),
+		/* FastAccessUniform table 0-3 pointers */
+		cs_mov48(compute_sr_base +  8, fau_gpuva),
+		cs_mov48(compute_sr_base + 10, 0x666666666666),
+		cs_mov48(compute_sr_base + 12, 0x777777777777),
+		cs_mov48(compute_sr_base + 14, 0x888888888888),
+		/* ShaderProgramDescriptor 0-3 pointers */
+		cs_mov48(compute_sr_base + 16, spd_gpuva),
+		cs_mov48(compute_sr_base + 18, 0x999999999999),
+		cs_mov48(compute_sr_base + 20, 0xaaaaaaaaaaaa),
+		cs_mov48(compute_sr_base + 22, 0xbbbbbbbbbbbb),
+		/* ThreadStorageDescriptor 0-3 pointers */
+		cs_mov48(compute_sr_base + 24, tsd_gpuva),
+		cs_mov48(compute_sr_base + 26, 0xdddddddddddd),
+		cs_mov48(compute_sr_base + 28, 0xeeeeeeeeeeee),
+		cs_mov48(compute_sr_base + 30, 0xffffffffffff),
+		/* global ID offset = 0 */
+		cs_mov32(compute_sr_base + 32, 0),
+		/* workgroup size 64x1x1, allow merge */
+		cs_mov32(compute_sr_base + 33, (63 << 0) | (0 << 10) | (0 << 20) | (1 << 31)),
+		/* job offset (x/y/z) = { 0, 0, 0 } */
+		cs_mov32(compute_sr_base + 34, 0),
+		cs_mov32(compute_sr_base + 35, 0),
+		cs_mov32(compute_sr_base + 36, 0),
+		/* job size (x/y/z) = { 64, 1, 1 } */
+		cs_mov32(compute_sr_base + 37, 64),
+		cs_mov32(compute_sr_base + 38, 1),
+		cs_mov32(compute_sr_base + 39, 1),
+		/* SET_SB_ENTRY.async_ep1.other1 */
+		cs_set_sb_entry(1, 1),
+		/* RUN_COMPUTE.increment64.x_axis.no_increment.srt0.spd0.tsd0.fau0 */
+		cs_run_compute(64, CS_TASK_AXIS_X, 0, 0, 0, 0, 0),
+		/* WAIT (RUN_COMPUTE) */
+		cs_wait(0xff, false),
+		/* FLUSH_CACHE.clean_invalidate_l2.clean_invalidate_lsc.invalidate_other.sb0 */
+		cs_flush(CS_FLUSH_MODE_CLEAN_AND_INVALIDATE,
+			 CS_FLUSH_MODE_CLEAN_AND_INVALIDATE,
+			 CS_FLUSH_MODE_INVALIDATE,
+			 0, zero_reg, 1),
+		/* WAIT (flush) */
+		cs_wait(0xff, false),
+		/* ERROR_BARRIER */
+		cs_error_barrier(),
+	};
+
+	memcpy(gpu_cmdbuf, gpu_instrs, sizeof(gpu_instrs));
+	*gpu_cmdbuf_size = sizeof(gpu_instrs);
+	memcpy(csf_cmdbuf, csf_instrs, sizeof(csf_instrs));
+	*csf_cmdbuf_size = sizeof(csf_instrs);
+}
+
 static size_t
 issue_store_multiple(uint8_t *cs, uint64_t kernel_va, uint32_t constant)
 {
@@ -118,6 +245,119 @@ int igt_main() {
 		igt_panthor_free_bo(fd, &result_bo);
 	}
 
+	igt_describe("Submit a simple compute job with memory access.");
+	igt_subtest("simple_compute") {
+		uint32_t vm_id;
+		uint32_t group_handle;
+		struct panthor_bo csf_cmdbuf_bo = {};
+		struct panthor_bo gpu_cmdbuf_bo = {};
+		struct panthor_bo resource_table_bo = {};
+		struct panthor_bo data_bo = {};
+		uint64_t csf_cmdbuf_gpuva;
+		uint32_t csf_cmdbuf_size;
+		uint64_t gpu_cmdbuf_gpuva;
+		uint32_t gpu_cmdbuf_size;
+		uint32_t resource_table_gpuva;
+		uint32_t data_gpuva;
+		uint32_t syncobj_handle;
+		uint32_t srt_offset;
+		uint32_t fau_offset;
+		uint32_t spd_offset;
+		uint32_t *spd_ptr;
+		uint32_t spd_gpuva;
+		uint32_t tsd_offset;
+		uint32_t *tsd_ptr;
+		int arch = igt_panthor_get_arch(fd);
+
+		igt_require(arch < 15);
+
+		igt_panthor_vm_create(fd, &vm_id, 0);
+
+		/* CSF ISA command stream */
+		csf_cmdbuf_gpuva = 0x1000000;
+		igt_panthor_bo_create_mapped(fd, &csf_cmdbuf_bo, 4096, 0, 0);
+		igt_panthor_vm_bind(fd, vm_id, csf_cmdbuf_bo.handle, csf_cmdbuf_gpuva,
+				    csf_cmdbuf_bo.size, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+		memset(csf_cmdbuf_bo.map, 0, csf_cmdbuf_bo.size);
+
+		/* GPU ISA command stream */
+		gpu_cmdbuf_gpuva = 0x2000000;
+		igt_panthor_bo_create_mapped(fd, &gpu_cmdbuf_bo, 4096, 0, 0);
+		igt_panthor_vm_bind(fd, vm_id, gpu_cmdbuf_bo.handle, gpu_cmdbuf_gpuva,
+				    gpu_cmdbuf_bo.size, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+		memset(gpu_cmdbuf_bo.map, 0, gpu_cmdbuf_bo.size);
+
+		/* resource tables passed to RUN_COMPUTE */
+		resource_table_gpuva = 0x3000000;
+		igt_panthor_bo_create_mapped(fd, &resource_table_bo, 4096, 0, 0);
+		igt_panthor_vm_bind(fd, vm_id, resource_table_bo.handle, resource_table_gpuva,
+				    resource_table_bo.size, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+		memset(resource_table_bo.map, 0, resource_table_bo.size);
+		/* ShaderResourceTable descriptor (zeroed) */
+		srt_offset = 0;
+		/* FastAccessUniform descriptor (zeroed) */
+		fau_offset = 128;
+		/* ShaderProgramDescriptor */
+		spd_offset = 256;
+		spd_gpuva = resource_table_gpuva + spd_offset;
+		if (arch == 14)
+			spd_gpuva |= 2; /* register allocation propagated into ptr */
+		spd_ptr = (uint32_t *) ((unsigned char *) resource_table_bo.map + spd_offset);
+		spd_ptr[0] = 0x8 | (0x1 << 4); /* compute shader */
+		spd_ptr[0] |= (0 << 16) | (0 << 17) | (0 << 19); /* no NaN suppress, FTZ, inf suppress */
+		spd_ptr[0] |= (0 << 29) | (2 << 30); /* no JUMP_EX, max 32 registers */
+		spd_ptr[1] |= (1 << 12); /* preload GlobalInvocationID.x into r60 */
+		spd_ptr[2] = gpu_cmdbuf_gpuva; /* initial PC */
+		/* ThreadStorageDescriptor */
+		tsd_offset = 512;
+		tsd_ptr = (uint32_t *) ((unsigned char *) resource_table_bo.map + tsd_offset);
+		tsd_ptr[1] = 0x1f; /* max wls_instances */
+
+		/* CPU<->GPU shared data */
+		data_gpuva = 0x4000000;
+		igt_panthor_bo_create_mapped(fd, &data_bo, 16384, 0, 0);
+		igt_panthor_vm_bind(fd, vm_id, data_bo.handle, data_gpuva,
+				    data_bo.size, DRM_PANTHOR_VM_BIND_OP_TYPE_MAP, 0);
+		for (unsigned int i = 0; i < 64 * 64; i++) {
+			uint32_t *x = data_bo.map + (i * sizeof(uint32_t));
+			*x = i;
+		}
+
+		record_compute_prog(csf_cmdbuf_bo.map, &csf_cmdbuf_size,
+				    gpu_cmdbuf_bo.map, &gpu_cmdbuf_size,
+				    resource_table_gpuva + srt_offset,
+				    resource_table_gpuva + fau_offset,
+				    spd_gpuva,
+				    resource_table_gpuva + tsd_offset,
+				    data_gpuva);
+
+		group_handle = igt_panthor_group_create_simple(fd, vm_id, 0);
+		igt_assert_neq(group_handle, 0);
+
+		syncobj_handle = syncobj_create(fd, 0);
+
+		igt_panthor_group_submit_simple(fd, group_handle, 0,
+						csf_cmdbuf_gpuva, csf_cmdbuf_size,
+						syncobj_handle, 0);
+		igt_assert(syncobj_wait(fd, &syncobj_handle, 1, INT64_MAX, 0, NULL));
+
+		for (unsigned int i = 0; i < 64 * 64; i++) {
+			uint32_t *x = data_bo.map + (i * sizeof(uint32_t));
+			igt_assert_eq(*x, i * i);
+		}
+
+		syncobj_destroy(fd, syncobj_handle);
+
+		igt_panthor_group_destroy(fd, group_handle, 0);
+
+		igt_panthor_vm_destroy(fd, vm_id, 0);
+
+		igt_panthor_free_bo(fd, &data_bo);
+		igt_panthor_free_bo(fd, &resource_table_bo);
+		igt_panthor_free_bo(fd, &gpu_cmdbuf_bo);
+		igt_panthor_free_bo(fd, &csf_cmdbuf_bo);
+	}
+
 	igt_fixture() {
 		drm_close_driver(fd);
 	}
-- 
2.47.3


  parent reply	other threads:[~2026-10-15 13:13 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 13:05 [PATCH 0/4] Add Panthor compute-shader test Daniel Stone
2026-10-15 13:05 ` [PATCH 1/4] panthor: Use all available GPU cores Daniel Stone
2026-10-15 15:50   ` Kamil Konieczny
2026-10-21 15:51   ` Liviu Dudau
2026-10-15 13:05 ` [PATCH 2/4] panthor: Add igt_panthor_get_arch() helper Daniel Stone
2026-10-15 15:52   ` Kamil Konieczny
2026-10-21 15:51   ` Liviu Dudau
2026-10-15 13:05 ` [PATCH 3/4] panthor: Add more CSF instructions Daniel Stone
2026-10-15 15:55   ` Kamil Konieczny
2026-10-21 15:53   ` Liviu Dudau
2026-10-15 13:05 ` Daniel Stone [this message]
2026-10-15 16:06   ` [PATCH 4/4] panthor: Add simple compute-shader test Kamil Konieczny
2026-10-21 15:58   ` Liviu Dudau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261015130837.710795-5-daniels@collabora.com \
    --to=daniels@collabora.com \
    --cc=adrian.larumbe@collabora.com \
    --cc=boris.brezillon@collabora.com \
    --cc=daniel.almeida@collabora.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=laura.nao@collabora.com \
    --cc=liviu.dudau@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.