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,
531 const char *samp_type,
532 const char *output_semantic,
533 const char *output_mask,
534 const char *conversion_decl,
535 const char *conversion)
537 static const char shader_templ[] =
539 "DCL IN[0], GENERIC[0], LINEAR\n"
541 "DCL SVIEW[0], %s, %s\n"
547 "F2U TEMP[0], IN[0]\n"
549 "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
551 "MOV OUT[0]%s, TEMP[0]\n"
554 const char *type = tgsi_texture_names[tgsi_tex];
555 char text[sizeof(shader_templ)+400];
556 struct tgsi_token tokens[1000];
557 struct pipe_shader_state state = {0};
559 assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
560 tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
562 snprintf(text, sizeof(text), shader_templ, type, samp_type,
563 output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
564 conversion_decl, sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
565 type, conversion, output_mask);
567 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
572 pipe_shader_state_from_tgsi(&state, tokens);
574 tgsi_dump(state.tokens, 0);
577 return pipe->create_fs_state(pipe, &state);
582 * Make a fragment shader that sets the output color to a color
583 * fetched from a multisample texture.
584 * \param tex_target one of PIPE_TEXTURE_x
587 util_make_fs_blit_msaa_color(struct pipe_context *pipe,
588 enum tgsi_texture_type tgsi_tex,
589 enum tgsi_return_type stype,
590 enum tgsi_return_type dtype,
593 const char *samp_type;
594 const char *conversion_decl = "";
595 const char *conversion = "";
597 if (stype == TGSI_RETURN_TYPE_UINT) {
600 if (dtype == TGSI_RETURN_TYPE_SINT) {
601 conversion_decl = "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
602 conversion = "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n";
604 } else if (stype == TGSI_RETURN_TYPE_SINT) {
607 if (dtype == TGSI_RETURN_TYPE_UINT) {
608 conversion_decl = "IMM[0] INT32 {0, 0, 0, 0}\n";
609 conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
612 assert(dtype == TGSI_RETURN_TYPE_FLOAT);
616 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, samp_type,
617 "COLOR[0]", "", conversion_decl,
623 * Make a fragment shader that sets the output depth to a depth value
624 * fetched from a multisample texture.
625 * \param tex_target one of PIPE_TEXTURE_x
628 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
629 enum tgsi_texture_type tgsi_tex,
632 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "FLOAT",
633 "POSITION", ".z", "",
634 "MOV TEMP[0].z, TEMP[0].xxxx\n");
639 * Make a fragment shader that sets the output stencil to a stencil value
640 * fetched from a multisample texture.
641 * \param tex_target one of PIPE_TEXTURE_x
644 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
645 enum tgsi_texture_type tgsi_tex,
648 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "UINT",
650 "MOV TEMP[0].y, TEMP[0].xxxx\n");
655 * Make a fragment shader that sets the output depth and stencil to depth
656 * and stencil values fetched from two multisample textures / samplers.
657 * The sizes of both textures should match (it should be one depth-stencil
659 * \param tex_target one of PIPE_TEXTURE_x
662 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
663 enum tgsi_texture_type tgsi_tex,
666 static const char shader_templ[] =
668 "DCL IN[0], GENERIC[0], LINEAR\n"
670 "DCL SVIEW[0], %s, FLOAT\n"
671 "DCL SVIEW[1], %s, UINT\n"
672 "DCL OUT[0], POSITION\n"
673 "DCL OUT[1], STENCIL\n"
677 "F2U TEMP[0], IN[0]\n"
679 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
680 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
683 const char *type = tgsi_texture_names[tgsi_tex];
684 char text[sizeof(shader_templ)+400];
685 struct tgsi_token tokens[1000];
686 struct pipe_shader_state state = {0};
688 assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
689 tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
691 sprintf(text, shader_templ, type, type,
692 sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
693 sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
696 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
700 pipe_shader_state_from_tgsi(&state, tokens);
702 tgsi_dump(state.tokens, 0);
705 return pipe->create_fs_state(pipe, &state);
710 util_make_fs_msaa_resolve(struct pipe_context *pipe,
711 enum tgsi_texture_type tgsi_tex, unsigned nr_samples,
712 enum tgsi_return_type stype)
714 struct ureg_program *ureg;
715 struct ureg_src sampler, coord;
716 struct ureg_dst out, tmp_sum, tmp_coord, tmp;
719 ureg = ureg_create(PIPE_SHADER_FRAGMENT);
724 sampler = ureg_DECL_sampler(ureg, 0);
725 ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
726 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
727 TGSI_INTERPOLATE_LINEAR);
728 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
729 tmp_sum = ureg_DECL_temporary(ureg);
730 tmp_coord = ureg_DECL_temporary(ureg);
731 tmp = ureg_DECL_temporary(ureg);
734 ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
735 ureg_F2U(ureg, tmp_coord, coord);
737 for (i = 0; i < nr_samples; i++) {
738 /* Read one sample. */
739 ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W),
740 ureg_imm1u(ureg, i));
741 ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler);
743 if (stype == TGSI_RETURN_TYPE_UINT)
744 ureg_U2F(ureg, tmp, ureg_src(tmp));
745 else if (stype == TGSI_RETURN_TYPE_SINT)
746 ureg_I2F(ureg, tmp, ureg_src(tmp));
748 /* Add it to the sum.*/
749 ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp));
752 /* Calculate the average and return. */
753 ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum),
754 ureg_imm1f(ureg, 1.0 / nr_samples));
756 if (stype == TGSI_RETURN_TYPE_UINT)
757 ureg_F2U(ureg, out, ureg_src(tmp_sum));
758 else if (stype == TGSI_RETURN_TYPE_SINT)
759 ureg_F2I(ureg, out, ureg_src(tmp_sum));
761 ureg_MOV(ureg, out, ureg_src(tmp_sum));
765 return ureg_create_shader_and_destroy(ureg, pipe);
770 util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
771 enum tgsi_texture_type tgsi_tex,
773 enum tgsi_return_type stype)
775 struct ureg_program *ureg;
776 struct ureg_src sampler, coord;
777 struct ureg_dst out, tmp, top, bottom;
778 struct ureg_dst tmp_coord[4], tmp_sum[4];
781 ureg = ureg_create(PIPE_SHADER_FRAGMENT);
786 sampler = ureg_DECL_sampler(ureg, 0);
787 ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
788 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
789 TGSI_INTERPOLATE_LINEAR);
790 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
791 for (c = 0; c < 4; c++)
792 tmp_sum[c] = ureg_DECL_temporary(ureg);
793 for (c = 0; c < 4; c++)
794 tmp_coord[c] = ureg_DECL_temporary(ureg);
795 tmp = ureg_DECL_temporary(ureg);
796 top = ureg_DECL_temporary(ureg);
797 bottom = ureg_DECL_temporary(ureg);
800 for (c = 0; c < 4; c++)
801 ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
803 /* Get 4 texture coordinates for the bilinear filter. */
804 ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */
805 ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]),
806 ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */
807 ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]),
808 ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */
809 ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
810 ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
812 for (i = 0; i < nr_samples; i++) {
813 for (c = 0; c < 4; c++) {
814 /* Read one sample. */
815 ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W),
816 ureg_imm1u(ureg, i));
817 ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler);
819 if (stype == TGSI_RETURN_TYPE_UINT)
820 ureg_U2F(ureg, tmp, ureg_src(tmp));
821 else if (stype == TGSI_RETURN_TYPE_SINT)
822 ureg_I2F(ureg, tmp, ureg_src(tmp));
824 /* Add it to the sum.*/
825 ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp));
829 /* Calculate the average. */
830 for (c = 0; c < 4; c++)
831 ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]),
832 ureg_imm1f(ureg, 1.0 / nr_samples));
834 /* Take the 4 average values and apply a standard bilinear filter. */
835 ureg_FRC(ureg, tmp, coord);
838 ureg_scalar(ureg_src(tmp), 0),
839 ureg_src(tmp_sum[1]),
840 ureg_src(tmp_sum[0]));
842 ureg_LRP(ureg, bottom,
843 ureg_scalar(ureg_src(tmp), 0),
844 ureg_src(tmp_sum[3]),
845 ureg_src(tmp_sum[2]));
848 ureg_scalar(ureg_src(tmp), 1),
852 /* Convert to the texture format and return. */
853 if (stype == TGSI_RETURN_TYPE_UINT)
854 ureg_F2U(ureg, out, ureg_src(tmp));
855 else if (stype == TGSI_RETURN_TYPE_SINT)
856 ureg_F2I(ureg, out, ureg_src(tmp));
858 ureg_MOV(ureg, out, ureg_src(tmp));
862 return ureg_create_shader_and_destroy(ureg, pipe);
866 util_make_geometry_passthrough_shader(struct pipe_context *pipe,
868 const ubyte *semantic_names,
869 const ubyte *semantic_indexes)
871 static const unsigned zero[4] = {0, 0, 0, 0};
873 struct ureg_program *ureg;
874 struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
875 struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
880 ureg = ureg_create(PIPE_SHADER_GEOMETRY);
884 ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS);
885 ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS);
886 ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1);
887 ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1);
888 imm = ureg_DECL_immediate_uint(ureg, zero, 4);
891 * Loop over all the attribs and declare the corresponding
892 * declarations in the geometry shader
894 for (i = 0; i < num_attribs; i++) {
895 src[i] = ureg_DECL_input(ureg, semantic_names[i],
896 semantic_indexes[i], 0, 1);
897 src[i] = ureg_src_dimension(src[i], 0);
898 dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]);
901 /* MOV dst[i] src[i] */
902 for (i = 0; i < num_attribs; i++) {
903 ureg_MOV(ureg, dst[i], src[i]);
907 ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0);
912 return ureg_create_shader_and_destroy(ureg, pipe);
917 * Blit from color to ZS or from ZS to color in a manner that is equivalent
920 * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24).
922 * Depth and stencil samplers are used to load depth and stencil,
923 * and they are packed and the result is written to a color output.
925 * A color sampler is used to load a color value, which is unpacked and
926 * written to depth and stencil shader outputs.
929 util_make_fs_pack_color_zs(struct pipe_context *pipe,
930 enum tgsi_texture_type tex_target,
931 enum pipe_format zs_format,
934 struct ureg_program *ureg;
935 struct ureg_src depth_sampler, stencil_sampler, color_sampler, coord;
936 struct ureg_dst out, depth, depth_x, stencil, out_depth, out_stencil, color;
938 assert(zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT || /* color is R32_UINT */
939 zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || /* color is R32_UINT */
940 zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || /* color is R32G32_UINT */
941 zs_format == PIPE_FORMAT_Z24X8_UNORM || /* color is R32_UINT */
942 zs_format == PIPE_FORMAT_X8Z24_UNORM); /* color is R32_UINT */
944 bool has_stencil = zs_format != PIPE_FORMAT_Z24X8_UNORM &&
945 zs_format != PIPE_FORMAT_X8Z24_UNORM;
946 bool is_z24 = zs_format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT;
947 bool z24_is_high = zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
948 zs_format == PIPE_FORMAT_X8Z24_UNORM;
950 ureg = ureg_create(PIPE_SHADER_FRAGMENT);
954 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
955 TGSI_INTERPOLATE_LINEAR);
959 depth_sampler = ureg_DECL_sampler(ureg, 0);
960 ureg_DECL_sampler_view(ureg, 0, tex_target,
961 TGSI_RETURN_TYPE_FLOAT,
962 TGSI_RETURN_TYPE_FLOAT,
963 TGSI_RETURN_TYPE_FLOAT,
964 TGSI_RETURN_TYPE_FLOAT);
966 depth = ureg_DECL_temporary(ureg);
967 depth_x = ureg_writemask(depth, TGSI_WRITEMASK_X);
968 ureg_load_tex(ureg, depth_x, coord, depth_sampler, tex_target, true, true);
972 double imm = 0xffffff;
973 struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2);
974 struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg),
977 ureg_F2D(ureg, tmp_xy, ureg_src(depth));
978 ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64);
979 ureg_D2U(ureg, depth_x, ureg_src(tmp_xy));
982 ureg_SHL(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 8));
984 ureg_AND(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 0xffffff));
989 stencil_sampler = ureg_DECL_sampler(ureg, 1);
990 ureg_DECL_sampler_view(ureg, 0, tex_target,
991 TGSI_RETURN_TYPE_UINT,
992 TGSI_RETURN_TYPE_UINT,
993 TGSI_RETURN_TYPE_UINT,
994 TGSI_RETURN_TYPE_UINT);
996 stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
997 ureg_load_tex(ureg, stencil, coord, stencil_sampler, tex_target,
1000 /* Pack stencil into depth. */
1003 ureg_SHL(ureg, stencil, ureg_src(stencil), ureg_imm1u(ureg, 24));
1005 ureg_OR(ureg, depth_x, ureg_src(depth), ureg_src(stencil));
1009 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
1012 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_X), ureg_src(depth));
1015 ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Y),
1016 ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X));
1017 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_XY), ureg_src(depth));
1020 color_sampler = ureg_DECL_sampler(ureg, 0);
1021 ureg_DECL_sampler_view(ureg, 0, tex_target,
1022 TGSI_RETURN_TYPE_UINT,
1023 TGSI_RETURN_TYPE_UINT,
1024 TGSI_RETURN_TYPE_UINT,
1025 TGSI_RETURN_TYPE_UINT);
1027 color = ureg_DECL_temporary(ureg);
1028 ureg_load_tex(ureg, color, coord, color_sampler, tex_target, true, true);
1030 depth = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1031 stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1034 double imm = 1.0 / 0xffffff;
1035 struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2);
1036 struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg),
1039 ureg_UBFE(ureg, depth, ureg_src(color),
1040 ureg_imm1u(ureg, z24_is_high ? 8 : 0),
1041 ureg_imm1u(ureg, 24));
1042 ureg_U2D(ureg, tmp_xy, ureg_src(depth));
1043 ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64);
1044 ureg_D2F(ureg, depth, ureg_src(tmp_xy));
1046 /* depth = color.x; (Z32_S8X24) */
1047 ureg_MOV(ureg, depth, ureg_src(color));
1050 out_depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
1051 ureg_MOV(ureg, ureg_writemask(out_depth, TGSI_WRITEMASK_Z),
1052 ureg_scalar(ureg_src(depth), TGSI_SWIZZLE_X));
1056 ureg_UBFE(ureg, stencil, ureg_src(color),
1057 ureg_imm1u(ureg, z24_is_high ? 0 : 24),
1058 ureg_imm1u(ureg, 8));
1060 /* stencil = color.y[0:7]; (Z32_S8X24) */
1061 ureg_UBFE(ureg, stencil,
1062 ureg_scalar(ureg_src(color), TGSI_SWIZZLE_Y),
1063 ureg_imm1u(ureg, 0),
1064 ureg_imm1u(ureg, 8));
1067 out_stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0);
1068 ureg_MOV(ureg, ureg_writemask(out_stencil, TGSI_WRITEMASK_Y),
1069 ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X));
1075 return ureg_create_shader_and_destroy(ureg, pipe);
1080 * Create passthrough tessellation control shader.
1081 * Passthrough tessellation control shader has output of vertex shader
1082 * as input and input of tessellation eval shader as output.
1085 util_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe,
1086 uint num_vs_outputs,
1087 uint num_tes_inputs,
1088 const ubyte *vs_semantic_names,
1089 const ubyte *vs_semantic_indexes,
1090 const ubyte *tes_semantic_names,
1091 const ubyte *tes_semantic_indexes,
1092 const unsigned vertices_per_patch)
1097 struct ureg_program *ureg;
1098 struct ureg_dst temp, addr;
1099 struct ureg_src invocationID;
1100 struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
1101 struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
1103 ureg = ureg_create(PIPE_SHADER_TESS_CTRL);
1108 ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, vertices_per_patch);
1112 for (i = 0; i < num_tes_inputs; i++) {
1113 switch (tes_semantic_names[i]) {
1114 case TGSI_SEMANTIC_POSITION:
1115 case TGSI_SEMANTIC_PSIZE:
1116 case TGSI_SEMANTIC_COLOR:
1117 case TGSI_SEMANTIC_BCOLOR:
1118 case TGSI_SEMANTIC_CLIPDIST:
1119 case TGSI_SEMANTIC_CLIPVERTEX:
1120 case TGSI_SEMANTIC_TEXCOORD:
1121 case TGSI_SEMANTIC_FOG:
1122 case TGSI_SEMANTIC_GENERIC:
1123 for (j = 0; j < num_vs_outputs; j++) {
1124 if (tes_semantic_names[i] == vs_semantic_names[j] &&
1125 tes_semantic_indexes[i] == vs_semantic_indexes[j]) {
1127 dst[num_regs] = ureg_DECL_output(ureg,
1128 tes_semantic_names[i],
1129 tes_semantic_indexes[i]);
1130 src[num_regs] = ureg_DECL_input(ureg, vs_semantic_names[j],
1131 vs_semantic_indexes[j],
1134 if (tes_semantic_names[i] == TGSI_SEMANTIC_GENERIC ||
1135 tes_semantic_names[i] == TGSI_SEMANTIC_POSITION) {
1136 src[num_regs] = ureg_src_dimension(src[num_regs], 0);
1137 dst[num_regs] = ureg_dst_dimension(dst[num_regs], 0);
1150 dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSOUTER,
1152 src[num_regs] = ureg_DECL_constant(ureg, 0);
1154 dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSINNER,
1156 src[num_regs] = ureg_DECL_constant(ureg, 1);
1159 if (vertices_per_patch > 1) {
1160 invocationID = ureg_DECL_system_value(ureg,
1161 TGSI_SEMANTIC_INVOCATIONID, 0);
1162 temp = ureg_DECL_local_temporary(ureg);
1163 addr = ureg_DECL_address(ureg);
1164 ureg_UARL(ureg, ureg_writemask(addr, TGSI_WRITEMASK_X),
1165 ureg_scalar(invocationID, TGSI_SWIZZLE_X));
1168 for (i = 0; i < num_regs; i++) {
1169 if (dst[i].Dimension && vertices_per_patch > 1) {
1170 struct ureg_src addr_x = ureg_scalar(ureg_src(addr), TGSI_SWIZZLE_X);
1171 ureg_MOV(ureg, temp, ureg_src_dimension_indirect(src[i],
1173 ureg_MOV(ureg, ureg_dst_dimension_indirect(dst[i],
1174 addr_x, 0), ureg_src(temp));
1177 ureg_MOV(ureg, dst[i], src[i]);
1182 return ureg_create_shader_and_destroy(ureg, pipe);
1186 util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src)
1188 static const char shader_templ[] =
1190 "DCL IN[0], GENERIC[0], LINEAR\n"
1192 "DCL SVIEW[0], 2D, UINT\n"
1196 "F2U TEMP[0], IN[0]\n"
1197 "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
1198 "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
1199 "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
1200 "U2F TEMP[0].x, TEMP[0]\n"
1201 "KILL_IF -TEMP[0].xxxx\n"
1204 char text[sizeof(shader_templ)+100];
1205 struct tgsi_token tokens[1000];
1206 struct pipe_shader_state state = { 0 };
1208 enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA :
1211 sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex]);
1213 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
1218 pipe_shader_state_from_tgsi(&state, tokens);
1220 return pipe->create_fs_state(pipe, &state);