blob: c1d30f2417e50bc6cb36229d50c9db66d4c307d0 [file] [log] [blame]
/*
* Copyright © 2015 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.
*/
/** @file gem_read_read_speed.c
*
* This is a test of performance with multiple readers from the same source.
*/
#include "igt.h"
#include "igt_sysfs.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <inttypes.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <drm.h>
#include "intel_bufmgr.h"
IGT_TEST_DESCRIPTION("Test speed of concurrent reads between engines.");
igt_render_copyfunc_t rendercopy;
struct intel_batchbuffer *batch;
int width, height;
static int semaphores_enabled(int fd)
{
bool enabled = false;
int dir;
dir = igt_sysfs_open_parameters(fd);
if (dir < 0)
return false;
enabled = igt_sysfs_get_boolean(dir, "semaphores");
close(dir);
return enabled;
}
static drm_intel_bo *rcs_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
{
struct igt_buf d = {
.bo = dst,
.size = width * height * 4,
.num_tiles = width * height * 4,
.stride = width * 4,
}, s = {
.bo = src,
.size = width * height * 4,
.num_tiles = width * height * 4,
.stride = width * 4,
};
uint32_t swizzle;
drm_intel_bo *bo = batch->bo;
drm_intel_bo_reference(bo);
drm_intel_bo_get_tiling(dst, &d.tiling, &swizzle);
drm_intel_bo_get_tiling(src, &s.tiling, &swizzle);
rendercopy(batch, NULL,
&s, 0, 0,
width, height,
&d, 0, 0);
return bo;
}
static drm_intel_bo *bcs_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
{
drm_intel_bo *bo = batch->bo;
drm_intel_bo_reference(bo);
intel_blt_copy(batch,
src, 0, 0, 4*width,
dst, 0, 0, 4*width,
width, height, 32);
return bo;
}
static void
set_bo(drm_intel_bo *bo, uint32_t val)
{
int size = width * height;
uint32_t *vaddr;
do_or_die(drm_intel_bo_map(bo, 1));
vaddr = bo->virtual;
while (size--)
*vaddr++ = val;
drm_intel_bo_unmap(bo);
}
static double elapsed(const struct timespec *start,
const struct timespec *end,
int loop)
{
return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000)/loop;
}
static drm_intel_bo *create_bo(drm_intel_bufmgr *bufmgr,
const char *name)
{
uint32_t tiling_mode = I915_TILING_X;
unsigned long pitch;
return drm_intel_bo_alloc_tiled(bufmgr, name,
width, height, 4,
&tiling_mode, &pitch, 0);
}
static void run(drm_intel_bufmgr *bufmgr, int _width, int _height,
bool write_bcs, bool write_rcs)
{
drm_intel_bo *src = NULL, *bcs = NULL, *rcs = NULL;
drm_intel_bo *bcs_batch, *rcs_batch;
struct timespec start, end;
int loops = 1000;
width = _width;
height = _height;
src = create_bo(bufmgr, "src");
bcs = create_bo(bufmgr, "bcs");
rcs = create_bo(bufmgr, "rcs");
set_bo(src, 0xdeadbeef);
if (write_bcs) {
bcs_batch = bcs_copy_bo(src, bcs);
} else {
bcs_batch = bcs_copy_bo(bcs, src);
}
if (write_rcs) {
rcs_batch = rcs_copy_bo(src, rcs);
} else {
rcs_batch = rcs_copy_bo(rcs, src);
}
drm_intel_bo_unreference(rcs);
drm_intel_bo_unreference(bcs);
drm_intel_gem_bo_start_gtt_access(src, true);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < loops; i++) {
drm_intel_gem_bo_context_exec(rcs_batch, NULL, 4096, I915_EXEC_RENDER);
drm_intel_gem_bo_context_exec(bcs_batch, NULL, 4096, I915_EXEC_BLT);
}
drm_intel_gem_bo_start_gtt_access(src, true);
clock_gettime(CLOCK_MONOTONIC, &end);
igt_info("Time to %s-%s %dx%d [%dk]: %7.3fµs\n",
write_bcs ? "write" : "read",
write_rcs ? "write" : "read",
width, height, 4*width*height/1024,
elapsed(&start, &end, loops));
drm_intel_bo_unreference(rcs_batch);
drm_intel_bo_unreference(bcs_batch);
drm_intel_bo_unreference(src);
}
igt_main
{
const int sizes[] = {1, 128, 256, 512, 1024, 2048, 4096, 8192, 0};
drm_intel_bufmgr *bufmgr = NULL;
int fd, i;
igt_skip_on_simulation();
igt_fixture {
int devid;
fd = drm_open_driver(DRIVER_INTEL);
igt_require_gem(fd);
devid = intel_get_drm_devid(fd);
igt_require(intel_gen(devid) >= 6);
rendercopy = igt_get_render_copyfunc(devid);
igt_require(rendercopy);
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
igt_assert(bufmgr);
batch = intel_batchbuffer_alloc(bufmgr, devid);
igt_info("Semaphores: %d\n", semaphores_enabled(fd));
}
for (i = 0; sizes[i] != 0; i++) {
igt_subtest_f("read-read-%dx%d", sizes[i], sizes[i])
run(bufmgr, sizes[i], sizes[i], false, false);
igt_subtest_f("read-write-%dx%d", sizes[i], sizes[i])
run(bufmgr, sizes[i], sizes[i], false, true);
igt_subtest_f("write-read-%dx%d", sizes[i], sizes[i])
run(bufmgr, sizes[i], sizes[i], true, false);
igt_subtest_f("write-write-%dx%d", sizes[i], sizes[i])
run(bufmgr, sizes[i], sizes[i], true, true);
}
}