[i-g-t,3/4] tests/gem_media_vme: Simple test to exercise the VME block

Submitted by Tvrtko Ursulin on Jan. 8, 2019, 11:24 a.m.

Details

Message ID 20190108112450.29108-4-tvrtko.ursulin@linux.intel.com
State New
Series "Per context dynamic (sub)slice power-gating"
Headers show

Commit Message

Tvrtko Ursulin Jan. 8, 2019, 11:24 a.m.
From: Tony Ye <tony.ye@intel.com>

Simple test which exercises the VME fixed function block.

v2: (Tvrtko Ursulin)
 * Small cleanups like copyright date, tabs, remove unused bits.

v3: (Tony Ye)
 * Added curbe data entry for dst surface.
 * Read the dst surface after the VME kernel being executed.

v4: (Tony Ye)
 * Added the media_vme.gxa kernel source code and compile instructions.

v5: (Tvrtko Ursulin)
 * Added hang detector.

Signed-off-by: Tony Ye <tony.ye@intel.com>
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Tony Ye <tony.ye@intel.com>
---
 lib/gpu_cmds.c                              | 136 ++++++++++++++++++++
 lib/gpu_cmds.h                              |  20 ++-
 lib/i915/shaders/media/README_media_vme.txt |  65 ++++++++++
 lib/i915/shaders/media/media_vme.gxa        |  51 ++++++++
 lib/intel_batchbuffer.c                     |   9 ++
 lib/intel_batchbuffer.h                     |   7 +
 lib/media_fill.c                            | 110 ++++++++++++++++
 lib/media_fill.h                            |   6 +
 lib/surfaceformat.h                         |   2 +
 tests/Makefile.sources                      |   3 +
 tests/i915/gem_media_vme.c                  | 118 +++++++++++++++++
 tests/meson.build                           |   1 +
 12 files changed, 526 insertions(+), 2 deletions(-)
 create mode 100755 lib/i915/shaders/media/README_media_vme.txt
 create mode 100755 lib/i915/shaders/media/media_vme.gxa
 create mode 100644 tests/i915/gem_media_vme.c

Patch hide | download patch | download mbox

diff --git a/lib/gpu_cmds.c b/lib/gpu_cmds.c
index 556a94c6f0b6..b490a63bdfef 100644
--- a/lib/gpu_cmds.c
+++ b/lib/gpu_cmds.c
@@ -52,6 +52,22 @@  gen7_fill_curbe_buffer_data(struct intel_batchbuffer *batch,
 	return offset;
 }
 
