1 /**************************************************************************
3 * Copyright 2014 Advanced Micro Devices, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
28 #include "util/u_tests.h"
30 #include "util/u_draw_quad.h"
31 #include "util/format/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 "state_tracker/winsys_handle.h"
44 #define TOLERANCE 0.01
46 static struct pipe_resource
*
47 util_create_texture2d(struct pipe_screen
*screen
, unsigned width
,
48 unsigned height
, enum pipe_format format
,
51 struct pipe_resource templ
= {{0}};
53 templ
.target
= PIPE_TEXTURE_2D
;
55 templ
.height0
= height
;
58 templ
.nr_samples
= num_samples
;
59 templ
.nr_storage_samples
= num_samples
;
60 templ
.format
= format
;
61 templ
.usage
= PIPE_USAGE_DEFAULT
;
62 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
|
63 (util_format_is_depth_or_stencil(format
) ?
64 PIPE_BIND_DEPTH_STENCIL
: PIPE_BIND_RENDER_TARGET
);
66 return screen
->resource_create(screen
, &templ
);
70 util_set_framebuffer_cb0(struct cso_context
*cso
, struct pipe_context
*ctx
,
71 struct pipe_resource
*tex
)
73 struct pipe_surface templ
= {{0}}, *surf
;
74 struct pipe_framebuffer_state fb
= {0};
76 templ
.format
= tex
->format
;
77 surf
= ctx
->create_surface(ctx
, tex
, &templ
);
79 fb
.width
= tex
->width0
;
80 fb
.height
= tex
->height0
;
84 cso_set_framebuffer(cso
, &fb
);
85 pipe_surface_reference(&surf
, NULL
);
89 util_set_blend_normal(struct cso_context
*cso
)
91 struct pipe_blend_state blend
= {0};
93 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
94 cso_set_blend(cso
, &blend
);
98 util_set_dsa_disable(struct cso_context
*cso
)
100 struct pipe_depth_stencil_alpha_state dsa
= {{0}};
102 cso_set_depth_stencil_alpha(cso
, &dsa
);
106 util_set_rasterizer_normal(struct cso_context
*cso
)
108 struct pipe_rasterizer_state rs
= {0};
110 rs
.half_pixel_center
= 1;
111 rs
.bottom_edge_rule
= 1;
112 rs
.depth_clip_near
= 1;
113 rs
.depth_clip_far
= 1;
115 cso_set_rasterizer(cso
, &rs
);
119 util_set_max_viewport(struct cso_context
*cso
, struct pipe_resource
*tex
)
121 struct pipe_viewport_state viewport
;
123 viewport
.scale
[0] = 0.5f
* tex
->width0
;
124 viewport
.scale
[1] = 0.5f
* tex
->height0
;
125 viewport
.scale
[2] = 1.0f
;
126 viewport
.translate
[0] = 0.5f
* tex
->width0
;
127 viewport
.translate
[1] = 0.5f
* tex
->height0
;
128 viewport
.translate
[2] = 0.0f
;
130 cso_set_viewport(cso
, &viewport
);
134 util_set_interleaved_vertex_elements(struct cso_context
*cso
,
135 unsigned num_elements
)
137 struct cso_velems_state velem
;
140 memset(&velem
, 0, sizeof(velem
));
141 velem
.count
= num_elements
;
142 for (i
= 0; i
< num_elements
; i
++) {
143 velem
.velems
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
144 velem
.velems
[i
].src_offset
= i
* 16;
147 cso_set_vertex_elements(cso
, &velem
);
151 util_set_passthrough_vertex_shader(struct cso_context
*cso
,
152 struct pipe_context
*ctx
,
155 static const enum tgsi_semantic vs_attribs
[] = {
156 TGSI_SEMANTIC_POSITION
,
157 TGSI_SEMANTIC_GENERIC
159 static const uint vs_indices
[] = {0, 0};
162 vs
= util_make_vertex_passthrough_shader(ctx
, 2, vs_attribs
, vs_indices
,
164 cso_set_vertex_shader_handle(cso
, vs
);
169 util_set_common_states_and_clear(struct cso_context
*cso
, struct pipe_context
*ctx
,
170 struct pipe_resource
*cb
)
172 static const float clear_color
[] = {0.1, 0.1, 0.1, 0.1};
174 util_set_framebuffer_cb0(cso
, ctx
, cb
);
175 util_set_blend_normal(cso
);
176 util_set_dsa_disable(cso
);
177 util_set_rasterizer_normal(cso
);
178 util_set_max_viewport(cso
, cb
);
180 ctx
->clear(ctx
, PIPE_CLEAR_COLOR0
, (void*)clear_color
, 0, 0);
184 util_draw_fullscreen_quad(struct cso_context
*cso
)
186 static float vertices
[] = {
187 -1, -1, 0, 1, 0, 0, 0, 0,
188 -1, 1, 0, 1, 0, 1, 0, 0,
189 1, 1, 0, 1, 1, 1, 0, 0,
190 1, -1, 0, 1, 1, 0, 0, 0
192 util_set_interleaved_vertex_elements(cso
, 2);
193 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
197 util_draw_fullscreen_quad_fill(struct cso_context
*cso
,
198 float r
, float g
, float b
, float a
)
201 -1, -1, 0, 1, r
, g
, b
, a
,
202 -1, 1, 0, 1, r
, g
, b
, a
,
203 1, 1, 0, 1, r
, g
, b
, a
,
204 1, -1, 0, 1, r
, g
, b
, a
,
206 util_set_interleaved_vertex_elements(cso
, 2);
207 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
211 * Probe and test if the rectangle contains the expected color.
213 * If "num_expected_colors" > 1, at least one expected color must match
214 * the probed color. "expected" should be an array of 4*num_expected_colors
218 util_probe_rect_rgba_multi(struct pipe_context
*ctx
, struct pipe_resource
*tex
,
219 unsigned offx
, unsigned offy
, unsigned w
,
221 const float *expected
,
222 unsigned num_expected_colors
)
224 struct pipe_transfer
*transfer
;
226 float *pixels
= malloc(w
* h
* 4 * sizeof(float));
230 map
= pipe_transfer_map(ctx
, tex
, 0, 0, PIPE_TRANSFER_READ
,
231 offx
, offy
, w
, h
, &transfer
);
232 pipe_get_tile_rgba(transfer
, map
, 0, 0, w
, h
, tex
->format
, pixels
);
233 pipe_transfer_unmap(ctx
, transfer
);
235 for (e
= 0; e
< num_expected_colors
; e
++) {
236 for (y
= 0; y
< h
; y
++) {
237 for (x
= 0; x
< w
; x
++) {
238 float *probe
= &pixels
[(y
*w
+ x
)*4];
240 for (c
= 0; c
< 4; c
++) {
241 if (fabs(probe
[c
] - expected
[e
*4+c
]) >= TOLERANCE
) {
242 if (e
< num_expected_colors
-1)
243 goto next_color
; /* test the next expected color */
245 printf("Probe color at (%i,%i), ", offx
+x
, offy
+y
);
246 printf("Expected: %.3f, %.3f, %.3f, %.3f, ",
247 expected
[e
*4], expected
[e
*4+1],
248 expected
[e
*4+2], expected
[e
*4+3]);
249 printf("Got: %.3f, %.3f, %.3f, %.3f\n",
250 probe
[0], probe
[1], probe
[2], probe
[3]);
257 break; /* this color was successful */
268 util_probe_rect_rgba(struct pipe_context
*ctx
, struct pipe_resource
*tex
,
269 unsigned offx
, unsigned offy
, unsigned w
, unsigned h
,
270 const float *expected
)
272 return util_probe_rect_rgba_multi(ctx
, tex
, offx
, offy
, w
, h
, expected
, 1);
277 FAIL
= 0, /* also "false" */
278 PASS
= 1 /* also "true" */
282 util_report_result_helper(int status
, const char *name
, ...)
288 vsnprintf(buf
, sizeof(buf
), name
, ap
);
291 printf("Test(%s) = %s\n", buf
,
292 status
== SKIP
? "skip" :
293 status
== PASS
? "pass" : "fail");
296 #define util_report_result(status) util_report_result_helper(status, __func__)
299 * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
301 * The viewport state is set as usual, but it should have no effect.
302 * Clipping should also be disabled.
304 * POSITION.xyz should already be multiplied by 1/w and POSITION.w should
305 * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't
306 * multiplied by 1/w (otherwise nothing would be rendered).
308 * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w
309 * during perspective interpolation is not tested.
312 tgsi_vs_window_space_position(struct pipe_context
*ctx
)
314 struct cso_context
*cso
;
315 struct pipe_resource
*cb
;
318 static const float red
[] = {1, 0, 0, 1};
320 if (!ctx
->screen
->get_param(ctx
->screen
,
321 PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION
)) {
322 util_report_result(SKIP
);
326 cso
= cso_create_context(ctx
, 0);
327 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
328 PIPE_FORMAT_R8G8B8A8_UNORM
, 0);
329 util_set_common_states_and_clear(cso
, ctx
, cb
);
331 /* Fragment shader. */
332 fs
= util_make_fragment_passthrough_shader(ctx
, TGSI_SEMANTIC_GENERIC
,
333 TGSI_INTERPOLATE_LINEAR
, TRUE
);
334 cso_set_fragment_shader_handle(cso
, fs
);
337 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, true);
341 static float vertices
[] = {
342 0, 0, 0, 0, 1, 0, 0, 1,
343 0, 256, 0, 0, 1, 0, 0, 1,
344 256, 256, 0, 0, 1, 0, 0, 1,
345 256, 0, 0, 0, 1, 0, 0, 1,
347 util_set_interleaved_vertex_elements(cso
, 2);
348 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
352 pass
= pass
&& util_probe_rect_rgba(ctx
, cb
, 0, 0,
353 cb
->width0
, cb
->height0
, red
);
356 cso_destroy_context(cso
);
357 ctx
->delete_vs_state(ctx
, vs
);
358 ctx
->delete_fs_state(ctx
, fs
);
359 pipe_resource_reference(&cb
, NULL
);
361 util_report_result(pass
);
365 null_sampler_view(struct pipe_context
*ctx
, unsigned tgsi_tex_target
)
367 struct cso_context
*cso
;
368 struct pipe_resource
*cb
;
371 /* 2 expected colors: */
372 static const float expected_tex
[] = {0, 0, 0, 1,
374 static const float expected_buf
[] = {0, 0, 0, 0};
375 const float *expected
= tgsi_tex_target
== TGSI_TEXTURE_BUFFER
?
376 expected_buf
: expected_tex
;
377 unsigned num_expected
= tgsi_tex_target
== TGSI_TEXTURE_BUFFER
? 1 : 2;
379 if (tgsi_tex_target
== TGSI_TEXTURE_BUFFER
&&
380 !ctx
->screen
->get_param(ctx
->screen
, PIPE_CAP_TEXTURE_BUFFER_OBJECTS
)) {
381 util_report_result_helper(SKIP
, "%s: %s", __func__
,
382 tgsi_texture_names
[tgsi_tex_target
]);
386 cso
= cso_create_context(ctx
, 0);
387 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
388 PIPE_FORMAT_R8G8B8A8_UNORM
, 0);
389 util_set_common_states_and_clear(cso
, ctx
, cb
);
391 ctx
->set_sampler_views(ctx
, PIPE_SHADER_FRAGMENT
, 0, 1, NULL
);
393 /* Fragment shader. */
394 fs
= util_make_fragment_tex_shader(ctx
, tgsi_tex_target
,
395 TGSI_INTERPOLATE_LINEAR
,
396 TGSI_RETURN_TYPE_FLOAT
,
397 TGSI_RETURN_TYPE_FLOAT
, false, false);
398 cso_set_fragment_shader_handle(cso
, fs
);
401 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
402 util_draw_fullscreen_quad(cso
);
405 pass
= pass
&& util_probe_rect_rgba_multi(ctx
, cb
, 0, 0,
406 cb
->width0
, cb
->height0
, expected
,
410 cso_destroy_context(cso
);
411 ctx
->delete_vs_state(ctx
, vs
);
412 ctx
->delete_fs_state(ctx
, fs
);
413 pipe_resource_reference(&cb
, NULL
);
415 util_report_result_helper(pass
, "%s: %s", __func__
,
416 tgsi_texture_names
[tgsi_tex_target
]);
420 util_test_constant_buffer(struct pipe_context
*ctx
,
421 struct pipe_resource
*constbuf
)
423 struct cso_context
*cso
;
424 struct pipe_resource
*cb
;
427 static const float zero
[] = {0, 0, 0, 0};
429 cso
= cso_create_context(ctx
, 0);
430 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
431 PIPE_FORMAT_R8G8B8A8_UNORM
, 0);
432 util_set_common_states_and_clear(cso
, ctx
, cb
);
434 pipe_set_constant_buffer(ctx
, PIPE_SHADER_FRAGMENT
, 0, constbuf
);
436 /* Fragment shader. */
438 static const char *text
= /* I don't like ureg... */
441 "DCL OUT[0], COLOR\n"
443 "MOV OUT[0], CONST[0][0]\n"
445 struct tgsi_token tokens
[1000];
446 struct pipe_shader_state state
;
448 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
449 puts("Can't compile a fragment shader.");
450 util_report_result(FAIL
);
453 pipe_shader_state_from_tgsi(&state
, tokens
);
454 fs
= ctx
->create_fs_state(ctx
, &state
);
455 cso_set_fragment_shader_handle(cso
, fs
);
459 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
460 util_draw_fullscreen_quad(cso
);
463 pass
= pass
&& util_probe_rect_rgba(ctx
, cb
, 0, 0, cb
->width0
,
467 cso_destroy_context(cso
);
468 ctx
->delete_vs_state(ctx
, vs
);
469 ctx
->delete_fs_state(ctx
, fs
);
470 pipe_resource_reference(&cb
, NULL
);
472 util_report_result(pass
);
476 null_fragment_shader(struct pipe_context
*ctx
)
478 struct cso_context
*cso
;
479 struct pipe_resource
*cb
;
481 struct pipe_rasterizer_state rs
= {0};
482 struct pipe_query
*query
;
483 union pipe_query_result qresult
;
485 cso
= cso_create_context(ctx
, 0);
486 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
487 PIPE_FORMAT_R8G8B8A8_UNORM
, 0);
488 util_set_common_states_and_clear(cso
, ctx
, cb
);
490 /* No rasterization. */
491 rs
.rasterizer_discard
= 1;
492 cso_set_rasterizer(cso
, &rs
);
494 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
496 query
= ctx
->create_query(ctx
, PIPE_QUERY_PRIMITIVES_GENERATED
, 0);
497 ctx
->begin_query(ctx
, query
);
498 util_draw_fullscreen_quad(cso
);
499 ctx
->end_query(ctx
, query
);
500 ctx
->get_query_result(ctx
, query
, true, &qresult
);
503 cso_destroy_context(cso
);
504 ctx
->delete_vs_state(ctx
, vs
);
505 ctx
->destroy_query(ctx
, query
);
506 pipe_resource_reference(&cb
, NULL
);
508 /* Check PRIMITIVES_GENERATED. */
509 util_report_result(qresult
.u64
== 2);
512 #if defined(PIPE_OS_LINUX) && defined(HAVE_LIBDRM)
515 #define sync_merge(str, fd1, fd2) (-1)
516 #define sync_wait(fd, timeout) (-1)
520 test_sync_file_fences(struct pipe_context
*ctx
)
522 struct pipe_screen
*screen
= ctx
->screen
;
524 enum pipe_fd_type fd_type
= PIPE_FD_TYPE_NATIVE_SYNC
;
526 if (!screen
->get_param(screen
, PIPE_CAP_NATIVE_FENCE_FD
))
529 struct cso_context
*cso
= cso_create_context(ctx
, 0);
530 struct pipe_resource
*buf
=
531 pipe_buffer_create(screen
, 0, PIPE_USAGE_DEFAULT
, 1024 * 1024);
532 struct pipe_resource
*tex
=
533 util_create_texture2d(screen
, 4096, 1024, PIPE_FORMAT_R8_UNORM
, 0);
534 struct pipe_fence_handle
*buf_fence
= NULL
, *tex_fence
= NULL
;
536 /* Run 2 clears, get fencess. */
538 ctx
->clear_buffer(ctx
, buf
, 0, buf
->width0
, &value
, sizeof(value
));
539 ctx
->flush(ctx
, &buf_fence
, PIPE_FLUSH_FENCE_FD
);
542 u_box_2d(0, 0, tex
->width0
, tex
->height0
, &box
);
543 ctx
->clear_texture(ctx
, tex
, 0, &box
, &value
);
544 ctx
->flush(ctx
, &tex_fence
, PIPE_FLUSH_FENCE_FD
);
545 pass
= pass
&& buf_fence
&& tex_fence
;
548 int buf_fd
= screen
->fence_get_fd(screen
, buf_fence
);
549 int tex_fd
= screen
->fence_get_fd(screen
, tex_fence
);
550 pass
= pass
&& buf_fd
>= 0 && tex_fd
>= 0;
553 int merged_fd
= sync_merge("test", buf_fd
, tex_fd
);
554 pass
= pass
&& merged_fd
>= 0;
556 /* (Re)import all fences. */
557 struct pipe_fence_handle
*re_buf_fence
= NULL
, *re_tex_fence
= NULL
;
558 struct pipe_fence_handle
*merged_fence
= NULL
;
559 ctx
->create_fence_fd(ctx
, &re_buf_fence
, buf_fd
, fd_type
);
560 ctx
->create_fence_fd(ctx
, &re_tex_fence
, tex_fd
, fd_type
);
561 ctx
->create_fence_fd(ctx
, &merged_fence
, merged_fd
, fd_type
);
562 pass
= pass
&& re_buf_fence
&& re_tex_fence
&& merged_fence
;
564 /* Run another clear after waiting for everything. */
565 struct pipe_fence_handle
*final_fence
= NULL
;
566 ctx
->fence_server_sync(ctx
, merged_fence
);
568 ctx
->clear_buffer(ctx
, buf
, 0, buf
->width0
, &value
, sizeof(value
));
569 ctx
->flush(ctx
, &final_fence
, PIPE_FLUSH_FENCE_FD
);
570 pass
= pass
&& final_fence
;
572 /* Wait for the last fence. */
573 int final_fd
= screen
->fence_get_fd(screen
, final_fence
);
574 pass
= pass
&& final_fd
>= 0;
575 pass
= pass
&& sync_wait(final_fd
, -1) == 0;
577 /* Check that all fences are signalled. */
578 pass
= pass
&& sync_wait(buf_fd
, 0) == 0;
579 pass
= pass
&& sync_wait(tex_fd
, 0) == 0;
580 pass
= pass
&& sync_wait(merged_fd
, 0) == 0;
582 pass
= pass
&& screen
->fence_finish(screen
, NULL
, buf_fence
, 0);
583 pass
= pass
&& screen
->fence_finish(screen
, NULL
, tex_fence
, 0);
584 pass
= pass
&& screen
->fence_finish(screen
, NULL
, re_buf_fence
, 0);
585 pass
= pass
&& screen
->fence_finish(screen
, NULL
, re_tex_fence
, 0);
586 pass
= pass
&& screen
->fence_finish(screen
, NULL
, merged_fence
, 0);
587 pass
= pass
&& screen
->fence_finish(screen
, NULL
, final_fence
, 0);
590 #ifndef PIPE_OS_WINDOWS
601 screen
->fence_reference(screen
, &buf_fence
, NULL
);
602 screen
->fence_reference(screen
, &tex_fence
, NULL
);
603 screen
->fence_reference(screen
, &re_buf_fence
, NULL
);
604 screen
->fence_reference(screen
, &re_tex_fence
, NULL
);
605 screen
->fence_reference(screen
, &merged_fence
, NULL
);
606 screen
->fence_reference(screen
, &final_fence
, NULL
);
608 cso_destroy_context(cso
);
609 pipe_resource_reference(&buf
, NULL
);
610 pipe_resource_reference(&tex
, NULL
);
612 util_report_result(pass
);
616 test_texture_barrier(struct pipe_context
*ctx
, bool use_fbfetch
,
617 unsigned num_samples
)
619 struct cso_context
*cso
;
620 struct pipe_resource
*cb
;
621 struct pipe_sampler_view
*view
= NULL
;
625 assert(num_samples
>= 1 && num_samples
<= 8);
627 snprintf(name
, sizeof(name
), "%s: %s, %u samples", __func__
,
628 use_fbfetch
? "FBFETCH" : "sampler", MAX2(num_samples
, 1));
630 if (!ctx
->screen
->get_param(ctx
->screen
, PIPE_CAP_TEXTURE_BARRIER
)) {
631 util_report_result_helper(SKIP
, name
);
635 !ctx
->screen
->get_param(ctx
->screen
, PIPE_CAP_FBFETCH
)) {
636 util_report_result_helper(SKIP
, name
);
640 cso
= cso_create_context(ctx
, 0);
641 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
642 PIPE_FORMAT_R8G8B8A8_UNORM
, num_samples
);
643 util_set_common_states_and_clear(cso
, ctx
, cb
);
645 /* Clear each sample to a different value. */
646 if (num_samples
> 1) {
648 util_make_fragment_passthrough_shader(ctx
, TGSI_SEMANTIC_GENERIC
,
649 TGSI_INTERPOLATE_LINEAR
, TRUE
);
650 cso_set_fragment_shader_handle(cso
, fs
);
653 void *vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
655 for (unsigned i
= 0; i
< num_samples
/ 2; i
++) {
658 /* 2 consecutive samples should have the same color to test MSAA
659 * compression properly.
661 if (num_samples
== 2) {
664 /* The average value must be 0.1 */
665 static const float values
[] = {
671 ctx
->set_sample_mask(ctx
, 0x3 << (i
* 2));
672 util_draw_fullscreen_quad_fill(cso
, value
, value
, value
, value
);
674 ctx
->set_sample_mask(ctx
, ~0);
676 cso_set_vertex_shader_handle(cso
, NULL
);
677 cso_set_fragment_shader_handle(cso
, NULL
);
678 ctx
->delete_vs_state(ctx
, vs
);
679 ctx
->delete_fs_state(ctx
, fs
);
683 /* Fragment shader. */
685 "DCL OUT[0], COLOR[0]\n"
687 "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
689 "FBFETCH TEMP[0], OUT[0]\n"
690 "ADD OUT[0], TEMP[0], IMM[0]\n"
693 struct pipe_sampler_view templ
= {{0}};
694 templ
.format
= cb
->format
;
695 templ
.target
= cb
->target
;
696 templ
.swizzle_r
= PIPE_SWIZZLE_X
;
697 templ
.swizzle_g
= PIPE_SWIZZLE_Y
;
698 templ
.swizzle_b
= PIPE_SWIZZLE_Z
;
699 templ
.swizzle_a
= PIPE_SWIZZLE_W
;
700 view
= ctx
->create_sampler_view(ctx
, cb
, &templ
);
701 ctx
->set_sampler_views(ctx
, PIPE_SHADER_FRAGMENT
, 0, 1, &view
);
703 /* Fragment shader. */
704 if (num_samples
> 1) {
706 "DCL SV[0], POSITION\n"
707 "DCL SV[1], SAMPLEID\n"
709 "DCL SVIEW[0], 2D_MSAA, FLOAT\n"
710 "DCL OUT[0], COLOR[0]\n"
712 "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
714 "F2I TEMP[0].xy, SV[0].xyyy\n"
715 "MOV TEMP[0].w, SV[1].xxxx\n"
716 "TXF TEMP[0], TEMP[0], SAMP[0], 2D_MSAA\n"
717 "ADD OUT[0], TEMP[0], IMM[0]\n"
721 "DCL SV[0], POSITION\n"
723 "DCL SVIEW[0], 2D, FLOAT\n"
724 "DCL OUT[0], COLOR[0]\n"
726 "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n"
727 "IMM[1] INT32 { 0, 0, 0, 0}\n"
729 "F2I TEMP[0].xy, SV[0].xyyy\n"
730 "MOV TEMP[0].zw, IMM[1]\n"
731 "TXF TEMP[0], TEMP[0], SAMP[0], 2D\n"
732 "ADD OUT[0], TEMP[0], IMM[0]\n"
737 struct tgsi_token tokens
[1000];
738 struct pipe_shader_state state
;
740 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
742 util_report_result_helper(FAIL
, name
);
745 pipe_shader_state_from_tgsi(&state
, tokens
);
747 void *fs
= ctx
->create_fs_state(ctx
, &state
);
748 cso_set_fragment_shader_handle(cso
, fs
);
751 void *vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
753 if (num_samples
> 1 && !use_fbfetch
)
754 ctx
->set_min_samples(ctx
, num_samples
);
756 for (int i
= 0; i
< 2; i
++) {
757 ctx
->texture_barrier(ctx
,
758 use_fbfetch
? PIPE_TEXTURE_BARRIER_FRAMEBUFFER
:
759 PIPE_TEXTURE_BARRIER_SAMPLER
);
760 util_draw_fullscreen_quad(cso
);
762 if (num_samples
> 1 && !use_fbfetch
)
763 ctx
->set_min_samples(ctx
, 1);
768 * result = 0.1 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.3, 0.5, 0.7, 0.9)
771 * sample0 = 0.0 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.2, 0.4, 0.6, 0.8)
773 * sample2 = 0.2 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.4, 0.6, 0.8, 1.0)
775 * resolved = sum(sample[0:3]) / 4 = (0.3, 0.5, 0.7, 0.9)
777 static const float expected
[] = {0.3, 0.5, 0.7, 0.9};
778 bool pass
= util_probe_rect_rgba(ctx
, cb
, 0, 0,
779 cb
->width0
, cb
->height0
, expected
);
782 cso_destroy_context(cso
);
783 ctx
->delete_vs_state(ctx
, vs
);
784 ctx
->delete_fs_state(ctx
, fs
);
785 pipe_sampler_view_reference(&view
, NULL
);
786 pipe_resource_reference(&cb
, NULL
);
788 util_report_result_helper(pass
, name
);
792 test_compute_clear_image(struct pipe_context
*ctx
)
794 struct pipe_resource
*cb
;
797 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
798 PIPE_FORMAT_R8G8B8A8_UNORM
, 1);
800 /* Compute shader. */
802 "PROPERTY CS_FIXED_BLOCK_WIDTH 8\n"
803 "PROPERTY CS_FIXED_BLOCK_HEIGHT 8\n"
804 "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n"
805 "DCL SV[0], THREAD_ID\n"
806 "DCL SV[1], BLOCK_ID\n"
807 "DCL IMAGE[0], 2D, PIPE_FORMAT_R8G8B8A8_UNORM, WR\n"
809 "IMM[0] UINT32 { 8, 8, 0, 0}\n"
810 "IMM[1] FLT32 { 1, 0, 0, 0}\n"
812 /* TEMP[0].xy = SV[1] * IMM[0] + SV[0]; */
813 "UMAD TEMP[0].xy, SV[1], IMM[0], SV[0]\n"
814 "STORE IMAGE[0], TEMP[0], IMM[1], 2D, PIPE_FORMAT_R8G8B8A8_UNORM\n"
817 struct tgsi_token tokens
[1000];
818 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
820 util_report_result(FAIL
);
824 struct pipe_compute_state state
= {0};
825 state
.ir_type
= PIPE_SHADER_IR_TGSI
;
828 void *compute_shader
= ctx
->create_compute_state(ctx
, &state
);
829 ctx
->bind_compute_state(ctx
, compute_shader
);
831 /* Bind the image. */
832 struct pipe_image_view image
= {0};
834 image
.shader_access
= image
.access
= PIPE_IMAGE_ACCESS_READ_WRITE
;
835 image
.format
= cb
->format
;
837 ctx
->set_shader_images(ctx
, PIPE_SHADER_COMPUTE
, 0, 1, &image
);
839 /* Dispatch compute. */
840 struct pipe_grid_info info
= {0};
844 info
.grid
[0] = cb
->width0
/ 8;
845 info
.grid
[1] = cb
->height0
/ 8;
848 ctx
->launch_grid(ctx
, &info
);
851 static const float expected
[] = {1.0, 0.0, 0.0, 0.0};
852 bool pass
= util_probe_rect_rgba(ctx
, cb
, 0, 0,
853 cb
->width0
, cb
->height0
, expected
);
856 ctx
->delete_compute_state(ctx
, compute_shader
);
857 pipe_resource_reference(&cb
, NULL
);
859 util_report_result(pass
);
862 #define NV12_WIDTH 2560
863 #define NV12_HEIGHT 1440
866 nv12_validate_resource_fields(struct pipe_resource
*tex
)
868 return tex
->format
== util_format_get_plane_format(PIPE_FORMAT_NV12
, 0) &&
869 tex
->width0
== NV12_WIDTH
&&
870 tex
->height0
== NV12_HEIGHT
&&
871 tex
->last_level
== 0 &&
872 tex
->usage
== PIPE_USAGE_DEFAULT
&&
874 tex
->next
->format
== util_format_get_plane_format(PIPE_FORMAT_NV12
, 1) &&
875 tex
->next
->width0
== tex
->width0
/ 2 &&
876 tex
->next
->height0
== tex
->height0
/ 2 &&
877 tex
->next
->usage
== tex
->usage
;
880 /* This test enforces the behavior of NV12 allocation and exports. */
882 test_nv12(struct pipe_screen
*screen
)
884 struct pipe_resource
*tex
= util_create_texture2d(screen
, NV12_WIDTH
, NV12_HEIGHT
,
885 PIPE_FORMAT_NV12
, 1);
888 printf("resource_create failed\n");
889 util_report_result(false);
893 if (!nv12_validate_resource_fields(tex
)) {
894 printf("incorrect pipe_resource fields\n");
895 util_report_result(false);
899 /* resource_get_param */
900 if (screen
->resource_get_param
) {
902 uint64_t handle
, dmabuf
, offset
, stride
, planes
;
906 for (unsigned i
= 0; i
< 3; i
++) {
907 struct pipe_resource
*res
= i
== 2 ? tex
->next
: tex
;
908 unsigned plane
= i
== 2 ? 0 : i
;
910 if (!screen
->resource_get_param(screen
, NULL
, res
, plane
, 0,
911 PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS
,
912 0, &handle
[i
].handle
)) {
913 printf("resource_get_param failed\n");
914 util_report_result(false);
918 if (!screen
->resource_get_param(screen
, NULL
, res
, plane
, 0,
919 PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD
,
920 0, &handle
[i
].dmabuf
)) {
921 printf("resource_get_param failed\n");
922 util_report_result(false);
926 if (!screen
->resource_get_param(screen
, NULL
, res
, plane
, 0,
927 PIPE_RESOURCE_PARAM_OFFSET
,
928 0, &handle
[i
].offset
)) {
929 printf("resource_get_param failed\n");
930 util_report_result(false);
934 if (!screen
->resource_get_param(screen
, NULL
, res
, plane
, 0,
935 PIPE_RESOURCE_PARAM_STRIDE
,
936 0, &handle
[i
].stride
)) {
937 printf("resource_get_param failed\n");
938 util_report_result(false);
942 if (!screen
->resource_get_param(screen
, NULL
, res
, plane
, 0,
943 PIPE_RESOURCE_PARAM_NPLANES
,
944 0, &handle
[i
].planes
)) {
945 printf("resource_get_param failed\n");
946 util_report_result(false);
951 /* Validate export. */
952 bool get_param_pass
= /* Sanity checking */
953 handle
[0].handle
&& handle
[1].handle
&& handle
[2].handle
&&
954 handle
[0].dmabuf
&& handle
[1].dmabuf
&& handle
[2].dmabuf
&&
955 handle
[0].stride
&& handle
[1].stride
&& handle
[2].stride
&&
956 handle
[0].planes
== 2 &&
957 handle
[1].planes
== 2 &&
958 handle
[2].planes
== 2 &&
959 /* Different planes */
960 handle
[0].handle
== handle
[1].handle
&&
961 handle
[0].offset
!= handle
[1].offset
&&
963 handle
[1].handle
== handle
[2].handle
&&
964 handle
[1].stride
== handle
[2].stride
&&
965 handle
[1].offset
== handle
[2].offset
;
967 if (!get_param_pass
) {
968 printf("resource_get_param returned incorrect values\n");
969 util_report_result(false);
974 /* resource_get_handle */
975 struct winsys_handle handle
[4] = {{0}};
978 for (unsigned i
= 0; i
< 4; i
++) {
979 handle
[i
].type
= i
< 2 ? WINSYS_HANDLE_TYPE_KMS
: WINSYS_HANDLE_TYPE_FD
;
980 handle
[i
].plane
= i
% 2;
982 if (!screen
->resource_get_handle(screen
, NULL
, tex
, &handle
[i
], 0)) {
983 printf("resource_get_handle failed\n");
984 util_report_result(false);
989 /* Validate export. */
990 bool get_handle_pass
= /* Sanity checking */
991 handle
[0].handle
&& handle
[1].handle
&&
992 handle
[0].stride
&& handle
[1].stride
&&
993 handle
[2].handle
&& handle
[3].handle
&&
994 handle
[2].stride
&& handle
[3].stride
&&
995 /* KMS - different planes */
996 handle
[0].handle
== handle
[1].handle
&&
997 handle
[0].offset
!= handle
[1].offset
&&
998 /* DMABUF - different planes */
999 handle
[2].offset
!= handle
[3].offset
&&
1000 /* KMS and DMABUF equivalence */
1001 handle
[0].offset
== handle
[2].offset
&&
1002 handle
[1].offset
== handle
[3].offset
&&
1003 handle
[0].stride
== handle
[2].stride
&&
1004 handle
[1].stride
== handle
[3].stride
;
1006 if (!get_handle_pass
) {
1007 printf("resource_get_handle returned incorrect values\n");
1008 util_report_result(false);
1012 util_report_result(true);
1015 pipe_resource_reference(&tex
, NULL
);
1019 * Run all tests. This should be run with a clean context after
1023 util_run_tests(struct pipe_screen
*screen
)
1025 struct pipe_context
*ctx
= screen
->context_create(screen
, NULL
, 0);
1027 null_fragment_shader(ctx
);
1028 tgsi_vs_window_space_position(ctx
);
1029 null_sampler_view(ctx
, TGSI_TEXTURE_2D
);
1030 null_sampler_view(ctx
, TGSI_TEXTURE_BUFFER
);
1031 util_test_constant_buffer(ctx
, NULL
);
1032 test_sync_file_fences(ctx
);
1034 for (int i
= 1; i
<= 8; i
= i
* 2)
1035 test_texture_barrier(ctx
, false, i
);
1036 for (int i
= 1; i
<= 8; i
= i
* 2)
1037 test_texture_barrier(ctx
, true, i
);
1040 ctx
= screen
->context_create(screen
, NULL
, PIPE_CONTEXT_COMPUTE_ONLY
);
1041 test_compute_clear_image(ctx
);
1046 puts("Done. Exiting..");