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 "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 */
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
59 util_make_vertex_passthrough_shader(struct pipe_context
*pipe
,
61 const uint
*semantic_names
,
62 const uint
*semantic_indexes
,
65 return util_make_vertex_passthrough_shader_with_so(pipe
, num_attribs
,
72 util_make_vertex_passthrough_shader_with_so(struct pipe_context
*pipe
,
74 const uint
*semantic_names
,
75 const uint
*semantic_indexes
,
77 const struct pipe_stream_output_info
*so
)
79 struct ureg_program
*ureg
;
82 ureg
= ureg_create( PIPE_SHADER_VERTEX
);
87 ureg_property(ureg
, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION
, TRUE
);
89 for (i
= 0; i
< num_attribs
; i
++) {
93 src
= ureg_DECL_vs_input( ureg
, i
);
95 dst
= ureg_DECL_output( ureg
,
99 ureg_MOV( ureg
, dst
, src
);
104 return ureg_create_shader_with_so_and_destroy( ureg
, pipe
, so
);
108 void *util_make_layered_clear_vertex_shader(struct pipe_context
*pipe
)
110 static const char text
[] =
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"
119 "MOV OUT[0], IN[0]\n"
120 "MOV OUT[1], IN[1]\n"
121 "MOV OUT[2], SV[0]\n"
123 struct tgsi_token tokens
[1000];
124 struct pipe_shader_state state
;
126 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
130 pipe_shader_state_from_tgsi(&state
, tokens
);
131 return pipe
->create_vs_state(pipe
, &state
);
135 * Takes position and color, and outputs position, color, and instance id.
137 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context
*pipe
)
139 static const char text
[] =
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"
148 "MOV OUT[0], IN[0]\n"
149 "MOV OUT[1], IN[1]\n"
150 "MOV OUT[2].x, SV[0].xxxx\n"
152 struct tgsi_token tokens
[1000];
153 struct pipe_shader_state state
;
155 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
159 pipe_shader_state_from_tgsi(&state
, tokens
);
160 return pipe
->create_vs_state(pipe
, &state
);
164 * Takes position, color, and target layer, and emits vertices on that target
165 * layer, with the specified color.
167 void *util_make_layered_clear_geometry_shader(struct pipe_context
*pipe
)
169 static const char text
[] =
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"
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"
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"
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"
196 struct tgsi_token tokens
[1000];
197 struct pipe_shader_state state
;
199 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
203 pipe_shader_state_from_tgsi(&state
, tokens
);
204 return pipe
->create_gs_state(pipe
, &state
);
208 * Make simple fragment texture shader:
209 * IMM {0,0,0,1} // (if writemask != 0xf)
210 * MOV TEMP[0], IMM[0] // (if writemask != 0xf)
211 * TEX TEMP[0].writemask, IN[0], SAMP[0], 2D;
212 * .. optional SINT <-> UINT clamping ..
213 * MOV OUT[0], TEMP[0]
216 * \param tex_target one of PIPE_TEXTURE_x
217 * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
218 * \param writemask mask of TGSI_WRITEMASK_x
221 util_make_fragment_tex_shader_writemask(struct pipe_context
*pipe
,
223 unsigned interp_mode
,
225 enum tgsi_return_type stype
,
226 enum tgsi_return_type dtype
)
228 struct ureg_program
*ureg
;
229 struct ureg_src sampler
;
231 struct ureg_dst temp
;
234 assert((stype
== TGSI_RETURN_TYPE_FLOAT
) == (dtype
== TGSI_RETURN_TYPE_FLOAT
));
235 assert(interp_mode
== TGSI_INTERPOLATE_LINEAR
||
236 interp_mode
== TGSI_INTERPOLATE_PERSPECTIVE
);
238 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
242 sampler
= ureg_DECL_sampler( ureg
, 0 );
244 ureg_DECL_sampler_view(ureg
, 0, tex_target
, stype
, stype
, stype
, stype
);
246 tex
= ureg_DECL_fs_input( ureg
,
247 TGSI_SEMANTIC_GENERIC
, 0,
250 out
= ureg_DECL_output( ureg
,
254 temp
= ureg_DECL_temporary(ureg
);
256 if (writemask
!= TGSI_WRITEMASK_XYZW
) {
257 struct ureg_src imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
259 ureg_MOV( ureg
, out
, imm
);
262 if (tex_target
== TGSI_TEXTURE_BUFFER
)
264 ureg_writemask(temp
, writemask
),
265 tex_target
, tex
, sampler
);
268 ureg_writemask(temp
, writemask
),
269 tex_target
, tex
, sampler
);
271 if (stype
!= dtype
) {
272 if (stype
== TGSI_RETURN_TYPE_SINT
) {
273 assert(dtype
== TGSI_RETURN_TYPE_UINT
);
275 ureg_IMAX(ureg
, temp
, ureg_src(temp
), ureg_imm1i(ureg
, 0));
277 assert(stype
== TGSI_RETURN_TYPE_UINT
);
278 assert(dtype
== TGSI_RETURN_TYPE_SINT
);
280 ureg_UMIN(ureg
, temp
, ureg_src(temp
), ureg_imm1u(ureg
, (1u << 31) - 1));
284 ureg_MOV(ureg
, out
, ureg_src(temp
));
288 return ureg_create_shader_and_destroy( ureg
, pipe
);
293 * Make a simple fragment shader that sets the output color to a color
294 * taken from a texture.
295 * \param tex_target one of PIPE_TEXTURE_x
298 util_make_fragment_tex_shader(struct pipe_context
*pipe
, unsigned tex_target
,
299 unsigned interp_mode
,
300 enum tgsi_return_type stype
,
301 enum tgsi_return_type dtype
)
303 return util_make_fragment_tex_shader_writemask( pipe
,
312 * Make a simple fragment texture shader which reads an X component from
313 * a texture and writes it as depth.
316 util_make_fragment_tex_shader_writedepth(struct pipe_context
*pipe
,
318 unsigned interp_mode
)
320 struct ureg_program
*ureg
;
321 struct ureg_src sampler
;
323 struct ureg_dst out
, depth
;
326 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
330 sampler
= ureg_DECL_sampler( ureg
, 0 );
332 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
333 TGSI_RETURN_TYPE_FLOAT
,
334 TGSI_RETURN_TYPE_FLOAT
,
335 TGSI_RETURN_TYPE_FLOAT
,
336 TGSI_RETURN_TYPE_FLOAT
);
338 tex
= ureg_DECL_fs_input( ureg
,
339 TGSI_SEMANTIC_GENERIC
, 0,
342 out
= ureg_DECL_output( ureg
,
346 depth
= ureg_DECL_output( ureg
,
347 TGSI_SEMANTIC_POSITION
,
350 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
352 ureg_MOV( ureg
, out
, imm
);
355 ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
356 tex_target
, tex
, sampler
);
359 return ureg_create_shader_and_destroy( ureg
, pipe
);
364 * Make a simple fragment texture shader which reads the texture unit 0 and 1
365 * and writes it as depth and stencil, respectively.
368 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context
*pipe
,
370 unsigned interp_mode
)
372 struct ureg_program
*ureg
;
373 struct ureg_src depth_sampler
, stencil_sampler
;
375 struct ureg_dst out
, depth
, stencil
;
378 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
382 depth_sampler
= ureg_DECL_sampler( ureg
, 0 );
383 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
384 TGSI_RETURN_TYPE_FLOAT
,
385 TGSI_RETURN_TYPE_FLOAT
,
386 TGSI_RETURN_TYPE_FLOAT
,
387 TGSI_RETURN_TYPE_FLOAT
);
388 stencil_sampler
= ureg_DECL_sampler( ureg
, 1 );
389 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
390 TGSI_RETURN_TYPE_UINT
,
391 TGSI_RETURN_TYPE_UINT
,
392 TGSI_RETURN_TYPE_UINT
,
393 TGSI_RETURN_TYPE_UINT
);
395 tex
= ureg_DECL_fs_input( ureg
,
396 TGSI_SEMANTIC_GENERIC
, 0,
399 out
= ureg_DECL_output( ureg
,
403 depth
= ureg_DECL_output( ureg
,
404 TGSI_SEMANTIC_POSITION
,
407 stencil
= ureg_DECL_output( ureg
,
408 TGSI_SEMANTIC_STENCIL
,
411 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
413 ureg_MOV( ureg
, out
, imm
);
416 ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
417 tex_target
, tex
, depth_sampler
);
419 ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
420 tex_target
, tex
, stencil_sampler
);
423 return ureg_create_shader_and_destroy( ureg
, pipe
);
428 * Make a simple fragment texture shader which reads a texture and writes it
432 util_make_fragment_tex_shader_writestencil(struct pipe_context
*pipe
,
434 unsigned interp_mode
)
436 struct ureg_program
*ureg
;
437 struct ureg_src stencil_sampler
;
439 struct ureg_dst out
, stencil
;
442 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
446 stencil_sampler
= ureg_DECL_sampler( ureg
, 0 );
448 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
449 TGSI_RETURN_TYPE_UINT
,
450 TGSI_RETURN_TYPE_UINT
,
451 TGSI_RETURN_TYPE_UINT
,
452 TGSI_RETURN_TYPE_UINT
);
454 tex
= ureg_DECL_fs_input( ureg
,
455 TGSI_SEMANTIC_GENERIC
, 0,
458 out
= ureg_DECL_output( ureg
,
462 stencil
= ureg_DECL_output( ureg
,
463 TGSI_SEMANTIC_STENCIL
,
466 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
468 ureg_MOV( ureg
, out
, imm
);
471 ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
472 tex_target
, tex
, stencil_sampler
);
475 return ureg_create_shader_and_destroy( ureg
, pipe
);
480 * Make simple fragment color pass-through shader that replicates OUT[0]
481 * to all bound colorbuffers.
484 util_make_fragment_passthrough_shader(struct pipe_context
*pipe
,
486 int input_interpolate
,
487 boolean write_all_cbufs
)
489 static const char shader_templ
[] =
492 "DCL IN[0], %s[0], %s\n"
493 "DCL OUT[0], COLOR[0]\n"
495 "MOV OUT[0], IN[0]\n"
498 char text
[sizeof(shader_templ
)+100];
499 struct tgsi_token tokens
[1000];
500 struct pipe_shader_state state
;
502 sprintf(text
, shader_templ
,
503 write_all_cbufs
? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
504 tgsi_semantic_names
[input_semantic
],
505 tgsi_interpolate_names
[input_interpolate
]);
507 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
511 pipe_shader_state_from_tgsi(&state
, tokens
);
513 tgsi_dump(state
.tokens
, 0);
516 return pipe
->create_fs_state(pipe
, &state
);
521 util_make_empty_fragment_shader(struct pipe_context
*pipe
)
523 struct ureg_program
*ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
528 return ureg_create_shader_and_destroy(ureg
, pipe
);
533 * Make a fragment shader that copies the input color to N output colors.
536 util_make_fragment_cloneinput_shader(struct pipe_context
*pipe
, int num_cbufs
,
538 int input_interpolate
)
540 struct ureg_program
*ureg
;
542 struct ureg_dst dst
[PIPE_MAX_COLOR_BUFS
];
545 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
547 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
551 src
= ureg_DECL_fs_input( ureg
, input_semantic
, 0,
554 for (i
= 0; i
< num_cbufs
; i
++)
555 dst
[i
] = ureg_DECL_output( ureg
, TGSI_SEMANTIC_COLOR
, i
);
557 for (i
= 0; i
< num_cbufs
; i
++)
558 ureg_MOV( ureg
, dst
[i
], src
);
562 return ureg_create_shader_and_destroy( ureg
, pipe
);
567 util_make_fs_blit_msaa_gen(struct pipe_context
*pipe
,
569 const char *samp_type
,
570 const char *output_semantic
,
571 const char *output_mask
,
572 const char *conversion_decl
,
573 const char *conversion
)
575 static const char shader_templ
[] =
577 "DCL IN[0], GENERIC[0], LINEAR\n"
579 "DCL SVIEW[0], %s, %s\n"
584 "F2U TEMP[0], IN[0]\n"
585 "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
587 "MOV OUT[0]%s, TEMP[0]\n"
590 const char *type
= tgsi_texture_names
[tgsi_tex
];
591 char text
[sizeof(shader_templ
)+100];
592 struct tgsi_token tokens
[1000];
593 struct pipe_shader_state state
;
595 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
596 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
598 snprintf(text
, sizeof(text
), shader_templ
, type
, samp_type
,
599 output_semantic
, conversion_decl
, type
, conversion
, output_mask
);
601 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
606 pipe_shader_state_from_tgsi(&state
, tokens
);
608 tgsi_dump(state
.tokens
, 0);
611 return pipe
->create_fs_state(pipe
, &state
);
616 * Make a fragment shader that sets the output color to a color
617 * fetched from a multisample texture.
618 * \param tex_target one of PIPE_TEXTURE_x
621 util_make_fs_blit_msaa_color(struct pipe_context
*pipe
,
623 enum tgsi_return_type stype
,
624 enum tgsi_return_type dtype
)
626 const char *samp_type
;
627 const char *conversion_decl
= "";
628 const char *conversion
= "";
630 if (stype
== TGSI_RETURN_TYPE_UINT
) {
633 if (dtype
== TGSI_RETURN_TYPE_SINT
) {
634 conversion_decl
= "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
635 conversion
= "UMIN TEMP[0], TEMP[0], IMM[0].x\n";
637 } else if (stype
== TGSI_RETURN_TYPE_SINT
) {
640 if (dtype
== TGSI_RETURN_TYPE_UINT
) {
641 conversion_decl
= "IMM[0] INT32 {0, 0, 0, 0}\n";
642 conversion
= "IMAX TEMP[0], TEMP[0], IMM[0].x\n";
645 assert(dtype
== TGSI_RETURN_TYPE_FLOAT
);
649 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, samp_type
,
650 "COLOR[0]", "", conversion_decl
,
656 * Make a fragment shader that sets the output depth to a depth value
657 * fetched from a multisample texture.
658 * \param tex_target one of PIPE_TEXTURE_x
661 util_make_fs_blit_msaa_depth(struct pipe_context
*pipe
,
664 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "FLOAT",
665 "POSITION", ".z", "", "");
670 * Make a fragment shader that sets the output stencil to a stencil value
671 * fetched from a multisample texture.
672 * \param tex_target one of PIPE_TEXTURE_x
675 util_make_fs_blit_msaa_stencil(struct pipe_context
*pipe
,
678 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "UINT",
679 "STENCIL", ".y", "", "");
684 * Make a fragment shader that sets the output depth and stencil to depth
685 * and stencil values fetched from two multisample textures / samplers.
686 * The sizes of both textures should match (it should be one depth-stencil
688 * \param tex_target one of PIPE_TEXTURE_x
691 util_make_fs_blit_msaa_depthstencil(struct pipe_context
*pipe
,
694 static const char shader_templ
[] =
696 "DCL IN[0], GENERIC[0], LINEAR\n"
698 "DCL SVIEW[0..1], %s, FLOAT\n"
699 "DCL OUT[0], POSITION\n"
700 "DCL OUT[1], STENCIL\n"
703 "F2U TEMP[0], IN[0]\n"
704 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
705 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
708 const char *type
= tgsi_texture_names
[tgsi_tex
];
709 char text
[sizeof(shader_templ
)+100];
710 struct tgsi_token tokens
[1000];
711 struct pipe_shader_state state
;
713 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
714 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
716 sprintf(text
, shader_templ
, type
, type
, type
);
718 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
722 pipe_shader_state_from_tgsi(&state
, tokens
);
724 tgsi_dump(state
.tokens
, 0);
727 return pipe
->create_fs_state(pipe
, &state
);
732 util_make_fs_msaa_resolve(struct pipe_context
*pipe
,
733 unsigned tgsi_tex
, unsigned nr_samples
,
734 enum tgsi_return_type stype
)
736 struct ureg_program
*ureg
;
737 struct ureg_src sampler
, coord
;
738 struct ureg_dst out
, tmp_sum
, tmp_coord
, tmp
;
741 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
746 sampler
= ureg_DECL_sampler(ureg
, 0);
747 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
748 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
749 TGSI_INTERPOLATE_LINEAR
);
750 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
751 tmp_sum
= ureg_DECL_temporary(ureg
);
752 tmp_coord
= ureg_DECL_temporary(ureg
);
753 tmp
= ureg_DECL_temporary(ureg
);
756 ureg_MOV(ureg
, tmp_sum
, ureg_imm1f(ureg
, 0));
757 ureg_F2U(ureg
, tmp_coord
, coord
);
759 for (i
= 0; i
< nr_samples
; i
++) {
760 /* Read one sample. */
761 ureg_MOV(ureg
, ureg_writemask(tmp_coord
, TGSI_WRITEMASK_W
),
762 ureg_imm1u(ureg
, i
));
763 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
), sampler
);
765 if (stype
== TGSI_RETURN_TYPE_UINT
)
766 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
767 else if (stype
== TGSI_RETURN_TYPE_SINT
)
768 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
770 /* Add it to the sum.*/
771 ureg_ADD(ureg
, tmp_sum
, ureg_src(tmp_sum
), ureg_src(tmp
));
774 /* Calculate the average and return. */
775 ureg_MUL(ureg
, tmp_sum
, ureg_src(tmp_sum
),
776 ureg_imm1f(ureg
, 1.0 / nr_samples
));
778 if (stype
== TGSI_RETURN_TYPE_UINT
)
779 ureg_F2U(ureg
, out
, ureg_src(tmp_sum
));
780 else if (stype
== TGSI_RETURN_TYPE_SINT
)
781 ureg_F2I(ureg
, out
, ureg_src(tmp_sum
));
783 ureg_MOV(ureg
, out
, ureg_src(tmp_sum
));
787 return ureg_create_shader_and_destroy(ureg
, pipe
);
792 util_make_fs_msaa_resolve_bilinear(struct pipe_context
*pipe
,
793 unsigned tgsi_tex
, unsigned nr_samples
,
794 enum tgsi_return_type stype
)
796 struct ureg_program
*ureg
;
797 struct ureg_src sampler
, coord
;
798 struct ureg_dst out
, tmp
, top
, bottom
;
799 struct ureg_dst tmp_coord
[4], tmp_sum
[4];
802 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
807 sampler
= ureg_DECL_sampler(ureg
, 0);
808 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
809 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
810 TGSI_INTERPOLATE_LINEAR
);
811 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
812 for (c
= 0; c
< 4; c
++)
813 tmp_sum
[c
] = ureg_DECL_temporary(ureg
);
814 for (c
= 0; c
< 4; c
++)
815 tmp_coord
[c
] = ureg_DECL_temporary(ureg
);
816 tmp
= ureg_DECL_temporary(ureg
);
817 top
= ureg_DECL_temporary(ureg
);
818 bottom
= ureg_DECL_temporary(ureg
);
821 for (c
= 0; c
< 4; c
++)
822 ureg_MOV(ureg
, tmp_sum
[c
], ureg_imm1f(ureg
, 0));
824 /* Get 4 texture coordinates for the bilinear filter. */
825 ureg_F2U(ureg
, tmp_coord
[0], coord
); /* top-left */
826 ureg_UADD(ureg
, tmp_coord
[1], ureg_src(tmp_coord
[0]),
827 ureg_imm4u(ureg
, 1, 0, 0, 0)); /* top-right */
828 ureg_UADD(ureg
, tmp_coord
[2], ureg_src(tmp_coord
[0]),
829 ureg_imm4u(ureg
, 0, 1, 0, 0)); /* bottom-left */
830 ureg_UADD(ureg
, tmp_coord
[3], ureg_src(tmp_coord
[0]),
831 ureg_imm4u(ureg
, 1, 1, 0, 0)); /* bottom-right */
833 for (i
= 0; i
< nr_samples
; i
++) {
834 for (c
= 0; c
< 4; c
++) {
835 /* Read one sample. */
836 ureg_MOV(ureg
, ureg_writemask(tmp_coord
[c
], TGSI_WRITEMASK_W
),
837 ureg_imm1u(ureg
, i
));
838 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
[c
]), sampler
);
840 if (stype
== TGSI_RETURN_TYPE_UINT
)
841 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
842 else if (stype
== TGSI_RETURN_TYPE_SINT
)
843 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
845 /* Add it to the sum.*/
846 ureg_ADD(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]), ureg_src(tmp
));
850 /* Calculate the average. */
851 for (c
= 0; c
< 4; c
++)
852 ureg_MUL(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]),
853 ureg_imm1f(ureg
, 1.0 / nr_samples
));
855 /* Take the 4 average values and apply a standard bilinear filter. */
856 ureg_FRC(ureg
, tmp
, coord
);
859 ureg_scalar(ureg_src(tmp
), 0),
860 ureg_src(tmp_sum
[1]),
861 ureg_src(tmp_sum
[0]));
863 ureg_LRP(ureg
, bottom
,
864 ureg_scalar(ureg_src(tmp
), 0),
865 ureg_src(tmp_sum
[3]),
866 ureg_src(tmp_sum
[2]));
869 ureg_scalar(ureg_src(tmp
), 1),
873 /* Convert to the texture format and return. */
874 if (stype
== TGSI_RETURN_TYPE_UINT
)
875 ureg_F2U(ureg
, out
, ureg_src(tmp
));
876 else if (stype
== TGSI_RETURN_TYPE_SINT
)
877 ureg_F2I(ureg
, out
, ureg_src(tmp
));
879 ureg_MOV(ureg
, out
, ureg_src(tmp
));
883 return ureg_create_shader_and_destroy(ureg
, pipe
);
887 util_make_geometry_passthrough_shader(struct pipe_context
*pipe
,
889 const ubyte
*semantic_names
,
890 const ubyte
*semantic_indexes
)
892 static const unsigned zero
[4] = {0, 0, 0, 0};
894 struct ureg_program
*ureg
;
895 struct ureg_dst dst
[PIPE_MAX_SHADER_OUTPUTS
];
896 struct ureg_src src
[PIPE_MAX_SHADER_INPUTS
];
901 ureg
= ureg_create(PIPE_SHADER_GEOMETRY
);
905 ureg_property(ureg
, TGSI_PROPERTY_GS_INPUT_PRIM
, PIPE_PRIM_POINTS
);
906 ureg_property(ureg
, TGSI_PROPERTY_GS_OUTPUT_PRIM
, PIPE_PRIM_POINTS
);
907 ureg_property(ureg
, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES
, 1);
908 ureg_property(ureg
, TGSI_PROPERTY_GS_INVOCATIONS
, 1);
909 imm
= ureg_DECL_immediate_uint(ureg
, zero
, 4);
912 * Loop over all the attribs and declare the corresponding
913 * declarations in the geometry shader
915 for (i
= 0; i
< num_attribs
; i
++) {
916 src
[i
] = ureg_DECL_input(ureg
, semantic_names
[i
],
917 semantic_indexes
[i
], 0, 1);
918 src
[i
] = ureg_src_dimension(src
[i
], 0);
919 dst
[i
] = ureg_DECL_output(ureg
, semantic_names
[i
], semantic_indexes
[i
]);
922 /* MOV dst[i] src[i] */
923 for (i
= 0; i
< num_attribs
; i
++) {
924 ureg_MOV(ureg
, dst
[i
], src
[i
]);
928 ureg_insn(ureg
, TGSI_OPCODE_EMIT
, NULL
, 0, &imm
, 1);
933 return ureg_create_shader_and_destroy(ureg
, pipe
);