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