e8599e320313b4597d2ae3e6c2f27608fa202019
[mesa.git] / src / gallium / auxiliary / util / u_tests.c
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[3]);
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 enum pipe_fd_type fd_type = PIPE_FD_TYPE_NATIVE_SYNC;
506
507 if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
508 return;
509
510 struct cso_context *cso = cso_create_context(ctx, 0);
511 struct pipe_resource *buf =
512 pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024);
513 struct pipe_resource *tex =
514 util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM);
515 struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL;
516
517 /* Run 2 clears, get fencess. */
518 uint32_t value = 0;
519 ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
520 ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD);
521
522 struct pipe_box box;
523 u_box_2d(0, 0, tex->width0, tex->height0, &box);
524 ctx->clear_texture(ctx, tex, 0, &box, &value);
525 ctx->flush(ctx, &tex_fence, PIPE_FLUSH_FENCE_FD);
526 pass = pass && buf_fence && tex_fence;
527
528 /* Export fences. */
529 int buf_fd = screen->fence_get_fd(screen, buf_fence);
530 int tex_fd = screen->fence_get_fd(screen, tex_fence);
531 pass = pass && buf_fd >= 0 && tex_fd >= 0;
532
533 /* Merge fences. */
534 int merged_fd = sync_merge("test", buf_fd, tex_fd);
535 pass = pass && merged_fd >= 0;
536
537 /* (Re)import all fences. */
538 struct pipe_fence_handle *re_buf_fence = NULL, *re_tex_fence = NULL;
539 struct pipe_fence_handle *merged_fence = NULL;
540 ctx->create_fence_fd(ctx, &re_buf_fence, buf_fd, fd_type);
541 ctx->create_fence_fd(ctx, &re_tex_fence, tex_fd, fd_type);
542 ctx->create_fence_fd(ctx, &merged_fence, merged_fd, fd_type);
543 pass = pass && re_buf_fence && re_tex_fence && merged_fence;
544
545 /* Run another clear after waiting for everything. */
546 struct pipe_fence_handle *final_fence = NULL;
547 ctx->fence_server_sync(ctx, merged_fence);
548 value = 0xff;
549 ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
550 ctx->flush(ctx, &final_fence, PIPE_FLUSH_FENCE_FD);
551 pass = pass && final_fence;
552
553 /* Wait for the last fence. */
554 int final_fd = screen->fence_get_fd(screen, final_fence);
555 pass = pass && final_fd >= 0;
556 pass = pass && sync_wait(final_fd, -1) == 0;
557
558 /* Check that all fences are signalled. */
559 pass = pass && sync_wait(buf_fd, 0) == 0;
560 pass = pass && sync_wait(tex_fd, 0) == 0;
561 pass = pass && sync_wait(merged_fd, 0) == 0;
562
563 pass = pass && screen->fence_finish(screen, NULL, buf_fence, 0);
564 pass = pass && screen->fence_finish(screen, NULL, tex_fence, 0);
565 pass = pass && screen->fence_finish(screen, NULL, re_buf_fence, 0);
566 pass = pass && screen->fence_finish(screen, NULL, re_tex_fence, 0);
567 pass = pass && screen->fence_finish(screen, NULL, merged_fence, 0);
568 pass = pass && screen->fence_finish(screen, NULL, final_fence, 0);
569
570 /* Cleanup. */
571 #ifndef PIPE_OS_WINDOWS
572 if (buf_fd >= 0)
573 close(buf_fd);
574 if (tex_fd >= 0)
575 close(tex_fd);
576 if (merged_fd >= 0)
577 close(merged_fd);
578 if (final_fd >= 0)
579 close(final_fd);
580 #endif
581
582 screen->fence_reference(screen, &buf_fence, NULL);
583 screen->fence_reference(screen, &tex_fence, NULL);
584 screen->fence_reference(screen, &re_buf_fence, NULL);
585 screen->fence_reference(screen, &re_tex_fence, NULL);
586 screen->fence_reference(screen, &merged_fence, NULL);
587 screen->fence_reference(screen, &final_fence, NULL);
588
589 cso_destroy_context(cso);
590 pipe_resource_reference(&buf, NULL);
591 pipe_resource_reference(&tex, NULL);
592
593 util_report_result(pass);
594 }
595
596 static void
597 test_texture_barrier(struct pipe_context *ctx, bool use_fbfetch)
598 {
599 struct cso_context *cso;
600 struct pipe_resource *cb;
601 void *fs, *vs;
602 struct pipe_sampler_view *view = NULL;
603 const char *text;
604
605 if (!ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BARRIER)) {
606 util_report_result_helper(SKIP, "%s: %s", __func__,
607 use_fbfetch ? "FBFETCH" : "sampler");
608 return;
609 }
610 if (use_fbfetch &&
611 !ctx->screen->get_param(ctx->screen, PIPE_CAP_TGSI_FS_FBFETCH)) {
612 util_report_result_helper(SKIP, "%s: %s", __func__,
613 use_fbfetch ? "FBFETCH" : "sampler");
614 return;
615 }
616
617 cso = cso_create_context(ctx, 0);
618 cb = util_create_texture2d(ctx->screen, 256, 256,
619 PIPE_FORMAT_R8G8B8A8_UNORM);
620 util_set_common_states_and_clear(cso, ctx, cb);
621
622 if (use_fbfetch) {
623 /* Fragment shader. */
624 text = "FRAG\n"
625 "DCL OUT[0], COLOR[0]\n"
626 "DCL TEMP[0]\n"
627 "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
628
629 "FBFETCH TEMP[0], OUT[0]\n"
630 "ADD OUT[0], TEMP[0], IMM[0]\n"
631 "END\n";
632 } else {
633 struct pipe_sampler_view templ = {{0}};
634 templ.format = cb->format;
635 templ.target = cb->target;
636 templ.swizzle_r = PIPE_SWIZZLE_X;
637 templ.swizzle_g = PIPE_SWIZZLE_Y;
638 templ.swizzle_b = PIPE_SWIZZLE_Z;
639 templ.swizzle_a = PIPE_SWIZZLE_W;
640 view = ctx->create_sampler_view(ctx, cb, &templ);
641 ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &view);
642
643 /* Fragment shader. */
644 text = "FRAG\n"
645 "DCL SV[0], POSITION\n"
646 "DCL SAMP[0]\n"
647 "DCL SVIEW[0], 2D, FLOAT\n"
648 "DCL OUT[0], COLOR[0]\n"
649 "DCL TEMP[0]\n"
650 "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
651 "IMM[1] INT32 { 0, 0, 0, 0}\n"
652
653 "F2I TEMP[0].xy, SV[0].xyyy\n"
654 "MOV TEMP[0].z, IMM[1].xxxx\n"
655 "TXF TEMP[0], TEMP[0].xyzz, SAMP[0], 2D\n"
656 "ADD OUT[0], TEMP[0], IMM[0]\n"
657 "END\n";
658 }
659
660 struct tgsi_token tokens[1000];
661 struct pipe_shader_state state;
662
663 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
664 assert(0);
665 util_report_result_helper(FAIL, "%s: %s", __func__,
666 use_fbfetch ? "FBFETCH" : "sampler");
667 return;
668 }
669 pipe_shader_state_from_tgsi(&state, tokens);
670 #if 0
671 tgsi_dump(state.tokens, 0);
672 #endif
673
674 fs = ctx->create_fs_state(ctx, &state);
675 cso_set_fragment_shader_handle(cso, fs);
676
677 /* Vertex shader. */
678 vs = util_set_passthrough_vertex_shader(cso, ctx, false);
679
680 for (int i = 0; i < 2; i++) {
681 ctx->texture_barrier(ctx,
682 use_fbfetch ? PIPE_TEXTURE_BARRIER_FRAMEBUFFER :
683 PIPE_TEXTURE_BARRIER_SAMPLER);
684 util_draw_fullscreen_quad(cso);
685 }
686
687 /* Probe pixels. */
688 static const float expected[] = {0.3, 0.5, 0.7, 0.9};
689 bool pass = util_probe_rect_rgba(ctx, cb, 0, 0,
690 cb->width0, cb->height0, expected);
691
692 /* Cleanup. */
693 cso_destroy_context(cso);
694 ctx->delete_vs_state(ctx, vs);
695 ctx->delete_fs_state(ctx, fs);
696 pipe_sampler_view_reference(&view, NULL);
697 pipe_resource_reference(&cb, NULL);
698
699 util_report_result_helper(pass, "%s: %s", __func__,
700 use_fbfetch ? "FBFETCH" : "sampler");
701 }
702
703 /**
704 * Run all tests. This should be run with a clean context after
705 * context_create.
706 */
707 void
708 util_run_tests(struct pipe_screen *screen)
709 {
710 struct pipe_context *ctx = screen->context_create(screen, NULL, 0);
711
712 null_fragment_shader(ctx);
713 tgsi_vs_window_space_position(ctx);
714 null_sampler_view(ctx, TGSI_TEXTURE_2D);
715 null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
716 util_test_constant_buffer(ctx, NULL);
717 test_sync_file_fences(ctx);
718 test_texture_barrier(ctx, false);
719 test_texture_barrier(ctx, true);
720
721 ctx->destroy(ctx);
722
723 puts("Done. Exiting..");
724 exit(0);
725 }