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