1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
5 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
31 * Simple vertex/fragment shader generators.
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 */
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
60 util_make_vertex_passthrough_shader(struct pipe_context
*pipe
,
62 const uint
*semantic_names
,
63 const uint
*semantic_indexes
,
66 return util_make_vertex_passthrough_shader_with_so(pipe
, num_attribs
,
73 util_make_vertex_passthrough_shader_with_so(struct pipe_context
*pipe
,
75 const uint
*semantic_names
,
76 const uint
*semantic_indexes
,
78 const struct pipe_stream_output_info
*so
)
80 struct ureg_program
*ureg
;
83 ureg
= ureg_create( PIPE_SHADER_VERTEX
);
88 ureg_property(ureg
, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION
, TRUE
);
90 for (i
= 0; i
< num_attribs
; i
++) {
94 src
= ureg_DECL_vs_input( ureg
, i
);
96 dst
= ureg_DECL_output( ureg
,
100 ureg_MOV( ureg
, dst
, src
);
105 return ureg_create_shader_with_so_and_destroy( ureg
, pipe
, so
);
109 void *util_make_layered_clear_vertex_shader(struct pipe_context
*pipe
)
111 static const char text
[] =
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"
120 "MOV OUT[0], IN[0]\n"
121 "MOV OUT[1], IN[1]\n"
122 "MOV OUT[2].x, SV[0].xxxx\n"
124 struct tgsi_token tokens
[1000];
125 struct pipe_shader_state state
;
127 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
131 pipe_shader_state_from_tgsi(&state
, tokens
);
132 return pipe
->create_vs_state(pipe
, &state
);
136 * Takes position and color, and outputs position, color, and instance id.
138 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context
*pipe
)
140 static const char text
[] =
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"
149 "MOV OUT[0], IN[0]\n"
150 "MOV OUT[1], IN[1]\n"
151 "MOV OUT[2].x, SV[0].xxxx\n"
153 struct tgsi_token tokens
[1000];
154 struct pipe_shader_state state
;
156 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
160 pipe_shader_state_from_tgsi(&state
, tokens
);
161 return pipe
->create_vs_state(pipe
, &state
);
165 * Takes position, color, and target layer, and emits vertices on that target
166 * layer, with the specified color.
168 void *util_make_layered_clear_geometry_shader(struct pipe_context
*pipe
)
170 static const char text
[] =
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"
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"
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"
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"
197 struct tgsi_token tokens
[1000];
198 struct pipe_shader_state state
;
200 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
204 pipe_shader_state_from_tgsi(&state
, tokens
);
205 return pipe
->create_gs_state(pipe
, &state
);
209 ureg_load_tex(struct ureg_program
*ureg
, struct ureg_dst out
,
210 struct ureg_src coord
, struct ureg_src sampler
,
211 unsigned tex_target
, bool load_level_zero
, bool use_txf
)
214 struct ureg_dst temp
= ureg_DECL_temporary(ureg
);
216 ureg_F2I(ureg
, temp
, coord
);
219 ureg_TXF_LZ(ureg
, out
, tex_target
, ureg_src(temp
), sampler
);
221 ureg_TXF(ureg
, out
, tex_target
, ureg_src(temp
), sampler
);
224 ureg_TEX_LZ(ureg
, out
, tex_target
, coord
, sampler
);
226 ureg_TEX(ureg
, out
, tex_target
, coord
, sampler
);
231 * Make simple fragment texture shader:
232 * IMM {0,0,0,1} // (if writemask != 0xf)
233 * MOV TEMP[0], IMM[0] // (if writemask != 0xf)
234 * TEX TEMP[0].writemask, IN[0], SAMP[0], 2D;
235 * .. optional SINT <-> UINT clamping ..
236 * MOV OUT[0], TEMP[0]
239 * \param tex_target one of PIPE_TEXTURE_x
240 * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
241 * \param writemask mask of TGSI_WRITEMASK_x
244 util_make_fragment_tex_shader_writemask(struct pipe_context
*pipe
,
246 unsigned interp_mode
,
248 enum tgsi_return_type stype
,
249 enum tgsi_return_type dtype
,
250 bool load_level_zero
,
253 struct ureg_program
*ureg
;
254 struct ureg_src sampler
;
256 struct ureg_dst temp
;
259 assert((stype
== TGSI_RETURN_TYPE_FLOAT
) == (dtype
== TGSI_RETURN_TYPE_FLOAT
));
260 assert(interp_mode
== TGSI_INTERPOLATE_LINEAR
||
261 interp_mode
== TGSI_INTERPOLATE_PERSPECTIVE
);
263 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
267 sampler
= ureg_DECL_sampler( ureg
, 0 );
269 ureg_DECL_sampler_view(ureg
, 0, tex_target
, stype
, stype
, stype
, stype
);
271 tex
= ureg_DECL_fs_input( ureg
,
272 TGSI_SEMANTIC_GENERIC
, 0,
275 out
= ureg_DECL_output( ureg
,
279 temp
= ureg_DECL_temporary(ureg
);
281 if (writemask
!= TGSI_WRITEMASK_XYZW
) {
282 struct ureg_src imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
284 ureg_MOV( ureg
, out
, imm
);
287 if (tex_target
== TGSI_TEXTURE_BUFFER
)
289 ureg_writemask(temp
, writemask
),
290 tex_target
, tex
, sampler
);
292 ureg_load_tex(ureg
, ureg_writemask(temp
, writemask
), tex
, sampler
,
293 tex_target
, load_level_zero
, use_txf
);
295 if (stype
!= dtype
) {
296 if (stype
== TGSI_RETURN_TYPE_SINT
) {
297 assert(dtype
== TGSI_RETURN_TYPE_UINT
);
299 ureg_IMAX(ureg
, temp
, ureg_src(temp
), ureg_imm1i(ureg
, 0));
301 assert(stype
== TGSI_RETURN_TYPE_UINT
);
302 assert(dtype
== TGSI_RETURN_TYPE_SINT
);
304 ureg_UMIN(ureg
, temp
, ureg_src(temp
), ureg_imm1u(ureg
, (1u << 31) - 1));
308 ureg_MOV(ureg
, out
, ureg_src(temp
));
312 return ureg_create_shader_and_destroy( ureg
, pipe
);
317 * Make a simple fragment shader that sets the output color to a color
318 * taken from a texture.
319 * \param tex_target one of PIPE_TEXTURE_x
322 util_make_fragment_tex_shader(struct pipe_context
*pipe
, unsigned tex_target
,
323 unsigned interp_mode
,
324 enum tgsi_return_type stype
,
325 enum tgsi_return_type dtype
,
326 bool load_level_zero
,
329 return util_make_fragment_tex_shader_writemask( pipe
,
333 stype
, dtype
, load_level_zero
,
339 * Make a simple fragment texture shader which reads an X component from
340 * a texture and writes it as depth.
343 util_make_fragment_tex_shader_writedepth(struct pipe_context
*pipe
,
345 unsigned interp_mode
,
346 bool load_level_zero
,
349 struct ureg_program
*ureg
;
350 struct ureg_src sampler
;
352 struct ureg_dst out
, depth
;
355 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
359 sampler
= ureg_DECL_sampler( ureg
, 0 );
361 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
362 TGSI_RETURN_TYPE_FLOAT
,
363 TGSI_RETURN_TYPE_FLOAT
,
364 TGSI_RETURN_TYPE_FLOAT
,
365 TGSI_RETURN_TYPE_FLOAT
);
367 tex
= ureg_DECL_fs_input( ureg
,
368 TGSI_SEMANTIC_GENERIC
, 0,
371 out
= ureg_DECL_output( ureg
,
375 depth
= ureg_DECL_output( ureg
,
376 TGSI_SEMANTIC_POSITION
,
379 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
381 ureg_MOV( ureg
, out
, imm
);
383 ureg_load_tex(ureg
, ureg_writemask(depth
, TGSI_WRITEMASK_Z
), tex
, sampler
,
384 tex_target
, load_level_zero
, use_txf
);
387 return ureg_create_shader_and_destroy( ureg
, pipe
);
392 * Make a simple fragment texture shader which reads the texture unit 0 and 1
393 * and writes it as depth and stencil, respectively.
396 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context
*pipe
,
398 unsigned interp_mode
,
399 bool load_level_zero
,
402 struct ureg_program
*ureg
;
403 struct ureg_src depth_sampler
, stencil_sampler
;
405 struct ureg_dst out
, depth
, stencil
;
408 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
412 depth_sampler
= ureg_DECL_sampler( ureg
, 0 );
413 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
414 TGSI_RETURN_TYPE_FLOAT
,
415 TGSI_RETURN_TYPE_FLOAT
,
416 TGSI_RETURN_TYPE_FLOAT
,
417 TGSI_RETURN_TYPE_FLOAT
);
418 stencil_sampler
= ureg_DECL_sampler( ureg
, 1 );
419 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
420 TGSI_RETURN_TYPE_UINT
,
421 TGSI_RETURN_TYPE_UINT
,
422 TGSI_RETURN_TYPE_UINT
,
423 TGSI_RETURN_TYPE_UINT
);
425 tex
= ureg_DECL_fs_input( ureg
,
426 TGSI_SEMANTIC_GENERIC
, 0,
429 out
= ureg_DECL_output( ureg
,
433 depth
= ureg_DECL_output( ureg
,
434 TGSI_SEMANTIC_POSITION
,
437 stencil
= ureg_DECL_output( ureg
,
438 TGSI_SEMANTIC_STENCIL
,
441 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
443 ureg_MOV( ureg
, out
, imm
);
445 ureg_load_tex(ureg
, ureg_writemask(depth
, TGSI_WRITEMASK_Z
), tex
,
446 depth_sampler
, tex_target
, load_level_zero
, use_txf
);
447 ureg_load_tex(ureg
, ureg_writemask(stencil
, TGSI_WRITEMASK_Y
), tex
,
448 stencil_sampler
, tex_target
, load_level_zero
, use_txf
);
451 return ureg_create_shader_and_destroy( ureg
, pipe
);
456 * Make a simple fragment texture shader which reads a texture and writes it
460 util_make_fragment_tex_shader_writestencil(struct pipe_context
*pipe
,
462 unsigned interp_mode
,
463 bool load_level_zero
,
466 struct ureg_program
*ureg
;
467 struct ureg_src stencil_sampler
;
469 struct ureg_dst out
, stencil
;
472 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
476 stencil_sampler
= ureg_DECL_sampler( ureg
, 0 );
478 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
479 TGSI_RETURN_TYPE_UINT
,
480 TGSI_RETURN_TYPE_UINT
,
481 TGSI_RETURN_TYPE_UINT
,
482 TGSI_RETURN_TYPE_UINT
);
484 tex
= ureg_DECL_fs_input( ureg
,
485 TGSI_SEMANTIC_GENERIC
, 0,
488 out
= ureg_DECL_output( ureg
,
492 stencil
= ureg_DECL_output( ureg
,
493 TGSI_SEMANTIC_STENCIL
,
496 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
498 ureg_MOV( ureg
, out
, imm
);
500 ureg_load_tex(ureg
, ureg_writemask(stencil
, TGSI_WRITEMASK_Y
), tex
,
501 stencil_sampler
, tex_target
, load_level_zero
, use_txf
);
504 return ureg_create_shader_and_destroy( ureg
, pipe
);
509 * Make simple fragment color pass-through shader that replicates OUT[0]
510 * to all bound colorbuffers.
513 util_make_fragment_passthrough_shader(struct pipe_context
*pipe
,
515 int input_interpolate
,
516 boolean write_all_cbufs
)
518 static const char shader_templ
[] =
521 "DCL IN[0], %s[0], %s\n"
522 "DCL OUT[0], COLOR[0]\n"
524 "MOV OUT[0], IN[0]\n"
527 char text
[sizeof(shader_templ
)+100];
528 struct tgsi_token tokens
[1000];
529 struct pipe_shader_state state
;
531 sprintf(text
, shader_templ
,
532 write_all_cbufs
? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
533 tgsi_semantic_names
[input_semantic
],
534 tgsi_interpolate_names
[input_interpolate
]);
536 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
540 pipe_shader_state_from_tgsi(&state
, tokens
);
542 tgsi_dump(state
.tokens
, 0);
545 return pipe
->create_fs_state(pipe
, &state
);
550 util_make_empty_fragment_shader(struct pipe_context
*pipe
)
552 struct ureg_program
*ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
557 return ureg_create_shader_and_destroy(ureg
, pipe
);
562 * Make a fragment shader that copies the input color to N output colors.
565 util_make_fragment_cloneinput_shader(struct pipe_context
*pipe
, int num_cbufs
,
567 int input_interpolate
)
569 struct ureg_program
*ureg
;
571 struct ureg_dst dst
[PIPE_MAX_COLOR_BUFS
];
574 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
576 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
580 src
= ureg_DECL_fs_input( ureg
, input_semantic
, 0,
583 for (i
= 0; i
< num_cbufs
; i
++)
584 dst
[i
] = ureg_DECL_output( ureg
, TGSI_SEMANTIC_COLOR
, i
);
586 for (i
= 0; i
< num_cbufs
; i
++)
587 ureg_MOV( ureg
, dst
[i
], src
);
591 return ureg_create_shader_and_destroy( ureg
, pipe
);
596 util_make_fs_blit_msaa_gen(struct pipe_context
*pipe
,
598 const char *samp_type
,
599 const char *output_semantic
,
600 const char *output_mask
,
601 const char *conversion_decl
,
602 const char *conversion
)
604 static const char shader_templ
[] =
606 "DCL IN[0], GENERIC[0], LINEAR\n"
608 "DCL SVIEW[0], %s, %s\n"
613 "F2U TEMP[0], IN[0]\n"
614 "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
616 "MOV OUT[0]%s, TEMP[0]\n"
619 const char *type
= tgsi_texture_names
[tgsi_tex
];
620 char text
[sizeof(shader_templ
)+100];
621 struct tgsi_token tokens
[1000];
622 struct pipe_shader_state state
;
624 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
625 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
627 util_snprintf(text
, sizeof(text
), shader_templ
, type
, samp_type
,
628 output_semantic
, conversion_decl
, type
, conversion
, output_mask
);
630 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
635 pipe_shader_state_from_tgsi(&state
, tokens
);
637 tgsi_dump(state
.tokens
, 0);
640 return pipe
->create_fs_state(pipe
, &state
);
645 * Make a fragment shader that sets the output color to a color
646 * fetched from a multisample texture.
647 * \param tex_target one of PIPE_TEXTURE_x
650 util_make_fs_blit_msaa_color(struct pipe_context
*pipe
,
652 enum tgsi_return_type stype
,
653 enum tgsi_return_type dtype
)
655 const char *samp_type
;
656 const char *conversion_decl
= "";
657 const char *conversion
= "";
659 if (stype
== TGSI_RETURN_TYPE_UINT
) {
662 if (dtype
== TGSI_RETURN_TYPE_SINT
) {
663 conversion_decl
= "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
664 conversion
= "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n";
666 } else if (stype
== TGSI_RETURN_TYPE_SINT
) {
669 if (dtype
== TGSI_RETURN_TYPE_UINT
) {
670 conversion_decl
= "IMM[0] INT32 {0, 0, 0, 0}\n";
671 conversion
= "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
674 assert(dtype
== TGSI_RETURN_TYPE_FLOAT
);
678 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, samp_type
,
679 "COLOR[0]", "", conversion_decl
,
685 * Make a fragment shader that sets the output depth to a depth value
686 * fetched from a multisample texture.
687 * \param tex_target one of PIPE_TEXTURE_x
690 util_make_fs_blit_msaa_depth(struct pipe_context
*pipe
,
693 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "FLOAT",
694 "POSITION", ".z", "", "");
699 * Make a fragment shader that sets the output stencil to a stencil value
700 * fetched from a multisample texture.
701 * \param tex_target one of PIPE_TEXTURE_x
704 util_make_fs_blit_msaa_stencil(struct pipe_context
*pipe
,
707 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "UINT",
708 "STENCIL", ".y", "", "");
713 * Make a fragment shader that sets the output depth and stencil to depth
714 * and stencil values fetched from two multisample textures / samplers.
715 * The sizes of both textures should match (it should be one depth-stencil
717 * \param tex_target one of PIPE_TEXTURE_x
720 util_make_fs_blit_msaa_depthstencil(struct pipe_context
*pipe
,
723 static const char shader_templ
[] =
725 "DCL IN[0], GENERIC[0], LINEAR\n"
727 "DCL SVIEW[0..1], %s, FLOAT\n"
728 "DCL OUT[0], POSITION\n"
729 "DCL OUT[1], STENCIL\n"
732 "F2U TEMP[0], IN[0]\n"
733 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
734 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
737 const char *type
= tgsi_texture_names
[tgsi_tex
];
738 char text
[sizeof(shader_templ
)+100];
739 struct tgsi_token tokens
[1000];
740 struct pipe_shader_state state
;
742 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
743 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
745 sprintf(text
, shader_templ
, type
, type
, type
);
747 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
751 pipe_shader_state_from_tgsi(&state
, tokens
);
753 tgsi_dump(state
.tokens
, 0);
756 return pipe
->create_fs_state(pipe
, &state
);
761 util_make_fs_msaa_resolve(struct pipe_context
*pipe
,
762 unsigned tgsi_tex
, unsigned nr_samples
,
763 enum tgsi_return_type stype
)
765 struct ureg_program
*ureg
;
766 struct ureg_src sampler
, coord
;
767 struct ureg_dst out
, tmp_sum
, tmp_coord
, tmp
;
770 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
775 sampler
= ureg_DECL_sampler(ureg
, 0);
776 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
777 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
778 TGSI_INTERPOLATE_LINEAR
);
779 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
780 tmp_sum
= ureg_DECL_temporary(ureg
);
781 tmp_coord
= ureg_DECL_temporary(ureg
);
782 tmp
= ureg_DECL_temporary(ureg
);
785 ureg_MOV(ureg
, tmp_sum
, ureg_imm1f(ureg
, 0));
786 ureg_F2U(ureg
, tmp_coord
, coord
);
788 for (i
= 0; i
< nr_samples
; i
++) {
789 /* Read one sample. */
790 ureg_MOV(ureg
, ureg_writemask(tmp_coord
, TGSI_WRITEMASK_W
),
791 ureg_imm1u(ureg
, i
));
792 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
), sampler
);
794 if (stype
== TGSI_RETURN_TYPE_UINT
)
795 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
796 else if (stype
== TGSI_RETURN_TYPE_SINT
)
797 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
799 /* Add it to the sum.*/
800 ureg_ADD(ureg
, tmp_sum
, ureg_src(tmp_sum
), ureg_src(tmp
));
803 /* Calculate the average and return. */
804 ureg_MUL(ureg
, tmp_sum
, ureg_src(tmp_sum
),
805 ureg_imm1f(ureg
, 1.0 / nr_samples
));
807 if (stype
== TGSI_RETURN_TYPE_UINT
)
808 ureg_F2U(ureg
, out
, ureg_src(tmp_sum
));
809 else if (stype
== TGSI_RETURN_TYPE_SINT
)
810 ureg_F2I(ureg
, out
, ureg_src(tmp_sum
));
812 ureg_MOV(ureg
, out
, ureg_src(tmp_sum
));
816 return ureg_create_shader_and_destroy(ureg
, pipe
);
821 util_make_fs_msaa_resolve_bilinear(struct pipe_context
*pipe
,
822 unsigned tgsi_tex
, unsigned nr_samples
,
823 enum tgsi_return_type stype
)
825 struct ureg_program
*ureg
;
826 struct ureg_src sampler
, coord
;
827 struct ureg_dst out
, tmp
, top
, bottom
;
828 struct ureg_dst tmp_coord
[4], tmp_sum
[4];
831 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
836 sampler
= ureg_DECL_sampler(ureg
, 0);
837 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
838 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
839 TGSI_INTERPOLATE_LINEAR
);
840 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
841 for (c
= 0; c
< 4; c
++)
842 tmp_sum
[c
] = ureg_DECL_temporary(ureg
);
843 for (c
= 0; c
< 4; c
++)
844 tmp_coord
[c
] = ureg_DECL_temporary(ureg
);
845 tmp
= ureg_DECL_temporary(ureg
);
846 top
= ureg_DECL_temporary(ureg
);
847 bottom
= ureg_DECL_temporary(ureg
);
850 for (c
= 0; c
< 4; c
++)
851 ureg_MOV(ureg
, tmp_sum
[c
], ureg_imm1f(ureg
, 0));
853 /* Get 4 texture coordinates for the bilinear filter. */
854 ureg_F2U(ureg
, tmp_coord
[0], coord
); /* top-left */
855 ureg_UADD(ureg
, tmp_coord
[1], ureg_src(tmp_coord
[0]),
856 ureg_imm4u(ureg
, 1, 0, 0, 0)); /* top-right */
857 ureg_UADD(ureg
, tmp_coord
[2], ureg_src(tmp_coord
[0]),
858 ureg_imm4u(ureg
, 0, 1, 0, 0)); /* bottom-left */
859 ureg_UADD(ureg
, tmp_coord
[3], ureg_src(tmp_coord
[0]),
860 ureg_imm4u(ureg
, 1, 1, 0, 0)); /* bottom-right */
862 for (i
= 0; i
< nr_samples
; i
++) {
863 for (c
= 0; c
< 4; c
++) {
864 /* Read one sample. */
865 ureg_MOV(ureg
, ureg_writemask(tmp_coord
[c
], TGSI_WRITEMASK_W
),
866 ureg_imm1u(ureg
, i
));
867 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
[c
]), sampler
);
869 if (stype
== TGSI_RETURN_TYPE_UINT
)
870 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
871 else if (stype
== TGSI_RETURN_TYPE_SINT
)
872 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
874 /* Add it to the sum.*/
875 ureg_ADD(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]), ureg_src(tmp
));
879 /* Calculate the average. */
880 for (c
= 0; c
< 4; c
++)
881 ureg_MUL(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]),
882 ureg_imm1f(ureg
, 1.0 / nr_samples
));
884 /* Take the 4 average values and apply a standard bilinear filter. */
885 ureg_FRC(ureg
, tmp
, coord
);
888 ureg_scalar(ureg_src(tmp
), 0),
889 ureg_src(tmp_sum
[1]),
890 ureg_src(tmp_sum
[0]));
892 ureg_LRP(ureg
, bottom
,
893 ureg_scalar(ureg_src(tmp
), 0),
894 ureg_src(tmp_sum
[3]),
895 ureg_src(tmp_sum
[2]));
898 ureg_scalar(ureg_src(tmp
), 1),
902 /* Convert to the texture format and return. */
903 if (stype
== TGSI_RETURN_TYPE_UINT
)
904 ureg_F2U(ureg
, out
, ureg_src(tmp
));
905 else if (stype
== TGSI_RETURN_TYPE_SINT
)
906 ureg_F2I(ureg
, out
, ureg_src(tmp
));
908 ureg_MOV(ureg
, out
, ureg_src(tmp
));
912 return ureg_create_shader_and_destroy(ureg
, pipe
);
916 util_make_geometry_passthrough_shader(struct pipe_context
*pipe
,
918 const ubyte
*semantic_names
,
919 const ubyte
*semantic_indexes
)
921 static const unsigned zero
[4] = {0, 0, 0, 0};
923 struct ureg_program
*ureg
;
924 struct ureg_dst dst
[PIPE_MAX_SHADER_OUTPUTS
];
925 struct ureg_src src
[PIPE_MAX_SHADER_INPUTS
];
930 ureg
= ureg_create(PIPE_SHADER_GEOMETRY
);
934 ureg_property(ureg
, TGSI_PROPERTY_GS_INPUT_PRIM
, PIPE_PRIM_POINTS
);
935 ureg_property(ureg
, TGSI_PROPERTY_GS_OUTPUT_PRIM
, PIPE_PRIM_POINTS
);
936 ureg_property(ureg
, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES
, 1);
937 ureg_property(ureg
, TGSI_PROPERTY_GS_INVOCATIONS
, 1);
938 imm
= ureg_DECL_immediate_uint(ureg
, zero
, 4);
941 * Loop over all the attribs and declare the corresponding
942 * declarations in the geometry shader
944 for (i
= 0; i
< num_attribs
; i
++) {
945 src
[i
] = ureg_DECL_input(ureg
, semantic_names
[i
],
946 semantic_indexes
[i
], 0, 1);
947 src
[i
] = ureg_src_dimension(src
[i
], 0);
948 dst
[i
] = ureg_DECL_output(ureg
, semantic_names
[i
], semantic_indexes
[i
]);
951 /* MOV dst[i] src[i] */
952 for (i
= 0; i
< num_attribs
; i
++) {
953 ureg_MOV(ureg
, dst
[i
], src
[i
]);
957 ureg_insn(ureg
, TGSI_OPCODE_EMIT
, NULL
, 0, &imm
, 1, 0);
962 return ureg_create_shader_and_destroy(ureg
, pipe
);