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