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