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