gallium/u_tests: test sync_file fences
[mesa.git] / src / gallium / auxiliary / util / u_tests.c
index 687e5118d7c300d347757fa07070d73242dc0d29..2e931c0cd01bce017e83bad2f8d2c6868469b44f 100644 (file)
@@ -375,7 +375,7 @@ null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
    fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
                                       TGSI_INTERPOLATE_LINEAR,
                                       TGSI_RETURN_TYPE_FLOAT,
-                                      TGSI_RETURN_TYPE_FLOAT);
+                                      TGSI_RETURN_TYPE_FLOAT, false, false);
    cso_set_fragment_shader_handle(cso, fs);
 
    /* Vertex shader. */
@@ -397,8 +397,9 @@ null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
                              tgsi_texture_names[tgsi_tex_target]);
 }
 
-static void
-null_constant_buffer(struct pipe_context *ctx)
+void
+util_test_constant_buffer(struct pipe_context *ctx,
+                          struct pipe_resource *constbuf)
 {
    struct cso_context *cso;
    struct pipe_resource *cb;
@@ -411,16 +412,16 @@ null_constant_buffer(struct pipe_context *ctx)
                               PIPE_FORMAT_R8G8B8A8_UNORM);
    util_set_common_states_and_clear(cso, ctx, cb);
 
-   ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, NULL);
+   pipe_set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, constbuf);
 
    /* Fragment shader. */
    {
       static const char *text = /* I don't like ureg... */
             "FRAG\n"
-            "DCL CONST[0]\n"
+            "DCL CONST[0][0]\n"
             "DCL OUT[0], COLOR\n"
 
-            "MOV OUT[0], CONST[0]\n"
+            "MOV OUT[0], CONST[0][0]\n"
             "END\n";
       struct tgsi_token tokens[1000];
       struct pipe_shader_state state;
@@ -489,6 +490,106 @@ null_fragment_shader(struct pipe_context *ctx)
    util_report_result(qresult.u64 == 2);
 }
 
+#ifdef PIPE_OS_LINUX
+#include <libsync.h>
+#else
+#define sync_merge(str, fd1, fd2) (-1)
+#define sync_wait(fd, timeout) (-1)
+#endif
+
+static void
+test_sync_file_fences(struct pipe_context *ctx)
+{
+   struct pipe_screen *screen = ctx->screen;
+   bool pass = true;
+
+   if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
+      return;
+
+   struct cso_context *cso = cso_create_context(ctx, 0);
+   struct pipe_resource *buf =
+      pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024);
+   struct pipe_resource *tex =
+      util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM);
+   struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL;
+
+   /* Run 2 clears, get fencess. */
+   uint32_t value = 0;
+   ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
+   ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD);
+
+   struct pipe_box box;
+   u_box_2d(0, 0, tex->width0, tex->height0, &box);
+   ctx->clear_texture(ctx, tex, 0, &box, &value);
+   ctx->flush(ctx, &tex_fence, PIPE_FLUSH_FENCE_FD);
+   pass = pass && buf_fence && tex_fence;
+
+   /* Export fences. */
+   int buf_fd = screen->fence_get_fd(screen, buf_fence);
+   int tex_fd = screen->fence_get_fd(screen, tex_fence);
+   pass = pass && buf_fd >= 0 && tex_fd >= 0;
+
+   /* Merge fences. */
+   int merged_fd = sync_merge("test", buf_fd, tex_fd);
+   pass = pass && merged_fd >= 0;
+
+   /* (Re)import all fences. */
+   struct pipe_fence_handle *re_buf_fence = NULL, *re_tex_fence = NULL;
+   struct pipe_fence_handle *merged_fence = NULL;
+   ctx->create_fence_fd(ctx, &re_buf_fence, buf_fd);
+   ctx->create_fence_fd(ctx, &re_tex_fence, tex_fd);
+   ctx->create_fence_fd(ctx, &merged_fence, merged_fd);
+   pass = pass && re_buf_fence && re_tex_fence && merged_fence;
+
+   /* Run another clear after waiting for everything. */
+   struct pipe_fence_handle *final_fence = NULL;
+   ctx->fence_server_sync(ctx, merged_fence);
+   value = 0xff;
+   ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
+   ctx->flush(ctx, &final_fence, PIPE_FLUSH_FENCE_FD);
+   pass = pass && final_fence;
+
+   /* Wait for the last fence. */
+   int final_fd = screen->fence_get_fd(screen, final_fence);
+   pass = pass && final_fd >= 0;
+   pass = pass && sync_wait(final_fd, -1) == 0;
+
+   /* Check that all fences are signalled. */
+   pass = pass && sync_wait(buf_fd, 0) == 0;
+   pass = pass && sync_wait(tex_fd, 0) == 0;
+   pass = pass && sync_wait(merged_fd, 0) == 0;
+
+   pass = pass && screen->fence_finish(screen, NULL, buf_fence, 0);
+   pass = pass && screen->fence_finish(screen, NULL, tex_fence, 0);
+   pass = pass && screen->fence_finish(screen, NULL, re_buf_fence, 0);
+   pass = pass && screen->fence_finish(screen, NULL, re_tex_fence, 0);
+   pass = pass && screen->fence_finish(screen, NULL, merged_fence, 0);
+   pass = pass && screen->fence_finish(screen, NULL, final_fence, 0);
+
+   /* Cleanup. */
+   if (buf_fd >= 0)
+      close(buf_fd);
+   if (tex_fd >= 0)
+      close(tex_fd);
+   if (merged_fd >= 0)
+      close(merged_fd);
+   if (final_fd >= 0)
+      close(final_fd);
+
+   screen->fence_reference(screen, &buf_fence, NULL);
+   screen->fence_reference(screen, &tex_fence, NULL);
+   screen->fence_reference(screen, &re_buf_fence, NULL);
+   screen->fence_reference(screen, &re_tex_fence, NULL);
+   screen->fence_reference(screen, &merged_fence, NULL);
+   screen->fence_reference(screen, &final_fence, NULL);
+
+   cso_destroy_context(cso);
+   pipe_resource_reference(&buf, NULL);
+   pipe_resource_reference(&tex, NULL);
+
+   util_report_result(pass);
+}
+
 /**
  * Run all tests. This should be run with a clean context after
  * context_create.
@@ -502,7 +603,8 @@ util_run_tests(struct pipe_screen *screen)
    tgsi_vs_window_space_position(ctx);
    null_sampler_view(ctx, TGSI_TEXTURE_2D);
    null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
-   null_constant_buffer(ctx);
+   util_test_constant_buffer(ctx, NULL);
+   test_sync_file_fences(ctx);
 
    ctx->destroy(ctx);