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