[igt-dev] [PATCH i-g-t v7 2/2] tests/kms_ccs: CCS Clear Color test
Mika Kahola
mika.kahola at intel.com
Fri Oct 23 13:05:26 UTC 2020
The patch proposes a method to test CCS with clear color
capability.
The test paints a solid color on primary fb and a small sprite fb.
These are cleared with fast clear feature. A crc is captured and
compared against the reference.
v2: Modify _gen9_render_copyfunc to support fast clear (Matt)
Enable fast clear bit on 3D sequence (Matt)
Add helper function to figure out clear color modifier (Matt)
v3: Remove unrelated line additions/removes
v4: Fast clear with color (Imre)
v5: Write raw 32-bit color values to register (Imre)
Require 32-bit color format
v6: Rebase to use batchbuffer without libdrm dependency
v7: Enable clear color (Nanley)
Signed-off-by: Mika Kahola <mika.kahola at intel.com>
---
lib/gen8_render.h | 1 +
lib/gen9_render.h | 6 ++-
lib/intel_batchbuffer.c | 10 +++++
lib/intel_batchbuffer.h | 6 +++
lib/rendercopy.h | 4 ++
lib/rendercopy_gen9.c | 79 ++++++++++++++++++++++++++++------
tests/kms_ccs.c | 94 ++++++++++++++++++++++++++++++++++++++---
7 files changed, 181 insertions(+), 19 deletions(-)
diff --git a/lib/gen8_render.h b/lib/gen8_render.h
index 31dc01bc..1b0f527e 100644
--- a/lib/gen8_render.h
+++ b/lib/gen8_render.h
@@ -26,6 +26,7 @@
# define GEN8_VS_FLOATING_POINT_MODE_ALTERNATE (1 << 16)
+#define GEN8_3DSTATE_FAST_CLEAR_ENABLE (1 << 8)
#define GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP \
GEN4_3D(3, 0, 0x21)
#define GEN8_3DSTATE_PS_BLEND GEN4_3D(3, 0, 0x4d)
diff --git a/lib/gen9_render.h b/lib/gen9_render.h
index 6274e902..b4cdf18a 100644
--- a/lib/gen9_render.h
+++ b/lib/gen9_render.h
@@ -131,7 +131,11 @@ struct gen9_surface_state {
} ss10;
struct {
- uint32_t aux_base_addr_hi;
+ uint32_t aux_base_addr_hi:20;
+ uint32_t procedual_texture:1;
+ uint32_t clearvalue_addr_enable:1;
+ uint32_t quilt_height:5;
+ uint32_t quilt_width:5;
} ss11;
/* register can be used for either
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index fc73495c..905f69ff 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -1096,6 +1096,16 @@ igt_vebox_copyfunc_t igt_get_vebox_copyfunc(int devid)
return copy;
}
+igt_render_clearfunc_t igt_get_render_clearfunc(int devid)
+{
+ igt_render_clearfunc_t clear = NULL;
+
+ if (IS_GEN12(devid))
+ clear = gen12_render_clearfunc;
+
+ return clear;
+}
+
/**
* igt_get_media_fillfunc:
* @devid: pci device id
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index ab1b0c28..4f0b33ee 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -374,6 +374,12 @@ typedef void (*igt_vebox_copyfunc_t)(struct intel_bb *ibb,
igt_vebox_copyfunc_t igt_get_vebox_copyfunc(int devid);
+typedef void (*igt_render_clearfunc_t)(struct intel_bb *ibb,
+ struct intel_buf *dst, unsigned int dst_x, unsigned int dst_y,
+ unsigned int width, unsigned int height,
+ uint32_t r, uint32_t g, uint32_t b);
+igt_render_clearfunc_t igt_get_render_clearfunc(int devid);
+
/**
* igt_fillfunc_t:
* @i915: drm fd
diff --git a/lib/rendercopy.h b/lib/rendercopy.h
index 7d5f0802..394fc94e 100644
--- a/lib/rendercopy.h
+++ b/lib/rendercopy.h
@@ -23,6 +23,10 @@ static inline void emit_vertex_normalized(struct intel_bb *ibb,
intel_bb_out(ibb, u.ui);
}
+void gen12_render_clearfunc(struct intel_bb *ibb,
+ struct intel_buf *dst, unsigned int dst_x, unsigned int dst_y,
+ unsigned int width, unsigned int height,
+ uint32_t r, uint32_t g, uint32_t b);
void gen12_render_copyfunc(struct intel_bb *ibb,
struct intel_buf *src, uint32_t src_x, uint32_t src_y,
uint32_t width, uint32_t height,
diff --git a/lib/rendercopy_gen9.c b/lib/rendercopy_gen9.c
index ef6855c9..fb6f6ba3 100644
--- a/lib/rendercopy_gen9.c
+++ b/lib/rendercopy_gen9.c
@@ -117,7 +117,7 @@ static const uint32_t gen12_render_copy[][4] = {
/* Mostly copy+paste from gen6, except height, width, pitch moved */
static uint32_t
-gen8_bind_buf(struct intel_bb *ibb, const struct intel_buf *buf, int is_dst) {
+gen8_bind_buf(struct intel_bb *ibb, const struct intel_buf *buf, int is_dst, bool fast_clear) {
struct gen9_surface_state *ss;
uint32_t write_domain, read_domain;
uint64_t address;
@@ -190,6 +190,9 @@ gen8_bind_buf(struct intel_bb *ibb, const struct intel_buf *buf, int is_dst) {
buf->addr.offset);
ss->ss10.aux_base_addr = (address + buf->ccs[0].offset);
ss->ss11.aux_base_addr_hi = (address + buf->ccs[0].offset) >> 32;
+
+ if (fast_clear)
+ ss->ss11.clearvalue_addr_enable = 1;
}
if (buf->cc.offset) {
@@ -217,8 +220,10 @@ gen8_bind_surfaces(struct intel_bb *ibb,
binding_table = intel_bb_ptr_align(ibb, 32);
binding_table_offset = intel_bb_ptr_add_return_prev_offset(ibb, 32);
- binding_table[0] = gen8_bind_buf(ibb, dst, 1);
- binding_table[1] = gen8_bind_buf(ibb, src, 0);
+ binding_table[0] = gen8_bind_buf(ibb, dst, 1, 1);
+
+ if (src != NULL)
+ binding_table[1] = gen8_bind_buf(ibb, src, 1, 0);
return binding_table_offset;
}
@@ -274,16 +279,25 @@ gen7_fill_vertex_buffer_data(struct intel_bb *ibb,
offset = intel_bb_offset(ibb);
emit_vertex_2s(ibb, dst_x + width, dst_y + height);
- emit_vertex_normalized(ibb, src_x + width, intel_buf_width(src));
- emit_vertex_normalized(ibb, src_y + height, intel_buf_height(src));
+
+ if (src != NULL) {
+ emit_vertex_normalized(ibb, src_x + width, intel_buf_width(src));
+ emit_vertex_normalized(ibb, src_y + height, intel_buf_height(src));
+ }
emit_vertex_2s(ibb, dst_x, dst_y + height);
- emit_vertex_normalized(ibb, src_x, intel_buf_width(src));
- emit_vertex_normalized(ibb, src_y + height, intel_buf_height(src));
+
+ if (src != NULL) {
+ emit_vertex_normalized(ibb, src_x, intel_buf_width(src));
+ emit_vertex_normalized(ibb, src_y + height, intel_buf_height(src));
+ }
emit_vertex_2s(ibb, dst_x, dst_y);
- emit_vertex_normalized(ibb, src_x, intel_buf_width(src));
- emit_vertex_normalized(ibb, src_y, intel_buf_height(src));
+
+ if (src != NULL) {
+ emit_vertex_normalized(ibb, src_x, intel_buf_width(src));
+ emit_vertex_normalized(ibb, src_y, intel_buf_height(src));
+ }
return offset;
}
@@ -729,7 +743,7 @@ gen8_emit_sf(struct intel_bb *ibb)
}
static void
-gen8_emit_ps(struct intel_bb *ibb, uint32_t kernel) {
+gen8_emit_ps(struct intel_bb *ibb, uint32_t kernel, bool fast_clear) {
const int max_threads = 63;
intel_bb_out(ibb, GEN6_3DSTATE_WM | (2 - 2));
@@ -757,6 +771,10 @@ gen8_emit_ps(struct intel_bb *ibb, uint32_t kernel) {
2 << GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT);
intel_bb_out(ibb, 0); /* scratch space stuff */
intel_bb_out(ibb, 0); /* scratch hi */
+
+ if (fast_clear)
+ intel_bb_out(ibb, GEN8_3DSTATE_FAST_CLEAR_ENABLE);
+
intel_bb_out(ibb, (max_threads - 1) << GEN8_3DSTATE_PS_MAX_THREADS_SHIFT |
GEN6_3DSTATE_WM_16_DISPATCH_ENABLE);
intel_bb_out(ibb, 6 << GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT);
@@ -890,13 +908,20 @@ void _gen9_render_copyfunc(struct intel_bb *ibb,
uint32_t scissor_state;
uint32_t vertex_buffer;
uint32_t aux_pgtable_state;
+ bool fast_clear = src != NULL ? false : true;
- igt_assert(src->bpp == dst->bpp);
+ if (src != NULL)
+ igt_assert(src->bpp == dst->bpp);
+
+ if (!fast_clear)
+ igt_assert(src->bpp == dst->bpp);
intel_bb_flush_render(ibb);
intel_bb_add_intel_buf(ibb, dst, true);
- intel_bb_add_intel_buf(ibb, src, false);
+
+ if (!fast_clear)
+ intel_bb_add_intel_buf(ibb, src, false);
intel_bb_ptr_set(ibb, BATCH_STATE_SPLIT);
@@ -949,11 +974,13 @@ void _gen9_render_copyfunc(struct intel_bb *ibb,
intel_bb_out(ibb, 0);
intel_bb_out(ibb, 0);
+ gen8_emit_ps(ibb, ps_kernel_off, fast_clear);
+
gen7_emit_clip(ibb);
gen8_emit_sf(ibb);
- gen8_emit_ps(ibb, ps_kernel_off);
+ gen8_emit_ps(ibb, ps_kernel_off, fast_clear);
intel_bb_out(ibb, GEN7_3DSTATE_BINDING_TABLE_POINTERS_PS);
intel_bb_out(ibb, ps_binding_table);
@@ -1027,3 +1054,29 @@ void gen12_render_copyfunc(struct intel_bb *ibb,
gen12_aux_pgtable_cleanup(ibb, &pgtable_info);
}
+
+void gen12_render_clearfunc(struct intel_bb *ibb,
+ struct intel_buf *dst,
+ unsigned int dst_x, unsigned int dst_y,
+ unsigned int width, unsigned int height,
+ uint32_t r, uint32_t g, uint32_t b)
+{
+ struct aux_pgtable_info pgtable_info = { };
+
+ gen12_aux_pgtable_init(&pgtable_info, ibb, NULL, dst);
+
+ /* BSpec 21136 */
+ intel_bb_ptr_set(ibb, dst->cc.offset);
+ intel_bb_out(ibb, r);
+ intel_bb_out(ibb, b);
+ intel_bb_out(ibb, g);
+ intel_bb_out(ibb, 0xffffffff);
+
+ _gen9_render_copyfunc(ibb, NULL, 0, 0,
+ width, height, dst, dst_x, dst_y,
+ pgtable_info.pgtable_buf,
+ gen12_render_copy,
+ sizeof(gen12_render_copy));
+
+ gen12_aux_pgtable_cleanup(ibb, &pgtable_info);
+}
diff --git a/tests/kms_ccs.c b/tests/kms_ccs.c
index 53abecce..fac1ed4e 100644
--- a/tests/kms_ccs.c
+++ b/tests/kms_ccs.c
@@ -50,10 +50,12 @@ enum test_fb_flags {
FB_MISALIGN_AUX_STRIDE = 1 << 2,
FB_SMALL_AUX_STRIDE = 1 << 3,
FB_ZERO_AUX_STRIDE = 1 << 4,
+ FB_CLEAR_COLOR = 1 << 5,
};
typedef struct {
int drm_fd;
+ int devid;
igt_display_t display;
igt_output_t *output;
enum pipe pipe;
@@ -62,6 +64,11 @@ typedef struct {
igt_pipe_crc_t *pipe_crc;
uint32_t format;
uint64_t ccs_modifier;
+ struct igt_fb primary_fb;
+ igt_plane_t *primary;
+ igt_render_clearfunc_t fast_clear;
+ struct buf_ops *bops;
+ struct intel_bb *ibb;
} data_t;
static const struct {
@@ -120,6 +127,16 @@ static void addfb_init(struct igt_fb *fb, struct drm_mode_fb_cmd2 *f)
}
}
+static bool is_ccs_cc_modifier(uint64_t modifier)
+{
+ switch (modifier) {
+ case LOCAL_I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
* The CCS planes of compressed framebuffers contain non-zero bytes if the
* engine compressed effectively the framebuffer. The actual encoding of these
@@ -290,6 +307,32 @@ static igt_plane_t *compatible_main_plane(data_t *data)
return igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY);
}
+static struct intel_buf *init_buf(data_t *data, const struct igt_fb *fb, const char *buf_name)
+{
+ struct intel_buf *buf;
+ uint32_t name, handle, tiling, stride, width, height, bpp, size;
+
+ igt_assert_eq(fb->offsets[0], 0);
+ tiling = igt_fb_mod_to_tiling(fb->modifier);
+ stride = fb->strides[0];
+ bpp = fb->plane_bpp[0];
+ size = fb->size;
+ width = stride / (bpp / 8);
+ height = size / stride;
+ name = gem_flink(data->drm_fd, fb->gem_handle);
+ handle = gem_open(data->drm_fd, name);
+ buf = intel_buf_create_using_handle(data->bops, handle, width, height, bpp, 0, tiling, 0);
+ intel_buf_set_name(buf, buf_name);
+ intel_buf_set_ownership(buf, true);
+
+ return buf;
+}
+
+static void fini_buf(struct intel_buf *buf)
+{
+ intel_buf_destroy(buf);
+}
+
static bool try_config(data_t *data, enum test_fb_flags fb_flags,
igt_crc_t *crc)
{
@@ -349,6 +392,37 @@ static bool try_config(data_t *data, enum test_fb_flags fb_flags,
if (data->flags & TEST_BAD_ROTATION_90)
igt_plane_set_rotation(primary, IGT_ROTATION_90);
+ if (fb_flags & FB_CLEAR_COLOR) {
+ struct intel_buf *dst;
+
+ /* require 32-bit bpp for a fast clear test */
+ igt_skip_on(data->primary_fb.plane_bpp[0] != 32);
+
+ data->ibb = intel_bb_create(data->drm_fd, 4096);
+ data->bops = buf_ops_create(data->drm_fd);
+
+ dst = init_buf(data, &data->primary_fb, "fast clear dst");
+ gem_set_domain(data->drm_fd, data->primary_fb.gem_handle,
+ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+
+ /*
+ * We expect the kernel to limit the max fb
+ * size/stride to something that can still
+ * rendered with the blitter/render engine.
+ */
+ data->fast_clear(data->ibb, dst, 0, 0,
+ data->primary_fb.width,
+ data->primary_fb.height,
+ colors[0].r*UINT32_MAX,
+ colors[0].g*UINT32_MAX,
+ colors[0].b*UINT32_MAX);
+
+ fini_buf(dst);
+ intel_bb_reset(data->ibb, true);
+
+ return true;
+ }
+
ret = igt_display_try_commit2(display, commit);
if (data->flags & TEST_BAD_ROTATION_90) {
igt_assert_eq(ret, -EINVAL);
@@ -386,10 +460,18 @@ static int test_ccs(data_t *data)
if (data->flags & TEST_CRC) {
data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
- if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) &&
- try_config(data, fb_flags, &crc)) {
- igt_assert_crc_equal(&crc, &ref_crc);
- valid_tests++;
+ if (is_ccs_cc_modifier(data->ccs_modifier)) {
+ if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) &&
+ try_config(data, fb_flags | FB_COMPRESSED | FB_CLEAR_COLOR, &crc)) {
+ igt_assert_crc_equal(&crc, &ref_crc);
+ valid_tests++;
+ }
+ } else {
+ if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) &&
+ try_config(data, fb_flags, &crc)) {
+ igt_assert_crc_equal(&crc, &ref_crc);
+ valid_tests++;
+ }
}
igt_pipe_crc_free(data->pipe_crc);
@@ -471,11 +553,13 @@ igt_main_args("c", NULL, help_str, opt_handler, NULL)
igt_fixture {
data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
- igt_require(intel_gen(intel_get_drm_devid(data.drm_fd)) >= 9);
+ data.devid = intel_gen(intel_get_drm_devid(data.drm_fd));
+ igt_require(data.devid >= 9);
kmstest_set_vt_graphics_mode();
igt_require_pipe_crc(data.drm_fd);
igt_display_require(&data.display, data.drm_fd);
+ data.fast_clear = igt_get_render_clearfunc(data.devid);
}
for_each_pipe_static(pipe) {
--
2.25.1
More information about the igt-dev
mailing list