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