• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
util_create_texture2d(struct pipe_screen * screen,unsigned width,unsigned height,enum pipe_format format)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
util_set_framebuffer_cb0(struct cso_context * cso,struct pipe_context * ctx,struct pipe_resource * tex)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
util_set_blend_normal(struct cso_context * cso)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
util_set_dsa_disable(struct cso_context * cso)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
util_set_rasterizer_normal(struct cso_context * cso)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
util_set_max_viewport(struct cso_context * cso,struct pipe_resource * tex)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
util_set_interleaved_vertex_elements(struct cso_context * cso,unsigned num_elements)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 *
util_set_passthrough_vertex_shader(struct cso_context * cso,struct pipe_context * ctx,bool window_space)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
util_set_common_states_and_clear(struct cso_context * cso,struct pipe_context * ctx,struct pipe_resource * cb)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
util_draw_fullscreen_quad(struct cso_context * cso)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
util_probe_rect_rgba_multi(struct pipe_context * ctx,struct pipe_resource * tex,unsigned offx,unsigned offy,unsigned w,unsigned h,const float * expected,unsigned num_expected_colors)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
util_probe_rect_rgba(struct pipe_context * ctx,struct pipe_resource * tex,unsigned offx,unsigned offy,unsigned w,unsigned h,const float * expected)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
util_report_result_helper(int status,const char * name,...)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
tgsi_vs_window_space_position(struct pipe_context * ctx)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
null_sampler_view(struct pipe_context * ctx,unsigned tgsi_tex_target)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
util_test_constant_buffer(struct pipe_context * ctx,struct pipe_resource * constbuf)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
null_fragment_shader(struct pipe_context * ctx)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
test_sync_file_fences(struct pipe_context * ctx)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
util_run_tests(struct pipe_screen * screen)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