+uint32_t
+gen11_fill_curbe_buffer_data(struct intel_batchbuffer *batch)
+{
+	uint32_t *curbe_buffer;
+	uint32_t offset;
+
+	curbe_buffer = intel_batchbuffer_subdata_alloc(batch,
+						       sizeof(uint32_t) * 8,
+						       64);
+	offset = intel_batchbuffer_subdata_offset(batch, curbe_buffer);
+	*curbe_buffer++ = 0;
+	*curbe_buffer   = 1;
+
+	return offset;
+}
+
 uint32_t
 gen7_fill_surface_state(struct intel_batchbuffer *batch,
 			const struct igt_buf *buf,
@@ -119,6 +135,26 @@  gen7_fill_binding_table(struct intel_batchbuffer *batch,
 	return offset;
 }
 
+uint32_t
+gen11_fill_binding_table(struct intel_batchbuffer *batch,
+			const struct igt_buf *src,const struct igt_buf *dst)
+{
+	uint32_t *binding_table, offset;
+
+	binding_table = intel_batchbuffer_subdata_alloc(batch, 64, 64);
+	offset = intel_batchbuffer_subdata_offset(batch, binding_table);
+	binding_table[0] = gen11_fill_surface_state(batch, src,
+						SURFACE_1D,SURFACEFORMAT_R32G32B32A32_FLOAT,
+						0,0,
+						0);
+	binding_table[1] = gen11_fill_surface_state(batch, dst,
+						SURFACE_BUFFER, SURFACEFORMAT_RAW,
+						1,1,
+						1);
+
+	return offset;
+}
+
 uint32_t
 gen7_fill_kernel(struct intel_batchbuffer *batch,
 		const uint32_t kernel[][4],
@@ -384,6 +420,71 @@  gen8_fill_surface_state(struct intel_batchbuffer *batch,
 	return offset;
 }
 
+uint32_t
+gen11_fill_surface_state(struct intel_batchbuffer *batch,
+			const struct igt_buf *buf,
+			uint32_t surface_type,
+			uint32_t format,
+			uint32_t vertical_alignment,
+			uint32_t horizontal_alignment,
+			int is_dst)
+{
+	struct gen8_surface_state *ss;
+	uint32_t write_domain, read_domain, offset;
+	int ret;
+
+	if (is_dst) {
+		write_domain = read_domain = I915_GEM_DOMAIN_RENDER;
+	} else {
+		write_domain = 0;
+		read_domain = I915_GEM_DOMAIN_SAMPLER;
+	}
+
+	ss = intel_batchbuffer_subdata_alloc(batch, sizeof(*ss), 64);
+	offset = intel_batchbuffer_subdata_offset(batch, ss);
+
+	ss->ss0.surface_type = surface_type;
+	ss->ss0.surface_format = format;
+	ss->ss0.render_cache_read_write = 1;
+	ss->ss0.vertical_alignment = vertical_alignment; /* align 4 */
+	ss->ss0.horizontal_alignment = horizontal_alignment; /* align 4 */
+
+	if (buf->tiling == I915_TILING_X)
+		ss->ss0.tiled_mode = 2;
+	else if (buf->tiling == I915_TILING_Y)
+		ss->ss0.tiled_mode = 3;
+	else
+		ss->ss0.tiled_mode = 0;
+
+	ss->ss8.base_addr = buf->bo->offset;
+
+	ret = drm_intel_bo_emit_reloc(batch->bo,
+				intel_batchbuffer_subdata_offset(batch, ss) + 8 * 4,
+				buf->bo, 0, read_domain, write_domain);
+	igt_assert(ret == 0);
+
+	if (is_dst) {
+		ss->ss1.memory_object_control = 2;
+		ss->ss2.height = 1;
+		ss->ss2.width  = 95;
+		ss->ss3.pitch  = 0;
+		ss->ss7.shader_chanel_select_r = 4;
+		ss->ss7.shader_chanel_select_g = 5;
+		ss->ss7.shader_chanel_select_b = 6;
+		ss->ss7.shader_chanel_select_a = 7;
+	}
+	else {
+		ss->ss1.qpitch = 4040;
+		ss->ss1.base_mip_level = 31;
+		ss->ss2.height = 9216;
+		ss->ss2.width  = 1019;
+		ss->ss3.pitch  = 64;
+		ss->ss5.mip_count = 2;
+	}
+
+	return offset;
+}
+
 uint32_t
 gen8_fill_interface_descriptor(struct intel_batchbuffer *batch,
 			       const struct igt_buf *dst,
@@ -419,6 +520,41 @@  gen8_fill_interface_descriptor(struct intel_batchbuffer *batch,
 	return offset;
 }
 
+uint32_t
+gen11_fill_interface_descriptor(struct intel_batchbuffer *batch,
+			       const struct igt_buf *src,const struct igt_buf *dst,
+			       const uint32_t kernel[][4],
+			       size_t size)
+{
+	struct gen8_interface_descriptor_data *idd;
+	uint32_t offset;
+	uint32_t binding_table_offset, kernel_offset;
+
+	binding_table_offset = gen11_fill_binding_table(batch, src,dst);
+	kernel_offset = gen7_fill_kernel(batch, kernel, size);
+
+	idd = intel_batchbuffer_subdata_alloc(batch, sizeof(*idd), 64);
+	offset = intel_batchbuffer_subdata_offset(batch, idd);
+
+	idd->desc0.kernel_start_pointer = (kernel_offset >> 6);
+
+	idd->desc2.single_program_flow = 1;
+	idd->desc2.floating_point_mode = GEN8_FLOATING_POINT_IEEE_754;
+
+	idd->desc3.sampler_count = 0;      /* 0 samplers used */
+	idd->desc3.sampler_state_pointer = 0;
+
+	idd->desc4.binding_table_entry_count = 0;
+	idd->desc4.binding_table_pointer = (binding_table_offset >> 5);
+
+	idd->desc5.constant_urb_entry_read_offset = 0;
+	idd->desc5.constant_urb_entry_read_length = 1; /* grf 1 */
+
+	idd->desc6.num_threads_in_tg = 1;
+
+	return offset;
+}
+
 void
 gen8_emit_state_base_address(struct intel_batchbuffer *batch)
 {
diff --git a/lib/gpu_cmds.h b/lib/gpu_cmds.h
index 79bc4d6473ba..ca671fb52daf 100644
--- a/lib/gpu_cmds.h
+++ b/lib/gpu_cmds.h
@@ -43,6 +43,8 @@  gen7_render_flush(struct intel_batchbuffer *batch, uint32_t batch_end);
 uint32_t
 gen7_fill_curbe_buffer_data(struct intel_batchbuffer *batch,
 			uint8_t color);
+uint32_t
+gen11_fill_curbe_buffer_data(struct intel_batchbuffer *batch);
 
 uint32_t
 gen7_fill_surface_state(struct intel_batchbuffer *batch,
@@ -53,6 +55,9 @@  gen7_fill_surface_state(struct intel_batchbuffer *batch,
 uint32_t
 gen7_fill_binding_table(struct intel_batchbuffer *batch,
 			const struct igt_buf *dst);
+uint32_t
+gen11_fill_binding_table(struct intel_batchbuffer *batch,
+			const struct igt_buf *src,const struct igt_buf *dst);
 
 uint32_t
 gen7_fill_kernel(struct intel_batchbuffer *batch,
@@ -99,13 +104,24 @@  gen8_fill_surface_state(struct intel_batchbuffer *batch,
 			const struct igt_buf *buf,
 			uint32_t format,
 			int is_dst);
-
+uint32_t
+gen11_fill_surface_state(struct intel_batchbuffer *batch,
+			const struct igt_buf *buf,
+			uint32_t surface_type,
+			uint32_t format,
+			uint32_t vertical_alignment,
+			uint32_t horizontal_alignment,
+			int is_dst);
 uint32_t
 gen8_fill_interface_descriptor(struct intel_batchbuffer *batch,
 			       const struct igt_buf *dst,
 			       const uint32_t kernel[][4],
 			       size_t size);
-
+uint32_t
+gen11_fill_interface_descriptor(struct intel_batchbuffer *batch,
+			       const struct igt_buf *src,const struct igt_buf *dst,
+			       const uint32_t kernel[][4],
+			       size_t size);
 void
 gen8_emit_state_base_address(struct intel_batchbuffer *batch);
 
diff --git a/lib/i915/shaders/media/README_media_vme.txt b/lib/i915/shaders/media/README_media_vme.txt
new file mode 100755
index 000000000000..2470fdd89825
--- /dev/null
+++ b/lib/i915/shaders/media/README_media_vme.txt
@@ -0,0 +1,65 @@ 
+Step1: Building IGA (Intel Graphics Assembler)
+========================================================================
+
+1. Download or clone IGC (Intel Graphics Compiler)
+
+   https://github.com/intel/intel-graphics-compiler.git
+
+2. Chdir into 'intel-graphics-compiler' (or any other workspace folder of choice)
+
+   It should read the following folder strucutre:
+
+   workspace
+      |- visa
+      |- IGC
+      |- inc
+      |- 3d
+      |- skuwa
+
+3. Chdir into IGA sub-component
+
+   cd visa/iga
+
+4. Create build directory
+
+    mkdir build
+
+5. Change into build directory
+
+    cd build
+
+6. Run cmake
+
+   cmake ../
+
+7. Run make to build IGA project
+
+   make
+
+8. Get the output executable "iga64" in IGAExe folder
+
+   usage: ./iga64 OPTIONS ARGS
+   where OPTIONS:
+     -h     --help                     shows help on an option
+     -d     --disassemble              disassembles the input file
+     -a     --assemble                 assembles the input file
+     -n     --numeric-labels           use numeric labels
+     -p     --platform        DEVICE   specifies the platform (e.g. "GEN9")
+     -o     --output          FILE     specifies the output file
+
+   EXAMPLES:
+   ./iga64  file.gxa  -p=11 -a  -o file.krn
+
+Step2: Building ASM code
+========================================================================
+1. Command line to convert asm code to binary:
+
+   iga64 media_vme.gxa -p=11 -a -o media_vme.krn
+
+2. Pad 128 bytes zeros to the kernel:
+
+   dd if=/dev/zero bs=1 count=128 >> media_vme.krn
+
+3. Generate hexdump:
+
+   hexdump -v  -e '4/4 "0x%08x " "\n"' media_vme.krn > media_vme.hex
diff --git a/lib/i915/shaders/media/media_vme.gxa b/lib/i915/shaders/media/media_vme.gxa
new file mode 100755
index 000000000000..93a0ed2f12d6
--- /dev/null
+++ b/lib/i915/shaders/media/media_vme.gxa
@@ -0,0 +1,51 @@ 
+/*
+* Copyright (c) 2018, Intel Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+       mov (8|M0)       r1.8<1>:w       0x20000000:v
+       mov (8|M0)       r20.0<1>:w      0x1:v
+(W)    mov (1|M0)       r1.2<1>:f       0x3818000C:f
+       mov (8|M0)       r20.8<1>:w      0x10:v
+       mov (8|M0)       r21.0<1>:w      0x10000:v
+(W)    mov (1|M0)       r1.3<1>:f       0x22222222:f
+       add (1|M0)       a0.0<1>:d       r1.0<0;1,0>:d     276307968:d
+       mov (8|M0)       r2.0<1>:f       0x0:f
+       mov (8|M0)       r5.0<1>:f       0x0:f
+       mov (8|M0)       r6.0<1>:f       0x0:f
+       mov (8|M0)       r9.0<1>:f       0x0:f
+       mov (8|M0)       r3.0<1>:d       r1.8<8;8,1>:w
+       mul (8|M0)       r4.0<1>:d       r1.2<0;1,0>:d     r20.0<8;8,1>:w
+       mul (8|M0)       r7.0<1>:d       r20.8<8;8,1>:w    256:w
+       mul (8|M0)       r8.0<1>:d       r1.3<0;1,0>:d     r21.0<8;8,1>:w
+(W)    mov (1|M0)       r17.2<1>:f      0x0:f
+       send (16|M0)     r10:uw          r2:f              0xD     a0.0{NoPreempt}
+       mov (1|M0)       r10.14<1>:hf    0xBEEF:hf
+(W)    add (1|M0)       a0.0<1>:ud      r1.1<0;1,0>:ud    0x20A0400:ud
+       mov (1|M0)       r10.15<1>:hf    0xDEAD:hf
+(W)    mov (1|M0)       r18.2<1>:f      0x8:f
+(W)    mov (1|M0)       r19.2<1>:f      0xC:f
+(W)    mov (8|M0)       r127.0<1>:f     r0.0<8;8,1>:f
+(W)    sends (16|M0)    null:uw         r17               r10     0x10A    a0.0
+(W)    add (1|M0)       a0.0<1>:ud      r1.1<0;1,0>:ud    0x20A0300:ud
+(W)    sends (16|M0)    null:uw         r18               r14     0x8A     a0.0
+(W)    add (1|M0)       a0.0<1>:ud      r1.1<0;1,0>:ud    0x20A0200:ud
+(W)    sends (8|M0)     null:ud         r19               r16     0x4A     a0.0
+(W)    send (8|M0)      null            r127:f            0x27    0x2000010 {EOT}
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index ad2e718f898c..22697c94fb13 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -873,6 +873,15 @@  igt_fillfunc_t igt_get_media_fillfunc(int devid)
 	return fill;
 }
 
+igt_vme_func_t igt_get_media_vme_func(int devid)
+{
+	igt_vme_func_t fill = NULL;
+
+	if (IS_GEN9(devid) || IS_GEN10(devid) || IS_GEN11(devid))
+		fill = gen11_media_vme_func;
+
+	return fill;
+}
 /**
  * igt_get_gpgpu_fillfunc:
  * @devid: pci device id
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index ecc23f08da77..e5f6e6d045b8 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -325,6 +325,13 @@  typedef void (*igt_fillfunc_t)(struct intel_batchbuffer *batch,
 igt_fillfunc_t igt_get_media_fillfunc(int devid);
 igt_fillfunc_t igt_get_gpgpu_fillfunc(int devid);
 
+typedef void (*igt_vme_func_t)(struct intel_batchbuffer *batch,
+			       const struct igt_buf *src,
+			       unsigned int width, unsigned int height,
+			       const struct igt_buf *dst);
+
+igt_vme_func_t igt_get_media_vme_func(int devid);
+
 /**
  * igt_media_spinfunc_t:
  * @batch: batchbuffer object
diff --git a/lib/media_fill.c b/lib/media_fill.c
index 4942229505ff..b1e84727394a 100644
--- a/lib/media_fill.c
+++ b/lib/media_fill.c
@@ -61,6 +61,46 @@  static const uint32_t gen8_media_kernel[][4] = {
 	{ 0x07800031, 0x20000a40, 0x0e000e00, 0x82000010 },
 };
 
+static const uint32_t gen11_media_vme_kernel[][4] = {
+	{ 0x00600001, 0x20302e68,  0x00000000,  0x20000000 },
+	{ 0x00600001, 0x22802e68,  0x00000000,  0x00000001 },
+	{ 0x00000001, 0x20284f2c,  0x00000000,  0x3818000c },
+	{ 0x00600001, 0x22902e68,  0x00000000,  0x00000010 },
+	{ 0x00600001, 0x22a02e68,  0x00000000,  0x00010000 },
+	{ 0x00000001, 0x202c4f2c,  0x00000000,  0x22222222 },
+	{ 0x00000040, 0x22000a20,  0x0e000020,  0x10782000 },
+	{ 0x00600001, 0x20404f28,  0x00000000,  0x00000000 },
+	{ 0x00600001, 0x20a04f28,  0x00000000,  0x00000000 },
+	{ 0x00600001, 0x20c04f28,  0x00000000,  0x00000000 },
+	{ 0x00600001, 0x21204f28,  0x00000000,  0x00000000 },
+	{ 0x00600001, 0x20601a28,  0x008d0030,  0x00000000 },
+	{ 0x00600041, 0x20800a28,  0x1a000028,  0x008d0280 },
+	{ 0x00600041, 0x20e01a28,  0x1e8d0290,  0x01000100 },
+	{ 0x00600041, 0x21000a28,  0x1a00002c,  0x008d02a0 },
+	{ 0x00000001, 0x22284f2c,  0x00000000,  0x00000000 },
+	{ 0x0d80c031, 0x21404a48,  0x00000040,  0x00000200 },
+	{ 0x00000001, 0x215c4708,  0x00000000,  0xbeefbeef },
+	{ 0x00000040, 0x22000204,  0x06000024,  0x020a0400 },
+	{ 0x00000001, 0x215e4708,  0x00000000,  0xdeaddead },
+	{ 0x00000001, 0x22484f2c,  0x00000000,  0x00000008 },
+	{ 0x00000001, 0x22684f2c,  0x00000000,  0x0000000c },
+	{ 0x00600001, 0x2fe04b2c,  0x008d0000,  0x00000000 },
+	{ 0x0a800033, 0x0000a054,  0x00002224,  0x00000000 },
+	{ 0x00000040, 0x22000204,  0x06000024,  0x020a0300 },
+	{ 0x0a800033, 0x0000e054,  0x00002242,  0x00000000 },
+	{ 0x00000040, 0x22000204,  0x06000024,  0x020a0200 },
+	{ 0x0a600033, 0x00010014,  0x00002261,  0x00000000 },
+	{ 0x07600031, 0x20004a04,  0x06000fe0,  0x82000010 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+	{ 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
+};
+
 /*
  * This sets up the media pipeline,
  *
@@ -245,3 +285,73 @@  gen9_media_fillfunc(struct intel_batchbuffer *batch,
 			      gen8_media_kernel, sizeof(gen8_media_kernel));
 
 }
+
+static void
+__gen11_media_vme_func(struct intel_batchbuffer *batch,
+		       const struct igt_buf *src,
+		       unsigned int width, unsigned int height,
+		       const struct igt_buf *dst,
+		       const uint32_t kernel[][4],
+		       size_t kernel_size)
+{
+	uint32_t curbe_buffer, interface_descriptor;
+	uint32_t batch_end;
+
+	intel_batchbuffer_flush(batch);
+
+	/* setup states */
+	batch->ptr = &batch->buffer[BATCH_STATE_SPLIT];
+
+	curbe_buffer = gen11_fill_curbe_buffer_data(batch);
+	interface_descriptor = gen11_fill_interface_descriptor(batch, src, dst,
+					kernel, kernel_size);
+	assert(batch->ptr < &batch->buffer[4095]);
+
+	/* media pipeline */
+	batch->ptr = batch->buffer;
+	OUT_BATCH(GEN8_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA |
+		  GEN9_FORCE_MEDIA_AWAKE_ENABLE |
+		  GEN9_SAMPLER_DOP_GATE_DISABLE |
+		  GEN9_PIPELINE_SELECTION_MASK |
+		  GEN9_SAMPLER_DOP_GATE_MASK |
+		  GEN9_FORCE_MEDIA_AWAKE_MASK);
+	gen9_emit_state_base_address(batch);
+
+	gen8_emit_vfe_state(batch, THREADS, MEDIA_URB_ENTRIES, MEDIA_URB_SIZE,
+			    MEDIA_CURBE_SIZE);
+
+	gen7_emit_curbe_load(batch, curbe_buffer);
+
+	gen7_emit_interface_descriptor_load(batch, interface_descriptor);
+
+	gen7_emit_media_objects(batch, 0, 0, width, height);
+
+	OUT_BATCH(GEN8_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA |
+		  GEN9_FORCE_MEDIA_AWAKE_DISABLE |
+		  GEN9_SAMPLER_DOP_GATE_ENABLE |
+		  GEN9_PIPELINE_SELECTION_MASK |
+		  GEN9_SAMPLER_DOP_GATE_MASK |
+		  GEN9_FORCE_MEDIA_AWAKE_MASK);
+
+	OUT_BATCH(MI_BATCH_BUFFER_END);
+
+	batch_end = intel_batchbuffer_align(batch, 8);
+	assert(batch_end < BATCH_STATE_SPLIT);
+
+	gen7_render_flush(batch, batch_end);
+	intel_batchbuffer_reset(batch);
+}
+
+void
+gen11_media_vme_func(struct intel_batchbuffer *batch,
+		     const struct igt_buf *src,
+		     unsigned int width, unsigned int height,
+		     const struct igt_buf *dst)
+{
+	__gen11_media_vme_func(batch,
+			       src,
+			       width, height,
+			       dst,
+			       gen11_media_vme_kernel,
+			       sizeof(gen11_media_vme_kernel));
+}
diff --git a/lib/media_fill.h b/lib/media_fill.h
index e365da9e47d2..1d5c5fa826a3 100644
--- a/lib/media_fill.h
+++ b/lib/media_fill.h
@@ -49,4 +49,10 @@  gen9_media_fillfunc(struct intel_batchbuffer *batch,
 		    unsigned int width, unsigned int height,
 		    uint8_t color);
 
+void
+gen11_media_vme_func(struct intel_batchbuffer *batch,
+		     const struct igt_buf *src,
+		     unsigned int width, unsigned int height,
+		     const struct igt_buf *dst);
+
 #endif /* RENDE_MEDIA_FILL_H */
diff --git a/lib/surfaceformat.h b/lib/surfaceformat.h
index 5d7ed2cadc2d..32ea373262ca 100644
--- a/lib/surfaceformat.h
+++ b/lib/surfaceformat.h
@@ -171,6 +171,8 @@ 
 #define SURFACEFORMAT_R16G16B16_SSCALED	0x19E
 #define SURFACEFORMAT_R16G16B16_USCALED	0x19F
 
+#define SURFACEFORMAT_RAW	0x1FF
+
 #define SURFACERETURNFORMAT_FLOAT32	0
 #define SURFACERETURNFORMAT_S1	1
 
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 3dfeb5b67274..6dabb9dbf247 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -302,6 +302,9 @@  gem_madvise_SOURCES = i915/gem_madvise.c
 TESTS_progs += gem_media_fill
 gem_media_fill_SOURCES = i915/gem_media_fill.c
 
+TESTS_progs += gem_media_vme
+gem_media_vme_SOURCES = i915/gem_media_vme.c
+
 TESTS_progs += gem_mmap
 gem_mmap_SOURCES = i915/gem_mmap.c
 
diff --git a/tests/i915/gem_media_vme.c b/tests/i915/gem_media_vme.c
new file mode 100644
index 000000000000..47e949c781f2
--- /dev/null
+++ b/tests/i915/gem_media_vme.c
@@ -0,0 +1,118 @@ 
+/*
+ * Copyright © 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "igt.h"
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "intel_bufmgr.h"
+
+IGT_TEST_DESCRIPTION("A very simple workload for the VME media block.");
+
+#define WIDTH	64
+#define STRIDE	(WIDTH)
+#define HEIGHT	64
+
+#define INPUT_SIZE	(WIDTH * HEIGHT * sizeof(char) * 1.5)
+#define OUTPUT_SIZE	(56*sizeof(int))
+
+static void
+scratch_buf_init(drm_intel_bufmgr *bufmgr,
+		 struct igt_buf *buf,
+		 unsigned int size)
+{
+	drm_intel_bo *bo;
+
+	bo = drm_intel_bo_alloc(bufmgr, "", size, 4096);
+	igt_assert(bo);
+
+	memset(buf, 0, sizeof(*buf));
+
+	buf->bo = bo;
+	buf->tiling = I915_TILING_NONE;
+	buf->size = size;
+}
+
+static void scratch_buf_init_src(drm_intel_bufmgr *bufmgr, struct igt_buf *buf)
+{
+	scratch_buf_init(bufmgr, buf, INPUT_SIZE);
+
+	/*
+	 * Ideally we would read src surface from file "SourceFrameI.yu12".
+	 * But even without it, we can still triger the rcs0 resetting
+	 * with this vme kernel.
+	 */
+
+	buf->stride = STRIDE;
+}
+
+static void scratch_buf_init_dst(drm_intel_bufmgr *bufmgr, struct igt_buf *buf)
+{
+	scratch_buf_init(bufmgr, buf, OUTPUT_SIZE);
+
+	buf->stride = 1;
+}
+
+igt_simple_main
+{
+	int drm_fd;
+	uint32_t devid;
+	drm_intel_bufmgr *bufmgr;
+	igt_vme_func_t media_vme;
+	struct intel_batchbuffer *batch;
+	struct igt_buf src, dst;
+	uint8_t dst_linear[OUTPUT_SIZE];
+
+	drm_fd = drm_open_driver(DRIVER_INTEL);
+	igt_require_gem(drm_fd);
+
+	devid = intel_get_drm_devid(drm_fd);
+
+	media_vme = igt_get_media_vme_func(devid);
+	igt_require_f(media_vme, "no media-vme function\n");
+
+	bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
+	igt_assert(bufmgr);
+
+	batch = intel_batchbuffer_alloc(bufmgr, devid);
+	igt_assert(batch);
+
+	scratch_buf_init_src(bufmgr, &src);
+	scratch_buf_init_dst(bufmgr, &dst);
+
+	igt_fork_hang_detector(drm_fd);
+
+	media_vme(batch, &src, WIDTH, HEIGHT, &dst);
+	gem_read(drm_fd, dst.bo->handle, 0,
+			dst_linear, sizeof(dst_linear));
+
+	igt_stop_hang_detector();
+}
diff --git a/tests/meson.build b/tests/meson.build
index f41f724af8af..e3a4a84ea7cc 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -166,6 +166,7 @@  gem_progs = [
 	'gem_lut_handle',
 	'gem_madvise',
 	'gem_media_fill',
+	'gem_media_vme',
 	'gem_mmap',
 	'gem_mmap_gtt',
 	'gem_mmap_offset_exhaustion',

Comments

Chris Wilson Jan. 8, 2019, 2:23 p.m.
Quoting Tvrtko Ursulin (2019-01-08 11:24:49)
> From: Tony Ye <tony.ye@intel.com>
> 
> Simple test which exercises the VME fixed function block.
> 
> v2: (Tvrtko Ursulin)
>  * Small cleanups like copyright date, tabs, remove unused bits.
> 
> v3: (Tony Ye)
>  * Added curbe data entry for dst surface.
>  * Read the dst surface after the VME kernel being executed.
> 
> v4: (Tony Ye)
>  * Added the media_vme.gxa kernel source code and compile instructions.
> 
> v5: (Tvrtko Ursulin)
>  * Added hang detector.
> 
> Signed-off-by: Tony Ye <tony.ye@intel.com>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Tony Ye <tony.ye@intel.com>
> ---
>  lib/gpu_cmds.c                              | 136 ++++++++++++++++++++
>  lib/gpu_cmds.h                              |  20 ++-
>  lib/i915/shaders/media/README_media_vme.txt |  65 ++++++++++
>  lib/i915/shaders/media/media_vme.gxa        |  51 ++++++++
>  lib/intel_batchbuffer.c                     |   9 ++
>  lib/intel_batchbuffer.h                     |   7 +
>  lib/media_fill.c                            | 110 ++++++++++++++++
>  lib/media_fill.h                            |   6 +
>  lib/surfaceformat.h                         |   2 +
>  tests/Makefile.sources                      |   3 +
>  tests/i915/gem_media_vme.c                  | 118 +++++++++++++++++
>  tests/meson.build                           |   1 +
>  12 files changed, 526 insertions(+), 2 deletions(-)
>  create mode 100755 lib/i915/shaders/media/README_media_vme.txt
>  create mode 100755 lib/i915/shaders/media/media_vme.gxa
>  create mode 100644 tests/i915/gem_media_vme.c
> 
> diff --git a/lib/gpu_cmds.c b/lib/gpu_cmds.c
> index 556a94c6f0b6..b490a63bdfef 100644
> --- a/lib/gpu_cmds.c
> +++ b/lib/gpu_cmds.c
> @@ -52,6 +52,22 @@ gen7_fill_curbe_buffer_data(struct intel_batchbuffer *batch,
>         return offset;
>  }
>  
> +uint32_t
> +gen11_fill_curbe_buffer_data(struct intel_batchbuffer *batch)
> +{
> +       uint32_t *curbe_buffer;
> +       uint32_t offset;
> +
> +       curbe_buffer = intel_batchbuffer_subdata_alloc(batch,
> +                                                      sizeof(uint32_t) * 8,
> +                                                      64);
> +       offset = intel_batchbuffer_subdata_offset(batch, curbe_buffer);
> +       *curbe_buffer++ = 0;
> +       *curbe_buffer   = 1;
> +
> +       return offset;
> +}
> +
>  uint32_t
>  gen7_fill_surface_state(struct intel_batchbuffer *batch,
>                         const struct igt_buf *buf,
> @@ -119,6 +135,26 @@ gen7_fill_binding_table(struct intel_batchbuffer *batch,
>         return offset;
>  }
>  
> +uint32_t
> +gen11_fill_binding_table(struct intel_batchbuffer *batch,
> +                       const struct igt_buf *src,const struct igt_buf *dst)
> +{
> +       uint32_t *binding_table, offset;
> +
> +       binding_table = intel_batchbuffer_subdata_alloc(batch, 64, 64);
> +       offset = intel_batchbuffer_subdata_offset(batch, binding_table);
> +       binding_table[0] = gen11_fill_surface_state(batch, src,
> +                                               SURFACE_1D,SURFACEFORMAT_R32G32B32A32_FLOAT,
> +                                               0,0,
> +                                               0);
> +       binding_table[1] = gen11_fill_surface_state(batch, dst,
> +                                               SURFACE_BUFFER, SURFACEFORMAT_RAW,
> +                                               1,1,
> +                                               1);
> +
> +       return offset;
> +}
> +
>  uint32_t
>  gen7_fill_kernel(struct intel_batchbuffer *batch,
>                 const uint32_t kernel[][4],
> @@ -384,6 +420,71 @@ gen8_fill_surface_state(struct intel_batchbuffer *batch,
>         return offset;
>  }
>  
> +uint32_t
> +gen11_fill_surface_state(struct intel_batchbuffer *batch,
> +                       const struct igt_buf *buf,
> +                       uint32_t surface_type,
> +                       uint32_t format,
> +                       uint32_t vertical_alignment,
> +                       uint32_t horizontal_alignment,
> +                       int is_dst)
> +{
> +       struct gen8_surface_state *ss;
> +       uint32_t write_domain, read_domain, offset;
> +       int ret;
> +
> +       if (is_dst) {
> +               write_domain = read_domain = I915_GEM_DOMAIN_RENDER;
> +       } else {
> +               write_domain = 0;
> +               read_domain = I915_GEM_DOMAIN_SAMPLER;
> +       }
> +
> +       ss = intel_batchbuffer_subdata_alloc(batch, sizeof(*ss), 64);
> +       offset = intel_batchbuffer_subdata_offset(batch, ss);
> +
> +       ss->ss0.surface_type = surface_type;
> +       ss->ss0.surface_format = format;
> +       ss->ss0.render_cache_read_write = 1;
> +       ss->ss0.vertical_alignment = vertical_alignment; /* align 4 */
> +       ss->ss0.horizontal_alignment = horizontal_alignment; /* align 4 */
> +
> +       if (buf->tiling == I915_TILING_X)
> +               ss->ss0.tiled_mode = 2;
> +       else if (buf->tiling == I915_TILING_Y)
> +               ss->ss0.tiled_mode = 3;
> +       else
> +               ss->ss0.tiled_mode = 0;
> +
> +       ss->ss8.base_addr = buf->bo->offset;
> +
> +       ret = drm_intel_bo_emit_reloc(batch->bo,
> +                               intel_batchbuffer_subdata_offset(batch, ss) + 8 * 4,
> +                               buf->bo, 0, read_domain, write_domain);
> +       igt_assert(ret == 0);
> +
> +       if (is_dst) {
> +               ss->ss1.memory_object_control = 2;
> +               ss->ss2.height = 1;
> +               ss->ss2.width  = 95;
> +               ss->ss3.pitch  = 0;
> +               ss->ss7.shader_chanel_select_r = 4;
> +               ss->ss7.shader_chanel_select_g = 5;
> +               ss->ss7.shader_chanel_select_b = 6;
> +               ss->ss7.shader_chanel_select_a = 7;
> +       }
> +       else {
> +               ss->ss1.qpitch = 4040;
> +               ss->ss1.base_mip_level = 31;
> +               ss->ss2.height = 9216;
> +               ss->ss2.width  = 1019;
> +               ss->ss3.pitch  = 64;
> +               ss->ss5.mip_count = 2;
> +       }
> +
> +       return offset;
> +}
> +
>  uint32_t
>  gen8_fill_interface_descriptor(struct intel_batchbuffer *batch,
>                                const struct igt_buf *dst,
> @@ -419,6 +520,41 @@ gen8_fill_interface_descriptor(struct intel_batchbuffer *batch,
>         return offset;
>  }
>  
> +uint32_t
> +gen11_fill_interface_descriptor(struct intel_batchbuffer *batch,
> +                              const struct igt_buf *src,const struct igt_buf *dst,
> +                              const uint32_t kernel[][4],
> +                              size_t size)
> +{
> +       struct gen8_interface_descriptor_data *idd;
> +       uint32_t offset;
> +       uint32_t binding_table_offset, kernel_offset;
> +
> +       binding_table_offset = gen11_fill_binding_table(batch, src,dst);
> +       kernel_offset = gen7_fill_kernel(batch, kernel, size);
> +
> +       idd = intel_batchbuffer_subdata_alloc(batch, sizeof(*idd), 64);
> +       offset = intel_batchbuffer_subdata_offset(batch, idd);
> +
> +       idd->desc0.kernel_start_pointer = (kernel_offset >> 6);
> +
> +       idd->desc2.single_program_flow = 1;
> +       idd->desc2.floating_point_mode = GEN8_FLOATING_POINT_IEEE_754;
> +
> +       idd->desc3.sampler_count = 0;      /* 0 samplers used */
> +       idd->desc3.sampler_state_pointer = 0;
> +
> +       idd->desc4.binding_table_entry_count = 0;
> +       idd->desc4.binding_table_pointer = (binding_table_offset >> 5);
> +
> +       idd->desc5.constant_urb_entry_read_offset = 0;
> +       idd->desc5.constant_urb_entry_read_length = 1; /* grf 1 */
> +
> +       idd->desc6.num_threads_in_tg = 1;
> +
> +       return offset;
> +}
> +
>  void
>  gen8_emit_state_base_address(struct intel_batchbuffer *batch)
>  {
> diff --git a/lib/gpu_cmds.h b/lib/gpu_cmds.h
> index 79bc4d6473ba..ca671fb52daf 100644
> --- a/lib/gpu_cmds.h
> +++ b/lib/gpu_cmds.h
> @@ -43,6 +43,8 @@ gen7_render_flush(struct intel_batchbuffer *batch, uint32_t batch_end);
>  uint32_t
>  gen7_fill_curbe_buffer_data(struct intel_batchbuffer *batch,
>                         uint8_t color);
> +uint32_t
> +gen11_fill_curbe_buffer_data(struct intel_batchbuffer *batch);
>  
>  uint32_t
>  gen7_fill_surface_state(struct intel_batchbuffer *batch,
> @@ -53,6 +55,9 @@ gen7_fill_surface_state(struct intel_batchbuffer *batch,
>  uint32_t
>  gen7_fill_binding_table(struct intel_batchbuffer *batch,
>                         const struct igt_buf *dst);
> +uint32_t
> +gen11_fill_binding_table(struct intel_batchbuffer *batch,
> +                       const struct igt_buf *src,const struct igt_buf *dst);
>  
>  uint32_t
>  gen7_fill_kernel(struct intel_batchbuffer *batch,
> @@ -99,13 +104,24 @@ gen8_fill_surface_state(struct intel_batchbuffer *batch,
>                         const struct igt_buf *buf,
>                         uint32_t format,
>                         int is_dst);
> -
> +uint32_t
> +gen11_fill_surface_state(struct intel_batchbuffer *batch,
> +                       const struct igt_buf *buf,
> +                       uint32_t surface_type,
> +                       uint32_t format,
> +                       uint32_t vertical_alignment,
> +                       uint32_t horizontal_alignment,
> +                       int is_dst);
>  uint32_t
>  gen8_fill_interface_descriptor(struct intel_batchbuffer *batch,
>                                const struct igt_buf *dst,
>                                const uint32_t kernel[][4],
>                                size_t size);
> -
> +uint32_t
> +gen11_fill_interface_descriptor(struct intel_batchbuffer *batch,
> +                              const struct igt_buf *src,const struct igt_buf *dst,
> +                              const uint32_t kernel[][4],
> +                              size_t size);
>  void
>  gen8_emit_state_base_address(struct intel_batchbuffer *batch);
>  
> diff --git a/lib/i915/shaders/media/README_media_vme.txt b/lib/i915/shaders/media/README_media_vme.txt
> new file mode 100755
> index 000000000000..2470fdd89825
> --- /dev/null
> +++ b/lib/i915/shaders/media/README_media_vme.txt
> @@ -0,0 +1,65 @@
> +Step1: Building IGA (Intel Graphics Assembler)
> +========================================================================
> +
> +1. Download or clone IGC (Intel Graphics Compiler)
> +
> +   https://github.com/intel/intel-graphics-compiler.git
> +
> +2. Chdir into 'intel-graphics-compiler' (or any other workspace folder of choice)
> +
> +   It should read the following folder strucutre:
> +
> +   workspace
> +      |- visa
> +      |- IGC
> +      |- inc
> +      |- 3d
> +      |- skuwa
> +
> +3. Chdir into IGA sub-component
> +
> +   cd visa/iga
> +
> +4. Create build directory
> +
> +    mkdir build
> +
> +5. Change into build directory
> +
> +    cd build
> +
> +6. Run cmake
> +
> +   cmake ../
> +
> +7. Run make to build IGA project
> +
> +   make
> +
> +8. Get the output executable "iga64" in IGAExe folder
> +
> +   usage: ./iga64 OPTIONS ARGS
> +   where OPTIONS:
> +     -h     --help                     shows help on an option
> +     -d     --disassemble              disassembles the input file
> +     -a     --assemble                 assembles the input file
> +     -n     --numeric-labels           use numeric labels
> +     -p     --platform        DEVICE   specifies the platform (e.g. "GEN9")
> +     -o     --output          FILE     specifies the output file
> +
> +   EXAMPLES:
> +   ./iga64  file.gxa  -p=11 -a  -o file.krn
> +
> +Step2: Building ASM code
> +========================================================================
> +1. Command line to convert asm code to binary:
> +
> +   iga64 media_vme.gxa -p=11 -a -o media_vme.krn
> +
> +2. Pad 128 bytes zeros to the kernel:
> +
> +   dd if=/dev/zero bs=1 count=128 >> media_vme.krn
> +
> +3. Generate hexdump:
> +
> +   hexdump -v  -e '4/4 "0x%08x " "\n"' media_vme.krn > media_vme.hex
> diff --git a/lib/i915/shaders/media/media_vme.gxa b/lib/i915/shaders/media/media_vme.gxa
> new file mode 100755
> index 000000000000..93a0ed2f12d6
> --- /dev/null
> +++ b/lib/i915/shaders/media/media_vme.gxa
> @@ -0,0 +1,51 @@
> +/*
> +* Copyright (c) 2018, Intel Corporation
> +*
> +* Permission is hereby granted, free of charge, to any person obtaining a
> +* copy of this software and associated documentation files (the "Software"),
> +* to deal in the Software without restriction, including without limitation
> +* the rights to use, copy, modify, merge, publish, distribute, sublicense,
> +* and/or sell copies of the Software, and to permit persons to whom the
> +* Software is furnished to do so, subject to the following conditions:
> +*
> +* The above copyright notice and this permission notice shall be included
> +* in all copies or substantial portions of the Software.
> +*
> +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> +* OTHER DEALINGS IN THE SOFTWARE.
> +*/
> +
> +       mov (8|M0)       r1.8<1>:w       0x20000000:v
> +       mov (8|M0)       r20.0<1>:w      0x1:v
> +(W)    mov (1|M0)       r1.2<1>:f       0x3818000C:f
> +       mov (8|M0)       r20.8<1>:w      0x10:v
> +       mov (8|M0)       r21.0<1>:w      0x10000:v
> +(W)    mov (1|M0)       r1.3<1>:f       0x22222222:f
> +       add (1|M0)       a0.0<1>:d       r1.0<0;1,0>:d     276307968:d
> +       mov (8|M0)       r2.0<1>:f       0x0:f
> +       mov (8|M0)       r5.0<1>:f       0x0:f
> +       mov (8|M0)       r6.0<1>:f       0x0:f
> +       mov (8|M0)       r9.0<1>:f       0x0:f
> +       mov (8|M0)       r3.0<1>:d       r1.8<8;8,1>:w
> +       mul (8|M0)       r4.0<1>:d       r1.2<0;1,0>:d     r20.0<8;8,1>:w
> +       mul (8|M0)       r7.0<1>:d       r20.8<8;8,1>:w    256:w
> +       mul (8|M0)       r8.0<1>:d       r1.3<0;1,0>:d     r21.0<8;8,1>:w
> +(W)    mov (1|M0)       r17.2<1>:f      0x0:f
> +       send (16|M0)     r10:uw          r2:f              0xD     a0.0{NoPreempt}
> +       mov (1|M0)       r10.14<1>:hf    0xBEEF:hf
> +(W)    add (1|M0)       a0.0<1>:ud      r1.1<0;1,0>:ud    0x20A0400:ud
> +       mov (1|M0)       r10.15<1>:hf    0xDEAD:hf
> +(W)    mov (1|M0)       r18.2<1>:f      0x8:f
> +(W)    mov (1|M0)       r19.2<1>:f      0xC:f
> +(W)    mov (8|M0)       r127.0<1>:f     r0.0<8;8,1>:f
> +(W)    sends (16|M0)    null:uw         r17               r10     0x10A    a0.0
> +(W)    add (1|M0)       a0.0<1>:ud      r1.1<0;1,0>:ud    0x20A0300:ud
> +(W)    sends (16|M0)    null:uw         r18               r14     0x8A     a0.0
> +(W)    add (1|M0)       a0.0<1>:ud      r1.1<0;1,0>:ud    0x20A0200:ud
> +(W)    sends (8|M0)     null:ud         r19               r16     0x4A     a0.0
> +(W)    send (8|M0)      null            r127:f            0x27    0x2000010 {EOT}
> diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
> index ad2e718f898c..22697c94fb13 100644
> --- a/lib/intel_batchbuffer.c
> +++ b/lib/intel_batchbuffer.c
> @@ -873,6 +873,15 @@ igt_fillfunc_t igt_get_media_fillfunc(int devid)
>         return fill;
>  }
>  
> +igt_vme_func_t igt_get_media_vme_func(int devid)
> +{
> +       igt_vme_func_t fill = NULL;
> +
> +       if (IS_GEN9(devid) || IS_GEN10(devid) || IS_GEN11(devid))
> +               fill = gen11_media_vme_func;
> +
> +       return fill;
> +}
>  /**
>   * igt_get_gpgpu_fillfunc:
>   * @devid: pci device id
> diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
> index ecc23f08da77..e5f6e6d045b8 100644
> --- a/lib/intel_batchbuffer.h
> +++ b/lib/intel_batchbuffer.h
> @@ -325,6 +325,13 @@ typedef void (*igt_fillfunc_t)(struct intel_batchbuffer *batch,
>  igt_fillfunc_t igt_get_media_fillfunc(int devid);
>  igt_fillfunc_t igt_get_gpgpu_fillfunc(int devid);
>  
> +typedef void (*igt_vme_func_t)(struct intel_batchbuffer *batch,
> +                              const struct igt_buf *src,
> +                              unsigned int width, unsigned int height,
> +                              const struct igt_buf *dst);
> +
> +igt_vme_func_t igt_get_media_vme_func(int devid);
> +
>  /**
>   * igt_media_spinfunc_t:
>   * @batch: batchbuffer object
> diff --git a/lib/media_fill.c b/lib/media_fill.c
> index 4942229505ff..b1e84727394a 100644
> --- a/lib/media_fill.c
> +++ b/lib/media_fill.c
> @@ -61,6 +61,46 @@ static const uint32_t gen8_media_kernel[][4] = {
>         { 0x07800031, 0x20000a40, 0x0e000e00, 0x82000010 },
>  };
>  
> +static const uint32_t gen11_media_vme_kernel[][4] = {
> +       { 0x00600001, 0x20302e68,  0x00000000,  0x20000000 },
> +       { 0x00600001, 0x22802e68,  0x00000000,  0x00000001 },
> +       { 0x00000001, 0x20284f2c,  0x00000000,  0x3818000c },
> +       { 0x00600001, 0x22902e68,  0x00000000,  0x00000010 },
> +       { 0x00600001, 0x22a02e68,  0x00000000,  0x00010000 },
> +       { 0x00000001, 0x202c4f2c,  0x00000000,  0x22222222 },
> +       { 0x00000040, 0x22000a20,  0x0e000020,  0x10782000 },
> +       { 0x00600001, 0x20404f28,  0x00000000,  0x00000000 },
> +       { 0x00600001, 0x20a04f28,  0x00000000,  0x00000000 },
> +       { 0x00600001, 0x20c04f28,  0x00000000,  0x00000000 },
> +       { 0x00600001, 0x21204f28,  0x00000000,  0x00000000 },
> +       { 0x00600001, 0x20601a28,  0x008d0030,  0x00000000 },
> +       { 0x00600041, 0x20800a28,  0x1a000028,  0x008d0280 },
> +       { 0x00600041, 0x20e01a28,  0x1e8d0290,  0x01000100 },
> +       { 0x00600041, 0x21000a28,  0x1a00002c,  0x008d02a0 },
> +       { 0x00000001, 0x22284f2c,  0x00000000,  0x00000000 },
> +       { 0x0d80c031, 0x21404a48,  0x00000040,  0x00000200 },
> +       { 0x00000001, 0x215c4708,  0x00000000,  0xbeefbeef },
> +       { 0x00000040, 0x22000204,  0x06000024,  0x020a0400 },
> +       { 0x00000001, 0x215e4708,  0x00000000,  0xdeaddead },
> +       { 0x00000001, 0x22484f2c,  0x00000000,  0x00000008 },
> +       { 0x00000001, 0x22684f2c,  0x00000000,  0x0000000c },
> +       { 0x00600001, 0x2fe04b2c,  0x008d0000,  0x00000000 },
> +       { 0x0a800033, 0x0000a054,  0x00002224,  0x00000000 },
> +       { 0x00000040, 0x22000204,  0x06000024,  0x020a0300 },
> +       { 0x0a800033, 0x0000e054,  0x00002242,  0x00000000 },
> +       { 0x00000040, 0x22000204,  0x06000024,  0x020a0200 },
> +       { 0x0a600033, 0x00010014,  0x00002261,  0x00000000 },
> +       { 0x07600031, 0x20004a04,  0x06000fe0,  0x82000010 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +       { 0x00000000, 0x00000000,  0x00000000,  0x00000000 },
> +};
> +
>  /*
>   * This sets up the media pipeline,
>   *
> @@ -245,3 +285,73 @@ gen9_media_fillfunc(struct intel_batchbuffer *batch,
>                               gen8_media_kernel, sizeof(gen8_media_kernel));
>  
>  }
> +
> +static void
> +__gen11_media_vme_func(struct intel_batchbuffer *batch,
> +                      const struct igt_buf *src,
> +                      unsigned int width, unsigned int height,
> +                      const struct igt_buf *dst,
> +                      const uint32_t kernel[][4],
> +                      size_t kernel_size)
> +{
> +       uint32_t curbe_buffer, interface_descriptor;
> +       uint32_t batch_end;
> +
> +       intel_batchbuffer_flush(batch);
> +
> +       /* setup states */
> +       batch->ptr = &batch->buffer[BATCH_STATE_SPLIT];
> +
> +       curbe_buffer = gen11_fill_curbe_buffer_data(batch);
> +       interface_descriptor = gen11_fill_interface_descriptor(batch, src, dst,
> +                                       kernel, kernel_size);
> +       assert(batch->ptr < &batch->buffer[4095]);
> +
> +       /* media pipeline */
> +       batch->ptr = batch->buffer;
> +       OUT_BATCH(GEN8_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA |
> +                 GEN9_FORCE_MEDIA_AWAKE_ENABLE |
> +                 GEN9_SAMPLER_DOP_GATE_DISABLE |
> +                 GEN9_PIPELINE_SELECTION_MASK |
> +                 GEN9_SAMPLER_DOP_GATE_MASK |
> +                 GEN9_FORCE_MEDIA_AWAKE_MASK);
> +       gen9_emit_state_base_address(batch);
> +
> +       gen8_emit_vfe_state(batch, THREADS, MEDIA_URB_ENTRIES, MEDIA_URB_SIZE,
> +                           MEDIA_CURBE_SIZE);
> +
> +       gen7_emit_curbe_load(batch, curbe_buffer);
> +
> +       gen7_emit_interface_descriptor_load(batch, interface_descriptor);
> +
> +       gen7_emit_media_objects(batch, 0, 0, width, height);
> +
> +       OUT_BATCH(GEN8_PIPELINE_SELECT | PIPELINE_SELECT_MEDIA |
> +                 GEN9_FORCE_MEDIA_AWAKE_DISABLE |
> +                 GEN9_SAMPLER_DOP_GATE_ENABLE |
> +                 GEN9_PIPELINE_SELECTION_MASK |
> +                 GEN9_SAMPLER_DOP_GATE_MASK |
> +                 GEN9_FORCE_MEDIA_AWAKE_MASK);
> +
> +       OUT_BATCH(MI_BATCH_BUFFER_END);
> +
> +       batch_end = intel_batchbuffer_align(batch, 8);
> +       assert(batch_end < BATCH_STATE_SPLIT);
> +
> +       gen7_render_flush(batch, batch_end);
> +       intel_batchbuffer_reset(batch);
> +}
> +
> +void
> +gen11_media_vme_func(struct intel_batchbuffer *batch,
> +                    const struct igt_buf *src,
> +                    unsigned int width, unsigned int height,
> +                    const struct igt_buf *dst)
> +{
> +       __gen11_media_vme_func(batch,
> +                              src,
> +                              width, height,
> +                              dst,
> +                              gen11_media_vme_kernel,
> +                              sizeof(gen11_media_vme_kernel));
> +}
> diff --git a/lib/media_fill.h b/lib/media_fill.h
> index e365da9e47d2..1d5c5fa826a3 100644
> --- a/lib/media_fill.h
> +++ b/lib/media_fill.h
> @@ -49,4 +49,10 @@ gen9_media_fillfunc(struct intel_batchbuffer *batch,
>                     unsigned int width, unsigned int height,
>                     uint8_t color);
>  
> +void
> +gen11_media_vme_func(struct intel_batchbuffer *batch,
> +                    const struct igt_buf *src,
> +                    unsigned int width, unsigned int height,
> +                    const struct igt_buf *dst);
> +
>  #endif /* RENDE_MEDIA_FILL_H */
> diff --git a/lib/surfaceformat.h b/lib/surfaceformat.h
> index 5d7ed2cadc2d..32ea373262ca 100644
> --- a/lib/surfaceformat.h
> +++ b/lib/surfaceformat.h
> @@ -171,6 +171,8 @@
>  #define SURFACEFORMAT_R16G16B16_SSCALED        0x19E
>  #define SURFACEFORMAT_R16G16B16_USCALED        0x19F
>  
> +#define SURFACEFORMAT_RAW      0x1FF
> +
>  #define SURFACERETURNFORMAT_FLOAT32    0
>  #define SURFACERETURNFORMAT_S1 1
>  
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index 3dfeb5b67274..6dabb9dbf247 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -302,6 +302,9 @@ gem_madvise_SOURCES = i915/gem_madvise.c
>  TESTS_progs += gem_media_fill
>  gem_media_fill_SOURCES = i915/gem_media_fill.c
>  
> +TESTS_progs += gem_media_vme
> +gem_media_vme_SOURCES = i915/gem_media_vme.c
> +
>  TESTS_progs += gem_mmap
>  gem_mmap_SOURCES = i915/gem_mmap.c
>  
> diff --git a/tests/i915/gem_media_vme.c b/tests/i915/gem_media_vme.c
> new file mode 100644
> index 000000000000..47e949c781f2
> --- /dev/null
> +++ b/tests/i915/gem_media_vme.c
> @@ -0,0 +1,118 @@
> +/*
> + * Copyright © 2018 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +#include "igt.h"
> +#include <stdbool.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <sys/ioctl.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <inttypes.h>
> +#include <errno.h>
> +#include <sys/stat.h>
> +#include <sys/time.h>
> +#include "drm.h"
> +#include "intel_bufmgr.h"
> +
> +IGT_TEST_DESCRIPTION("A very simple workload for the VME media block.");
> +
> +#define WIDTH  64
> +#define STRIDE (WIDTH)
> +#define HEIGHT 64
> +
> +#define INPUT_SIZE     (WIDTH * HEIGHT * sizeof(char) * 1.5)
> +#define OUTPUT_SIZE    (56*sizeof(int))
> +
> +static void
> +scratch_buf_init(drm_intel_bufmgr *bufmgr,
> +                struct igt_buf *buf,
> +                unsigned int size)
> +{
> +       drm_intel_bo *bo;
> +
> +       bo = drm_intel_bo_alloc(bufmgr, "", size, 4096);
> +       igt_assert(bo);
> +
> +       memset(buf, 0, sizeof(*buf));
> +
> +       buf->bo = bo;
> +       buf->tiling = I915_TILING_NONE;
> +       buf->size = size;
> +}
> +
> +static void scratch_buf_init_src(drm_intel_bufmgr *bufmgr, struct igt_buf *buf)
> +{
> +       scratch_buf_init(bufmgr, buf, INPUT_SIZE);
> +
> +       /*
> +        * Ideally we would read src surface from file "SourceFrameI.yu12".
> +        * But even without it, we can still triger the rcs0 resetting
> +        * with this vme kernel.
> +        */
> +
> +       buf->stride = STRIDE;
> +}
> +
> +static void scratch_buf_init_dst(drm_intel_bufmgr *bufmgr, struct igt_buf *buf)
> +{
> +       scratch_buf_init(bufmgr, buf, OUTPUT_SIZE);
> +
> +       buf->stride = 1;
> +}
> +
> +igt_simple_main
> +{
> +       int drm_fd;
> +       uint32_t devid;
> +       drm_intel_bufmgr *bufmgr;
> +       igt_vme_func_t media_vme;
> +       struct intel_batchbuffer *batch;
> +       struct igt_buf src, dst;
> +       uint8_t dst_linear[OUTPUT_SIZE];
> +
> +       drm_fd = drm_open_driver(DRIVER_INTEL);
> +       igt_require_gem(drm_fd);
> +
> +       devid = intel_get_drm_devid(drm_fd);
> +
> +       media_vme = igt_get_media_vme_func(devid);
> +       igt_require_f(media_vme, "no media-vme function\n");
> +
> +       bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
> +       igt_assert(bufmgr);
> +
> +       batch = intel_batchbuffer_alloc(bufmgr, devid);
> +       igt_assert(batch);
> +
> +       scratch_buf_init_src(bufmgr, &src);
> +       scratch_buf_init_dst(bufmgr, &dst);
> +
> +       igt_fork_hang_detector(drm_fd);
> +
> +       media_vme(batch, &src, WIDTH, HEIGHT, &dst);
> +       gem_read(drm_fd, dst.bo->handle, 0,
> +                       dst_linear, sizeof(dst_linear));

Still think this should be gem_sync(bo->handle) to avoid any illusions
that the result is being checked.

I resisted one whole sentence of not saying libdrm_intel, flee!
-Chris
Joonas Lahtinen Jan. 8, 2019, 2:56 p.m.
Quoting Tvrtko Ursulin (2019-01-08 13:24:49)
> From: Tony Ye <tony.ye@intel.com>
> 
> Simple test which exercises the VME fixed function block.
> 
> v2: (Tvrtko Ursulin)
>  * Small cleanups like copyright date, tabs, remove unused bits.
> 
> v3: (Tony Ye)
>  * Added curbe data entry for dst surface.
>  * Read the dst surface after the VME kernel being executed.
> 
> v4: (Tony Ye)
>  * Added the media_vme.gxa kernel source code and compile instructions.
> 
> v5: (Tvrtko Ursulin)
>  * Added hang detector.
> 
> Signed-off-by: Tony Ye <tony.ye@intel.com>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Tony Ye <tony.ye@intel.com>

One could further improve this by checking some effect of the shader
kernel on the output surface, just to double check that it both executed
and didn't hang as suggested by Chris

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

Regards, Joonas