Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright 2014 Advanced Micro Devices, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 #include "util/u_tests.h"
     29 
     30 #include "util/u_draw_quad.h"
     31 #include "util/u_format.h"
     32 #include "util/u_inlines.h"
     33 #include "util/u_memory.h"
     34 #include "util/u_simple_shaders.h"
     35 #include "util/u_surface.h"
     36 #include "util/u_string.h"
     37 #include "util/u_tile.h"
     38 #include "tgsi/tgsi_strings.h"
     39 #include "tgsi/tgsi_text.h"
     40 #include "cso_cache/cso_context.h"
     41 #include <stdio.h>
     42 
     43 #define TOLERANCE 0.01
     44 
     45 static struct pipe_resource *
     46 util_create_texture2d(struct pipe_screen *screen, unsigned width,
     47                       unsigned height, enum pipe_format format)
     48 {
     49    struct pipe_resource templ = {{0}};
     50 
     51    templ.target = PIPE_TEXTURE_2D;
     52    templ.width0 = width;
     53    templ.height0 = height;
     54    templ.depth0 = 1;
     55    templ.array_size = 1;
     56    templ.format = format;
     57    templ.usage = PIPE_USAGE_DEFAULT;
     58    templ.bind = PIPE_BIND_SAMPLER_VIEW |
     59                 (util_format_is_depth_or_stencil(format) ?
     60                     PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET);
     61 
     62    return screen->resource_create(screen, &templ);
     63 }
     64 
     65 static void
     66 util_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx,
     67 			 struct pipe_resource *tex)
     68 {
     69    struct pipe_surface templ = {{0}}, *surf;
     70    struct pipe_framebuffer_state fb = {0};
     71 
     72    templ.format = tex->format;
     73    surf = ctx->create_surface(ctx, tex, &templ);
     74 
     75    fb.width = tex->width0;
     76    fb.height = tex->height0;
     77    fb.cbufs[0] = surf;
     78    fb.nr_cbufs = 1;
     79 
     80    cso_set_framebuffer(cso, &fb);
     81    pipe_surface_reference(&surf, NULL);
     82 }
     83 
     84 static void
     85 util_set_blend_normal(struct cso_context *cso)
     86 {
     87    struct pipe_blend_state blend = {0};
     88 
     89    blend.rt[0].colormask = PIPE_MASK_RGBA;
     90    cso_set_blend(cso, &blend);
     91 }
     92 
     93 static void
     94 util_set_dsa_disable(struct cso_context *cso)
     95 {
     96    struct pipe_depth_stencil_alpha_state dsa = {{0}};
     97 
     98    cso_set_depth_stencil_alpha(cso, &dsa);
     99 }
    100 
    101 static void
    102 util_set_rasterizer_normal(struct cso_context *cso)
    103 {
    104    struct pipe_rasterizer_state rs = {0};
    105 
    106    rs.half_pixel_center = 1;
    107    rs.bottom_edge_rule = 1;
    108    rs.depth_clip = 1;
    109 
    110    cso_set_rasterizer(cso, &rs);
    111 }
    112 
    113 static void
    114 util_set_max_viewport(struct cso_context *cso, struct pipe_resource *tex)
    115 {
    116    struct pipe_viewport_state viewport;
    117 
    118    viewport.scale[0] = 0.5f * tex->width0;
    119    viewport.scale[1] = 0.5f * tex->height0;
    120    viewport.scale[2] = 1.0f;
    121    viewport.translate[0] = 0.5f * tex->width0;
    122    viewport.translate[1] = 0.5f * tex->height0;
    123    viewport.translate[2] = 0.0f;
    124 
    125    cso_set_viewport(cso, &viewport);
    126 }
    127 
    128 static void
    129 util_set_interleaved_vertex_elements(struct cso_context *cso,
    130                                      unsigned num_elements)
    131 {
    132    unsigned i;
    133    struct pipe_vertex_element *velem =
    134       calloc(1, num_elements * sizeof(struct pipe_vertex_element));
    135 
    136    for (i = 0; i < num_elements; i++) {
    137       velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    138       velem[i].src_offset = i * 16;
    139    }
    140 
    141    cso_set_vertex_elements(cso, num_elements, velem);
    142    free(velem);
    143 }
    144 
    145 static void *
    146 util_set_passthrough_vertex_shader(struct cso_context *cso,
    147                                    struct pipe_context *ctx,
    148                                    bool window_space)
    149 {
    150    static const uint vs_attribs[] = {
    151       TGSI_SEMANTIC_POSITION,
    152       TGSI_SEMANTIC_GENERIC
    153    };
    154    static const uint vs_indices[] = {0, 0};
    155    void *vs;
    156 
    157    vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices,
    158                                             window_space);
    159    cso_set_vertex_shader_handle(cso, vs);
    160    return vs;
    161 }
    162 
    163 static void
    164 util_set_common_states_and_clear(struct cso_context *cso, struct pipe_context *ctx,
    165                                  struct pipe_resource *cb)
    166 {
    167    static const float clear_color[] = {0.1, 0.1, 0.1, 0.1};
    168 
    169    util_set_framebuffer_cb0(cso, ctx, cb);
    170    util_set_blend_normal(cso);
    171    util_set_dsa_disable(cso);
    172    util_set_rasterizer_normal(cso);
    173    util_set_max_viewport(cso, cb);
    174 
    175    ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0);
    176 }
    177 
    178 static void
    179 util_draw_fullscreen_quad(struct cso_context *cso)
    180 {
    181    static float vertices[] = {
    182      -1, -1, 0, 1,   0, 0, 0, 0,
    183      -1,  1, 0, 1,   0, 1, 0, 0,
    184       1,  1, 0, 1,   1, 1, 0, 0,
    185       1, -1, 0, 1,   1, 0, 0, 0
    186    };
    187    util_set_interleaved_vertex_elements(cso, 2);
    188    util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
    189 }
    190 
    191 /**
    192  * Probe and test if the rectangle contains the expected color.
    193  *
    194  * If "num_expected_colors" > 1, at least one expected color must match
    195  * the probed color. "expected" should be an array of 4*num_expected_colors
    196  * floats.
    197  */
    198 static bool
    199 util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
    200                            unsigned offx, unsigned offy, unsigned w,
    201                            unsigned h,
    202                            const float *expected,
    203                            unsigned num_expected_colors)
    204 {
    205    struct pipe_transfer *transfer;
    206    void *map;
    207    float *pixels = malloc(w * h * 4 * sizeof(float));
    208    unsigned x,y,e,c;
    209    bool pass = true;
    210 
    211    map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
    212                            offx, offy, w, h, &transfer);
    213    pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels);
    214    pipe_transfer_unmap(ctx, transfer);
    215 
    216    for (e = 0; e < num_expected_colors; e++) {
    217       for (y = 0; y < h; y++) {
    218          for (x = 0; x < w; x++) {
    219             float *probe = &pixels[(y*w + x)*4];
    220 
    221             for (c = 0; c < 4; c++) {
    222                if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) {
    223                   if (e < num_expected_colors-1)
    224                      goto next_color; /* test the next expected color */
    225 
    226                   printf("Probe color at (%i,%i),  ", offx+x, offy+y);
    227                   printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
    228                          expected[e*4], expected[e*4+1],
    229                          expected[e*4+2], expected[e*4+3]);
    230                   printf("Got: %.3f, %.3f, %.3f, %.3f\n",
    231                          probe[0], probe[1], probe[2], probe[2]);
    232                   pass = false;
    233                   goto done;
    234                }
    235             }
    236          }
    237       }
    238       break; /* this color was successful */
    239 
    240    next_color:;
    241    }
    242 done:
    243 
    244    free(pixels);
    245    return pass;
    246 }
    247 
    248 static bool
    249 util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
    250                      unsigned offx, unsigned offy, unsigned w, unsigned h,
    251                      const float *expected)
    252 {
    253    return util_probe_rect_rgba_multi(ctx, tex, offx, offy, w, h, expected, 1);
    254 }
    255 
    256 enum {
    257    SKIP = -1,
    258    FAIL = 0, /* also "false" */
    259    PASS = 1 /* also "true" */
    260 };
    261 
    262 static void
    263 util_report_result_helper(int status, const char *name, ...)
    264 {
    265    char buf[256];
    266    va_list ap;
    267 
    268    va_start(ap, name);
    269    util_vsnprintf(buf, sizeof(buf), name, ap);
    270    va_end(ap);
    271 
    272    printf("Test(%s) = %s\n", buf,
    273           status == SKIP ? "skip" :
    274           status == PASS ? "pass" : "fail");
    275 }
    276 
    277 #define util_report_result(status) util_report_result_helper(status, __func__)
    278 
    279 /**
    280  * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
    281  *
    282  * The viewport state is set as usual, but it should have no effect.
    283  * Clipping should also be disabled.
    284  *
    285  * POSITION.xyz should already be multiplied by 1/w and POSITION.w should
    286  * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't
    287  * multiplied by 1/w (otherwise nothing would be rendered).
    288  *
    289  * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w
    290  *       during perspective interpolation is not tested.
    291  */
    292 static void
    293 tgsi_vs_window_space_position(struct pipe_context *ctx)
    294 {
    295    struct cso_context *cso;
    296    struct pipe_resource *cb;
    297    void *fs, *vs;
    298    bool pass = true;
    299    static const float red[] = {1, 0, 0, 1};
    300 
    301    if (!ctx->screen->get_param(ctx->screen,
    302                                PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) {
    303       util_report_result(SKIP);
    304       return;
    305    }
    306 
    307    cso = cso_create_context(ctx, 0);
    308    cb = util_create_texture2d(ctx->screen, 256, 256,
    309                               PIPE_FORMAT_R8G8B8A8_UNORM);
    310    util_set_common_states_and_clear(cso, ctx, cb);
    311 
    312    /* Fragment shader. */
    313    fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC,
    314                                        TGSI_INTERPOLATE_LINEAR, TRUE);
    315    cso_set_fragment_shader_handle(cso, fs);
    316 
    317    /* Vertex shader. */
    318    vs = util_set_passthrough_vertex_shader(cso, ctx, true);
    319 
    320    /* Draw. */
    321    {
    322       static float vertices[] = {
    323           0,   0, 0, 0,   1,  0, 0, 1,
    324           0, 256, 0, 0,   1,  0, 0, 1,
    325         256, 256, 0, 0,   1,  0, 0, 1,
    326         256,   0, 0, 0,   1,  0, 0, 1,
    327       };
    328       util_set_interleaved_vertex_elements(cso, 2);
    329       util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
    330    }
    331 
    332    /* Probe pixels. */
    333    pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0,
    334                                        cb->width0, cb->height0, red);
    335 
    336    /* Cleanup. */
    337    cso_destroy_context(cso);
    338    ctx->delete_vs_state(ctx, vs);
    339    ctx->delete_fs_state(ctx, fs);
    340    pipe_resource_reference(&cb, NULL);
    341 
    342    util_report_result(pass);
    343 }
    344 
    345 static void
    346 null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
    347 {
    348    struct cso_context *cso;
    349    struct pipe_resource *cb;
    350    void *fs, *vs;
    351    bool pass = true;
    352    /* 2 expected colors: */
    353    static const float expected_tex[] = {0, 0, 0, 1,
    354                                         0, 0, 0, 0};
    355    static const float expected_buf[] = {0, 0, 0, 0};
    356    const float *expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ?
    357                               expected_buf : expected_tex;
    358    unsigned num_expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ? 1 : 2;
    359 
    360    if (tgsi_tex_target == TGSI_TEXTURE_BUFFER &&
    361        !ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) {
    362       util_report_result_helper(SKIP, "%s: %s", __func__,
    363                                 tgsi_texture_names[tgsi_tex_target]);
    364       return;
    365    }
    366 
    367    cso = cso_create_context(ctx, 0);
    368    cb = util_create_texture2d(ctx->screen, 256, 256,
    369                               PIPE_FORMAT_R8G8B8A8_UNORM);
    370    util_set_common_states_and_clear(cso, ctx, cb);
    371 
    372    ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
    373 
    374    /* Fragment shader. */
    375    fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
    376                                       TGSI_INTERPOLATE_LINEAR,
    377                                       TGSI_RETURN_TYPE_FLOAT,
    378                                       TGSI_RETURN_TYPE_FLOAT, false, false);
    379    cso_set_fragment_shader_handle(cso, fs);
    380 
    381    /* Vertex shader. */
    382    vs = util_set_passthrough_vertex_shader(cso, ctx, false);
    383    util_draw_fullscreen_quad(cso);
    384 
    385    /* Probe pixels. */
    386    pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
    387                                   cb->width0, cb->height0, expected,
    388                                   num_expected);
    389 
    390    /* Cleanup. */
    391    cso_destroy_context(cso);
    392    ctx->delete_vs_state(ctx, vs);
    393    ctx->delete_fs_state(ctx, fs);
    394    pipe_resource_reference(&cb, NULL);
    395 
    396    util_report_result_helper(pass, "%s: %s", __func__,
    397                              tgsi_texture_names[tgsi_tex_target]);
    398 }
    399 
    400 void
    401 util_test_constant_buffer(struct pipe_context *ctx,
    402                           struct pipe_resource *constbuf)
    403 {
    404    struct cso_context *cso;
    405    struct pipe_resource *cb;
    406    void *fs, *vs;
    407    bool pass = true;
    408    static const float zero[] = {0, 0, 0, 0};
    409 
    410    cso = cso_create_context(ctx, 0);
    411    cb = util_create_texture2d(ctx->screen, 256, 256,
    412                               PIPE_FORMAT_R8G8B8A8_UNORM);
    413    util_set_common_states_and_clear(cso, ctx, cb);
    414 
    415    pipe_set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, constbuf);
    416 
    417    /* Fragment shader. */
    418    {
    419       static const char *text = /* I don't like ureg... */
    420             "FRAG\n"
    421             "DCL CONST[0][0]\n"
    422             "DCL OUT[0], COLOR\n"
    423 
    424             "MOV OUT[0], CONST[0][0]\n"
    425             "END\n";
    426       struct tgsi_token tokens[1000];
    427       struct pipe_shader_state state;
    428 
    429       if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
    430          puts("Can't compile a fragment shader.");
    431          util_report_result(FAIL);
    432          return;
    433       }
    434       pipe_shader_state_from_tgsi(&state, tokens);
    435       fs = ctx->create_fs_state(ctx, &state);
    436       cso_set_fragment_shader_handle(cso, fs);
    437    }
    438 
    439    /* Vertex shader. */
    440    vs = util_set_passthrough_vertex_shader(cso, ctx, false);
    441    util_draw_fullscreen_quad(cso);
    442 
    443    /* Probe pixels. */
    444    pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, cb->width0,
    445                                        cb->height0, zero);
    446 
    447    /* Cleanup. */
    448    cso_destroy_context(cso);
    449    ctx->delete_vs_state(ctx, vs);
    450    ctx->delete_fs_state(ctx, fs);
    451    pipe_resource_reference(&cb, NULL);
    452 
    453    util_report_result(pass);
    454 }
    455 
    456 static void
    457 null_fragment_shader(struct pipe_context *ctx)
    458 {
    459    struct cso_context *cso;
    460    struct pipe_resource *cb;
    461    void *vs;
    462    struct pipe_rasterizer_state rs = {0};
    463    struct pipe_query *query;
    464    union pipe_query_result qresult;
    465 
    466    cso = cso_create_context(ctx, 0);
    467    cb = util_create_texture2d(ctx->screen, 256, 256,
    468                               PIPE_FORMAT_R8G8B8A8_UNORM);
    469    util_set_common_states_and_clear(cso, ctx, cb);
    470 
    471    /* No rasterization. */
    472    rs.rasterizer_discard = 1;
    473    cso_set_rasterizer(cso, &rs);
    474 
    475    vs = util_set_passthrough_vertex_shader(cso, ctx, false);
    476 
    477    query = ctx->create_query(ctx, PIPE_QUERY_PRIMITIVES_GENERATED, 0);
    478    ctx->begin_query(ctx, query);
    479    util_draw_fullscreen_quad(cso);
    480    ctx->end_query(ctx, query);
    481    ctx->get_query_result(ctx, query, true, &qresult);
    482 
    483    /* Cleanup. */
    484    cso_destroy_context(cso);
    485    ctx->delete_vs_state(ctx, vs);
    486    ctx->destroy_query(ctx, query);
    487    pipe_resource_reference(&cb, NULL);
    488 
    489    /* Check PRIMITIVES_GENERATED. */
    490    util_report_result(qresult.u64 == 2);
    491 }
    492 
    493 #if defined(PIPE_OS_LINUX) && defined(HAVE_LIBDRM)
    494 #include <libsync.h>
    495 #else
    496 #define sync_merge(str, fd1, fd2) (-1)
    497 #define sync_wait(fd, timeout) (-1)
    498 #endif
    499 
    500 static void
    501 test_sync_file_fences(struct pipe_context *ctx)
    502 {
    503    struct pipe_screen *screen = ctx->screen;
    504    bool pass = true;
    505 
    506    if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
    507       return;
    508 
    509    struct cso_context *cso = cso_create_context(ctx, 0);
    510    struct pipe_resource *buf =
    511       pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024);
    512    struct pipe_resource *tex =
    513       util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM);
    514    struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL;
    515 
    516    /* Run 2 clears, get fencess. */
    517    uint32_t value = 0;
    518    ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
    519    ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD);
    520 
    521    struct pipe_box box;
    522    u_box_2d(0, 0, tex->width0, tex->height0, &box);
    523    ctx->clear_texture(ctx, tex, 0, &box, &value);
    524    ctx->flush(ctx, &tex_fence, PIPE_FLUSH_FENCE_FD);
    525    pass = pass && buf_fence && tex_fence;
    526 
    527    /* Export fences. */
    528    int buf_fd = screen->fence_get_fd(screen, buf_fence);
    529    int tex_fd = screen->fence_get_fd(screen, tex_fence);
    530    pass = pass && buf_fd >= 0 && tex_fd >= 0;
    531 
    532    /* Merge fences. */
    533    int merged_fd = sync_merge("test", buf_fd, tex_fd);
    534    pass = pass && merged_fd >= 0;
    535 
    536    /* (Re)import all fences. */
    537    struct pipe_fence_handle *re_buf_fence = NULL, *re_tex_fence = NULL;
    538    struct pipe_fence_handle *merged_fence = NULL;
    539    ctx->create_fence_fd(ctx, &re_buf_fence, buf_fd);
    540    ctx->create_fence_fd(ctx, &re_tex_fence, tex_fd);
    541    ctx->create_fence_fd(ctx, &merged_fence, merged_fd);
    542    pass = pass && re_buf_fence && re_tex_fence && merged_fence;
    543 
    544    /* Run another clear after waiting for everything. */
    545    struct pipe_fence_handle *final_fence = NULL;
    546    ctx->fence_server_sync(ctx, merged_fence);
    547    value = 0xff;
    548    ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
    549    ctx->flush(ctx, &final_fence, PIPE_FLUSH_FENCE_FD);
    550    pass = pass && final_fence;
    551 
    552    /* Wait for the last fence. */
    553    int final_fd = screen->fence_get_fd(screen, final_fence);
    554    pass = pass && final_fd >= 0;
    555    pass = pass && sync_wait(final_fd, -1) == 0;
    556 
    557    /* Check that all fences are signalled. */
    558    pass = pass && sync_wait(buf_fd, 0) == 0;
    559    pass = pass && sync_wait(tex_fd, 0) == 0;
    560    pass = pass && sync_wait(merged_fd, 0) == 0;
    561 
    562    pass = pass && screen->fence_finish(screen, NULL, buf_fence, 0);
    563    pass = pass && screen->fence_finish(screen, NULL, tex_fence, 0);
    564    pass = pass && screen->fence_finish(screen, NULL, re_buf_fence, 0);
    565    pass = pass && screen->fence_finish(screen, NULL, re_tex_fence, 0);
    566    pass = pass && screen->fence_finish(screen, NULL, merged_fence, 0);
    567    pass = pass && screen->fence_finish(screen, NULL, final_fence, 0);
    568 
    569    /* Cleanup. */
    570 #ifndef PIPE_OS_WINDOWS
    571    if (buf_fd >= 0)
    572       close(buf_fd);
    573    if (tex_fd >= 0)
    574       close(tex_fd);
    575    if (merged_fd >= 0)
    576       close(merged_fd);
    577    if (final_fd >= 0)
    578       close(final_fd);
    579 #endif
    580 
    581    screen->fence_reference(screen, &buf_fence, NULL);
    582    screen->fence_reference(screen, &tex_fence, NULL);
    583    screen->fence_reference(screen, &re_buf_fence, NULL);
    584    screen->fence_reference(screen, &re_tex_fence, NULL);
    585    screen->fence_reference(screen, &merged_fence, NULL);
    586    screen->fence_reference(screen, &final_fence, NULL);
    587 
    588    cso_destroy_context(cso);
    589    pipe_resource_reference(&buf, NULL);
    590    pipe_resource_reference(&tex, NULL);
    591 
    592    util_report_result(pass);
    593 }
    594 
    595 /**
    596  * Run all tests. This should be run with a clean context after
    597  * context_create.
    598  */
    599 void
    600 util_run_tests(struct pipe_screen *screen)
    601 {
    602    struct pipe_context *ctx = screen->context_create(screen, NULL, 0);
    603 
    604    null_fragment_shader(ctx);
    605    tgsi_vs_window_space_position(ctx);
    606    null_sampler_view(ctx, TGSI_TEXTURE_2D);
    607    null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
    608    util_test_constant_buffer(ctx, NULL);
    609    test_sync_file_fences(ctx);
    610 
    611    ctx->destroy(ctx);
    612 
    613    puts("Done. Exiting..");
    614    exit(0);
    615 }
    616