1b8e80941Smrg/************************************************************************** 2b8e80941Smrg * 3b8e80941Smrg * Copyright 2014 Advanced Micro Devices, Inc. 4b8e80941Smrg * All Rights Reserved. 5b8e80941Smrg * 6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7b8e80941Smrg * copy of this software and associated documentation files (the 8b8e80941Smrg * "Software"), to deal in the Software without restriction, including 9b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish, 10b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to 11b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to 12b8e80941Smrg * the following conditions: 13b8e80941Smrg * 14b8e80941Smrg * The above copyright notice and this permission notice (including the 15b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions 16b8e80941Smrg * of the Software. 17b8e80941Smrg * 18b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21b8e80941Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b8e80941Smrg * 26b8e80941Smrg **************************************************************************/ 27b8e80941Smrg 28b8e80941Smrg#include "util/u_tests.h" 29b8e80941Smrg 30b8e80941Smrg#include "util/u_draw_quad.h" 31b8e80941Smrg#include "util/u_format.h" 32b8e80941Smrg#include "util/u_inlines.h" 33b8e80941Smrg#include "util/u_memory.h" 34b8e80941Smrg#include "util/u_simple_shaders.h" 35b8e80941Smrg#include "util/u_surface.h" 36b8e80941Smrg#include "util/u_string.h" 37b8e80941Smrg#include "util/u_tile.h" 38b8e80941Smrg#include "tgsi/tgsi_strings.h" 39b8e80941Smrg#include "tgsi/tgsi_text.h" 40b8e80941Smrg#include "cso_cache/cso_context.h" 41b8e80941Smrg#include <stdio.h> 42b8e80941Smrg 43b8e80941Smrg#define TOLERANCE 0.01 44b8e80941Smrg 45b8e80941Smrgstatic struct pipe_resource * 46b8e80941Smrgutil_create_texture2d(struct pipe_screen *screen, unsigned width, 47b8e80941Smrg unsigned height, enum pipe_format format, 48b8e80941Smrg unsigned num_samples) 49b8e80941Smrg{ 50b8e80941Smrg struct pipe_resource templ = {{0}}; 51b8e80941Smrg 52b8e80941Smrg templ.target = PIPE_TEXTURE_2D; 53b8e80941Smrg templ.width0 = width; 54b8e80941Smrg templ.height0 = height; 55b8e80941Smrg templ.depth0 = 1; 56b8e80941Smrg templ.array_size = 1; 57b8e80941Smrg templ.nr_samples = num_samples; 58b8e80941Smrg templ.nr_storage_samples = num_samples; 59b8e80941Smrg templ.format = format; 60b8e80941Smrg templ.usage = PIPE_USAGE_DEFAULT; 61b8e80941Smrg templ.bind = PIPE_BIND_SAMPLER_VIEW | 62b8e80941Smrg (util_format_is_depth_or_stencil(format) ? 63b8e80941Smrg PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET); 64b8e80941Smrg 65b8e80941Smrg return screen->resource_create(screen, &templ); 66b8e80941Smrg} 67b8e80941Smrg 68b8e80941Smrgstatic void 69b8e80941Smrgutil_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx, 70b8e80941Smrg struct pipe_resource *tex) 71b8e80941Smrg{ 72b8e80941Smrg struct pipe_surface templ = {{0}}, *surf; 73b8e80941Smrg struct pipe_framebuffer_state fb = {0}; 74b8e80941Smrg 75b8e80941Smrg templ.format = tex->format; 76b8e80941Smrg surf = ctx->create_surface(ctx, tex, &templ); 77b8e80941Smrg 78b8e80941Smrg fb.width = tex->width0; 79b8e80941Smrg fb.height = tex->height0; 80b8e80941Smrg fb.cbufs[0] = surf; 81b8e80941Smrg fb.nr_cbufs = 1; 82b8e80941Smrg 83b8e80941Smrg cso_set_framebuffer(cso, &fb); 84b8e80941Smrg pipe_surface_reference(&surf, NULL); 85b8e80941Smrg} 86b8e80941Smrg 87b8e80941Smrgstatic void 88b8e80941Smrgutil_set_blend_normal(struct cso_context *cso) 89b8e80941Smrg{ 90b8e80941Smrg struct pipe_blend_state blend = {0}; 91b8e80941Smrg 92b8e80941Smrg blend.rt[0].colormask = PIPE_MASK_RGBA; 93b8e80941Smrg cso_set_blend(cso, &blend); 94b8e80941Smrg} 95b8e80941Smrg 96b8e80941Smrgstatic void 97b8e80941Smrgutil_set_dsa_disable(struct cso_context *cso) 98b8e80941Smrg{ 99b8e80941Smrg struct pipe_depth_stencil_alpha_state dsa = {{0}}; 100b8e80941Smrg 101b8e80941Smrg cso_set_depth_stencil_alpha(cso, &dsa); 102b8e80941Smrg} 103b8e80941Smrg 104b8e80941Smrgstatic void 105b8e80941Smrgutil_set_rasterizer_normal(struct cso_context *cso) 106b8e80941Smrg{ 107b8e80941Smrg struct pipe_rasterizer_state rs = {0}; 108b8e80941Smrg 109b8e80941Smrg rs.half_pixel_center = 1; 110b8e80941Smrg rs.bottom_edge_rule = 1; 111b8e80941Smrg rs.depth_clip_near = 1; 112b8e80941Smrg rs.depth_clip_far = 1; 113b8e80941Smrg 114b8e80941Smrg cso_set_rasterizer(cso, &rs); 115b8e80941Smrg} 116b8e80941Smrg 117b8e80941Smrgstatic void 118b8e80941Smrgutil_set_max_viewport(struct cso_context *cso, struct pipe_resource *tex) 119b8e80941Smrg{ 120b8e80941Smrg struct pipe_viewport_state viewport; 121b8e80941Smrg 122b8e80941Smrg viewport.scale[0] = 0.5f * tex->width0; 123b8e80941Smrg viewport.scale[1] = 0.5f * tex->height0; 124b8e80941Smrg viewport.scale[2] = 1.0f; 125b8e80941Smrg viewport.translate[0] = 0.5f * tex->width0; 126b8e80941Smrg viewport.translate[1] = 0.5f * tex->height0; 127b8e80941Smrg viewport.translate[2] = 0.0f; 128b8e80941Smrg 129b8e80941Smrg cso_set_viewport(cso, &viewport); 130b8e80941Smrg} 131b8e80941Smrg 132b8e80941Smrgstatic void 133b8e80941Smrgutil_set_interleaved_vertex_elements(struct cso_context *cso, 134b8e80941Smrg unsigned num_elements) 135b8e80941Smrg{ 136b8e80941Smrg unsigned i; 137b8e80941Smrg struct pipe_vertex_element *velem = 138b8e80941Smrg calloc(1, num_elements * sizeof(struct pipe_vertex_element)); 139b8e80941Smrg 140b8e80941Smrg for (i = 0; i < num_elements; i++) { 141b8e80941Smrg velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 142b8e80941Smrg velem[i].src_offset = i * 16; 143b8e80941Smrg } 144b8e80941Smrg 145b8e80941Smrg cso_set_vertex_elements(cso, num_elements, velem); 146b8e80941Smrg free(velem); 147b8e80941Smrg} 148b8e80941Smrg 149b8e80941Smrgstatic void * 150b8e80941Smrgutil_set_passthrough_vertex_shader(struct cso_context *cso, 151b8e80941Smrg struct pipe_context *ctx, 152b8e80941Smrg bool window_space) 153b8e80941Smrg{ 154b8e80941Smrg static const enum tgsi_semantic vs_attribs[] = { 155b8e80941Smrg TGSI_SEMANTIC_POSITION, 156b8e80941Smrg TGSI_SEMANTIC_GENERIC 157b8e80941Smrg }; 158b8e80941Smrg static const uint vs_indices[] = {0, 0}; 159b8e80941Smrg void *vs; 160b8e80941Smrg 161b8e80941Smrg vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices, 162b8e80941Smrg window_space); 163b8e80941Smrg cso_set_vertex_shader_handle(cso, vs); 164b8e80941Smrg return vs; 165b8e80941Smrg} 166b8e80941Smrg 167b8e80941Smrgstatic void 168b8e80941Smrgutil_set_common_states_and_clear(struct cso_context *cso, struct pipe_context *ctx, 169b8e80941Smrg struct pipe_resource *cb) 170b8e80941Smrg{ 171b8e80941Smrg static const float clear_color[] = {0.1, 0.1, 0.1, 0.1}; 172b8e80941Smrg 173b8e80941Smrg util_set_framebuffer_cb0(cso, ctx, cb); 174b8e80941Smrg util_set_blend_normal(cso); 175b8e80941Smrg util_set_dsa_disable(cso); 176b8e80941Smrg util_set_rasterizer_normal(cso); 177b8e80941Smrg util_set_max_viewport(cso, cb); 178b8e80941Smrg 179b8e80941Smrg ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0); 180b8e80941Smrg} 181b8e80941Smrg 182b8e80941Smrgstatic void 183b8e80941Smrgutil_draw_fullscreen_quad(struct cso_context *cso) 184b8e80941Smrg{ 185b8e80941Smrg static float vertices[] = { 186b8e80941Smrg -1, -1, 0, 1, 0, 0, 0, 0, 187b8e80941Smrg -1, 1, 0, 1, 0, 1, 0, 0, 188b8e80941Smrg 1, 1, 0, 1, 1, 1, 0, 0, 189b8e80941Smrg 1, -1, 0, 1, 1, 0, 0, 0 190b8e80941Smrg }; 191b8e80941Smrg util_set_interleaved_vertex_elements(cso, 2); 192b8e80941Smrg util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2); 193b8e80941Smrg} 194b8e80941Smrg 195b8e80941Smrgstatic void 196b8e80941Smrgutil_draw_fullscreen_quad_fill(struct cso_context *cso, 197b8e80941Smrg float r, float g, float b, float a) 198b8e80941Smrg{ 199b8e80941Smrg float vertices[] = { 200b8e80941Smrg -1, -1, 0, 1, r, g, b, a, 201b8e80941Smrg -1, 1, 0, 1, r, g, b, a, 202b8e80941Smrg 1, 1, 0, 1, r, g, b, a, 203b8e80941Smrg 1, -1, 0, 1, r, g, b, a, 204b8e80941Smrg }; 205b8e80941Smrg util_set_interleaved_vertex_elements(cso, 2); 206b8e80941Smrg util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2); 207b8e80941Smrg} 208b8e80941Smrg 209b8e80941Smrg/** 210b8e80941Smrg * Probe and test if the rectangle contains the expected color. 211b8e80941Smrg * 212b8e80941Smrg * If "num_expected_colors" > 1, at least one expected color must match 213b8e80941Smrg * the probed color. "expected" should be an array of 4*num_expected_colors 214b8e80941Smrg * floats. 215b8e80941Smrg */ 216b8e80941Smrgstatic bool 217b8e80941Smrgutil_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex, 218b8e80941Smrg unsigned offx, unsigned offy, unsigned w, 219b8e80941Smrg unsigned h, 220b8e80941Smrg const float *expected, 221b8e80941Smrg unsigned num_expected_colors) 222b8e80941Smrg{ 223b8e80941Smrg struct pipe_transfer *transfer; 224b8e80941Smrg void *map; 225b8e80941Smrg float *pixels = malloc(w * h * 4 * sizeof(float)); 226b8e80941Smrg unsigned x,y,e,c; 227b8e80941Smrg bool pass = true; 228b8e80941Smrg 229b8e80941Smrg map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ, 230b8e80941Smrg offx, offy, w, h, &transfer); 231b8e80941Smrg pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels); 232b8e80941Smrg pipe_transfer_unmap(ctx, transfer); 233b8e80941Smrg 234b8e80941Smrg for (e = 0; e < num_expected_colors; e++) { 235b8e80941Smrg for (y = 0; y < h; y++) { 236b8e80941Smrg for (x = 0; x < w; x++) { 237b8e80941Smrg float *probe = &pixels[(y*w + x)*4]; 238b8e80941Smrg 239b8e80941Smrg for (c = 0; c < 4; c++) { 240b8e80941Smrg if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) { 241b8e80941Smrg if (e < num_expected_colors-1) 242b8e80941Smrg goto next_color; /* test the next expected color */ 243b8e80941Smrg 244b8e80941Smrg printf("Probe color at (%i,%i), ", offx+x, offy+y); 245b8e80941Smrg printf("Expected: %.3f, %.3f, %.3f, %.3f, ", 246b8e80941Smrg expected[e*4], expected[e*4+1], 247b8e80941Smrg expected[e*4+2], expected[e*4+3]); 248b8e80941Smrg printf("Got: %.3f, %.3f, %.3f, %.3f\n", 249b8e80941Smrg probe[0], probe[1], probe[2], probe[3]); 250b8e80941Smrg pass = false; 251b8e80941Smrg goto done; 252b8e80941Smrg } 253b8e80941Smrg } 254b8e80941Smrg } 255b8e80941Smrg } 256b8e80941Smrg break; /* this color was successful */ 257b8e80941Smrg 258b8e80941Smrg next_color:; 259b8e80941Smrg } 260b8e80941Smrgdone: 261b8e80941Smrg 262b8e80941Smrg free(pixels); 263b8e80941Smrg return pass; 264b8e80941Smrg} 265b8e80941Smrg 266b8e80941Smrgstatic bool 267b8e80941Smrgutil_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex, 268b8e80941Smrg unsigned offx, unsigned offy, unsigned w, unsigned h, 269b8e80941Smrg const float *expected) 270b8e80941Smrg{ 271b8e80941Smrg return util_probe_rect_rgba_multi(ctx, tex, offx, offy, w, h, expected, 1); 272b8e80941Smrg} 273b8e80941Smrg 274b8e80941Smrgenum { 275b8e80941Smrg SKIP = -1, 276b8e80941Smrg FAIL = 0, /* also "false" */ 277b8e80941Smrg PASS = 1 /* also "true" */ 278b8e80941Smrg}; 279b8e80941Smrg 280b8e80941Smrgstatic void 281b8e80941Smrgutil_report_result_helper(int status, const char *name, ...) 282b8e80941Smrg{ 283b8e80941Smrg char buf[256]; 284b8e80941Smrg va_list ap; 285b8e80941Smrg 286b8e80941Smrg va_start(ap, name); 287b8e80941Smrg util_vsnprintf(buf, sizeof(buf), name, ap); 288b8e80941Smrg va_end(ap); 289b8e80941Smrg 290b8e80941Smrg printf("Test(%s) = %s\n", buf, 291b8e80941Smrg status == SKIP ? "skip" : 292b8e80941Smrg status == PASS ? "pass" : "fail"); 293b8e80941Smrg} 294b8e80941Smrg 295b8e80941Smrg#define util_report_result(status) util_report_result_helper(status, __func__) 296b8e80941Smrg 297b8e80941Smrg/** 298b8e80941Smrg * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION. 299b8e80941Smrg * 300b8e80941Smrg * The viewport state is set as usual, but it should have no effect. 301b8e80941Smrg * Clipping should also be disabled. 302b8e80941Smrg * 303b8e80941Smrg * POSITION.xyz should already be multiplied by 1/w and POSITION.w should 304b8e80941Smrg * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't 305b8e80941Smrg * multiplied by 1/w (otherwise nothing would be rendered). 306b8e80941Smrg * 307b8e80941Smrg * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w 308b8e80941Smrg * during perspective interpolation is not tested. 309b8e80941Smrg */ 310b8e80941Smrgstatic void 311b8e80941Smrgtgsi_vs_window_space_position(struct pipe_context *ctx) 312b8e80941Smrg{ 313b8e80941Smrg struct cso_context *cso; 314b8e80941Smrg struct pipe_resource *cb; 315b8e80941Smrg void *fs, *vs; 316b8e80941Smrg bool pass = true; 317b8e80941Smrg static const float red[] = {1, 0, 0, 1}; 318b8e80941Smrg 319b8e80941Smrg if (!ctx->screen->get_param(ctx->screen, 320b8e80941Smrg PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) { 321b8e80941Smrg util_report_result(SKIP); 322b8e80941Smrg return; 323b8e80941Smrg } 324b8e80941Smrg 325b8e80941Smrg cso = cso_create_context(ctx, 0); 326b8e80941Smrg cb = util_create_texture2d(ctx->screen, 256, 256, 327b8e80941Smrg PIPE_FORMAT_R8G8B8A8_UNORM, 0); 328b8e80941Smrg util_set_common_states_and_clear(cso, ctx, cb); 329b8e80941Smrg 330b8e80941Smrg /* Fragment shader. */ 331b8e80941Smrg fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC, 332b8e80941Smrg TGSI_INTERPOLATE_LINEAR, TRUE); 333b8e80941Smrg cso_set_fragment_shader_handle(cso, fs); 334b8e80941Smrg 335b8e80941Smrg /* Vertex shader. */ 336b8e80941Smrg vs = util_set_passthrough_vertex_shader(cso, ctx, true); 337b8e80941Smrg 338b8e80941Smrg /* Draw. */ 339b8e80941Smrg { 340b8e80941Smrg static float vertices[] = { 341b8e80941Smrg 0, 0, 0, 0, 1, 0, 0, 1, 342b8e80941Smrg 0, 256, 0, 0, 1, 0, 0, 1, 343b8e80941Smrg 256, 256, 0, 0, 1, 0, 0, 1, 344b8e80941Smrg 256, 0, 0, 0, 1, 0, 0, 1, 345b8e80941Smrg }; 346b8e80941Smrg util_set_interleaved_vertex_elements(cso, 2); 347b8e80941Smrg util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2); 348b8e80941Smrg } 349b8e80941Smrg 350b8e80941Smrg /* Probe pixels. */ 351b8e80941Smrg pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, 352b8e80941Smrg cb->width0, cb->height0, red); 353b8e80941Smrg 354b8e80941Smrg /* Cleanup. */ 355b8e80941Smrg cso_destroy_context(cso); 356b8e80941Smrg ctx->delete_vs_state(ctx, vs); 357b8e80941Smrg ctx->delete_fs_state(ctx, fs); 358b8e80941Smrg pipe_resource_reference(&cb, NULL); 359b8e80941Smrg 360b8e80941Smrg util_report_result(pass); 361b8e80941Smrg} 362b8e80941Smrg 363b8e80941Smrgstatic void 364b8e80941Smrgnull_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target) 365b8e80941Smrg{ 366b8e80941Smrg struct cso_context *cso; 367b8e80941Smrg struct pipe_resource *cb; 368b8e80941Smrg void *fs, *vs; 369b8e80941Smrg bool pass = true; 370b8e80941Smrg /* 2 expected colors: */ 371b8e80941Smrg static const float expected_tex[] = {0, 0, 0, 1, 372b8e80941Smrg 0, 0, 0, 0}; 373b8e80941Smrg static const float expected_buf[] = {0, 0, 0, 0}; 374b8e80941Smrg const float *expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ? 375b8e80941Smrg expected_buf : expected_tex; 376b8e80941Smrg unsigned num_expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ? 1 : 2; 377b8e80941Smrg 378b8e80941Smrg if (tgsi_tex_target == TGSI_TEXTURE_BUFFER && 379b8e80941Smrg !ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) { 380b8e80941Smrg util_report_result_helper(SKIP, "%s: %s", __func__, 381b8e80941Smrg tgsi_texture_names[tgsi_tex_target]); 382b8e80941Smrg return; 383b8e80941Smrg } 384b8e80941Smrg 385b8e80941Smrg cso = cso_create_context(ctx, 0); 386b8e80941Smrg cb = util_create_texture2d(ctx->screen, 256, 256, 387b8e80941Smrg PIPE_FORMAT_R8G8B8A8_UNORM, 0); 388b8e80941Smrg util_set_common_states_and_clear(cso, ctx, cb); 389b8e80941Smrg 390b8e80941Smrg ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL); 391b8e80941Smrg 392b8e80941Smrg /* Fragment shader. */ 393b8e80941Smrg fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target, 394b8e80941Smrg TGSI_INTERPOLATE_LINEAR, 395b8e80941Smrg TGSI_RETURN_TYPE_FLOAT, 396b8e80941Smrg TGSI_RETURN_TYPE_FLOAT, false, false); 397b8e80941Smrg cso_set_fragment_shader_handle(cso, fs); 398b8e80941Smrg 399b8e80941Smrg /* Vertex shader. */ 400b8e80941Smrg vs = util_set_passthrough_vertex_shader(cso, ctx, false); 401b8e80941Smrg util_draw_fullscreen_quad(cso); 402b8e80941Smrg 403b8e80941Smrg /* Probe pixels. */ 404b8e80941Smrg pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0, 405b8e80941Smrg cb->width0, cb->height0, expected, 406b8e80941Smrg num_expected); 407b8e80941Smrg 408b8e80941Smrg /* Cleanup. */ 409b8e80941Smrg cso_destroy_context(cso); 410b8e80941Smrg ctx->delete_vs_state(ctx, vs); 411b8e80941Smrg ctx->delete_fs_state(ctx, fs); 412b8e80941Smrg pipe_resource_reference(&cb, NULL); 413b8e80941Smrg 414b8e80941Smrg util_report_result_helper(pass, "%s: %s", __func__, 415b8e80941Smrg tgsi_texture_names[tgsi_tex_target]); 416b8e80941Smrg} 417b8e80941Smrg 418b8e80941Smrgvoid 419b8e80941Smrgutil_test_constant_buffer(struct pipe_context *ctx, 420b8e80941Smrg struct pipe_resource *constbuf) 421b8e80941Smrg{ 422b8e80941Smrg struct cso_context *cso; 423b8e80941Smrg struct pipe_resource *cb; 424b8e80941Smrg void *fs, *vs; 425b8e80941Smrg bool pass = true; 426b8e80941Smrg static const float zero[] = {0, 0, 0, 0}; 427b8e80941Smrg 428b8e80941Smrg cso = cso_create_context(ctx, 0); 429b8e80941Smrg cb = util_create_texture2d(ctx->screen, 256, 256, 430b8e80941Smrg PIPE_FORMAT_R8G8B8A8_UNORM, 0); 431b8e80941Smrg util_set_common_states_and_clear(cso, ctx, cb); 432b8e80941Smrg 433b8e80941Smrg pipe_set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, constbuf); 434b8e80941Smrg 435b8e80941Smrg /* Fragment shader. */ 436b8e80941Smrg { 437b8e80941Smrg static const char *text = /* I don't like ureg... */ 438b8e80941Smrg "FRAG\n" 439b8e80941Smrg "DCL CONST[0][0]\n" 440b8e80941Smrg "DCL OUT[0], COLOR\n" 441b8e80941Smrg 442b8e80941Smrg "MOV OUT[0], CONST[0][0]\n" 443b8e80941Smrg "END\n"; 444b8e80941Smrg struct tgsi_token tokens[1000]; 445b8e80941Smrg struct pipe_shader_state state; 446b8e80941Smrg 447b8e80941Smrg if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 448b8e80941Smrg puts("Can't compile a fragment shader."); 449b8e80941Smrg util_report_result(FAIL); 450b8e80941Smrg return; 451b8e80941Smrg } 452b8e80941Smrg pipe_shader_state_from_tgsi(&state, tokens); 453b8e80941Smrg fs = ctx->create_fs_state(ctx, &state); 454b8e80941Smrg cso_set_fragment_shader_handle(cso, fs); 455b8e80941Smrg } 456b8e80941Smrg 457b8e80941Smrg /* Vertex shader. */ 458b8e80941Smrg vs = util_set_passthrough_vertex_shader(cso, ctx, false); 459b8e80941Smrg util_draw_fullscreen_quad(cso); 460b8e80941Smrg 461b8e80941Smrg /* Probe pixels. */ 462b8e80941Smrg pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, cb->width0, 463b8e80941Smrg cb->height0, zero); 464b8e80941Smrg 465b8e80941Smrg /* Cleanup. */ 466b8e80941Smrg cso_destroy_context(cso); 467b8e80941Smrg ctx->delete_vs_state(ctx, vs); 468b8e80941Smrg ctx->delete_fs_state(ctx, fs); 469b8e80941Smrg pipe_resource_reference(&cb, NULL); 470b8e80941Smrg 471b8e80941Smrg util_report_result(pass); 472b8e80941Smrg} 473b8e80941Smrg 474b8e80941Smrgstatic void 475b8e80941Smrgnull_fragment_shader(struct pipe_context *ctx) 476b8e80941Smrg{ 477b8e80941Smrg struct cso_context *cso; 478b8e80941Smrg struct pipe_resource *cb; 479b8e80941Smrg void *vs; 480b8e80941Smrg struct pipe_rasterizer_state rs = {0}; 481b8e80941Smrg struct pipe_query *query; 482b8e80941Smrg union pipe_query_result qresult; 483b8e80941Smrg 484b8e80941Smrg cso = cso_create_context(ctx, 0); 485b8e80941Smrg cb = util_create_texture2d(ctx->screen, 256, 256, 486b8e80941Smrg PIPE_FORMAT_R8G8B8A8_UNORM, 0); 487b8e80941Smrg util_set_common_states_and_clear(cso, ctx, cb); 488b8e80941Smrg 489b8e80941Smrg /* No rasterization. */ 490b8e80941Smrg rs.rasterizer_discard = 1; 491b8e80941Smrg cso_set_rasterizer(cso, &rs); 492b8e80941Smrg 493b8e80941Smrg vs = util_set_passthrough_vertex_shader(cso, ctx, false); 494b8e80941Smrg 495b8e80941Smrg query = ctx->create_query(ctx, PIPE_QUERY_PRIMITIVES_GENERATED, 0); 496b8e80941Smrg ctx->begin_query(ctx, query); 497b8e80941Smrg util_draw_fullscreen_quad(cso); 498b8e80941Smrg ctx->end_query(ctx, query); 499b8e80941Smrg ctx->get_query_result(ctx, query, true, &qresult); 500b8e80941Smrg 501b8e80941Smrg /* Cleanup. */ 502b8e80941Smrg cso_destroy_context(cso); 503b8e80941Smrg ctx->delete_vs_state(ctx, vs); 504b8e80941Smrg ctx->destroy_query(ctx, query); 505b8e80941Smrg pipe_resource_reference(&cb, NULL); 506b8e80941Smrg 507b8e80941Smrg /* Check PRIMITIVES_GENERATED. */ 508b8e80941Smrg util_report_result(qresult.u64 == 2); 509b8e80941Smrg} 510b8e80941Smrg 511b8e80941Smrg#if defined(PIPE_OS_LINUX) && defined(HAVE_LIBDRM) 512b8e80941Smrg#include <libsync.h> 513b8e80941Smrg#else 514b8e80941Smrg#define sync_merge(str, fd1, fd2) (-1) 515b8e80941Smrg#define sync_wait(fd, timeout) (-1) 516b8e80941Smrg#endif 517b8e80941Smrg 518b8e80941Smrgstatic void 519b8e80941Smrgtest_sync_file_fences(struct pipe_context *ctx) 520b8e80941Smrg{ 521b8e80941Smrg struct pipe_screen *screen = ctx->screen; 522b8e80941Smrg bool pass = true; 523b8e80941Smrg enum pipe_fd_type fd_type = PIPE_FD_TYPE_NATIVE_SYNC; 524b8e80941Smrg 525b8e80941Smrg if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD)) 526b8e80941Smrg return; 527b8e80941Smrg 528b8e80941Smrg struct cso_context *cso = cso_create_context(ctx, 0); 529b8e80941Smrg struct pipe_resource *buf = 530b8e80941Smrg pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024); 531b8e80941Smrg struct pipe_resource *tex = 532b8e80941Smrg util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM, 0); 533b8e80941Smrg struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL; 534b8e80941Smrg 535b8e80941Smrg /* Run 2 clears, get fencess. */ 536b8e80941Smrg uint32_t value = 0; 537b8e80941Smrg ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value)); 538b8e80941Smrg ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD); 539b8e80941Smrg 540b8e80941Smrg struct pipe_box box; 541b8e80941Smrg u_box_2d(0, 0, tex->width0, tex->height0, &box); 542b8e80941Smrg ctx->clear_texture(ctx, tex, 0, &box, &value); 543b8e80941Smrg ctx->flush(ctx, &tex_fence, PIPE_FLUSH_FENCE_FD); 544b8e80941Smrg pass = pass && buf_fence && tex_fence; 545b8e80941Smrg 546b8e80941Smrg /* Export fences. */ 547b8e80941Smrg int buf_fd = screen->fence_get_fd(screen, buf_fence); 548b8e80941Smrg int tex_fd = screen->fence_get_fd(screen, tex_fence); 549b8e80941Smrg pass = pass && buf_fd >= 0 && tex_fd >= 0; 550b8e80941Smrg 551b8e80941Smrg /* Merge fences. */ 552b8e80941Smrg int merged_fd = sync_merge("test", buf_fd, tex_fd); 553b8e80941Smrg pass = pass && merged_fd >= 0; 554b8e80941Smrg 555b8e80941Smrg /* (Re)import all fences. */ 556b8e80941Smrg struct pipe_fence_handle *re_buf_fence = NULL, *re_tex_fence = NULL; 557b8e80941Smrg struct pipe_fence_handle *merged_fence = NULL; 558b8e80941Smrg ctx->create_fence_fd(ctx, &re_buf_fence, buf_fd, fd_type); 559b8e80941Smrg ctx->create_fence_fd(ctx, &re_tex_fence, tex_fd, fd_type); 560b8e80941Smrg ctx->create_fence_fd(ctx, &merged_fence, merged_fd, fd_type); 561b8e80941Smrg pass = pass && re_buf_fence && re_tex_fence && merged_fence; 562b8e80941Smrg 563b8e80941Smrg /* Run another clear after waiting for everything. */ 564b8e80941Smrg struct pipe_fence_handle *final_fence = NULL; 565b8e80941Smrg ctx->fence_server_sync(ctx, merged_fence); 566b8e80941Smrg value = 0xff; 567b8e80941Smrg ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value)); 568b8e80941Smrg ctx->flush(ctx, &final_fence, PIPE_FLUSH_FENCE_FD); 569b8e80941Smrg pass = pass && final_fence; 570b8e80941Smrg 571b8e80941Smrg /* Wait for the last fence. */ 572b8e80941Smrg int final_fd = screen->fence_get_fd(screen, final_fence); 573b8e80941Smrg pass = pass && final_fd >= 0; 574b8e80941Smrg pass = pass && sync_wait(final_fd, -1) == 0; 575b8e80941Smrg 576b8e80941Smrg /* Check that all fences are signalled. */ 577b8e80941Smrg pass = pass && sync_wait(buf_fd, 0) == 0; 578b8e80941Smrg pass = pass && sync_wait(tex_fd, 0) == 0; 579b8e80941Smrg pass = pass && sync_wait(merged_fd, 0) == 0; 580b8e80941Smrg 581b8e80941Smrg pass = pass && screen->fence_finish(screen, NULL, buf_fence, 0); 582b8e80941Smrg pass = pass && screen->fence_finish(screen, NULL, tex_fence, 0); 583b8e80941Smrg pass = pass && screen->fence_finish(screen, NULL, re_buf_fence, 0); 584b8e80941Smrg pass = pass && screen->fence_finish(screen, NULL, re_tex_fence, 0); 585b8e80941Smrg pass = pass && screen->fence_finish(screen, NULL, merged_fence, 0); 586b8e80941Smrg pass = pass && screen->fence_finish(screen, NULL, final_fence, 0); 587b8e80941Smrg 588b8e80941Smrg /* Cleanup. */ 589b8e80941Smrg#ifndef PIPE_OS_WINDOWS 590b8e80941Smrg if (buf_fd >= 0) 591b8e80941Smrg close(buf_fd); 592b8e80941Smrg if (tex_fd >= 0) 593b8e80941Smrg close(tex_fd); 594b8e80941Smrg if (merged_fd >= 0) 595b8e80941Smrg close(merged_fd); 596b8e80941Smrg if (final_fd >= 0) 597b8e80941Smrg close(final_fd); 598b8e80941Smrg#endif 599b8e80941Smrg 600b8e80941Smrg screen->fence_reference(screen, &buf_fence, NULL); 601b8e80941Smrg screen->fence_reference(screen, &tex_fence, NULL); 602b8e80941Smrg screen->fence_reference(screen, &re_buf_fence, NULL); 603b8e80941Smrg screen->fence_reference(screen, &re_tex_fence, NULL); 604b8e80941Smrg screen->fence_reference(screen, &merged_fence, NULL); 605b8e80941Smrg screen->fence_reference(screen, &final_fence, NULL); 606b8e80941Smrg 607b8e80941Smrg cso_destroy_context(cso); 608b8e80941Smrg pipe_resource_reference(&buf, NULL); 609b8e80941Smrg pipe_resource_reference(&tex, NULL); 610b8e80941Smrg 611b8e80941Smrg util_report_result(pass); 612b8e80941Smrg} 613b8e80941Smrg 614b8e80941Smrgstatic void 615b8e80941Smrgtest_texture_barrier(struct pipe_context *ctx, bool use_fbfetch, 616b8e80941Smrg unsigned num_samples) 617b8e80941Smrg{ 618b8e80941Smrg struct cso_context *cso; 619b8e80941Smrg struct pipe_resource *cb; 620b8e80941Smrg struct pipe_sampler_view *view = NULL; 621b8e80941Smrg char name[256]; 622b8e80941Smrg const char *text; 623b8e80941Smrg 624b8e80941Smrg assert(num_samples >= 1 && num_samples <= 8); 625b8e80941Smrg 626b8e80941Smrg util_snprintf(name, sizeof(name), "%s: %s, %u samples", __func__, 627b8e80941Smrg use_fbfetch ? "FBFETCH" : "sampler", MAX2(num_samples, 1)); 628b8e80941Smrg 629b8e80941Smrg if (!ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BARRIER)) { 630b8e80941Smrg util_report_result_helper(SKIP, name); 631b8e80941Smrg return; 632b8e80941Smrg } 633b8e80941Smrg if (use_fbfetch && 634b8e80941Smrg !ctx->screen->get_param(ctx->screen, PIPE_CAP_TGSI_FS_FBFETCH)) { 635b8e80941Smrg util_report_result_helper(SKIP, name); 636b8e80941Smrg return; 637b8e80941Smrg } 638b8e80941Smrg 639b8e80941Smrg cso = cso_create_context(ctx, 0); 640b8e80941Smrg cb = util_create_texture2d(ctx->screen, 256, 256, 641b8e80941Smrg PIPE_FORMAT_R8G8B8A8_UNORM, num_samples); 642b8e80941Smrg util_set_common_states_and_clear(cso, ctx, cb); 643b8e80941Smrg 644b8e80941Smrg /* Clear each sample to a different value. */ 645b8e80941Smrg if (num_samples > 1) { 646b8e80941Smrg void *fs = 647b8e80941Smrg util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC, 648b8e80941Smrg TGSI_INTERPOLATE_LINEAR, TRUE); 649b8e80941Smrg cso_set_fragment_shader_handle(cso, fs); 650b8e80941Smrg 651b8e80941Smrg /* Vertex shader. */ 652b8e80941Smrg void *vs = util_set_passthrough_vertex_shader(cso, ctx, false); 653b8e80941Smrg 654b8e80941Smrg for (unsigned i = 0; i < num_samples / 2; i++) { 655b8e80941Smrg float value; 656b8e80941Smrg 657b8e80941Smrg /* 2 consecutive samples should have the same color to test MSAA 658b8e80941Smrg * compression properly. 659b8e80941Smrg */ 660b8e80941Smrg if (num_samples == 2) { 661b8e80941Smrg value = 0.1; 662b8e80941Smrg } else { 663b8e80941Smrg /* The average value must be 0.1 */ 664b8e80941Smrg static const float values[] = { 665b8e80941Smrg 0.0, 0.2, 0.05, 0.15 666b8e80941Smrg }; 667b8e80941Smrg value = values[i]; 668b8e80941Smrg } 669b8e80941Smrg 670b8e80941Smrg ctx->set_sample_mask(ctx, 0x3 << (i * 2)); 671b8e80941Smrg util_draw_fullscreen_quad_fill(cso, value, value, value, value); 672b8e80941Smrg } 673b8e80941Smrg ctx->set_sample_mask(ctx, ~0); 674b8e80941Smrg 675b8e80941Smrg cso_set_vertex_shader_handle(cso, NULL); 676b8e80941Smrg cso_set_fragment_shader_handle(cso, NULL); 677b8e80941Smrg ctx->delete_vs_state(ctx, vs); 678b8e80941Smrg ctx->delete_fs_state(ctx, fs); 679b8e80941Smrg } 680b8e80941Smrg 681b8e80941Smrg if (use_fbfetch) { 682b8e80941Smrg /* Fragment shader. */ 683b8e80941Smrg text = "FRAG\n" 684b8e80941Smrg "DCL OUT[0], COLOR[0]\n" 685b8e80941Smrg "DCL TEMP[0]\n" 686b8e80941Smrg "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n" 687b8e80941Smrg 688b8e80941Smrg "FBFETCH TEMP[0], OUT[0]\n" 689b8e80941Smrg "ADD OUT[0], TEMP[0], IMM[0]\n" 690b8e80941Smrg "END\n"; 691b8e80941Smrg } else { 692b8e80941Smrg struct pipe_sampler_view templ = {{0}}; 693b8e80941Smrg templ.format = cb->format; 694b8e80941Smrg templ.target = cb->target; 695b8e80941Smrg templ.swizzle_r = PIPE_SWIZZLE_X; 696b8e80941Smrg templ.swizzle_g = PIPE_SWIZZLE_Y; 697b8e80941Smrg templ.swizzle_b = PIPE_SWIZZLE_Z; 698b8e80941Smrg templ.swizzle_a = PIPE_SWIZZLE_W; 699b8e80941Smrg view = ctx->create_sampler_view(ctx, cb, &templ); 700b8e80941Smrg ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &view); 701b8e80941Smrg 702b8e80941Smrg /* Fragment shader. */ 703b8e80941Smrg if (num_samples > 1) { 704b8e80941Smrg text = "FRAG\n" 705b8e80941Smrg "DCL SV[0], POSITION\n" 706b8e80941Smrg "DCL SV[1], SAMPLEID\n" 707b8e80941Smrg "DCL SAMP[0]\n" 708b8e80941Smrg "DCL SVIEW[0], 2D_MSAA, FLOAT\n" 709b8e80941Smrg "DCL OUT[0], COLOR[0]\n" 710b8e80941Smrg "DCL TEMP[0]\n" 711b8e80941Smrg "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n" 712b8e80941Smrg 713b8e80941Smrg "F2I TEMP[0].xy, SV[0].xyyy\n" 714b8e80941Smrg "MOV TEMP[0].w, SV[1].xxxx\n" 715b8e80941Smrg "TXF TEMP[0], TEMP[0], SAMP[0], 2D_MSAA\n" 716b8e80941Smrg "ADD OUT[0], TEMP[0], IMM[0]\n" 717b8e80941Smrg "END\n"; 718b8e80941Smrg } else { 719b8e80941Smrg text = "FRAG\n" 720b8e80941Smrg "DCL SV[0], POSITION\n" 721b8e80941Smrg "DCL SAMP[0]\n" 722b8e80941Smrg "DCL SVIEW[0], 2D, FLOAT\n" 723b8e80941Smrg "DCL OUT[0], COLOR[0]\n" 724b8e80941Smrg "DCL TEMP[0]\n" 725b8e80941Smrg "IMM[0] FLT32 { 0.1, 0.2, 0.3, 0.4}\n" 726b8e80941Smrg "IMM[1] INT32 { 0, 0, 0, 0}\n" 727b8e80941Smrg 728b8e80941Smrg "F2I TEMP[0].xy, SV[0].xyyy\n" 729b8e80941Smrg "MOV TEMP[0].zw, IMM[1]\n" 730b8e80941Smrg "TXF TEMP[0], TEMP[0], SAMP[0], 2D\n" 731b8e80941Smrg "ADD OUT[0], TEMP[0], IMM[0]\n" 732b8e80941Smrg "END\n"; 733b8e80941Smrg } 734b8e80941Smrg } 735b8e80941Smrg 736b8e80941Smrg struct tgsi_token tokens[1000]; 737b8e80941Smrg struct pipe_shader_state state; 738b8e80941Smrg 739b8e80941Smrg if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 740b8e80941Smrg assert(0); 741b8e80941Smrg util_report_result_helper(FAIL, name); 742b8e80941Smrg return; 743b8e80941Smrg } 744b8e80941Smrg pipe_shader_state_from_tgsi(&state, tokens); 745b8e80941Smrg 746b8e80941Smrg void *fs = ctx->create_fs_state(ctx, &state); 747b8e80941Smrg cso_set_fragment_shader_handle(cso, fs); 748b8e80941Smrg 749b8e80941Smrg /* Vertex shader. */ 750b8e80941Smrg void *vs = util_set_passthrough_vertex_shader(cso, ctx, false); 751b8e80941Smrg 752b8e80941Smrg if (num_samples > 1 && !use_fbfetch) 753b8e80941Smrg ctx->set_min_samples(ctx, num_samples); 754b8e80941Smrg 755b8e80941Smrg for (int i = 0; i < 2; i++) { 756b8e80941Smrg ctx->texture_barrier(ctx, 757b8e80941Smrg use_fbfetch ? PIPE_TEXTURE_BARRIER_FRAMEBUFFER : 758b8e80941Smrg PIPE_TEXTURE_BARRIER_SAMPLER); 759b8e80941Smrg util_draw_fullscreen_quad(cso); 760b8e80941Smrg } 761b8e80941Smrg if (num_samples > 1 && !use_fbfetch) 762b8e80941Smrg ctx->set_min_samples(ctx, 1); 763b8e80941Smrg 764b8e80941Smrg /* Probe pixels. 765b8e80941Smrg * 766b8e80941Smrg * For single sample: 767b8e80941Smrg * result = 0.1 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.3, 0.5, 0.7, 0.9) 768b8e80941Smrg * 769b8e80941Smrg * For MSAA 4x: 770b8e80941Smrg * sample0 = 0.0 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.2, 0.4, 0.6, 0.8) 771b8e80941Smrg * sample1 = sample0 772b8e80941Smrg * sample2 = 0.2 (clear) + (0.1, 0.2, 0.3, 0.4) * 2 = (0.4, 0.6, 0.8, 1.0) 773b8e80941Smrg * sample3 = sample2 774b8e80941Smrg * resolved = sum(sample[0:3]) / 4 = (0.3, 0.5, 0.7, 0.9) 775b8e80941Smrg */ 776b8e80941Smrg static const float expected[] = {0.3, 0.5, 0.7, 0.9}; 777b8e80941Smrg bool pass = util_probe_rect_rgba(ctx, cb, 0, 0, 778b8e80941Smrg cb->width0, cb->height0, expected); 779b8e80941Smrg 780b8e80941Smrg /* Cleanup. */ 781b8e80941Smrg cso_destroy_context(cso); 782b8e80941Smrg ctx->delete_vs_state(ctx, vs); 783b8e80941Smrg ctx->delete_fs_state(ctx, fs); 784b8e80941Smrg pipe_sampler_view_reference(&view, NULL); 785b8e80941Smrg pipe_resource_reference(&cb, NULL); 786b8e80941Smrg 787b8e80941Smrg util_report_result_helper(pass, name); 788b8e80941Smrg} 789b8e80941Smrg 790b8e80941Smrgstatic void 791b8e80941Smrgtest_compute_clear_image(struct pipe_context *ctx) 792b8e80941Smrg{ 793b8e80941Smrg struct pipe_resource *cb; 794b8e80941Smrg const char *text; 795b8e80941Smrg 796b8e80941Smrg cb = util_create_texture2d(ctx->screen, 256, 256, 797b8e80941Smrg PIPE_FORMAT_R8G8B8A8_UNORM, 1); 798b8e80941Smrg 799b8e80941Smrg /* Compute shader. */ 800b8e80941Smrg text = "COMP\n" 801b8e80941Smrg "PROPERTY CS_FIXED_BLOCK_WIDTH 8\n" 802b8e80941Smrg "PROPERTY CS_FIXED_BLOCK_HEIGHT 8\n" 803b8e80941Smrg "PROPERTY CS_FIXED_BLOCK_DEPTH 1\n" 804b8e80941Smrg "DCL SV[0], THREAD_ID\n" 805b8e80941Smrg "DCL SV[1], BLOCK_ID\n" 806b8e80941Smrg "DCL IMAGE[0], 2D, PIPE_FORMAT_R8G8B8A8_UNORM, WR\n" 807b8e80941Smrg "DCL TEMP[0]\n" 808b8e80941Smrg "IMM[0] UINT32 { 8, 8, 0, 0}\n" 809b8e80941Smrg "IMM[1] FLT32 { 1, 0, 0, 0}\n" 810b8e80941Smrg 811b8e80941Smrg /* TEMP[0].xy = SV[1] * IMM[0] + SV[0]; */ 812b8e80941Smrg "UMAD TEMP[0].xy, SV[1], IMM[0], SV[0]\n" 813b8e80941Smrg "STORE IMAGE[0], TEMP[0], IMM[1], 2D, PIPE_FORMAT_R8G8B8A8_UNORM\n" 814b8e80941Smrg "END\n"; 815b8e80941Smrg 816b8e80941Smrg struct tgsi_token tokens[1000]; 817b8e80941Smrg if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 818b8e80941Smrg assert(0); 819b8e80941Smrg util_report_result(FAIL); 820b8e80941Smrg return; 821b8e80941Smrg } 822b8e80941Smrg 823b8e80941Smrg struct pipe_compute_state state = {0}; 824b8e80941Smrg state.ir_type = PIPE_SHADER_IR_TGSI; 825b8e80941Smrg state.prog = tokens; 826b8e80941Smrg 827b8e80941Smrg void *compute_shader = ctx->create_compute_state(ctx, &state); 828b8e80941Smrg ctx->bind_compute_state(ctx, compute_shader); 829b8e80941Smrg 830b8e80941Smrg /* Bind the image. */ 831b8e80941Smrg struct pipe_image_view image = {0}; 832b8e80941Smrg image.resource = cb; 833b8e80941Smrg image.shader_access = image.access = PIPE_IMAGE_ACCESS_READ_WRITE; 834b8e80941Smrg image.format = cb->format; 835b8e80941Smrg 836b8e80941Smrg ctx->set_shader_images(ctx, PIPE_SHADER_COMPUTE, 0, 1, &image); 837b8e80941Smrg 838b8e80941Smrg /* Dispatch compute. */ 839b8e80941Smrg struct pipe_grid_info info = {0}; 840b8e80941Smrg info.block[0] = 8; 841b8e80941Smrg info.block[1] = 8; 842b8e80941Smrg info.block[2] = 1; 843b8e80941Smrg info.grid[0] = cb->width0 / 8; 844b8e80941Smrg info.grid[1] = cb->height0 / 8; 845b8e80941Smrg info.grid[2] = 1; 846b8e80941Smrg 847b8e80941Smrg ctx->launch_grid(ctx, &info); 848b8e80941Smrg 849b8e80941Smrg /* Check pixels. */ 850b8e80941Smrg static const float expected[] = {1.0, 0.0, 0.0, 0.0}; 851b8e80941Smrg bool pass = util_probe_rect_rgba(ctx, cb, 0, 0, 852b8e80941Smrg cb->width0, cb->height0, expected); 853b8e80941Smrg 854b8e80941Smrg /* Cleanup. */ 855b8e80941Smrg ctx->delete_compute_state(ctx, compute_shader); 856b8e80941Smrg pipe_resource_reference(&cb, NULL); 857b8e80941Smrg 858b8e80941Smrg util_report_result(pass); 859b8e80941Smrg} 860b8e80941Smrg 861b8e80941Smrg/** 862b8e80941Smrg * Run all tests. This should be run with a clean context after 863b8e80941Smrg * context_create. 864b8e80941Smrg */ 865b8e80941Smrgvoid 866b8e80941Smrgutil_run_tests(struct pipe_screen *screen) 867b8e80941Smrg{ 868b8e80941Smrg struct pipe_context *ctx = screen->context_create(screen, NULL, 0); 869b8e80941Smrg 870b8e80941Smrg null_fragment_shader(ctx); 871b8e80941Smrg tgsi_vs_window_space_position(ctx); 872b8e80941Smrg null_sampler_view(ctx, TGSI_TEXTURE_2D); 873b8e80941Smrg null_sampler_view(ctx, TGSI_TEXTURE_BUFFER); 874b8e80941Smrg util_test_constant_buffer(ctx, NULL); 875b8e80941Smrg test_sync_file_fences(ctx); 876b8e80941Smrg 877b8e80941Smrg for (int i = 1; i <= 8; i = i * 2) 878b8e80941Smrg test_texture_barrier(ctx, false, i); 879b8e80941Smrg for (int i = 1; i <= 8; i = i * 2) 880b8e80941Smrg test_texture_barrier(ctx, true, i); 881b8e80941Smrg ctx->destroy(ctx); 882b8e80941Smrg 883b8e80941Smrg ctx = screen->context_create(screen, NULL, PIPE_CONTEXT_COMPUTE_ONLY); 884b8e80941Smrg test_compute_clear_image(ctx); 885b8e80941Smrg ctx->destroy(ctx); 886b8e80941Smrg 887b8e80941Smrg puts("Done. Exiting.."); 888b8e80941Smrg exit(0); 889b8e80941Smrg} 890