xref: /aosp_15_r20/external/mesa3d/src/gallium/auxiliary/util/u_simple_shaders.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
4  * All Rights Reserved.
5  * Copyright 2009 Marek Olšák <[email protected]>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 /**
30  * @file
31  * Simple vertex/fragment shader generators.
32  *
33  * @author Brian Paul
34            Marek Olšák
35  */
36 
37 
38 #include "pipe/p_context.h"
39 #include "pipe/p_shader_tokens.h"
40 #include "pipe/p_state.h"
41 #include "util/u_simple_shaders.h"
42 #include "util/u_debug.h"
43 #include "util/u_memory.h"
44 #include "util/u_string.h"
45 #include "tgsi/tgsi_dump.h"
46 #include "tgsi/tgsi_strings.h"
47 #include "tgsi/tgsi_ureg.h"
48 #include "tgsi/tgsi_text.h"
49 #include <stdio.h> /* include last */
50 
51 
52 
53 /**
54  * Make simple vertex pass-through shader.
55  * \param num_attribs  number of attributes to pass through
56  * \param semantic_names  array of semantic names for each attribute
57  * \param semantic_indexes  array of semantic indexes for each attribute
58  */
59 void *
util_make_vertex_passthrough_shader(struct pipe_context * pipe,unsigned num_attribs,const enum tgsi_semantic * semantic_names,const unsigned * semantic_indexes,bool window_space)60 util_make_vertex_passthrough_shader(struct pipe_context *pipe,
61                                     unsigned num_attribs,
62                                     const enum tgsi_semantic *semantic_names,
63                                     const unsigned *semantic_indexes,
64                                     bool window_space)
65 {
66    return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
67                                                       semantic_names,
68                                                       semantic_indexes,
69                                                       window_space, false, NULL);
70 }
71 
72 void *
util_make_vertex_passthrough_shader_with_so(struct pipe_context * pipe,unsigned num_attribs,const enum tgsi_semantic * semantic_names,const unsigned * semantic_indexes,bool window_space,bool layered,const struct pipe_stream_output_info * so)73 util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
74                                     unsigned num_attribs,
75                                     const enum tgsi_semantic *semantic_names,
76                                     const unsigned *semantic_indexes,
77                                     bool window_space, bool layered,
78 				    const struct pipe_stream_output_info *so)
79 {
80    struct ureg_program *ureg;
81    unsigned i;
82 
83    ureg = ureg_create( PIPE_SHADER_VERTEX );
84    if (!ureg)
85       return NULL;
86 
87    if (window_space)
88       ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, true);
89 
90    for (i = 0; i < num_attribs; i++) {
91       struct ureg_src src;
92       struct ureg_dst dst;
93 
94       src = ureg_DECL_vs_input( ureg, i );
95 
96       dst = ureg_DECL_output( ureg,
97                               semantic_names[i],
98                               semantic_indexes[i]);
99 
100       ureg_MOV( ureg, dst, src );
101    }
102 
103    if (layered) {
104       struct ureg_src instance_id =
105          ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0);
106       struct ureg_dst layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0);
107 
108       ureg_MOV(ureg, ureg_writemask(layer, TGSI_WRITEMASK_X),
109                ureg_scalar(instance_id, TGSI_SWIZZLE_X));
110    }
111 
112    ureg_END( ureg );
113 
114    return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
115 }
116 
117 
util_make_layered_clear_vertex_shader(struct pipe_context * pipe)118 void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
119 {
120    const enum tgsi_semantic semantic_names[] = {TGSI_SEMANTIC_POSITION,
121                                                 TGSI_SEMANTIC_GENERIC};
122    const unsigned semantic_indices[] = {0, 0};
123 
124    return util_make_vertex_passthrough_shader_with_so(pipe, 2, semantic_names,
125                                                       semantic_indices, false,
126                                                       true, NULL);
127 }
128 
129 /**
130  * Takes position and color, and outputs position, color, and instance id.
131  */
util_make_layered_clear_helper_vertex_shader(struct pipe_context * pipe)132 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
133 {
134    static const char text[] =
135          "VERT\n"
136          "DCL IN[0]\n"
137          "DCL IN[1]\n"
138          "DCL SV[0], INSTANCEID\n"
139          "DCL OUT[0], POSITION\n"
140          "DCL OUT[1], GENERIC[0]\n"
141          "DCL OUT[2], GENERIC[1]\n"
142 
143          "MOV OUT[0], IN[0]\n"
144          "MOV OUT[1], IN[1]\n"
145          "MOV OUT[2].x, SV[0].xxxx\n"
146          "END\n";
147    struct tgsi_token tokens[1000];
148    struct pipe_shader_state state = {0};
149 
150    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
151       assert(0);
152       return NULL;
153    }
154    pipe_shader_state_from_tgsi(&state, tokens);
155    return pipe->create_vs_state(pipe, &state);
156 }
157 
158 /**
159  * Takes position, color, and target layer, and emits vertices on that target
160  * layer, with the specified color.
161  */
util_make_layered_clear_geometry_shader(struct pipe_context * pipe)162 void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
163 {
164    static const char text[] =
165       "GEOM\n"
166       "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
167       "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
168       "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
169       "PROPERTY GS_INVOCATIONS 1\n"
170       "DCL IN[][0], POSITION\n" /* position */
171       "DCL IN[][1], GENERIC[0]\n" /* color */
172       "DCL IN[][2], GENERIC[1]\n" /* vs invocation */
173       "DCL OUT[0], POSITION\n"
174       "DCL OUT[1], GENERIC[0]\n"
175       "DCL OUT[2], LAYER\n"
176       "IMM[0] INT32 {0, 0, 0, 0}\n"
177 
178       "MOV OUT[0], IN[0][0]\n"
179       "MOV OUT[1], IN[0][1]\n"
180       "MOV OUT[2].x, IN[0][2].xxxx\n"
181       "EMIT IMM[0].xxxx\n"
182       "MOV OUT[0], IN[1][0]\n"
183       "MOV OUT[1], IN[1][1]\n"
184       "MOV OUT[2].x, IN[1][2].xxxx\n"
185       "EMIT IMM[0].xxxx\n"
186       "MOV OUT[0], IN[2][0]\n"
187       "MOV OUT[1], IN[2][1]\n"
188       "MOV OUT[2].x, IN[2][2].xxxx\n"
189       "EMIT IMM[0].xxxx\n"
190       "END\n";
191    struct tgsi_token tokens[1000];
192    struct pipe_shader_state state = {0};
193 
194    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
195       assert(0);
196       return NULL;
197    }
198    pipe_shader_state_from_tgsi(&state, tokens);
199    return pipe->create_gs_state(pipe, &state);
200 }
201 
202 static void
ureg_load_tex(struct ureg_program * ureg,struct ureg_dst out,struct ureg_src coord,struct ureg_src sampler,enum tgsi_texture_type tex_target,bool load_level_zero,bool use_txf)203 ureg_load_tex(struct ureg_program *ureg, struct ureg_dst out,
204               struct ureg_src coord, struct ureg_src sampler,
205               enum tgsi_texture_type tex_target,
206               bool load_level_zero, bool use_txf)
207 {
208    if (use_txf) {
209       struct ureg_dst temp = ureg_DECL_temporary(ureg);
210 
211       /* Nearest filtering floors and then converts to integer, and then
212        * applies clamp to edge as clamp(coord, 0, dim - 1).
213        * u_blitter only uses this when the coordinates are in bounds,
214        * so no clamping is needed and we can use trunc instead of floor. trunc
215        * with f2i will get optimized out in NIR where f2i has round-to-zero
216        * behaviour already.
217        */
218       unsigned wrmask = tex_target == TGSI_TEXTURE_1D ||
219                         tex_target == TGSI_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_X :
220                         tex_target == TGSI_TEXTURE_3D ? TGSI_WRITEMASK_XYZ :
221                                                         TGSI_WRITEMASK_XY;
222 
223       ureg_MOV(ureg, temp, coord);
224       ureg_TRUNC(ureg, ureg_writemask(temp, wrmask), ureg_src(temp));
225       ureg_F2I(ureg, temp, ureg_src(temp));
226 
227       if (load_level_zero)
228          ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler);
229       else
230          ureg_TXF(ureg, out, tex_target, ureg_src(temp), sampler);
231    } else {
232       if (load_level_zero)
233          ureg_TEX_LZ(ureg, out, tex_target, coord, sampler);
234       else
235          ureg_TEX(ureg, out, tex_target, coord, sampler);
236    }
237 }
238 
239 /**
240  * Make simple fragment texture shader:
241  *  TEX TEMP[0], IN[0], SAMP[0], 2D;
242  *   .. optional SINT <-> UINT clamping ..
243  *  MOV OUT[0], TEMP[0]
244  *  END;
245  *
246  * \param tex_target  one of TGSI_TEXTURE_x
247  */
248 void *
util_make_fragment_tex_shader(struct pipe_context * pipe,enum tgsi_texture_type tex_target,enum tgsi_return_type stype,enum tgsi_return_type dtype,bool load_level_zero,bool use_txf)249 util_make_fragment_tex_shader(struct pipe_context *pipe,
250                               enum tgsi_texture_type tex_target,
251                               enum tgsi_return_type stype,
252                               enum tgsi_return_type dtype,
253                               bool load_level_zero,
254                               bool use_txf)
255 {
256    struct ureg_program *ureg;
257    struct ureg_src sampler;
258    struct ureg_src tex;
259    struct ureg_dst temp;
260    struct ureg_dst out;
261 
262    assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT));
263 
264    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
265    if (!ureg)
266       return NULL;
267 
268    sampler = ureg_DECL_sampler( ureg, 0 );
269 
270    ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype);
271 
272    tex = ureg_DECL_fs_input( ureg,
273                              TGSI_SEMANTIC_GENERIC, 0,
274                              TGSI_INTERPOLATE_LINEAR );
275 
276    out = ureg_DECL_output( ureg,
277                            TGSI_SEMANTIC_COLOR,
278                            0 );
279 
280    temp = ureg_DECL_temporary(ureg);
281 
282    if (tex_target == TGSI_TEXTURE_BUFFER)
283       ureg_TXF(ureg,
284                ureg_writemask(temp, TGSI_WRITEMASK_XYZW),
285                tex_target, tex, sampler);
286    else
287       ureg_load_tex(ureg, ureg_writemask(temp, TGSI_WRITEMASK_XYZW), tex, sampler,
288                     tex_target, load_level_zero, use_txf);
289 
290    if (stype != dtype) {
291       if (stype == TGSI_RETURN_TYPE_SINT) {
292          assert(dtype == TGSI_RETURN_TYPE_UINT);
293 
294          ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0));
295       } else {
296          assert(stype == TGSI_RETURN_TYPE_UINT);
297          assert(dtype == TGSI_RETURN_TYPE_SINT);
298 
299          ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1));
300       }
301    }
302 
303    ureg_MOV(ureg, out, ureg_src(temp));
304 
305    ureg_END( ureg );
306 
307    return ureg_create_shader_and_destroy( ureg, pipe );
308 }
309 
310 /**
311  * Make a simple fragment texture shader which reads the texture unit 0 and 1
312  * and writes it as depth and stencil, respectively.
313  */
314 void *
util_make_fs_blit_zs(struct pipe_context * pipe,unsigned zs_mask,enum tgsi_texture_type tex_target,bool load_level_zero,bool use_txf)315 util_make_fs_blit_zs(struct pipe_context *pipe, unsigned zs_mask,
316                      enum tgsi_texture_type tex_target,
317                      bool load_level_zero, bool use_txf)
318 {
319    struct ureg_program *ureg;
320    struct ureg_src depth_sampler, stencil_sampler, coord;
321    struct ureg_dst depth, stencil, tmp;
322 
323    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
324    if (!ureg)
325       return NULL;
326 
327    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
328                               TGSI_INTERPOLATE_LINEAR);
329    tmp = ureg_DECL_temporary(ureg);
330 
331    if (zs_mask & PIPE_MASK_Z) {
332       depth_sampler = ureg_DECL_sampler(ureg, 0);
333       ureg_DECL_sampler_view(ureg, 0, tex_target,
334                              TGSI_RETURN_TYPE_FLOAT,
335                              TGSI_RETURN_TYPE_FLOAT,
336                              TGSI_RETURN_TYPE_FLOAT,
337                              TGSI_RETURN_TYPE_FLOAT);
338 
339       ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord,
340                     depth_sampler, tex_target, load_level_zero, use_txf);
341 
342       depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
343       ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z),
344                ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
345    }
346 
347    if (zs_mask & PIPE_MASK_S) {
348       stencil_sampler = ureg_DECL_sampler(ureg, zs_mask & PIPE_MASK_Z ? 1 : 0);
349       ureg_DECL_sampler_view(ureg, zs_mask & PIPE_MASK_Z ? 1 : 0, tex_target,
350                              TGSI_RETURN_TYPE_UINT,
351                              TGSI_RETURN_TYPE_UINT,
352                              TGSI_RETURN_TYPE_UINT,
353                              TGSI_RETURN_TYPE_UINT);
354 
355       ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord,
356                     stencil_sampler, tex_target, load_level_zero, use_txf);
357 
358       stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0);
359       ureg_MOV(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y),
360                ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
361    }
362 
363    ureg_END(ureg);
364 
365    return ureg_create_shader_and_destroy(ureg, pipe);
366 }
367 
368 
369 /**
370  * Make simple fragment color pass-through shader that replicates OUT[0]
371  * to all bound colorbuffers.
372  */
373 void *
util_make_fragment_passthrough_shader(struct pipe_context * pipe,int input_semantic,int input_interpolate,bool write_all_cbufs)374 util_make_fragment_passthrough_shader(struct pipe_context *pipe,
375                                       int input_semantic,
376                                       int input_interpolate,
377                                       bool write_all_cbufs)
378 {
379    static const char shader_templ[] =
380          "FRAG\n"
381          "%s"
382          "DCL IN[0], %s[0], %s\n"
383          "DCL OUT[0], COLOR[0]\n"
384 
385          "MOV OUT[0], IN[0]\n"
386          "END\n";
387 
388    char text[sizeof(shader_templ)+100];
389    struct tgsi_token tokens[1000];
390    struct pipe_shader_state state = {0};
391 
392    sprintf(text, shader_templ,
393            write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
394            tgsi_semantic_names[input_semantic],
395            tgsi_interpolate_names[input_interpolate]);
396 
397    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
398       assert(0);
399       return NULL;
400    }
401    pipe_shader_state_from_tgsi(&state, tokens);
402 #if 0
403    tgsi_dump(state.tokens, 0);
404 #endif
405 
406    return pipe->create_fs_state(pipe, &state);
407 }
408 
409 
410 void *
util_make_empty_fragment_shader(struct pipe_context * pipe)411 util_make_empty_fragment_shader(struct pipe_context *pipe)
412 {
413    struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT);
414    if (!ureg)
415       return NULL;
416 
417    ureg_END(ureg);
418    return ureg_create_shader_and_destroy(ureg, pipe);
419 }
420 
421 
422 /**
423  * Make a fragment shader that copies the input color to N output colors.
424  */
425 void *
util_make_fragment_cloneinput_shader(struct pipe_context * pipe,int num_cbufs,int input_semantic,int input_interpolate)426 util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
427                                      int input_semantic,
428                                      int input_interpolate)
429 {
430    struct ureg_program *ureg;
431    struct ureg_src src;
432    struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
433    int i;
434 
435    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
436 
437    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
438    if (!ureg)
439       return NULL;
440 
441    src = ureg_DECL_fs_input( ureg, input_semantic, 0,
442                              input_interpolate );
443 
444    for (i = 0; i < num_cbufs; i++)
445       dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
446 
447    for (i = 0; i < num_cbufs; i++)
448       ureg_MOV( ureg, dst[i], src );
449 
450    ureg_END( ureg );
451 
452    return ureg_create_shader_and_destroy( ureg, pipe );
453 }
454 
455 
456 static void *
util_make_fs_blit_msaa_gen(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,bool sample_shading,bool has_txq,const char * samp_type,const char * output_semantic,const char * output_mask,const char * conversion)457 util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
458                            enum tgsi_texture_type tgsi_tex,
459                            bool sample_shading, bool has_txq,
460                            const char *samp_type,
461                            const char *output_semantic,
462                            const char *output_mask,
463                            const char *conversion)
464 {
465    char text[1000];
466    struct tgsi_token tokens[1000];
467    struct pipe_shader_state state = {0};
468 
469    if (has_txq) {
470       static const char shader_templ[] =
471             "FRAG\n"
472             "DCL IN[0], GENERIC[0], LINEAR\n"
473             "DCL SAMP[0]\n"
474             "DCL SVIEW[0], %s, %s\n"
475             "DCL OUT[0], %s\n"
476             "DCL TEMP[0..1]\n"
477             "IMM[0] INT32 {0, -1, 2147483647, 0}\n"
478             "%s"
479 
480             /* Nearest filtering floors and then converts to integer, and then
481              * applies clamp to edge as clamp(coord, 0, dim - 1).
482              */
483             "MOV TEMP[0], IN[0]\n"
484             "FLR TEMP[0].xy, TEMP[0]\n"
485             "F2I TEMP[0], TEMP[0]\n"
486             "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
487             /* Clamp to edge for the upper bound. */
488             "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n"
489             "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */
490             "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n"
491             /* Texel fetch. */
492             "%s"
493             "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
494             "%s"
495             "MOV OUT[0]%s, TEMP[0]\n"
496             "END\n";
497 
498       const char *type = tgsi_texture_names[tgsi_tex];
499 
500       assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
501              tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
502 
503       snprintf(text, sizeof(text), shader_templ, type, samp_type,
504                output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
505                type, sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
506                type, conversion, output_mask);
507    } else {
508       static const char shader_templ[] =
509             "FRAG\n"
510             "DCL IN[0], GENERIC[0], LINEAR\n"
511             "DCL SAMP[0]\n"
512             "DCL SVIEW[0], %s, %s\n"
513             "DCL OUT[0], %s\n"
514             "DCL TEMP[0..1]\n"
515             "IMM[0] INT32 {0, -1, 2147483647, 0}\n"
516             "%s"
517 
518             /* Nearest filtering floors and then converts to integer, and then
519              * applies clamp to edge as clamp(coord, 0, dim - 1). Don't clamp
520              * to dim - 1 because TXQ is unsupported.
521              */
522             "MOV TEMP[0], IN[0]\n"
523             "FLR TEMP[0].xy, TEMP[0]\n"
524             "F2I TEMP[0], TEMP[0]\n"
525             "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
526             /* Texel fetch. */
527             "%s"
528             "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
529             "%s"
530             "MOV OUT[0]%s, TEMP[0]\n"
531             "END\n";
532 
533       const char *type = tgsi_texture_names[tgsi_tex];
534 
535       assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
536              tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
537 
538       snprintf(text, sizeof(text), shader_templ, type, samp_type,
539                output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
540                sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
541                type, conversion, output_mask);
542    }
543 
544    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
545       puts(text);
546       assert(0);
547       return NULL;
548    }
549    pipe_shader_state_from_tgsi(&state, tokens);
550 #if 0
551    tgsi_dump(state.tokens, 0);
552 #endif
553 
554    return pipe->create_fs_state(pipe, &state);
555 }
556 
557 
558 /**
559  * Make a fragment shader that sets the output color to a color
560  * fetched from a multisample texture.
561  * \param tex_target  one of PIPE_TEXTURE_x
562  */
563 void *
util_make_fs_blit_msaa_color(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,enum tgsi_return_type stype,enum tgsi_return_type dtype,bool sample_shading,bool has_txq)564 util_make_fs_blit_msaa_color(struct pipe_context *pipe,
565                              enum tgsi_texture_type tgsi_tex,
566                              enum tgsi_return_type stype,
567                              enum tgsi_return_type dtype,
568                              bool sample_shading, bool has_txq)
569 {
570    const char *samp_type;
571    const char *conversion = "";
572 
573    if (stype == TGSI_RETURN_TYPE_UINT) {
574       samp_type = "UINT";
575 
576       if (dtype == TGSI_RETURN_TYPE_SINT) {
577          conversion = "UMIN TEMP[0], TEMP[0], IMM[0].zzzz\n";
578       }
579    } else if (stype == TGSI_RETURN_TYPE_SINT) {
580       samp_type = "SINT";
581 
582       if (dtype == TGSI_RETURN_TYPE_UINT) {
583          conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
584       }
585    } else {
586       assert(dtype == TGSI_RETURN_TYPE_FLOAT);
587       samp_type = "FLOAT";
588    }
589 
590    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq,
591                                      samp_type, "COLOR[0]", "", conversion);
592 }
593 
594 
595 /**
596  * Make a fragment shader that sets the output depth to a depth value
597  * fetched from a multisample texture.
598  * \param tex_target  one of PIPE_TEXTURE_x
599  */
600 void *
util_make_fs_blit_msaa_depth(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,bool sample_shading,bool has_txq)601 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
602                              enum tgsi_texture_type tgsi_tex,
603                              bool sample_shading, bool has_txq)
604 {
605    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq,
606                                      "FLOAT", "POSITION", ".z",
607                                      "MOV TEMP[0].z, TEMP[0].xxxx\n");
608 }
609 
610 
611 /**
612  * Make a fragment shader that sets the output stencil to a stencil value
613  * fetched from a multisample texture.
614  * \param tex_target  one of PIPE_TEXTURE_x
615  */
616 void *
util_make_fs_blit_msaa_stencil(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,bool sample_shading,bool has_txq)617 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
618                                enum tgsi_texture_type tgsi_tex,
619                                bool sample_shading, bool has_txq)
620 {
621    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq,
622                                      "UINT", "STENCIL", ".y",
623                                      "MOV TEMP[0].y, TEMP[0].xxxx\n");
624 }
625 
626 
627 /**
628  * Make a fragment shader that sets the output depth and stencil to depth
629  * and stencil values fetched from two multisample textures / samplers.
630  * The sizes of both textures should match (it should be one depth-stencil
631  * texture).
632  * \param tex_target  one of PIPE_TEXTURE_x
633  */
634 void *
util_make_fs_blit_msaa_depthstencil(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,bool sample_shading,bool has_txq)635 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
636                                     enum tgsi_texture_type tgsi_tex,
637                                     bool sample_shading, bool has_txq)
638 {
639    const char *type = tgsi_texture_names[tgsi_tex];
640    char text[1000];
641    struct tgsi_token tokens[1000];
642    struct pipe_shader_state state = {0};
643 
644    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
645           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
646 
647    if (has_txq) {
648       static const char shader_templ[] =
649             "FRAG\n"
650             "DCL IN[0], GENERIC[0], LINEAR\n"
651             "DCL SAMP[0..1]\n"
652             "DCL SVIEW[0], %s, FLOAT\n"
653             "DCL SVIEW[1], %s, UINT\n"
654             "DCL OUT[0], POSITION\n"
655             "DCL OUT[1], STENCIL\n"
656             "DCL TEMP[0..1]\n"
657             "IMM[0] INT32 {0, -1, 0, 0}\n"
658             "%s"
659 
660             /* Nearest filtering floors and then converts to integer, and then
661              * applies clamp to edge as clamp(coord, 0, dim - 1).
662              */
663             "MOV TEMP[0], IN[0]\n"
664             "FLR TEMP[0].xy, TEMP[0]\n"
665             "F2I TEMP[0], TEMP[0]\n"
666             "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
667             /* Clamp to edge for the upper bound. */
668             "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n"
669             "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */
670             "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n"
671             /* Texel fetch. */
672             "%s"
673             "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
674             "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
675             "END\n";
676 
677       sprintf(text, shader_templ, type, type,
678               sample_shading ? "DCL SV[0], SAMPLEID\n" : "", type,
679               sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
680               type, type);
681    } else {
682       static const char shader_templ[] =
683             "FRAG\n"
684             "DCL IN[0], GENERIC[0], LINEAR\n"
685             "DCL SAMP[0..1]\n"
686             "DCL SVIEW[0], %s, FLOAT\n"
687             "DCL SVIEW[1], %s, UINT\n"
688             "DCL OUT[0], POSITION\n"
689             "DCL OUT[1], STENCIL\n"
690             "DCL TEMP[0..1]\n"
691             "IMM[0] INT32 {0, -1, 0, 0}\n"
692             "%s"
693 
694             /* Nearest filtering floors and then converts to integer, and then
695              * applies clamp to edge as clamp(coord, 0, dim - 1). Don't clamp
696              * to dim - 1 because TXQ is unsupported.
697              */
698             "MOV TEMP[0], IN[0]\n"
699             "FLR TEMP[0].xy, TEMP[0]\n"
700             "F2I TEMP[0], TEMP[0]\n"
701             "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
702             /* Texel fetch. */
703             "%s"
704             "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
705             "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
706             "END\n";
707 
708       sprintf(text, shader_templ, type, type,
709               sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
710               sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
711               type, type);
712    }
713 
714    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
715       assert(0);
716       return NULL;
717    }
718    pipe_shader_state_from_tgsi(&state, tokens);
719 #if 0
720    tgsi_dump(state.tokens, 0);
721 #endif
722 
723    return pipe->create_fs_state(pipe, &state);
724 }
725 
726 
727 void *
util_make_fs_msaa_resolve(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,unsigned nr_samples,bool has_txq)728 util_make_fs_msaa_resolve(struct pipe_context *pipe,
729                           enum tgsi_texture_type tgsi_tex, unsigned nr_samples,
730                           bool has_txq)
731 {
732    struct ureg_program *ureg;
733    struct ureg_src sampler, coord;
734    struct ureg_dst out, tmp_sum, tmp_coord, tmp;
735    unsigned i;
736 
737    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
738    if (!ureg)
739       return NULL;
740 
741    /* Declarations. */
742    sampler = ureg_DECL_sampler(ureg, 0);
743    ureg_DECL_sampler_view(ureg, 0, tgsi_tex,
744                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
745                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
746    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
747                               TGSI_INTERPOLATE_LINEAR);
748    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
749    tmp_sum = ureg_DECL_temporary(ureg);
750    tmp_coord = ureg_DECL_temporary(ureg);
751    tmp = ureg_DECL_temporary(ureg);
752 
753    /* Instructions. */
754    ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
755 
756    /* Nearest filtering floors and then converts to integer, and then
757     * applies clamp to edge as clamp(coord, 0, dim - 1).
758     */
759    ureg_MOV(ureg, tmp_coord, coord);
760    ureg_FLR(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_XY),
761             ureg_src(tmp_coord));
762    ureg_F2I(ureg, tmp_coord, ureg_src(tmp_coord));
763    ureg_IMAX(ureg, tmp_coord, ureg_src(tmp_coord), ureg_imm1i(ureg, 0));
764 
765    /* Clamp to edge for the upper bound. */
766    if (has_txq) {
767       ureg_TXQ(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), tgsi_tex,
768                ureg_imm1u(ureg, 0), sampler);
769       ureg_UADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp),
770                 ureg_imm2i(ureg, -1, -1)); /* width - 1, height - 1 */
771       ureg_IMIN(ureg,  ureg_writemask(tmp_coord, TGSI_WRITEMASK_XY),
772                 ureg_src(tmp_coord), ureg_src(tmp));
773    }
774 
775    for (i = 0; i < nr_samples; i++) {
776       /* Read one sample. */
777       ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W),
778                ureg_imm1u(ureg, i));
779       ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler);
780 
781       /* Add it to the sum.*/
782       ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp));
783    }
784 
785    /* Calculate the average and return. */
786    ureg_MUL(ureg, out, ureg_src(tmp_sum),
787             ureg_imm1f(ureg, 1.0 / nr_samples));
788    ureg_END(ureg);
789 
790    return ureg_create_shader_and_destroy(ureg, pipe);
791 }
792 
793 
794 void *
util_make_fs_msaa_resolve_bilinear(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,unsigned nr_samples,bool has_txq)795 util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
796                                    enum tgsi_texture_type tgsi_tex,
797                                    unsigned nr_samples, bool has_txq)
798 {
799    struct ureg_program *ureg;
800    struct ureg_src sampler, coord;
801    struct ureg_dst out, tmp, top, bottom;
802    struct ureg_dst tmp_coord[4], tmp_sum[4], weights;
803    unsigned i, c;
804 
805    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
806    if (!ureg)
807       return NULL;
808 
809    /* Declarations. */
810    sampler = ureg_DECL_sampler(ureg, 0);
811    ureg_DECL_sampler_view(ureg, 0, tgsi_tex,
812                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
813                           TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
814    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
815                               TGSI_INTERPOLATE_LINEAR);
816    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
817    for (c = 0; c < 4; c++)
818       tmp_sum[c] = ureg_DECL_temporary(ureg);
819    for (c = 0; c < 4; c++)
820       tmp_coord[c] = ureg_DECL_temporary(ureg);
821    tmp = ureg_DECL_temporary(ureg);
822    top = ureg_DECL_temporary(ureg);
823    weights = ureg_DECL_temporary(ureg);
824    bottom = ureg_DECL_temporary(ureg);
825 
826    /* Instructions. */
827    for (c = 0; c < 4; c++)
828       ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
829 
830    /* Bilinear filtering starts with subtracting 0.5 from unnormalized
831     * coordinates.
832     */
833    ureg_MOV(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_ZW), coord);
834    ureg_ADD(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY), coord,
835             ureg_imm2f(ureg, -0.5, -0.5));
836 
837    /* Get the filter weights. */
838    ureg_FRC(ureg, ureg_writemask(weights, TGSI_WRITEMASK_XY),
839             ureg_src(tmp_coord[0]));
840 
841    /* Convert to integer by flooring to get the top-left coordinates. */
842    ureg_FLR(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY),
843          ureg_src(tmp_coord[0]));
844    ureg_F2I(ureg, tmp_coord[0], ureg_src(tmp_coord[0]));
845 
846    /* Get the bottom-right coordinates. */
847    ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
848              ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
849 
850    /* Clamp to edge. */
851    if (has_txq) {
852       ureg_TXQ(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), tgsi_tex,
853                ureg_imm1u(ureg, 0), sampler);
854       ureg_UADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp),
855                 ureg_imm2i(ureg, -1, -1)); /* width - 1, height - 1 */
856 
857       ureg_IMIN(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY),
858                 ureg_src(tmp_coord[0]), ureg_src(tmp));
859       ureg_IMIN(ureg, ureg_writemask(tmp_coord[3], TGSI_WRITEMASK_XY),
860                 ureg_src(tmp_coord[3]), ureg_src(tmp));
861    }
862 
863    ureg_IMAX(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY),
864              ureg_src(tmp_coord[0]), ureg_imm2i(ureg, 0, 0));
865    ureg_IMAX(ureg, ureg_writemask(tmp_coord[3], TGSI_WRITEMASK_XY),
866              ureg_src(tmp_coord[3]), ureg_imm2i(ureg, 0, 0));
867 
868    /* Get the remaining top-right and bottom-left coordinates. */
869    ureg_MOV(ureg, ureg_writemask(tmp_coord[1], TGSI_WRITEMASK_X),
870          ureg_src(tmp_coord[3]));
871    ureg_MOV(ureg, ureg_writemask(tmp_coord[1], TGSI_WRITEMASK_YZW),
872          ureg_src(tmp_coord[0])); /* top-right */
873 
874    ureg_MOV(ureg, ureg_writemask(tmp_coord[2], TGSI_WRITEMASK_Y),
875          ureg_src(tmp_coord[3]));
876    ureg_MOV(ureg, ureg_writemask(tmp_coord[2], TGSI_WRITEMASK_XZW),
877          ureg_src(tmp_coord[0])); /* bottom-left */
878 
879    for (i = 0; i < nr_samples; i++) {
880       for (c = 0; c < 4; c++) {
881          /* Read one sample. */
882          ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W),
883                   ureg_imm1u(ureg, i));
884          ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler);
885 
886          /* Add it to the sum.*/
887          ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp));
888       }
889    }
890 
891    /* Calculate the average. */
892    for (c = 0; c < 4; c++)
893       ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]),
894                ureg_imm1f(ureg, 1.0 / nr_samples));
895 
896    /* Take the 4 average values and apply a standard bilinear filter. */
897    ureg_LRP(ureg, top,
898             ureg_scalar(ureg_src(weights), 0),
899             ureg_src(tmp_sum[1]),
900             ureg_src(tmp_sum[0]));
901 
902    ureg_LRP(ureg, bottom,
903             ureg_scalar(ureg_src(weights), 0),
904             ureg_src(tmp_sum[3]),
905             ureg_src(tmp_sum[2]));
906 
907    ureg_LRP(ureg, out,
908             ureg_scalar(ureg_src(weights), 1),
909             ureg_src(bottom),
910             ureg_src(top));
911    ureg_END(ureg);
912 
913    return ureg_create_shader_and_destroy(ureg, pipe);
914 }
915 
916 void *
util_make_geometry_passthrough_shader(struct pipe_context * pipe,unsigned num_attribs,const uint8_t * semantic_names,const uint8_t * semantic_indexes)917 util_make_geometry_passthrough_shader(struct pipe_context *pipe,
918                                       unsigned num_attribs,
919                                       const uint8_t *semantic_names,
920                                       const uint8_t *semantic_indexes)
921 {
922    static const unsigned zero[4] = {0, 0, 0, 0};
923 
924    struct ureg_program *ureg;
925    struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
926    struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
927    struct ureg_src imm;
928 
929    unsigned i;
930 
931    ureg = ureg_create(PIPE_SHADER_GEOMETRY);
932    if (!ureg)
933       return NULL;
934 
935    ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, MESA_PRIM_POINTS);
936    ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, MESA_PRIM_POINTS);
937    ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1);
938    ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1);
939    imm = ureg_DECL_immediate_uint(ureg, zero, 4);
940 
941    /**
942     * Loop over all the attribs and declare the corresponding
943     * declarations in the geometry shader
944     */
945    for (i = 0; i < num_attribs; i++) {
946       src[i] = ureg_DECL_input(ureg, semantic_names[i],
947                                semantic_indexes[i], 0, 1);
948       src[i] = ureg_src_dimension(src[i], 0);
949       dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]);
950    }
951 
952    /* MOV dst[i] src[i] */
953    for (i = 0; i < num_attribs; i++) {
954       ureg_MOV(ureg, dst[i], src[i]);
955    }
956 
957    /* EMIT IMM[0] */
958    ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0);
959 
960    /* END */
961    ureg_END(ureg);
962 
963    return ureg_create_shader_and_destroy(ureg, pipe);
964 }
965 
966 
967 /**
968  * Blit from color to ZS or from ZS to color in a manner that is equivalent
969  * to memcpy.
970  *
971  * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24).
972  *
973  * Depth and stencil samplers are used to load depth and stencil,
974  * and they are packed and the result is written to a color output.
975  *   OR
976  * A color sampler is used to load a color value, which is unpacked and
977  * written to depth and stencil shader outputs.
978  */
979 void *
util_make_fs_pack_color_zs(struct pipe_context * pipe,enum tgsi_texture_type tex_target,enum pipe_format zs_format,bool dst_is_color)980 util_make_fs_pack_color_zs(struct pipe_context *pipe,
981                            enum tgsi_texture_type tex_target,
982                            enum pipe_format zs_format,
983                            bool dst_is_color)
984 {
985    struct ureg_program *ureg;
986    struct ureg_src depth_sampler, stencil_sampler, color_sampler, coord;
987    struct ureg_dst out, depth, depth_x, stencil, out_depth, out_stencil, color;
988 
989    assert(zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT || /* color is R32_UINT */
990           zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || /* color is R32_UINT */
991           zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || /* color is R32G32_UINT */
992           zs_format == PIPE_FORMAT_Z24X8_UNORM || /* color is R32_UINT */
993           zs_format == PIPE_FORMAT_X8Z24_UNORM); /* color is R32_UINT */
994 
995    bool has_stencil = zs_format != PIPE_FORMAT_Z24X8_UNORM &&
996                       zs_format != PIPE_FORMAT_X8Z24_UNORM;
997    bool is_z24 = zs_format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT;
998    bool z24_is_high = zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
999                       zs_format == PIPE_FORMAT_X8Z24_UNORM;
1000 
1001    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
1002    if (!ureg)
1003       return NULL;
1004 
1005    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
1006                               TGSI_INTERPOLATE_LINEAR);
1007 
1008    if (dst_is_color) {
1009       /* Load depth. */
1010       depth_sampler = ureg_DECL_sampler(ureg, 0);
1011       ureg_DECL_sampler_view(ureg, 0, tex_target,
1012                              TGSI_RETURN_TYPE_FLOAT,
1013                              TGSI_RETURN_TYPE_FLOAT,
1014                              TGSI_RETURN_TYPE_FLOAT,
1015                              TGSI_RETURN_TYPE_FLOAT);
1016 
1017       depth = ureg_DECL_temporary(ureg);
1018       depth_x = ureg_writemask(depth, TGSI_WRITEMASK_X);
1019       ureg_load_tex(ureg, depth_x, coord, depth_sampler, tex_target, true, true);
1020 
1021       /* Pack to Z24. */
1022       if (is_z24) {
1023          double imm = 0xffffff;
1024          struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2);
1025          struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg),
1026                                                  TGSI_WRITEMASK_XY);
1027 
1028          ureg_F2D(ureg, tmp_xy, ureg_src(depth));
1029          ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64);
1030          ureg_D2U(ureg, depth_x, ureg_src(tmp_xy));
1031 
1032          if (z24_is_high)
1033             ureg_SHL(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 8));
1034          else
1035             ureg_AND(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 0xffffff));
1036       }
1037 
1038       if (has_stencil) {
1039          /* Load stencil. */
1040          stencil_sampler = ureg_DECL_sampler(ureg, 1);
1041          ureg_DECL_sampler_view(ureg, 0, tex_target,
1042                                 TGSI_RETURN_TYPE_UINT,
1043                                 TGSI_RETURN_TYPE_UINT,
1044                                 TGSI_RETURN_TYPE_UINT,
1045                                 TGSI_RETURN_TYPE_UINT);
1046 
1047          stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1048          ureg_load_tex(ureg, stencil, coord, stencil_sampler, tex_target,
1049                        true, true);
1050 
1051          /* Pack stencil into depth. */
1052          if (is_z24) {
1053             if (!z24_is_high)
1054                ureg_SHL(ureg, stencil, ureg_src(stencil), ureg_imm1u(ureg, 24));
1055 
1056             ureg_OR(ureg, depth_x, ureg_src(depth), ureg_src(stencil));
1057          }
1058       }
1059 
1060       out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
1061 
1062       if (is_z24) {
1063          ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_X), ureg_src(depth));
1064       } else {
1065          /* Z32_S8X24 */
1066          ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Y),
1067                   ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X));
1068          ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_XY), ureg_src(depth));
1069       }
1070    } else {
1071       color_sampler = ureg_DECL_sampler(ureg, 0);
1072       ureg_DECL_sampler_view(ureg, 0, tex_target,
1073                              TGSI_RETURN_TYPE_UINT,
1074                              TGSI_RETURN_TYPE_UINT,
1075                              TGSI_RETURN_TYPE_UINT,
1076                              TGSI_RETURN_TYPE_UINT);
1077 
1078       color = ureg_DECL_temporary(ureg);
1079       ureg_load_tex(ureg, color, coord, color_sampler, tex_target, true, true);
1080 
1081       depth = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1082       stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1083 
1084       if (is_z24) {
1085          double imm = 1.0 / 0xffffff;
1086          struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2);
1087          struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg),
1088                                                  TGSI_WRITEMASK_XY);
1089 
1090          ureg_UBFE(ureg, depth, ureg_src(color),
1091                    ureg_imm1u(ureg, z24_is_high ? 8 : 0),
1092                    ureg_imm1u(ureg, 24));
1093          ureg_U2D(ureg, tmp_xy, ureg_src(depth));
1094          ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64);
1095          ureg_D2F(ureg, depth, ureg_src(tmp_xy));
1096       } else {
1097          /* depth = color.x; (Z32_S8X24) */
1098          ureg_MOV(ureg, depth, ureg_src(color));
1099       }
1100 
1101       out_depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
1102       ureg_MOV(ureg, ureg_writemask(out_depth, TGSI_WRITEMASK_Z),
1103                ureg_scalar(ureg_src(depth), TGSI_SWIZZLE_X));
1104 
1105       if (has_stencil) {
1106          if (is_z24) {
1107             ureg_UBFE(ureg, stencil, ureg_src(color),
1108                       ureg_imm1u(ureg, z24_is_high ? 0 : 24),
1109                       ureg_imm1u(ureg, 8));
1110          } else {
1111             /* stencil = color.y[0:7]; (Z32_S8X24) */
1112             ureg_UBFE(ureg, stencil,
1113                       ureg_scalar(ureg_src(color), TGSI_SWIZZLE_Y),
1114                       ureg_imm1u(ureg, 0),
1115                       ureg_imm1u(ureg, 8));
1116          }
1117 
1118          out_stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0);
1119          ureg_MOV(ureg, ureg_writemask(out_stencil, TGSI_WRITEMASK_Y),
1120                   ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X));
1121       }
1122    }
1123 
1124    ureg_END(ureg);
1125 
1126    return ureg_create_shader_and_destroy(ureg, pipe);
1127 }
1128 
1129 
1130 /**
1131  * Create passthrough tessellation control shader.
1132  * Passthrough tessellation control shader has output of vertex shader
1133  * as input and input of tessellation eval shader as output.
1134  */
1135 void *
util_make_tess_ctrl_passthrough_shader(struct pipe_context * pipe,unsigned num_vs_outputs,unsigned num_tes_inputs,const uint8_t * vs_semantic_names,const uint8_t * vs_semantic_indexes,const uint8_t * tes_semantic_names,const uint8_t * tes_semantic_indexes,const unsigned vertices_per_patch)1136 util_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe,
1137                                        unsigned num_vs_outputs,
1138                                        unsigned num_tes_inputs,
1139                                        const uint8_t *vs_semantic_names,
1140                                        const uint8_t *vs_semantic_indexes,
1141                                        const uint8_t *tes_semantic_names,
1142                                        const uint8_t *tes_semantic_indexes,
1143                                        const unsigned vertices_per_patch)
1144 {
1145    unsigned i, j;
1146    unsigned num_regs;
1147 
1148    struct ureg_program *ureg;
1149    struct ureg_dst temp, addr;
1150    struct ureg_src invocationID;
1151    struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
1152    struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
1153 
1154    ureg = ureg_create(PIPE_SHADER_TESS_CTRL);
1155 
1156    if (!ureg)
1157       return NULL;
1158 
1159    ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, vertices_per_patch);
1160 
1161    num_regs = 0;
1162 
1163    for (i = 0; i < num_tes_inputs; i++) {
1164       switch (tes_semantic_names[i]) {
1165       case TGSI_SEMANTIC_POSITION:
1166       case TGSI_SEMANTIC_PSIZE:
1167       case TGSI_SEMANTIC_COLOR:
1168       case TGSI_SEMANTIC_BCOLOR:
1169       case TGSI_SEMANTIC_CLIPDIST:
1170       case TGSI_SEMANTIC_CLIPVERTEX:
1171       case TGSI_SEMANTIC_TEXCOORD:
1172       case TGSI_SEMANTIC_FOG:
1173       case TGSI_SEMANTIC_GENERIC:
1174          for (j = 0; j < num_vs_outputs; j++) {
1175             if (tes_semantic_names[i] == vs_semantic_names[j] &&
1176                 tes_semantic_indexes[i] == vs_semantic_indexes[j]) {
1177 
1178                dst[num_regs] = ureg_DECL_output(ureg,
1179                                                tes_semantic_names[i],
1180                                                tes_semantic_indexes[i]);
1181                src[num_regs] = ureg_DECL_input(ureg, vs_semantic_names[j],
1182                                                vs_semantic_indexes[j],
1183                                                0, 1);
1184 
1185                if (tes_semantic_names[i] == TGSI_SEMANTIC_GENERIC ||
1186                    tes_semantic_names[i] == TGSI_SEMANTIC_POSITION) {
1187                   src[num_regs] = ureg_src_dimension(src[num_regs], 0);
1188                   dst[num_regs] = ureg_dst_dimension(dst[num_regs], 0);
1189                }
1190 
1191                num_regs++;
1192                break;
1193             }
1194          }
1195          break;
1196       default:
1197          break;
1198       }
1199    }
1200 
1201    dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSOUTER,
1202                                     num_regs);
1203    src[num_regs] = ureg_DECL_constant(ureg, 0);
1204    num_regs++;
1205    dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSINNER,
1206                                     num_regs);
1207    src[num_regs] = ureg_DECL_constant(ureg, 1);
1208    num_regs++;
1209 
1210    if (vertices_per_patch > 1) {
1211       invocationID = ureg_DECL_system_value(ureg,
1212                         TGSI_SEMANTIC_INVOCATIONID, 0);
1213       temp = ureg_DECL_local_temporary(ureg);
1214       addr = ureg_DECL_address(ureg);
1215       ureg_UARL(ureg, ureg_writemask(addr, TGSI_WRITEMASK_X),
1216                 ureg_scalar(invocationID, TGSI_SWIZZLE_X));
1217    }
1218 
1219    for (i = 0; i < num_regs; i++) {
1220       if (dst[i].Dimension && vertices_per_patch > 1) {
1221          struct ureg_src addr_x = ureg_scalar(ureg_src(addr), TGSI_SWIZZLE_X);
1222          ureg_MOV(ureg, temp, ureg_src_dimension_indirect(src[i],
1223                   addr_x, 0));
1224          ureg_MOV(ureg, ureg_dst_dimension_indirect(dst[i],
1225                   addr_x, 0), ureg_src(temp));
1226       }
1227       else
1228          ureg_MOV(ureg, dst[i], src[i]);
1229    }
1230 
1231    ureg_END(ureg);
1232 
1233    return ureg_create_shader_and_destroy(ureg, pipe);
1234 }
1235 
1236 void *
util_make_fs_stencil_blit(struct pipe_context * pipe,bool msaa_src,bool has_txq)1237 util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src, bool has_txq)
1238 {
1239    char text[1000];
1240    struct tgsi_token tokens[1000];
1241    struct pipe_shader_state state = { 0 };
1242    enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA :
1243                                                 TGSI_TEXTURE_2D;
1244 
1245    if (has_txq) {
1246       static const char shader_templ[] =
1247          "FRAG\n"
1248          "DCL IN[0], GENERIC[0], LINEAR\n"
1249          "DCL SAMP[0]\n"
1250          "DCL SVIEW[0], %s, UINT\n"
1251          "DCL CONST[0][0]\n"
1252          "DCL TEMP[0..1]\n"
1253          "IMM[0] INT32 {0, -1, 0, 0}\n"
1254 
1255          /* Nearest filtering floors and then converts to integer, and then
1256           * applies clamp to edge as clamp(coord, 0, dim - 1).
1257           */
1258          "MOV TEMP[0], IN[0]\n"
1259          "FLR TEMP[0].xy, TEMP[0]\n"
1260          "F2I TEMP[0], TEMP[0]\n"
1261          "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
1262          /* Clamp to edge for the upper bound. */
1263          "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n"
1264          "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */
1265          "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n"
1266          /* Texel fetch. */
1267          "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
1268          "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
1269          "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
1270          "U2F TEMP[0].x, TEMP[0]\n"
1271          "KILL_IF -TEMP[0].xxxx\n"
1272          "END\n";
1273 
1274       sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex],
1275               tgsi_texture_names[tgsi_tex], tgsi_texture_names[tgsi_tex]);
1276    } else {
1277       static const char shader_templ[] =
1278          "FRAG\n"
1279          "DCL IN[0], GENERIC[0], LINEAR\n"
1280          "DCL SAMP[0]\n"
1281          "DCL SVIEW[0], %s, UINT\n"
1282          "DCL CONST[0][0]\n"
1283          "DCL TEMP[0..1]\n"
1284          "IMM[0] INT32 {0, -1, 0, 0}\n"
1285 
1286          /* Nearest filtering floors and then converts to integer, and then
1287           * applies clamp to edge as clamp(coord, 0, dim - 1).
1288           */
1289          "MOV TEMP[0], IN[0]\n"
1290          "FLR TEMP[0].xy, TEMP[0]\n"
1291          "F2I TEMP[0], TEMP[0]\n"
1292          "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
1293          /* Texel fetch. */
1294          "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
1295          "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
1296          "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
1297          "U2F TEMP[0].x, TEMP[0]\n"
1298          "KILL_IF -TEMP[0].xxxx\n"
1299          "END\n";
1300 
1301       sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex],
1302               tgsi_texture_names[tgsi_tex]);
1303    }
1304 
1305    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
1306       assert(0);
1307       return NULL;
1308    }
1309 
1310    pipe_shader_state_from_tgsi(&state, tokens);
1311 
1312    return pipe->create_fs_state(pipe, &state);
1313 }
1314 
1315 void *
util_make_fs_clear_all_cbufs(struct pipe_context * pipe)1316 util_make_fs_clear_all_cbufs(struct pipe_context *pipe)
1317 {
1318    static const char text[] =
1319       "FRAG\n"
1320       "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
1321       "DCL OUT[0], COLOR[0]\n"
1322       "DCL CONST[0][0]\n"
1323 
1324       "MOV OUT[0], CONST[0][0]\n"
1325       "END\n";
1326 
1327    struct tgsi_token tokens[1000];
1328    struct pipe_shader_state state = { 0 };
1329 
1330    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
1331       assert(0);
1332       return NULL;
1333    }
1334 
1335    pipe_shader_state_from_tgsi(&state, tokens);
1336 
1337    return pipe->create_fs_state(pipe, &state);
1338 }
1339