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_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"
43 #define TOLERANCE 0.01
45 static struct pipe_resource
*
46 util_create_texture2d(struct pipe_screen
*screen
, unsigned width
,
47 unsigned height
, enum pipe_format format
)
49 struct pipe_resource templ
= {{0}};
51 templ
.target
= PIPE_TEXTURE_2D
;
53 templ
.height0
= height
;
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
);
62 return screen
->resource_create(screen
, &templ
);
66 util_set_framebuffer_cb0(struct cso_context
*cso
, struct pipe_context
*ctx
,
67 struct pipe_resource
*tex
)
69 struct pipe_surface templ
= {{0}}, *surf
;
70 struct pipe_framebuffer_state fb
= {0};
72 templ
.format
= tex
->format
;
73 surf
= ctx
->create_surface(ctx
, tex
, &templ
);
75 fb
.width
= tex
->width0
;
76 fb
.height
= tex
->height0
;
80 cso_set_framebuffer(cso
, &fb
);
81 pipe_surface_reference(&surf
, NULL
);
85 util_set_blend_normal(struct cso_context
*cso
)
87 struct pipe_blend_state blend
= {0};
89 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
90 cso_set_blend(cso
, &blend
);
94 util_set_dsa_disable(struct cso_context
*cso
)
96 struct pipe_depth_stencil_alpha_state dsa
= {{0}};
98 cso_set_depth_stencil_alpha(cso
, &dsa
);
102 util_set_rasterizer_normal(struct cso_context
*cso
)
104 struct pipe_rasterizer_state rs
= {0};
106 rs
.half_pixel_center
= 1;
107 rs
.bottom_edge_rule
= 1;
110 cso_set_rasterizer(cso
, &rs
);
114 util_set_max_viewport(struct cso_context
*cso
, struct pipe_resource
*tex
)
116 struct pipe_viewport_state viewport
;
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
;
125 cso_set_viewport(cso
, &viewport
);
129 util_set_interleaved_vertex_elements(struct cso_context
*cso
,
130 unsigned num_elements
)
133 struct pipe_vertex_element
*velem
=
134 calloc(1, num_elements
* sizeof(struct pipe_vertex_element
));
136 for (i
= 0; i
< num_elements
; i
++) {
137 velem
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
138 velem
[i
].src_offset
= i
* 16;
141 cso_set_vertex_elements(cso
, num_elements
, velem
);
146 util_set_passthrough_vertex_shader(struct cso_context
*cso
,
147 struct pipe_context
*ctx
,
150 static const uint vs_attribs
[] = {
151 TGSI_SEMANTIC_POSITION
,
152 TGSI_SEMANTIC_GENERIC
154 static const uint vs_indices
[] = {0, 0};
157 vs
= util_make_vertex_passthrough_shader(ctx
, 2, vs_attribs
, vs_indices
,
159 cso_set_vertex_shader_handle(cso
, vs
);
164 util_set_common_states_and_clear(struct cso_context
*cso
, struct pipe_context
*ctx
,
165 struct pipe_resource
*cb
)
167 static const float clear_color
[] = {0.1, 0.1, 0.1, 0.1};
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
);
175 ctx
->clear(ctx
, PIPE_CLEAR_COLOR0
, (void*)clear_color
, 0, 0);
179 util_draw_fullscreen_quad(struct cso_context
*cso
)
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
187 util_set_interleaved_vertex_elements(cso
, 2);
188 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
192 * Probe and test if the rectangle contains the expected color.
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
199 util_probe_rect_rgba_multi(struct pipe_context
*ctx
, struct pipe_resource
*tex
,
200 unsigned offx
, unsigned offy
, unsigned w
,
202 const float *expected
,
203 unsigned num_expected_colors
)
205 struct pipe_transfer
*transfer
;
207 float *pixels
= malloc(w
* h
* 4 * sizeof(float));
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
);
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];
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 */
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]);
238 break; /* this color was successful */
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
)
253 return util_probe_rect_rgba_multi(ctx
, tex
, offx
, offy
, w
, h
, expected
, 1);
258 FAIL
= 0, /* also "false" */
259 PASS
= 1 /* also "true" */
263 util_report_result_helper(int status
, const char *name
, ...)
269 util_vsnprintf(buf
, sizeof(buf
), name
, ap
);
272 printf("Test(%s) = %s\n", buf
,
273 status
== SKIP
? "skip" :
274 status
== PASS
? "pass" : "fail");
277 #define util_report_result(status) util_report_result_helper(status, __func__)
280 * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
282 * The viewport state is set as usual, but it should have no effect.
283 * Clipping should also be disabled.
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).
289 * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w
290 * during perspective interpolation is not tested.
293 tgsi_vs_window_space_position(struct pipe_context
*ctx
)
295 struct cso_context
*cso
;
296 struct pipe_resource
*cb
;
299 static const float red
[] = {1, 0, 0, 1};
301 if (!ctx
->screen
->get_param(ctx
->screen
,
302 PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION
)) {
303 util_report_result(SKIP
);
307 cso
= cso_create_context(ctx
);
308 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
309 PIPE_FORMAT_R8G8B8A8_UNORM
);
310 util_set_common_states_and_clear(cso
, ctx
, cb
);
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
);
318 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, true);
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,
328 util_set_interleaved_vertex_elements(cso
, 2);
329 util_draw_user_vertex_buffer(cso
, vertices
, PIPE_PRIM_QUADS
, 4, 2);
333 pass
= pass
&& util_probe_rect_rgba(ctx
, cb
, 0, 0,
334 cb
->width0
, cb
->height0
, red
);
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
);
342 util_report_result(pass
);
346 null_sampler_view(struct pipe_context
*ctx
, unsigned tgsi_tex_target
)
348 struct cso_context
*cso
;
349 struct pipe_resource
*cb
;
352 /* 2 expected colors: */
353 static const float expected_tex
[] = {0, 0, 0, 1,
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;
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
]);
367 cso
= cso_create_context(ctx
);
368 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
369 PIPE_FORMAT_R8G8B8A8_UNORM
);
370 util_set_common_states_and_clear(cso
, ctx
, cb
);
372 ctx
->set_sampler_views(ctx
, PIPE_SHADER_FRAGMENT
, 0, 1, NULL
);
374 /* Fragment shader. */
375 fs
= util_make_fragment_tex_shader(ctx
, tgsi_tex_target
,
376 TGSI_INTERPOLATE_LINEAR
);
377 cso_set_fragment_shader_handle(cso
, fs
);
380 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
381 util_draw_fullscreen_quad(cso
);
384 pass
= pass
&& util_probe_rect_rgba_multi(ctx
, cb
, 0, 0,
385 cb
->width0
, cb
->height0
, expected
,
389 cso_destroy_context(cso
);
390 ctx
->delete_vs_state(ctx
, vs
);
391 ctx
->delete_fs_state(ctx
, fs
);
392 pipe_resource_reference(&cb
, NULL
);
394 util_report_result_helper(pass
, "%s: %s", __func__
,
395 tgsi_texture_names
[tgsi_tex_target
]);
399 null_constant_buffer(struct pipe_context
*ctx
)
401 struct cso_context
*cso
;
402 struct pipe_resource
*cb
;
405 static const float zero
[] = {0, 0, 0, 0};
407 cso
= cso_create_context(ctx
);
408 cb
= util_create_texture2d(ctx
->screen
, 256, 256,
409 PIPE_FORMAT_R8G8B8A8_UNORM
);
410 util_set_common_states_and_clear(cso
, ctx
, cb
);
412 ctx
->set_constant_buffer(ctx
, PIPE_SHADER_FRAGMENT
, 0, NULL
);
414 /* Fragment shader. */
416 static const char *text
= /* I don't like ureg... */
419 "DCL OUT[0], COLOR\n"
421 "MOV OUT[0], CONST[0]\n"
423 struct tgsi_token tokens
[1000];
424 struct pipe_shader_state state
= {tokens
};
426 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
427 puts("Can't compile a fragment shader.");
428 util_report_result(FAIL
);
431 fs
= ctx
->create_fs_state(ctx
, &state
);
432 cso_set_fragment_shader_handle(cso
, fs
);
436 vs
= util_set_passthrough_vertex_shader(cso
, ctx
, false);
437 util_draw_fullscreen_quad(cso
);
440 pass
= pass
&& util_probe_rect_rgba(ctx
, cb
, 0, 0, cb
->width0
,
444 cso_destroy_context(cso
);
445 ctx
->delete_vs_state(ctx
, vs
);
446 ctx
->delete_fs_state(ctx
, fs
);
447 pipe_resource_reference(&cb
, NULL
);
449 util_report_result(pass
);
453 * Run all tests. This should be run with a clean context after
457 util_run_tests(struct pipe_screen
*screen
)
459 struct pipe_context
*ctx
= screen
->context_create(screen
, NULL
);
461 tgsi_vs_window_space_position(ctx
);
462 null_sampler_view(ctx
, TGSI_TEXTURE_2D
);
463 null_sampler_view(ctx
, TGSI_TEXTURE_BUFFER
);
464 null_constant_buffer(ctx
);
468 puts("Done. Exiting..");