• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
4  * All Rights Reserved.
5  * Copyright 2009 Marek Olšák <maraeo@gmail.com>
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,uint num_attribs,const uint * semantic_names,const uint * semantic_indexes,bool window_space)60 util_make_vertex_passthrough_shader(struct pipe_context *pipe,
61                                     uint num_attribs,
62                                     const uint *semantic_names,
63                                     const uint *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,uint num_attribs,const uint * semantic_names,const uint * 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                                     uint num_attribs,
75                                     const uint *semantic_names,
76                                     const uint *semantic_indexes,
77                                     bool window_space, bool layered,
78 				    const struct pipe_stream_output_info *so)
79 {
80    struct ureg_program *ureg;
81    uint 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 unsigned 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;
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;
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,unsigned 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               unsigned tex_target, bool load_level_zero, bool use_txf)
206 {
207    if (use_txf) {
208       struct ureg_dst temp = ureg_DECL_temporary(ureg);
209 
210       ureg_F2I(ureg, temp, coord);
211 
212       if (load_level_zero)
213          ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler);
214       else
215          ureg_TXF(ureg, out, tex_target, ureg_src(temp), sampler);
216    } else {
217       if (load_level_zero)
218          ureg_TEX_LZ(ureg, out, tex_target, coord, sampler);
219       else
220          ureg_TEX(ureg, out, tex_target, coord, sampler);
221    }
222 }
223 
224 /**
225  * Make simple fragment texture shader:
226  *  IMM {0,0,0,1}                         // (if writemask != 0xf)
227  *  MOV TEMP[0], IMM[0]                   // (if writemask != 0xf)
228  *  TEX TEMP[0].writemask, IN[0], SAMP[0], 2D;
229  *   .. optional SINT <-> UINT clamping ..
230  *  MOV OUT[0], TEMP[0]
231  *  END;
232  *
233  * \param tex_target  one of PIPE_TEXTURE_x
234  * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
235  * \param writemask  mask of TGSI_WRITEMASK_x
236  */
237 void *
util_make_fragment_tex_shader_writemask(struct pipe_context * pipe,unsigned tex_target,unsigned interp_mode,unsigned writemask,enum tgsi_return_type stype,enum tgsi_return_type dtype,bool load_level_zero,bool use_txf)238 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
239                                         unsigned tex_target,
240                                         unsigned interp_mode,
241                                         unsigned writemask,
242                                         enum tgsi_return_type stype,
243                                         enum tgsi_return_type dtype,
244                                         bool load_level_zero,
245                                         bool use_txf)
246 {
247    struct ureg_program *ureg;
248    struct ureg_src sampler;
249    struct ureg_src tex;
250    struct ureg_dst temp;
251    struct ureg_dst out;
252 
253    assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT));
254    assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
255           interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
256 
257    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
258    if (!ureg)
259       return NULL;
260 
261    sampler = ureg_DECL_sampler( ureg, 0 );
262 
263    ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype);
264 
265    tex = ureg_DECL_fs_input( ureg,
266                              TGSI_SEMANTIC_GENERIC, 0,
267                              interp_mode );
268 
269    out = ureg_DECL_output( ureg,
270                            TGSI_SEMANTIC_COLOR,
271                            0 );
272 
273    temp = ureg_DECL_temporary(ureg);
274 
275    if (writemask != TGSI_WRITEMASK_XYZW) {
276       struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
277 
278       ureg_MOV( ureg, out, imm );
279    }
280 
281    if (tex_target == TGSI_TEXTURE_BUFFER)
282       ureg_TXF(ureg,
283                ureg_writemask(temp, writemask),
284                tex_target, tex, sampler);
285    else
286       ureg_load_tex(ureg, ureg_writemask(temp, writemask), tex, sampler,
287                     tex_target, load_level_zero, use_txf);
288 
289    if (stype != dtype) {
290       if (stype == TGSI_RETURN_TYPE_SINT) {
291          assert(dtype == TGSI_RETURN_TYPE_UINT);
292 
293          ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0));
294       } else {
295          assert(stype == TGSI_RETURN_TYPE_UINT);
296          assert(dtype == TGSI_RETURN_TYPE_SINT);
297 
298          ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1));
299       }
300    }
301 
302    ureg_MOV(ureg, out, ureg_src(temp));
303 
304    ureg_END( ureg );
305 
306    return ureg_create_shader_and_destroy( ureg, pipe );
307 }
308 
309 
310 /**
311  * Make a simple fragment shader that sets the output color to a color
312  * taken from a texture.
313  * \param tex_target  one of PIPE_TEXTURE_x
314  */
315 void *
util_make_fragment_tex_shader(struct pipe_context * pipe,unsigned tex_target,unsigned interp_mode,enum tgsi_return_type stype,enum tgsi_return_type dtype,bool load_level_zero,bool use_txf)316 util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
317                               unsigned interp_mode,
318                               enum tgsi_return_type stype,
319                               enum tgsi_return_type dtype,
320                               bool load_level_zero,
321                               bool use_txf)
322 {
323    return util_make_fragment_tex_shader_writemask( pipe,
324                                                    tex_target,
325                                                    interp_mode,
326                                                    TGSI_WRITEMASK_XYZW,
327                                                    stype, dtype, load_level_zero,
328                                                    use_txf);
329 }
330 
331 
332 /**
333  * Make a simple fragment texture shader which reads an X component from
334  * a texture and writes it as depth.
335  */
336 void *
util_make_fragment_tex_shader_writedepth(struct pipe_context * pipe,unsigned tex_target,unsigned interp_mode,bool load_level_zero,bool use_txf)337 util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
338                                          unsigned tex_target,
339                                          unsigned interp_mode,
340                                          bool load_level_zero,
341                                          bool use_txf)
342 {
343    struct ureg_program *ureg;
344    struct ureg_src sampler;
345    struct ureg_src tex;
346    struct ureg_dst out, depth;
347    struct ureg_src imm;
348 
349    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
350    if (!ureg)
351       return NULL;
352 
353    sampler = ureg_DECL_sampler( ureg, 0 );
354 
355    ureg_DECL_sampler_view(ureg, 0, tex_target,
356                           TGSI_RETURN_TYPE_FLOAT,
357                           TGSI_RETURN_TYPE_FLOAT,
358                           TGSI_RETURN_TYPE_FLOAT,
359                           TGSI_RETURN_TYPE_FLOAT);
360 
361    tex = ureg_DECL_fs_input( ureg,
362                              TGSI_SEMANTIC_GENERIC, 0,
363                              interp_mode );
364 
365    out = ureg_DECL_output( ureg,
366                            TGSI_SEMANTIC_COLOR,
367                            0 );
368 
369    depth = ureg_DECL_output( ureg,
370                              TGSI_SEMANTIC_POSITION,
371                              0 );
372 
373    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
374 
375    ureg_MOV( ureg, out, imm );
376 
377    ureg_load_tex(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z), tex, sampler,
378                  tex_target, load_level_zero, use_txf);
379    ureg_END( ureg );
380 
381    return ureg_create_shader_and_destroy( ureg, pipe );
382 }
383 
384 
385 /**
386  * Make a simple fragment texture shader which reads the texture unit 0 and 1
387  * and writes it as depth and stencil, respectively.
388  */
389 void *
util_make_fragment_tex_shader_writedepthstencil(struct pipe_context * pipe,unsigned tex_target,unsigned interp_mode,bool load_level_zero,bool use_txf)390 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
391                                                 unsigned tex_target,
392                                                 unsigned interp_mode,
393                                                 bool load_level_zero,
394                                                 bool use_txf)
395 {
396    struct ureg_program *ureg;
397    struct ureg_src depth_sampler, stencil_sampler;
398    struct ureg_src tex;
399    struct ureg_dst out, depth, stencil;
400    struct ureg_src imm;
401 
402    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
403    if (!ureg)
404       return NULL;
405 
406    depth_sampler = ureg_DECL_sampler( ureg, 0 );
407    ureg_DECL_sampler_view(ureg, 0, tex_target,
408                           TGSI_RETURN_TYPE_FLOAT,
409                           TGSI_RETURN_TYPE_FLOAT,
410                           TGSI_RETURN_TYPE_FLOAT,
411                           TGSI_RETURN_TYPE_FLOAT);
412    stencil_sampler = ureg_DECL_sampler( ureg, 1 );
413    ureg_DECL_sampler_view(ureg, 0, tex_target,
414                           TGSI_RETURN_TYPE_UINT,
415                           TGSI_RETURN_TYPE_UINT,
416                           TGSI_RETURN_TYPE_UINT,
417                           TGSI_RETURN_TYPE_UINT);
418 
419    tex = ureg_DECL_fs_input( ureg,
420                              TGSI_SEMANTIC_GENERIC, 0,
421                              interp_mode );
422 
423    out = ureg_DECL_output( ureg,
424                            TGSI_SEMANTIC_COLOR,
425                            0 );
426 
427    depth = ureg_DECL_output( ureg,
428                              TGSI_SEMANTIC_POSITION,
429                              0 );
430 
431    stencil = ureg_DECL_output( ureg,
432                              TGSI_SEMANTIC_STENCIL,
433                              0 );
434 
435    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
436 
437    ureg_MOV( ureg, out, imm );
438 
439    ureg_load_tex(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z), tex,
440                  depth_sampler, tex_target, load_level_zero, use_txf);
441    ureg_load_tex(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y), tex,
442                  stencil_sampler, tex_target, load_level_zero, use_txf);
443    ureg_END( ureg );
444 
445    return ureg_create_shader_and_destroy( ureg, pipe );
446 }
447 
448 
449 /**
450  * Make a simple fragment texture shader which reads a texture and writes it
451  * as stencil.
452  */
453 void *
util_make_fragment_tex_shader_writestencil(struct pipe_context * pipe,unsigned tex_target,unsigned interp_mode,bool load_level_zero,bool use_txf)454 util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
455                                            unsigned tex_target,
456                                            unsigned interp_mode,
457                                            bool load_level_zero,
458                                            bool use_txf)
459 {
460    struct ureg_program *ureg;
461    struct ureg_src stencil_sampler;
462    struct ureg_src tex;
463    struct ureg_dst out, stencil;
464    struct ureg_src imm;
465 
466    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
467    if (!ureg)
468       return NULL;
469 
470    stencil_sampler = ureg_DECL_sampler( ureg, 0 );
471 
472    ureg_DECL_sampler_view(ureg, 0, tex_target,
473                           TGSI_RETURN_TYPE_UINT,
474                           TGSI_RETURN_TYPE_UINT,
475                           TGSI_RETURN_TYPE_UINT,
476                           TGSI_RETURN_TYPE_UINT);
477 
478    tex = ureg_DECL_fs_input( ureg,
479                              TGSI_SEMANTIC_GENERIC, 0,
480                              interp_mode );
481 
482    out = ureg_DECL_output( ureg,
483                            TGSI_SEMANTIC_COLOR,
484                            0 );
485 
486    stencil = ureg_DECL_output( ureg,
487                              TGSI_SEMANTIC_STENCIL,
488                              0 );
489 
490    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
491 
492    ureg_MOV( ureg, out, imm );
493 
494    ureg_load_tex(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y), tex,
495                  stencil_sampler, tex_target, load_level_zero, use_txf);
496    ureg_END( ureg );
497 
498    return ureg_create_shader_and_destroy( ureg, pipe );
499 }
500 
501 
502 /**
503  * Make simple fragment color pass-through shader that replicates OUT[0]
504  * to all bound colorbuffers.
505  */
506 void *
util_make_fragment_passthrough_shader(struct pipe_context * pipe,int input_semantic,int input_interpolate,boolean write_all_cbufs)507 util_make_fragment_passthrough_shader(struct pipe_context *pipe,
508                                       int input_semantic,
509                                       int input_interpolate,
510                                       boolean write_all_cbufs)
511 {
512    static const char shader_templ[] =
513          "FRAG\n"
514          "%s"
515          "DCL IN[0], %s[0], %s\n"
516          "DCL OUT[0], COLOR[0]\n"
517 
518          "MOV OUT[0], IN[0]\n"
519          "END\n";
520 
521    char text[sizeof(shader_templ)+100];
522    struct tgsi_token tokens[1000];
523    struct pipe_shader_state state;
524 
525    sprintf(text, shader_templ,
526            write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
527            tgsi_semantic_names[input_semantic],
528            tgsi_interpolate_names[input_interpolate]);
529 
530    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
531       assert(0);
532       return NULL;
533    }
534    pipe_shader_state_from_tgsi(&state, tokens);
535 #if 0
536    tgsi_dump(state.tokens, 0);
537 #endif
538 
539    return pipe->create_fs_state(pipe, &state);
540 }
541 
542 
543 void *
util_make_empty_fragment_shader(struct pipe_context * pipe)544 util_make_empty_fragment_shader(struct pipe_context *pipe)
545 {
546    struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT);
547    if (!ureg)
548       return NULL;
549 
550    ureg_END(ureg);
551    return ureg_create_shader_and_destroy(ureg, pipe);
552 }
553 
554 
555 /**
556  * Make a fragment shader that copies the input color to N output colors.
557  */
558 void *
util_make_fragment_cloneinput_shader(struct pipe_context * pipe,int num_cbufs,int input_semantic,int input_interpolate)559 util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
560                                      int input_semantic,
561                                      int input_interpolate)
562 {
563    struct ureg_program *ureg;
564    struct ureg_src src;
565    struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
566    int i;
567 
568    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
569 
570    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
571    if (!ureg)
572       return NULL;
573 
574    src = ureg_DECL_fs_input( ureg, input_semantic, 0,
575                              input_interpolate );
576 
577    for (i = 0; i < num_cbufs; i++)
578       dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
579 
580    for (i = 0; i < num_cbufs; i++)
581       ureg_MOV( ureg, dst[i], src );
582 
583    ureg_END( ureg );
584 
585    return ureg_create_shader_and_destroy( ureg, pipe );
586 }
587 
588 
589 static void *
util_make_fs_blit_msaa_gen(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,const char * samp_type,const char * output_semantic,const char * output_mask,const char * conversion_decl,const char * conversion)590 util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
591                            enum tgsi_texture_type tgsi_tex,
592                            const char *samp_type,
593                            const char *output_semantic,
594                            const char *output_mask,
595                            const char *conversion_decl,
596                            const char *conversion)
597 {
598    static const char shader_templ[] =
599          "FRAG\n"
600          "DCL IN[0], GENERIC[0], LINEAR\n"
601          "DCL SAMP[0]\n"
602          "DCL SVIEW[0], %s, %s\n"
603          "DCL OUT[0], %s\n"
604          "DCL TEMP[0]\n"
605          "%s"
606 
607          "F2U TEMP[0], IN[0]\n"
608          "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
609          "%s"
610          "MOV OUT[0]%s, TEMP[0]\n"
611          "END\n";
612 
613    const char *type = tgsi_texture_names[tgsi_tex];
614    char text[sizeof(shader_templ)+100];
615    struct tgsi_token tokens[1000];
616    struct pipe_shader_state state;
617 
618    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
619           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
620 
621    util_snprintf(text, sizeof(text), shader_templ, type, samp_type,
622                  output_semantic, conversion_decl, type, conversion, output_mask);
623 
624    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
625       puts(text);
626       assert(0);
627       return NULL;
628    }
629    pipe_shader_state_from_tgsi(&state, tokens);
630 #if 0
631    tgsi_dump(state.tokens, 0);
632 #endif
633 
634    return pipe->create_fs_state(pipe, &state);
635 }
636 
637 
638 /**
639  * Make a fragment shader that sets the output color to a color
640  * fetched from a multisample texture.
641  * \param tex_target  one of PIPE_TEXTURE_x
642  */
643 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)644 util_make_fs_blit_msaa_color(struct pipe_context *pipe,
645                              enum tgsi_texture_type tgsi_tex,
646                              enum tgsi_return_type stype,
647                              enum tgsi_return_type dtype)
648 {
649    const char *samp_type;
650    const char *conversion_decl = "";
651    const char *conversion = "";
652 
653    if (stype == TGSI_RETURN_TYPE_UINT) {
654       samp_type = "UINT";
655 
656       if (dtype == TGSI_RETURN_TYPE_SINT) {
657          conversion_decl = "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
658          conversion = "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n";
659       }
660    } else if (stype == TGSI_RETURN_TYPE_SINT) {
661       samp_type = "SINT";
662 
663       if (dtype == TGSI_RETURN_TYPE_UINT) {
664          conversion_decl = "IMM[0] INT32 {0, 0, 0, 0}\n";
665          conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
666       }
667    } else {
668       assert(dtype == TGSI_RETURN_TYPE_FLOAT);
669       samp_type = "FLOAT";
670    }
671 
672    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, samp_type,
673                                      "COLOR[0]", "", conversion_decl,
674                                      conversion);
675 }
676 
677 
678 /**
679  * Make a fragment shader that sets the output depth to a depth value
680  * fetched from a multisample texture.
681  * \param tex_target  one of PIPE_TEXTURE_x
682  */
683 void *
util_make_fs_blit_msaa_depth(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex)684 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
685                              enum tgsi_texture_type tgsi_tex)
686 {
687    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "FLOAT",
688                                      "POSITION", ".z", "", "");
689 }
690 
691 
692 /**
693  * Make a fragment shader that sets the output stencil to a stencil value
694  * fetched from a multisample texture.
695  * \param tex_target  one of PIPE_TEXTURE_x
696  */
697 void *
util_make_fs_blit_msaa_stencil(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex)698 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
699                                enum tgsi_texture_type tgsi_tex)
700 {
701    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "UINT",
702                                      "STENCIL", ".y", "", "");
703 }
704 
705 
706 /**
707  * Make a fragment shader that sets the output depth and stencil to depth
708  * and stencil values fetched from two multisample textures / samplers.
709  * The sizes of both textures should match (it should be one depth-stencil
710  * texture).
711  * \param tex_target  one of PIPE_TEXTURE_x
712  */
713 void *
util_make_fs_blit_msaa_depthstencil(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex)714 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
715                                     enum tgsi_texture_type tgsi_tex)
716 {
717    static const char shader_templ[] =
718          "FRAG\n"
719          "DCL IN[0], GENERIC[0], LINEAR\n"
720          "DCL SAMP[0..1]\n"
721          "DCL SVIEW[0..1], %s, FLOAT\n"
722          "DCL OUT[0], POSITION\n"
723          "DCL OUT[1], STENCIL\n"
724          "DCL TEMP[0]\n"
725 
726          "F2U TEMP[0], IN[0]\n"
727          "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
728          "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
729          "END\n";
730 
731    const char *type = tgsi_texture_names[tgsi_tex];
732    char text[sizeof(shader_templ)+100];
733    struct tgsi_token tokens[1000];
734    struct pipe_shader_state state;
735 
736    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
737           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
738 
739    sprintf(text, shader_templ, type, type, type);
740 
741    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
742       assert(0);
743       return NULL;
744    }
745    pipe_shader_state_from_tgsi(&state, tokens);
746 #if 0
747    tgsi_dump(state.tokens, 0);
748 #endif
749 
750    return pipe->create_fs_state(pipe, &state);
751 }
752 
753 
754 void *
util_make_fs_msaa_resolve(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,unsigned nr_samples,enum tgsi_return_type stype)755 util_make_fs_msaa_resolve(struct pipe_context *pipe,
756                           enum tgsi_texture_type tgsi_tex, unsigned nr_samples,
757                           enum tgsi_return_type stype)
758 {
759    struct ureg_program *ureg;
760    struct ureg_src sampler, coord;
761    struct ureg_dst out, tmp_sum, tmp_coord, tmp;
762    unsigned i;
763 
764    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
765    if (!ureg)
766       return NULL;
767 
768    /* Declarations. */
769    sampler = ureg_DECL_sampler(ureg, 0);
770    ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
771    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
772                               TGSI_INTERPOLATE_LINEAR);
773    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
774    tmp_sum = ureg_DECL_temporary(ureg);
775    tmp_coord = ureg_DECL_temporary(ureg);
776    tmp = ureg_DECL_temporary(ureg);
777 
778    /* Instructions. */
779    ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
780    ureg_F2U(ureg, tmp_coord, coord);
781 
782    for (i = 0; i < nr_samples; i++) {
783       /* Read one sample. */
784       ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W),
785                ureg_imm1u(ureg, i));
786       ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler);
787 
788       if (stype == TGSI_RETURN_TYPE_UINT)
789          ureg_U2F(ureg, tmp, ureg_src(tmp));
790       else if (stype == TGSI_RETURN_TYPE_SINT)
791          ureg_I2F(ureg, tmp, ureg_src(tmp));
792 
793       /* Add it to the sum.*/
794       ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp));
795    }
796 
797    /* Calculate the average and return. */
798    ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum),
799             ureg_imm1f(ureg, 1.0 / nr_samples));
800 
801    if (stype == TGSI_RETURN_TYPE_UINT)
802       ureg_F2U(ureg, out, ureg_src(tmp_sum));
803    else if (stype == TGSI_RETURN_TYPE_SINT)
804       ureg_F2I(ureg, out, ureg_src(tmp_sum));
805    else
806       ureg_MOV(ureg, out, ureg_src(tmp_sum));
807 
808    ureg_END(ureg);
809 
810    return ureg_create_shader_and_destroy(ureg, pipe);
811 }
812 
813 
814 void *
util_make_fs_msaa_resolve_bilinear(struct pipe_context * pipe,enum tgsi_texture_type tgsi_tex,unsigned nr_samples,enum tgsi_return_type stype)815 util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
816                                    enum tgsi_texture_type tgsi_tex,
817                                    unsigned nr_samples,
818                                    enum tgsi_return_type stype)
819 {
820    struct ureg_program *ureg;
821    struct ureg_src sampler, coord;
822    struct ureg_dst out, tmp, top, bottom;
823    struct ureg_dst tmp_coord[4], tmp_sum[4];
824    unsigned i, c;
825 
826    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
827    if (!ureg)
828       return NULL;
829 
830    /* Declarations. */
831    sampler = ureg_DECL_sampler(ureg, 0);
832    ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
833    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
834                               TGSI_INTERPOLATE_LINEAR);
835    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
836    for (c = 0; c < 4; c++)
837       tmp_sum[c] = ureg_DECL_temporary(ureg);
838    for (c = 0; c < 4; c++)
839       tmp_coord[c] = ureg_DECL_temporary(ureg);
840    tmp = ureg_DECL_temporary(ureg);
841    top = ureg_DECL_temporary(ureg);
842    bottom = ureg_DECL_temporary(ureg);
843 
844    /* Instructions. */
845    for (c = 0; c < 4; c++)
846       ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
847 
848    /* Get 4 texture coordinates for the bilinear filter. */
849    ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */
850    ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]),
851              ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */
852    ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]),
853              ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */
854    ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
855              ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
856 
857    for (i = 0; i < nr_samples; i++) {
858       for (c = 0; c < 4; c++) {
859          /* Read one sample. */
860          ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W),
861                   ureg_imm1u(ureg, i));
862          ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler);
863 
864          if (stype == TGSI_RETURN_TYPE_UINT)
865             ureg_U2F(ureg, tmp, ureg_src(tmp));
866          else if (stype == TGSI_RETURN_TYPE_SINT)
867             ureg_I2F(ureg, tmp, ureg_src(tmp));
868 
869          /* Add it to the sum.*/
870          ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp));
871       }
872    }
873 
874    /* Calculate the average. */
875    for (c = 0; c < 4; c++)
876       ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]),
877                ureg_imm1f(ureg, 1.0 / nr_samples));
878 
879    /* Take the 4 average values and apply a standard bilinear filter. */
880    ureg_FRC(ureg, tmp, coord);
881 
882    ureg_LRP(ureg, top,
883             ureg_scalar(ureg_src(tmp), 0),
884             ureg_src(tmp_sum[1]),
885             ureg_src(tmp_sum[0]));
886 
887    ureg_LRP(ureg, bottom,
888             ureg_scalar(ureg_src(tmp), 0),
889             ureg_src(tmp_sum[3]),
890             ureg_src(tmp_sum[2]));
891 
892    ureg_LRP(ureg, tmp,
893             ureg_scalar(ureg_src(tmp), 1),
894             ureg_src(bottom),
895             ureg_src(top));
896 
897    /* Convert to the texture format and return. */
898    if (stype == TGSI_RETURN_TYPE_UINT)
899       ureg_F2U(ureg, out, ureg_src(tmp));
900    else if (stype == TGSI_RETURN_TYPE_SINT)
901       ureg_F2I(ureg, out, ureg_src(tmp));
902    else
903       ureg_MOV(ureg, out, ureg_src(tmp));
904 
905    ureg_END(ureg);
906 
907    return ureg_create_shader_and_destroy(ureg, pipe);
908 }
909 
910 void *
util_make_geometry_passthrough_shader(struct pipe_context * pipe,uint num_attribs,const ubyte * semantic_names,const ubyte * semantic_indexes)911 util_make_geometry_passthrough_shader(struct pipe_context *pipe,
912                                       uint num_attribs,
913                                       const ubyte *semantic_names,
914                                       const ubyte *semantic_indexes)
915 {
916    static const unsigned zero[4] = {0, 0, 0, 0};
917 
918    struct ureg_program *ureg;
919    struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
920    struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
921    struct ureg_src imm;
922 
923    unsigned i;
924 
925    ureg = ureg_create(PIPE_SHADER_GEOMETRY);
926    if (!ureg)
927       return NULL;
928 
929    ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS);
930    ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS);
931    ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1);
932    ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1);
933    imm = ureg_DECL_immediate_uint(ureg, zero, 4);
934 
935    /**
936     * Loop over all the attribs and declare the corresponding
937     * declarations in the geometry shader
938     */
939    for (i = 0; i < num_attribs; i++) {
940       src[i] = ureg_DECL_input(ureg, semantic_names[i],
941                                semantic_indexes[i], 0, 1);
942       src[i] = ureg_src_dimension(src[i], 0);
943       dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]);
944    }
945 
946    /* MOV dst[i] src[i] */
947    for (i = 0; i < num_attribs; i++) {
948       ureg_MOV(ureg, dst[i], src[i]);
949    }
950 
951    /* EMIT IMM[0] */
952    ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0);
953 
954    /* END */
955    ureg_END(ureg);
956 
957    return ureg_create_shader_and_destroy(ureg, pipe);
958 }
959 
960