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/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_tile.h"
37 #include "tgsi/tgsi_text.h"
38 #include "cso_cache/cso_context.h"
41 #define TOLERANCE 0.01
43 static struct pipe_resource
*
44 util_create_texture2d(struct pipe_screen
*screen
, unsigned width
,
45 unsigned height
, enum pipe_format format
)
47 struct pipe_resource templ
= {{0}};
49 templ
.target
= PIPE_TEXTURE_2D
;
51 templ
.height0
= height
;
54 templ
.format
= format
;
55 templ
.usage
= PIPE_USAGE_DEFAULT
;
56 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
|
57 (util_format_is_depth_or_stencil(format
) ?
58 PIPE_BIND_DEPTH_STENCIL
: PIPE_BIND_RENDER_TARGET
);
60 return screen
->resource_create(screen
, &templ
);
64 util_set_framebuffer_cb0(struct cso_context
*cso
, struct pipe_context
*ctx
,
65 struct pipe_resource
*tex
)
67 struct pipe_surface templ
= {{0}}, *surf
;
68 struct pipe_framebuffer_state fb
= {0};
70 templ
.format
= tex
->format
;
71 surf
= ctx
->create_surface(ctx
, tex
, &templ
);
73 fb
.width
= tex
->width0
;
74 fb
.height
= tex
->height0
;
78 cso_set_framebuffer(cso
, &fb
);
79 pipe_surface_reference(&surf
, NULL
);
83 util_set_blend_normal(struct cso_context
*cso
)
85 struct pipe_blend_state blend
= {0};
87 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
88 cso_set_blend(cso
, &blend
);
92 util_set_dsa_disable(struct cso_context
*cso
)
94 struct pipe_depth_stencil_alpha_state dsa
= {{0}};
96 cso_set_depth_stencil_alpha(cso
, &dsa
);
100 util_set_rasterizer_normal(struct cso_context
*cso
)
102 struct pipe_rasterizer_state rs
= {0};
104 rs
.half_pixel_center
= 1;
105 rs
.bottom_edge_rule
= 1;
108 cso_set_rasterizer(cso
, &rs
);
112 util_set_max_viewport(struct cso_context
*cso
, struct pipe_resource
*tex
)
114 struct pipe_viewport_state viewport
;
116 viewport
.scale
[0] = 0.5f
* tex
->width0
;
117 viewport
.scale
[1] = 0.5f
* tex
->height0
;
118 viewport
.scale
[2] = 1.0f
;
119 viewport
.translate
[0] = 0.5f
* tex
->width0
;
120 viewport
.translate
[1] = 0.5f
* tex
->height0
;
121 viewport
.translate
[2] = 0.0f
;
123 cso_set_viewport(cso
, &viewport
);
127 util_set_interleaved_vertex_elements(struct cso_context
*cso
,
128 unsigned num_elements
)
131 struct pipe_vertex_element
*velem
=
132 calloc(1, num_elements
* sizeof(struct pipe_vertex_element
));
134 for (i
= 0; i
< num_elements
; i
++) {
135 velem
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
136 velem
[i
].src_offset
= i
* 16;
139 cso_set_vertex_elements(cso
, num_elements
, velem
);
144 util_set_passthrough_vertex_shader(struct cso_context
*cso
,
145 struct pipe_context
*ctx
,
148 static const uint vs_attribs
[] = {
149 TGSI_SEMANTIC_POSITION
,
150 TGSI_SEMANTIC_GENERIC
152 static const uint vs_indices
[] = {0, 0};
155 vs
= util_make_vertex_passthrough_shader(ctx
, 2, vs_attribs
, vs_indices
,
157 cso_set_vertex_shader_handle(cso
, vs
);
162 util_set_common_states_and_clear(struct cso_context
*cso
, struct pipe_context
*ctx
,
163 struct pipe_resource
*cb
)
165 static const float clear_color
[] = {0.1, 0.1, 0.1, 0.1};
167 util_set_framebuffer_cb0(cso
, ctx
, cb
);
168 util_set_blend_normal(cso
);
169 util_set_dsa_disable(cso
);
170 util_set_rasterizer_normal(cso
);
171 util_set_max_viewport(cso
, cb
);
173 ctx
->clear(ctx
, PIPE_CLEAR_COLOR0
, (void*)clear_color
, 0, 0);
177 util_draw_fullscreen_quad(struct cso_context
*cso
)
179 static float vertices
[] = {
180 -1, -1, 0, 1, 0, 0, 0, 0,
181 -1, 1, 0, 1, 0, 1, 0, 0,
182 1, 1, 0, 1, 1, 1, 0, 0,
183 1, -1, 0, 1, 1, 0, 0, 0
185 util_set_interleaved_vertex_elements(cso
, 2);
186 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
190 * Probe and test if the rectangle contains the expected color.
192 * If "num_expected_colors" > 1, at least one expected color must match
193 * the probed color. "expected" should be an array of 4*num_expected_colors
197 util_probe_rect_rgba_multi(struct pipe_context
*ctx
, struct pipe_resource
*tex
,
198 unsigned offx
, unsigned offy
, unsigned w
,
200 const float *expected
,
201 unsigned num_expected_colors
)
203 struct pipe_transfer
*transfer
;
205 float *pixels
= malloc(w
* h
* 4 * sizeof(float));
209 map
= pipe_transfer_map(ctx
, tex
, 0, 0, PIPE_TRANSFER_READ
,
210 offx
, offy
, w
, h
, &transfer
);
211 pipe_get_tile_rgba(transfer
, map
, 0, 0, w
, h
, pixels
);
212 pipe_transfer_unmap(ctx
, transfer
);
214 for (e
= 0; e
< num_expected_colors
; e
++) {
215 for (y
= 0; y
< h
; y
++) {
216 for (x
= 0; x
< w
; x
++) {
217 float *probe
= &pixels
[(y
*w
+ x
)*4];
219 for (c
= 0; c
< 4; c
++) {
220 if (fabs(probe
[c
] - expected
[e
*4+c
]) >= TOLERANCE
) {
221 if (e
< num_expected_colors
-1)
222 goto next_color
; /* test the next expected color */
224 printf("Probe color at (%i,%i), ", offx
+x
, offy
+y
);
225 printf("Expected: %.3f, %.3f, %.3f, %.3f, ",
226 expected
[e
*4], expected
[e
*4+1],
227 expected
[e
*4+2], expected
[e
*4+3]);
228 printf("Got: %.3f, %.3f, %.3f, %.3f\n",
229 probe
[0], probe
[1], probe
[2], probe
[2]);
236 break; /* this color was successful */
247 util_probe_rect_rgba(struct pipe_context
*ctx
, struct pipe_resource
*tex
,
248 unsigned offx
, unsigned offy
, unsigned w
, unsigned h
,
249 const float *expected
)
251 return util_probe_rect_rgba_multi(ctx
, tex
, offx
, offy
, w
, h
, expected
, 1);
256 FAIL
= 0, /* also "false" */
257 PASS
= 1 /* also "true" */
261 util_report_result_helper(const char *name
, int status
)
263 printf("Test(%s) = %s\n", name
,
264 status
== SKIP
? "skip" :
265 status
== PASS
? "pass" : "fail");
268 #define util_report_result(status) util_report_result_helper(__func__, status)
271 * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
273 * The viewport state is set as usual, but it should have no effect.
274 * Clipping should also be disabled.
276 * POSITION.xyz should already be multiplied by 1/w and POSITION.w should
277 * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't
278 * multiplied by 1/w (otherwise nothing would be rendered).
280 * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w
281 * during perspective interpolation is not tested.
284 tgsi_vs_window_space_position(struct pipe_context
*ctx
)
286 struct cso_context
*cso
;
287 struct pipe_resource
*cb
;
290 static const float red
[] = {1, 0, 0, 1};
292 if (!ctx
->screen
->get_param(ctx
->screen
,
293 PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION
)) {
294 util_report_result(SKIP
);
298 cso
= cso_create_context(ctx
);
299 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
300 PIPE_FORMAT_R8G8B8A8_UNORM
);
301 util_set_common_states_and_clear(cso
, ctx
, cb
);
303 /* Fragment shader. */
304 fs
= util_make_fragment_passthrough_shader(ctx
, TGSI_SEMANTIC_GENERIC
,
305 TGSI_INTERPOLATE_LINEAR
, TRUE
);
306 cso_set_fragment_shader_handle(cso
, fs
);
309 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, true);
313 static float vertices
[] = {
314 0, 0, 0, 0, 1, 0, 0, 1,
315 0, 256, 0, 0, 1, 0, 0, 1,
316 256, 256, 0, 0, 1, 0, 0, 1,
317 256, 0, 0, 0, 1, 0, 0, 1,
319 util_set_interleaved_vertex_elements(cso
, 2);
320 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
324 pass
= pass
&& util_probe_rect_rgba(ctx
, cb
, 0, 0,
325 cb
->width0
, cb
->height0
, red
);
328 cso_destroy_context(cso
);
329 ctx
->delete_vs_state(ctx
, vs
);
330 ctx
->delete_fs_state(ctx
, fs
);
331 pipe_resource_reference(&cb
, NULL
);
333 util_report_result(pass
);
337 null_sampler_view(struct pipe_context
*ctx
)
339 struct cso_context
*cso
;
340 struct pipe_resource
*cb
;
343 /* 2 expected colors: */
344 static const float expected
[] = {0, 0, 0, 1,
347 cso
= cso_create_context(ctx
);
348 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
349 PIPE_FORMAT_R8G8B8A8_UNORM
);
350 util_set_common_states_and_clear(cso
, ctx
, cb
);
352 ctx
->set_sampler_views(ctx
, PIPE_SHADER_FRAGMENT
, 0, 1, NULL
);
354 /* Fragment shader. */
355 fs
= util_make_fragment_tex_shader(ctx
, TGSI_TEXTURE_2D
,
356 TGSI_INTERPOLATE_LINEAR
);
357 cso_set_fragment_shader_handle(cso
, fs
);
360 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
361 util_draw_fullscreen_quad(cso
);
364 pass
= pass
&& util_probe_rect_rgba_multi(ctx
, cb
, 0, 0,
365 cb
->width0
, cb
->height0
, expected
, 2);
368 cso_destroy_context(cso
);
369 ctx
->delete_vs_state(ctx
, vs
);
370 ctx
->delete_fs_state(ctx
, fs
);
371 pipe_resource_reference(&cb
, NULL
);
373 util_report_result(pass
);
377 null_constant_buffer(struct pipe_context
*ctx
)
379 struct cso_context
*cso
;
380 struct pipe_resource
*cb
;
383 static const float zero
[] = {0, 0, 0, 0};
385 cso
= cso_create_context(ctx
);
386 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
387 PIPE_FORMAT_R8G8B8A8_UNORM
);
388 util_set_common_states_and_clear(cso
, ctx
, cb
);
390 ctx
->set_constant_buffer(ctx
, PIPE_SHADER_FRAGMENT
, 0, NULL
);
392 /* Fragment shader. */
394 static const char *text
= /* I don't like ureg... */
397 "DCL OUT[0], COLOR\n"
399 "MOV OUT[0], CONST[0]\n"
401 struct tgsi_token tokens
[1000];
402 struct pipe_shader_state state
= {tokens
};
404 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
405 puts("Can't compile a fragment shader.");
406 util_report_result(FAIL
);
409 fs
= ctx
->create_fs_state(ctx
, &state
);
410 cso_set_fragment_shader_handle(cso
, fs
);
414 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
415 util_draw_fullscreen_quad(cso
);
418 pass
= pass
&& util_probe_rect_rgba(ctx
, cb
, 0, 0, cb
->width0
,
422 cso_destroy_context(cso
);
423 ctx
->delete_vs_state(ctx
, vs
);
424 ctx
->delete_fs_state(ctx
, fs
);
425 pipe_resource_reference(&cb
, NULL
);
427 util_report_result(pass
);
431 * Run all tests. This should be run with a clean context after
435 util_run_tests(struct pipe_screen
*screen
)
437 struct pipe_context
*ctx
= screen
->context_create(screen
, NULL
);
439 tgsi_vs_window_space_position(ctx
);
440 null_sampler_view(ctx
);
441 null_constant_buffer(ctx
);
445 puts("Done. Exiting..");