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 enum tgsi_semantic
*semantic_names
,
63 const uint
*semantic_indexes
,
66 return util_make_vertex_passthrough_shader_with_so(pipe
, num_attribs
,
69 window_space
, false, NULL
);
73 util_make_vertex_passthrough_shader_with_so(struct pipe_context
*pipe
,
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
)
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
);
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);
108 ureg_MOV(ureg
, ureg_writemask(layer
, TGSI_WRITEMASK_X
),
109 ureg_scalar(instance_id
, TGSI_SWIZZLE_X
));
114 return ureg_create_shader_with_so_and_destroy( ureg
, pipe
, so
);
118 void *util_make_layered_clear_vertex_shader(struct pipe_context
*pipe
)
120 const enum tgsi_semantic semantic_names
[] = {TGSI_SEMANTIC_POSITION
,
121 TGSI_SEMANTIC_GENERIC
};
122 const unsigned semantic_indices
[] = {0, 0};
124 return util_make_vertex_passthrough_shader_with_so(pipe
, 2, semantic_names
,
125 semantic_indices
, false,
130 * Takes position and color, and outputs position, color, and instance id.
132 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context
*pipe
)
134 static const char text
[] =
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"
143 "MOV OUT[0], IN[0]\n"
144 "MOV OUT[1], IN[1]\n"
145 "MOV OUT[2].x, SV[0].xxxx\n"
147 struct tgsi_token tokens
[1000];
148 struct pipe_shader_state state
= {0};
150 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
154 pipe_shader_state_from_tgsi(&state
, tokens
);
155 return pipe
->create_vs_state(pipe
, &state
);
159 * Takes position, color, and target layer, and emits vertices on that target
160 * layer, with the specified color.
162 void *util_make_layered_clear_geometry_shader(struct pipe_context
*pipe
)
164 static const char text
[] =
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"
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"
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"
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"
191 struct tgsi_token tokens
[1000];
192 struct pipe_shader_state state
= {0};
194 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
198 pipe_shader_state_from_tgsi(&state
, tokens
);
199 return pipe
->create_gs_state(pipe
, &state
);
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
)
209 struct ureg_dst temp
= ureg_DECL_temporary(ureg
);
211 ureg_F2I(ureg
, temp
, coord
);
214 ureg_TXF_LZ(ureg
, out
, tex_target
, ureg_src(temp
), sampler
);
216 ureg_TXF(ureg
, out
, tex_target
, ureg_src(temp
), sampler
);
219 ureg_TEX_LZ(ureg
, out
, tex_target
, coord
, sampler
);
221 ureg_TEX(ureg
, out
, tex_target
, coord
, sampler
);
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]
233 * \param tex_target one of PIPE_TEXTURE_x
236 util_make_fragment_tex_shader_xrbias(struct pipe_context
*pipe
,
237 enum tgsi_texture_type tex_target
)
239 struct ureg_program
*ureg
;
240 struct ureg_src sampler
;
241 struct ureg_src coord
;
242 struct ureg_dst temp
;
245 enum tgsi_return_type stype
= TGSI_RETURN_TYPE_FLOAT
;
247 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
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
);
260 ureg_TEX(ureg
, temp
, tex_target
, coord
, sampler
);
261 ureg_MAD(ureg
, ureg_writemask(temp
, TGSI_WRITEMASK_XYZ
),
263 ureg_scalar(imm
, TGSI_SWIZZLE_X
),
264 ureg_scalar(imm
, TGSI_SWIZZLE_Y
));
265 ureg_MOV(ureg
, out
, ureg_src(temp
));
268 return ureg_create_shader_and_destroy(ureg
, pipe
);
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]
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
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
,
290 enum tgsi_return_type stype
,
291 enum tgsi_return_type dtype
,
292 bool load_level_zero
,
295 struct ureg_program
*ureg
;
296 struct ureg_src sampler
;
298 struct ureg_dst temp
;
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
);
305 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
309 sampler
= ureg_DECL_sampler( ureg
, 0 );
311 ureg_DECL_sampler_view(ureg
, 0, tex_target
, stype
, stype
, stype
, stype
);
313 tex
= ureg_DECL_fs_input( ureg
,
314 TGSI_SEMANTIC_GENERIC
, 0,
317 out
= ureg_DECL_output( ureg
,
321 temp
= ureg_DECL_temporary(ureg
);
323 if (writemask
!= TGSI_WRITEMASK_XYZW
) {
324 struct ureg_src imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
326 ureg_MOV(ureg
, temp
, imm
);
329 if (tex_target
== TGSI_TEXTURE_BUFFER
)
331 ureg_writemask(temp
, writemask
),
332 tex_target
, tex
, sampler
);
334 ureg_load_tex(ureg
, ureg_writemask(temp
, writemask
), tex
, sampler
,
335 tex_target
, load_level_zero
, use_txf
);
337 if (stype
!= dtype
) {
338 if (stype
== TGSI_RETURN_TYPE_SINT
) {
339 assert(dtype
== TGSI_RETURN_TYPE_UINT
);
341 ureg_IMAX(ureg
, temp
, ureg_src(temp
), ureg_imm1i(ureg
, 0));
343 assert(stype
== TGSI_RETURN_TYPE_UINT
);
344 assert(dtype
== TGSI_RETURN_TYPE_SINT
);
346 ureg_UMIN(ureg
, temp
, ureg_src(temp
), ureg_imm1u(ureg
, (1u << 31) - 1));
350 ureg_MOV(ureg
, out
, ureg_src(temp
));
354 return ureg_create_shader_and_destroy( ureg
, pipe
);
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
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
,
372 return util_make_fragment_tex_shader_writemask( pipe
,
376 stype
, dtype
, load_level_zero
,
382 * Make a simple fragment texture shader which reads the texture unit 0 and 1
383 * and writes it as depth and stencil, respectively.
386 util_make_fs_blit_zs(struct pipe_context
*pipe
, unsigned zs_mask
,
387 enum tgsi_texture_type tex_target
,
388 bool load_level_zero
, bool use_txf
)
390 struct ureg_program
*ureg
;
391 struct ureg_src depth_sampler
, stencil_sampler
, coord
;
392 struct ureg_dst depth
, stencil
, tmp
;
394 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
398 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
399 TGSI_INTERPOLATE_LINEAR
);
400 tmp
= ureg_DECL_temporary(ureg
);
402 if (zs_mask
& PIPE_MASK_Z
) {
403 depth_sampler
= ureg_DECL_sampler(ureg
, 0);
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
);
410 ureg_load_tex(ureg
, ureg_writemask(tmp
, TGSI_WRITEMASK_X
), coord
,
411 depth_sampler
, tex_target
, load_level_zero
, use_txf
);
413 depth
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0);
414 ureg_MOV(ureg
, ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
415 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
418 if (zs_mask
& PIPE_MASK_S
) {
419 stencil_sampler
= ureg_DECL_sampler(ureg
, zs_mask
& PIPE_MASK_Z
? 1 : 0);
420 ureg_DECL_sampler_view(ureg
, zs_mask
& PIPE_MASK_Z
? 1 : 0, tex_target
,
421 TGSI_RETURN_TYPE_UINT
,
422 TGSI_RETURN_TYPE_UINT
,
423 TGSI_RETURN_TYPE_UINT
,
424 TGSI_RETURN_TYPE_UINT
);
426 ureg_load_tex(ureg
, ureg_writemask(tmp
, TGSI_WRITEMASK_X
), coord
,
427 stencil_sampler
, tex_target
, load_level_zero
, use_txf
);
429 stencil
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_STENCIL
, 0);
430 ureg_MOV(ureg
, ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
431 ureg_scalar(ureg_src(tmp
), TGSI_SWIZZLE_X
));
436 return ureg_create_shader_and_destroy(ureg
, pipe
);
441 * Make simple fragment color pass-through shader that replicates OUT[0]
442 * to all bound colorbuffers.
445 util_make_fragment_passthrough_shader(struct pipe_context
*pipe
,
447 int input_interpolate
,
448 boolean write_all_cbufs
)
450 static const char shader_templ
[] =
453 "DCL IN[0], %s[0], %s\n"
454 "DCL OUT[0], COLOR[0]\n"
456 "MOV OUT[0], IN[0]\n"
459 char text
[sizeof(shader_templ
)+100];
460 struct tgsi_token tokens
[1000];
461 struct pipe_shader_state state
= {0};
463 sprintf(text
, shader_templ
,
464 write_all_cbufs
? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
465 tgsi_semantic_names
[input_semantic
],
466 tgsi_interpolate_names
[input_interpolate
]);
468 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
472 pipe_shader_state_from_tgsi(&state
, tokens
);
474 tgsi_dump(state
.tokens
, 0);
477 return pipe
->create_fs_state(pipe
, &state
);
482 util_make_empty_fragment_shader(struct pipe_context
*pipe
)
484 struct ureg_program
*ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
489 return ureg_create_shader_and_destroy(ureg
, pipe
);
494 * Make a fragment shader that copies the input color to N output colors.
497 util_make_fragment_cloneinput_shader(struct pipe_context
*pipe
, int num_cbufs
,
499 int input_interpolate
)
501 struct ureg_program
*ureg
;
503 struct ureg_dst dst
[PIPE_MAX_COLOR_BUFS
];
506 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
508 ureg
= ureg_create( PIPE_SHADER_FRAGMENT
);
512 src
= ureg_DECL_fs_input( ureg
, input_semantic
, 0,
515 for (i
= 0; i
< num_cbufs
; i
++)
516 dst
[i
] = ureg_DECL_output( ureg
, TGSI_SEMANTIC_COLOR
, i
);
518 for (i
= 0; i
< num_cbufs
; i
++)
519 ureg_MOV( ureg
, dst
[i
], src
);
523 return ureg_create_shader_and_destroy( ureg
, pipe
);
528 util_make_fs_blit_msaa_gen(struct pipe_context
*pipe
,
529 enum tgsi_texture_type tgsi_tex
,
530 const char *samp_type
,
531 const char *output_semantic
,
532 const char *output_mask
,
533 const char *conversion_decl
,
534 const char *conversion
)
536 static const char shader_templ
[] =
538 "DCL IN[0], GENERIC[0], LINEAR\n"
540 "DCL SVIEW[0], %s, %s\n"
545 "F2U TEMP[0], IN[0]\n"
546 "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
548 "MOV OUT[0]%s, TEMP[0]\n"
551 const char *type
= tgsi_texture_names
[tgsi_tex
];
552 char text
[sizeof(shader_templ
)+100];
553 struct tgsi_token tokens
[1000];
554 struct pipe_shader_state state
= {0};
556 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
557 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
559 snprintf(text
, sizeof(text
), shader_templ
, type
, samp_type
,
560 output_semantic
, conversion_decl
, type
, conversion
, output_mask
);
562 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
567 pipe_shader_state_from_tgsi(&state
, tokens
);
569 tgsi_dump(state
.tokens
, 0);
572 return pipe
->create_fs_state(pipe
, &state
);
577 * Make a fragment shader that sets the output color to a color
578 * fetched from a multisample texture.
579 * \param tex_target one of PIPE_TEXTURE_x
582 util_make_fs_blit_msaa_color(struct pipe_context
*pipe
,
583 enum tgsi_texture_type tgsi_tex
,
584 enum tgsi_return_type stype
,
585 enum tgsi_return_type dtype
)
587 const char *samp_type
;
588 const char *conversion_decl
= "";
589 const char *conversion
= "";
591 if (stype
== TGSI_RETURN_TYPE_UINT
) {
594 if (dtype
== TGSI_RETURN_TYPE_SINT
) {
595 conversion_decl
= "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
596 conversion
= "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n";
598 } else if (stype
== TGSI_RETURN_TYPE_SINT
) {
601 if (dtype
== TGSI_RETURN_TYPE_UINT
) {
602 conversion_decl
= "IMM[0] INT32 {0, 0, 0, 0}\n";
603 conversion
= "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
606 assert(dtype
== TGSI_RETURN_TYPE_FLOAT
);
610 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, samp_type
,
611 "COLOR[0]", "", conversion_decl
,
617 * Make a fragment shader that sets the output depth to a depth value
618 * fetched from a multisample texture.
619 * \param tex_target one of PIPE_TEXTURE_x
622 util_make_fs_blit_msaa_depth(struct pipe_context
*pipe
,
623 enum tgsi_texture_type tgsi_tex
)
625 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "FLOAT",
626 "POSITION", ".z", "", "");
631 * Make a fragment shader that sets the output stencil to a stencil value
632 * fetched from a multisample texture.
633 * \param tex_target one of PIPE_TEXTURE_x
636 util_make_fs_blit_msaa_stencil(struct pipe_context
*pipe
,
637 enum tgsi_texture_type tgsi_tex
)
639 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
, "UINT",
640 "STENCIL", ".y", "", "");
645 * Make a fragment shader that sets the output depth and stencil to depth
646 * and stencil values fetched from two multisample textures / samplers.
647 * The sizes of both textures should match (it should be one depth-stencil
649 * \param tex_target one of PIPE_TEXTURE_x
652 util_make_fs_blit_msaa_depthstencil(struct pipe_context
*pipe
,
653 enum tgsi_texture_type tgsi_tex
)
655 static const char shader_templ
[] =
657 "DCL IN[0], GENERIC[0], LINEAR\n"
659 "DCL SVIEW[0], %s, FLOAT\n"
660 "DCL SVIEW[1], %s, UINT\n"
661 "DCL OUT[0], POSITION\n"
662 "DCL OUT[1], STENCIL\n"
665 "F2U TEMP[0], IN[0]\n"
666 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
667 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
670 const char *type
= tgsi_texture_names
[tgsi_tex
];
671 char text
[sizeof(shader_templ
)+100];
672 struct tgsi_token tokens
[1000];
673 struct pipe_shader_state state
= {0};
675 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
676 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
678 sprintf(text
, shader_templ
, type
, type
, type
, type
);
680 if (!tgsi_text_translate(text
, tokens
, ARRAY_SIZE(tokens
))) {
684 pipe_shader_state_from_tgsi(&state
, tokens
);
686 tgsi_dump(state
.tokens
, 0);
689 return pipe
->create_fs_state(pipe
, &state
);
694 util_make_fs_msaa_resolve(struct pipe_context
*pipe
,
695 enum tgsi_texture_type tgsi_tex
, unsigned nr_samples
,
696 enum tgsi_return_type stype
)
698 struct ureg_program
*ureg
;
699 struct ureg_src sampler
, coord
;
700 struct ureg_dst out
, tmp_sum
, tmp_coord
, tmp
;
703 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
708 sampler
= ureg_DECL_sampler(ureg
, 0);
709 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
710 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
711 TGSI_INTERPOLATE_LINEAR
);
712 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
713 tmp_sum
= ureg_DECL_temporary(ureg
);
714 tmp_coord
= ureg_DECL_temporary(ureg
);
715 tmp
= ureg_DECL_temporary(ureg
);
718 ureg_MOV(ureg
, tmp_sum
, ureg_imm1f(ureg
, 0));
719 ureg_F2U(ureg
, tmp_coord
, coord
);
721 for (i
= 0; i
< nr_samples
; i
++) {
722 /* Read one sample. */
723 ureg_MOV(ureg
, ureg_writemask(tmp_coord
, TGSI_WRITEMASK_W
),
724 ureg_imm1u(ureg
, i
));
725 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
), sampler
);
727 if (stype
== TGSI_RETURN_TYPE_UINT
)
728 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
729 else if (stype
== TGSI_RETURN_TYPE_SINT
)
730 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
732 /* Add it to the sum.*/
733 ureg_ADD(ureg
, tmp_sum
, ureg_src(tmp_sum
), ureg_src(tmp
));
736 /* Calculate the average and return. */
737 ureg_MUL(ureg
, tmp_sum
, ureg_src(tmp_sum
),
738 ureg_imm1f(ureg
, 1.0 / nr_samples
));
740 if (stype
== TGSI_RETURN_TYPE_UINT
)
741 ureg_F2U(ureg
, out
, ureg_src(tmp_sum
));
742 else if (stype
== TGSI_RETURN_TYPE_SINT
)
743 ureg_F2I(ureg
, out
, ureg_src(tmp_sum
));
745 ureg_MOV(ureg
, out
, ureg_src(tmp_sum
));
749 return ureg_create_shader_and_destroy(ureg
, pipe
);
754 util_make_fs_msaa_resolve_bilinear(struct pipe_context
*pipe
,
755 enum tgsi_texture_type tgsi_tex
,
757 enum tgsi_return_type stype
)
759 struct ureg_program
*ureg
;
760 struct ureg_src sampler
, coord
;
761 struct ureg_dst out
, tmp
, top
, bottom
;
762 struct ureg_dst tmp_coord
[4], tmp_sum
[4];
765 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
770 sampler
= ureg_DECL_sampler(ureg
, 0);
771 ureg_DECL_sampler_view(ureg
, 0, tgsi_tex
, stype
, stype
, stype
, stype
);
772 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
773 TGSI_INTERPOLATE_LINEAR
);
774 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
775 for (c
= 0; c
< 4; c
++)
776 tmp_sum
[c
] = ureg_DECL_temporary(ureg
);
777 for (c
= 0; c
< 4; c
++)
778 tmp_coord
[c
] = ureg_DECL_temporary(ureg
);
779 tmp
= ureg_DECL_temporary(ureg
);
780 top
= ureg_DECL_temporary(ureg
);
781 bottom
= ureg_DECL_temporary(ureg
);
784 for (c
= 0; c
< 4; c
++)
785 ureg_MOV(ureg
, tmp_sum
[c
], ureg_imm1f(ureg
, 0));
787 /* Get 4 texture coordinates for the bilinear filter. */
788 ureg_F2U(ureg
, tmp_coord
[0], coord
); /* top-left */
789 ureg_UADD(ureg
, tmp_coord
[1], ureg_src(tmp_coord
[0]),
790 ureg_imm4u(ureg
, 1, 0, 0, 0)); /* top-right */
791 ureg_UADD(ureg
, tmp_coord
[2], ureg_src(tmp_coord
[0]),
792 ureg_imm4u(ureg
, 0, 1, 0, 0)); /* bottom-left */
793 ureg_UADD(ureg
, tmp_coord
[3], ureg_src(tmp_coord
[0]),
794 ureg_imm4u(ureg
, 1, 1, 0, 0)); /* bottom-right */
796 for (i
= 0; i
< nr_samples
; i
++) {
797 for (c
= 0; c
< 4; c
++) {
798 /* Read one sample. */
799 ureg_MOV(ureg
, ureg_writemask(tmp_coord
[c
], TGSI_WRITEMASK_W
),
800 ureg_imm1u(ureg
, i
));
801 ureg_TXF(ureg
, tmp
, tgsi_tex
, ureg_src(tmp_coord
[c
]), sampler
);
803 if (stype
== TGSI_RETURN_TYPE_UINT
)
804 ureg_U2F(ureg
, tmp
, ureg_src(tmp
));
805 else if (stype
== TGSI_RETURN_TYPE_SINT
)
806 ureg_I2F(ureg
, tmp
, ureg_src(tmp
));
808 /* Add it to the sum.*/
809 ureg_ADD(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]), ureg_src(tmp
));
813 /* Calculate the average. */
814 for (c
= 0; c
< 4; c
++)
815 ureg_MUL(ureg
, tmp_sum
[c
], ureg_src(tmp_sum
[c
]),
816 ureg_imm1f(ureg
, 1.0 / nr_samples
));
818 /* Take the 4 average values and apply a standard bilinear filter. */
819 ureg_FRC(ureg
, tmp
, coord
);
822 ureg_scalar(ureg_src(tmp
), 0),
823 ureg_src(tmp_sum
[1]),
824 ureg_src(tmp_sum
[0]));
826 ureg_LRP(ureg
, bottom
,
827 ureg_scalar(ureg_src(tmp
), 0),
828 ureg_src(tmp_sum
[3]),
829 ureg_src(tmp_sum
[2]));
832 ureg_scalar(ureg_src(tmp
), 1),
836 /* Convert to the texture format and return. */
837 if (stype
== TGSI_RETURN_TYPE_UINT
)
838 ureg_F2U(ureg
, out
, ureg_src(tmp
));
839 else if (stype
== TGSI_RETURN_TYPE_SINT
)
840 ureg_F2I(ureg
, out
, ureg_src(tmp
));
842 ureg_MOV(ureg
, out
, ureg_src(tmp
));
846 return ureg_create_shader_and_destroy(ureg
, pipe
);
850 util_make_geometry_passthrough_shader(struct pipe_context
*pipe
,
852 const ubyte
*semantic_names
,
853 const ubyte
*semantic_indexes
)
855 static const unsigned zero
[4] = {0, 0, 0, 0};
857 struct ureg_program
*ureg
;
858 struct ureg_dst dst
[PIPE_MAX_SHADER_OUTPUTS
];
859 struct ureg_src src
[PIPE_MAX_SHADER_INPUTS
];
864 ureg
= ureg_create(PIPE_SHADER_GEOMETRY
);
868 ureg_property(ureg
, TGSI_PROPERTY_GS_INPUT_PRIM
, PIPE_PRIM_POINTS
);
869 ureg_property(ureg
, TGSI_PROPERTY_GS_OUTPUT_PRIM
, PIPE_PRIM_POINTS
);
870 ureg_property(ureg
, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES
, 1);
871 ureg_property(ureg
, TGSI_PROPERTY_GS_INVOCATIONS
, 1);
872 imm
= ureg_DECL_immediate_uint(ureg
, zero
, 4);
875 * Loop over all the attribs and declare the corresponding
876 * declarations in the geometry shader
878 for (i
= 0; i
< num_attribs
; i
++) {
879 src
[i
] = ureg_DECL_input(ureg
, semantic_names
[i
],
880 semantic_indexes
[i
], 0, 1);
881 src
[i
] = ureg_src_dimension(src
[i
], 0);
882 dst
[i
] = ureg_DECL_output(ureg
, semantic_names
[i
], semantic_indexes
[i
]);
885 /* MOV dst[i] src[i] */
886 for (i
= 0; i
< num_attribs
; i
++) {
887 ureg_MOV(ureg
, dst
[i
], src
[i
]);
891 ureg_insn(ureg
, TGSI_OPCODE_EMIT
, NULL
, 0, &imm
, 1, 0);
896 return ureg_create_shader_and_destroy(ureg
, pipe
);
901 * Blit from color to ZS or from ZS to color in a manner that is equivalent
904 * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24).
906 * Depth and stencil samplers are used to load depth and stencil,
907 * and they are packed and the result is written to a color output.
909 * A color sampler is used to load a color value, which is unpacked and
910 * written to depth and stencil shader outputs.
913 util_make_fs_pack_color_zs(struct pipe_context
*pipe
,
914 enum tgsi_texture_type tex_target
,
915 enum pipe_format zs_format
,
918 struct ureg_program
*ureg
;
919 struct ureg_src depth_sampler
, stencil_sampler
, color_sampler
, coord
;
920 struct ureg_dst out
, depth
, depth_x
, stencil
, out_depth
, out_stencil
, color
;
922 assert(zs_format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
|| /* color is R32_UINT */
923 zs_format
== PIPE_FORMAT_S8_UINT_Z24_UNORM
|| /* color is R32_UINT */
924 zs_format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
|| /* color is R32G32_UINT */
925 zs_format
== PIPE_FORMAT_Z24X8_UNORM
|| /* color is R32_UINT */
926 zs_format
== PIPE_FORMAT_X8Z24_UNORM
); /* color is R32_UINT */
928 bool has_stencil
= zs_format
!= PIPE_FORMAT_Z24X8_UNORM
&&
929 zs_format
!= PIPE_FORMAT_X8Z24_UNORM
;
930 bool is_z24
= zs_format
!= PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
;
931 bool z24_is_high
= zs_format
== PIPE_FORMAT_S8_UINT_Z24_UNORM
||
932 zs_format
== PIPE_FORMAT_X8Z24_UNORM
;
934 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
938 coord
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_GENERIC
, 0,
939 TGSI_INTERPOLATE_LINEAR
);
943 depth_sampler
= ureg_DECL_sampler(ureg
, 0);
944 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
945 TGSI_RETURN_TYPE_FLOAT
,
946 TGSI_RETURN_TYPE_FLOAT
,
947 TGSI_RETURN_TYPE_FLOAT
,
948 TGSI_RETURN_TYPE_FLOAT
);
950 depth
= ureg_DECL_temporary(ureg
);
951 depth_x
= ureg_writemask(depth
, TGSI_WRITEMASK_X
);
952 ureg_load_tex(ureg
, depth_x
, coord
, depth_sampler
, tex_target
, true, true);
956 double imm
= 0xffffff;
957 struct ureg_src imm_f64
= ureg_DECL_immediate_f64(ureg
, &imm
, 2);
958 struct ureg_dst tmp_xy
= ureg_writemask(ureg_DECL_temporary(ureg
),
961 ureg_F2D(ureg
, tmp_xy
, ureg_src(depth
));
962 ureg_DMUL(ureg
, tmp_xy
, ureg_src(tmp_xy
), imm_f64
);
963 ureg_D2U(ureg
, depth_x
, ureg_src(tmp_xy
));
966 ureg_SHL(ureg
, depth_x
, ureg_src(depth
), ureg_imm1u(ureg
, 8));
968 ureg_AND(ureg
, depth_x
, ureg_src(depth
), ureg_imm1u(ureg
, 0xffffff));
973 stencil_sampler
= ureg_DECL_sampler(ureg
, 1);
974 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
975 TGSI_RETURN_TYPE_UINT
,
976 TGSI_RETURN_TYPE_UINT
,
977 TGSI_RETURN_TYPE_UINT
,
978 TGSI_RETURN_TYPE_UINT
);
980 stencil
= ureg_writemask(ureg_DECL_temporary(ureg
), TGSI_WRITEMASK_X
);
981 ureg_load_tex(ureg
, stencil
, coord
, stencil_sampler
, tex_target
,
984 /* Pack stencil into depth. */
987 ureg_SHL(ureg
, stencil
, ureg_src(stencil
), ureg_imm1u(ureg
, 24));
989 ureg_OR(ureg
, depth_x
, ureg_src(depth
), ureg_src(stencil
));
993 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
996 ureg_MOV(ureg
, ureg_writemask(out
, TGSI_WRITEMASK_X
), ureg_src(depth
));
999 ureg_MOV(ureg
, ureg_writemask(depth
, TGSI_WRITEMASK_Y
),
1000 ureg_scalar(ureg_src(stencil
), TGSI_SWIZZLE_X
));
1001 ureg_MOV(ureg
, ureg_writemask(out
, TGSI_WRITEMASK_XY
), ureg_src(depth
));
1004 color_sampler
= ureg_DECL_sampler(ureg
, 0);
1005 ureg_DECL_sampler_view(ureg
, 0, tex_target
,
1006 TGSI_RETURN_TYPE_UINT
,
1007 TGSI_RETURN_TYPE_UINT
,
1008 TGSI_RETURN_TYPE_UINT
,
1009 TGSI_RETURN_TYPE_UINT
);
1011 color
= ureg_DECL_temporary(ureg
);
1012 ureg_load_tex(ureg
, color
, coord
, color_sampler
, tex_target
, true, true);
1014 depth
= ureg_writemask(ureg_DECL_temporary(ureg
), TGSI_WRITEMASK_X
);
1015 stencil
= ureg_writemask(ureg_DECL_temporary(ureg
), TGSI_WRITEMASK_X
);
1018 double imm
= 1.0 / 0xffffff;
1019 struct ureg_src imm_f64
= ureg_DECL_immediate_f64(ureg
, &imm
, 2);
1020 struct ureg_dst tmp_xy
= ureg_writemask(ureg_DECL_temporary(ureg
),
1023 ureg_UBFE(ureg
, depth
, ureg_src(color
),
1024 ureg_imm1u(ureg
, z24_is_high
? 8 : 0),
1025 ureg_imm1u(ureg
, 24));
1026 ureg_U2D(ureg
, tmp_xy
, ureg_src(depth
));
1027 ureg_DMUL(ureg
, tmp_xy
, ureg_src(tmp_xy
), imm_f64
);
1028 ureg_D2F(ureg
, depth
, ureg_src(tmp_xy
));
1030 /* depth = color.x; (Z32_S8X24) */
1031 ureg_MOV(ureg
, depth
, ureg_src(color
));
1034 out_depth
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0);
1035 ureg_MOV(ureg
, ureg_writemask(out_depth
, TGSI_WRITEMASK_Z
),
1036 ureg_scalar(ureg_src(depth
), TGSI_SWIZZLE_X
));
1040 ureg_UBFE(ureg
, stencil
, ureg_src(color
),
1041 ureg_imm1u(ureg
, z24_is_high
? 0 : 24),
1042 ureg_imm1u(ureg
, 8));
1044 /* stencil = color.y[0:7]; (Z32_S8X24) */
1045 ureg_UBFE(ureg
, stencil
,
1046 ureg_scalar(ureg_src(color
), TGSI_SWIZZLE_Y
),
1047 ureg_imm1u(ureg
, 0),
1048 ureg_imm1u(ureg
, 8));
1051 out_stencil
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_STENCIL
, 0);
1052 ureg_MOV(ureg
, ureg_writemask(out_stencil
, TGSI_WRITEMASK_Y
),
1053 ureg_scalar(ureg_src(stencil
), TGSI_SWIZZLE_X
));
1059 return ureg_create_shader_and_destroy(ureg
, pipe
);
1064 * Create passthrough tessellation control shader.
1065 * Passthrough tessellation control shader has output of vertex shader
1066 * as input and input of tessellation eval shader as output.
1069 util_make_tess_ctrl_passthrough_shader(struct pipe_context
*pipe
,
1070 uint num_vs_outputs
,
1071 uint num_tes_inputs
,
1072 const ubyte
*vs_semantic_names
,
1073 const ubyte
*vs_semantic_indexes
,
1074 const ubyte
*tes_semantic_names
,
1075 const ubyte
*tes_semantic_indexes
,
1076 const unsigned vertices_per_patch
)
1081 struct ureg_program
*ureg
;
1082 struct ureg_dst temp
, addr
;
1083 struct ureg_src invocationID
;
1084 struct ureg_dst dst
[PIPE_MAX_SHADER_OUTPUTS
];
1085 struct ureg_src src
[PIPE_MAX_SHADER_INPUTS
];
1087 ureg
= ureg_create(PIPE_SHADER_TESS_CTRL
);
1092 ureg_property(ureg
, TGSI_PROPERTY_TCS_VERTICES_OUT
, vertices_per_patch
);
1096 for (i
= 0; i
< num_tes_inputs
; i
++) {
1097 switch (tes_semantic_names
[i
]) {
1098 case TGSI_SEMANTIC_POSITION
:
1099 case TGSI_SEMANTIC_PSIZE
:
1100 case TGSI_SEMANTIC_COLOR
:
1101 case TGSI_SEMANTIC_BCOLOR
:
1102 case TGSI_SEMANTIC_CLIPDIST
:
1103 case TGSI_SEMANTIC_CLIPVERTEX
:
1104 case TGSI_SEMANTIC_TEXCOORD
:
1105 case TGSI_SEMANTIC_FOG
:
1106 case TGSI_SEMANTIC_GENERIC
:
1107 for (j
= 0; j
< num_vs_outputs
; j
++) {
1108 if (tes_semantic_names
[i
] == vs_semantic_names
[j
] &&
1109 tes_semantic_indexes
[i
] == vs_semantic_indexes
[j
]) {
1111 dst
[num_regs
] = ureg_DECL_output(ureg
,
1112 tes_semantic_names
[i
],
1113 tes_semantic_indexes
[i
]);
1114 src
[num_regs
] = ureg_DECL_input(ureg
, vs_semantic_names
[j
],
1115 vs_semantic_indexes
[j
],
1118 if (tes_semantic_names
[i
] == TGSI_SEMANTIC_GENERIC
||
1119 tes_semantic_names
[i
] == TGSI_SEMANTIC_POSITION
) {
1120 src
[num_regs
] = ureg_src_dimension(src
[num_regs
], 0);
1121 dst
[num_regs
] = ureg_dst_dimension(dst
[num_regs
], 0);
1134 dst
[num_regs
] = ureg_DECL_output(ureg
, TGSI_SEMANTIC_TESSOUTER
,
1136 src
[num_regs
] = ureg_DECL_constant(ureg
, 0);
1138 dst
[num_regs
] = ureg_DECL_output(ureg
, TGSI_SEMANTIC_TESSINNER
,
1140 src
[num_regs
] = ureg_DECL_constant(ureg
, 1);
1143 if (vertices_per_patch
> 1) {
1144 invocationID
= ureg_DECL_system_value(ureg
,
1145 TGSI_SEMANTIC_INVOCATIONID
, 0);
1146 temp
= ureg_DECL_local_temporary(ureg
);
1147 addr
= ureg_DECL_address(ureg
);
1148 ureg_UARL(ureg
, ureg_writemask(addr
, TGSI_WRITEMASK_X
),
1149 ureg_scalar(invocationID
, TGSI_SWIZZLE_X
));
1152 for (i
= 0; i
< num_regs
; i
++) {
1153 if (dst
[i
].Dimension
&& vertices_per_patch
> 1) {
1154 struct ureg_src addr_x
= ureg_scalar(ureg_src(addr
), TGSI_SWIZZLE_X
);
1155 ureg_MOV(ureg
, temp
, ureg_src_dimension_indirect(src
[i
],
1157 ureg_MOV(ureg
, ureg_dst_dimension_indirect(dst
[i
],
1158 addr_x
, 0), ureg_src(temp
));
1161 ureg_MOV(ureg
, dst
[i
], src
[i
]);
1166 return ureg_create_shader_and_destroy(ureg
, pipe
);