1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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
)
64 return util_make_vertex_passthrough_shader_with_so(pipe
, num_attribs
,
66 semantic_indexes
, NULL
);
70 util_make_vertex_passthrough_shader_with_so(struct pipe_context
*pipe
,
72 const uint
*semantic_names
,
73 const uint
*semantic_indexes
,
74 const struct pipe_stream_output_info
*so
)
76 struct ureg_program
*ureg
;
79 ureg
= ureg_create( TGSI_PROCESSOR_VERTEX
);
83 for (i
= 0; i
< num_attribs
; i
++) {
87 src
= ureg_DECL_vs_input( ureg
, i
);
89 dst
= ureg_DECL_output( ureg
,
93 ureg_MOV( ureg
, dst
, src
);
98 return ureg_create_shader_with_so_and_destroy( ureg
, pipe
, so
);
103 * Make simple fragment texture shader:
104 * IMM {0,0,0,1} // (if writemask != 0xf)
105 * MOV OUT[0], IMM[0] // (if writemask != 0xf)
106 * TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
109 * \param tex_target one of PIPE_TEXTURE_x
110 * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
111 * \param writemask mask of TGSI_WRITEMASK_x
114 util_make_fragment_tex_shader_writemask(struct pipe_context
*pipe
,
116 unsigned interp_mode
,
119 struct ureg_program
*ureg
;
120 struct ureg_src sampler
;
124 assert(interp_mode
== TGSI_INTERPOLATE_LINEAR
||
125 interp_mode
== TGSI_INTERPOLATE_PERSPECTIVE
);
127 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
131 sampler
= ureg_DECL_sampler( ureg
, 0 );
133 tex
= ureg_DECL_fs_input( ureg
,
134 TGSI_SEMANTIC_GENERIC
, 0,
137 out
= ureg_DECL_output( ureg
,
141 if (writemask
!= TGSI_WRITEMASK_XYZW
) {
142 struct ureg_src imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
144 ureg_MOV( ureg
, out
, imm
);
148 ureg_writemask(out
, writemask
),
149 tex_target
, tex
, sampler
);
152 return ureg_create_shader_and_destroy( ureg
, pipe
);
157 * Make a simple fragment shader that sets the output color to a color
158 * taken from a texture.
159 * \param tex_target one of PIPE_TEXTURE_x
162 util_make_fragment_tex_shader(struct pipe_context
*pipe
, unsigned tex_target
,
163 unsigned interp_mode
)
165 return util_make_fragment_tex_shader_writemask( pipe
,
168 TGSI_WRITEMASK_XYZW
);
173 * Make a simple fragment texture shader which reads an X component from
174 * a texture and writes it as depth.
177 util_make_fragment_tex_shader_writedepth(struct pipe_context
*pipe
,
179 unsigned interp_mode
)
181 struct ureg_program
*ureg
;
182 struct ureg_src sampler
;
184 struct ureg_dst out
, depth
;
187 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
191 sampler
= ureg_DECL_sampler( ureg
, 0 );
193 tex
= ureg_DECL_fs_input( ureg
,
194 TGSI_SEMANTIC_GENERIC
, 0,
197 out
= ureg_DECL_output( ureg
,
201 depth
= ureg_DECL_output( ureg
,
202 TGSI_SEMANTIC_POSITION
,
205 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
207 ureg_MOV( ureg
, out
, imm
);
210 ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
211 tex_target
, tex
, sampler
);
214 return ureg_create_shader_and_destroy( ureg
, pipe
);
219 * Make a simple fragment texture shader which reads the texture unit 0 and 1
220 * and writes it as depth and stencil, respectively.
223 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context
*pipe
,
225 unsigned interp_mode
)
227 struct ureg_program
*ureg
;
228 struct ureg_src depth_sampler
, stencil_sampler
;
230 struct ureg_dst out
, depth
, stencil
;
233 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
237 depth_sampler
= ureg_DECL_sampler( ureg
, 0 );
238 stencil_sampler
= ureg_DECL_sampler( ureg
, 1 );
240 tex
= ureg_DECL_fs_input( ureg
,
241 TGSI_SEMANTIC_GENERIC
, 0,
244 out
= ureg_DECL_output( ureg
,
248 depth
= ureg_DECL_output( ureg
,
249 TGSI_SEMANTIC_POSITION
,
252 stencil
= ureg_DECL_output( ureg
,
253 TGSI_SEMANTIC_STENCIL
,
256 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
258 ureg_MOV( ureg
, out
, imm
);
261 ureg_writemask(depth
, TGSI_WRITEMASK_Z
),
262 tex_target
, tex
, depth_sampler
);
264 ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
265 tex_target
, tex
, stencil_sampler
);
268 return ureg_create_shader_and_destroy( ureg
, pipe
);
273 * Make a simple fragment texture shader which reads a texture and writes it
277 util_make_fragment_tex_shader_writestencil(struct pipe_context
*pipe
,
279 unsigned interp_mode
)
281 struct ureg_program
*ureg
;
282 struct ureg_src stencil_sampler
;
284 struct ureg_dst out
, stencil
;
287 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
291 stencil_sampler
= ureg_DECL_sampler( ureg
, 0 );
293 tex
= ureg_DECL_fs_input( ureg
,
294 TGSI_SEMANTIC_GENERIC
, 0,
297 out
= ureg_DECL_output( ureg
,
301 stencil
= ureg_DECL_output( ureg
,
302 TGSI_SEMANTIC_STENCIL
,
305 imm
= ureg_imm4f( ureg
, 0, 0, 0, 1 );
307 ureg_MOV( ureg
, out
, imm
);
310 ureg_writemask(stencil
, TGSI_WRITEMASK_Y
),
311 tex_target
, tex
, stencil_sampler
);
314 return ureg_create_shader_and_destroy( ureg
, pipe
);
319 * Make simple fragment color pass-through shader that replicates OUT[0]
320 * to all bound colorbuffers.
323 util_make_fragment_passthrough_shader(struct pipe_context
*pipe
,
325 int input_interpolate
)
327 static const char shader_templ
[] =
329 "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
330 "DCL IN[0], %s[0], %s\n"
331 "DCL OUT[0], COLOR[0]\n"
333 "MOV OUT[0], IN[0]\n"
336 char text
[sizeof(shader_templ
)+100];
337 struct tgsi_token tokens
[1000];
338 struct pipe_shader_state state
= {tokens
};
340 sprintf(text
, shader_templ
, tgsi_semantic_names
[input_semantic
],
341 tgsi_interpolate_names
[input_interpolate
]);
343 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
348 tgsi_dump(state
.tokens
, 0);
351 return pipe
->create_fs_state(pipe
, &state
);
356 * Make a fragment shader that copies the input color to N output colors.
359 util_make_fragment_cloneinput_shader(struct pipe_context
*pipe
, int num_cbufs
,
361 int input_interpolate
)
363 struct ureg_program
*ureg
;
365 struct ureg_dst dst
[PIPE_MAX_COLOR_BUFS
];
368 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
370 ureg
= ureg_create( TGSI_PROCESSOR_FRAGMENT
);
374 src
= ureg_DECL_fs_input( ureg
, input_semantic
, 0,
377 for (i
= 0; i
< num_cbufs
; i
++)
378 dst
[i
] = ureg_DECL_output( ureg
, TGSI_SEMANTIC_COLOR
, i
);
380 for (i
= 0; i
< num_cbufs
; i
++)
381 ureg_MOV( ureg
, dst
[i
], src
);
385 return ureg_create_shader_and_destroy( ureg
, pipe
);
390 util_make_fs_blit_msaa_gen(struct pipe_context
*pipe
,
392 const char *output_semantic
,
393 const char *output_mask
)
395 static const char shader_templ
[] =
397 "DCL IN[0], GENERIC[0], LINEAR\n"
402 "F2U TEMP[0], IN[0]\n"
403 "TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n"
406 const char *type
= tgsi_texture_names
[tgsi_tex
];
407 char text
[sizeof(shader_templ
)+100];
408 struct tgsi_token tokens
[1000];
409 struct pipe_shader_state state
= {tokens
};
411 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
412 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
414 sprintf(text
, shader_templ
, output_semantic
, output_mask
, type
);
416 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
422 tgsi_dump(state
.tokens
, 0);
425 return pipe
->create_fs_state(pipe
, &state
);
430 * Make a fragment shader that sets the output color to a color
431 * fetched from a multisample texture.
432 * \param tex_target one of PIPE_TEXTURE_x
435 util_make_fs_blit_msaa_color(struct pipe_context
*pipe
,
438 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
,
444 * Make a fragment shader that sets the output depth to a depth value
445 * fetched from a multisample texture.
446 * \param tex_target one of PIPE_TEXTURE_x
449 util_make_fs_blit_msaa_depth(struct pipe_context
*pipe
,
452 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
,
458 * Make a fragment shader that sets the output stencil to a stencil value
459 * fetched from a multisample texture.
460 * \param tex_target one of PIPE_TEXTURE_x
463 util_make_fs_blit_msaa_stencil(struct pipe_context
*pipe
,
466 return util_make_fs_blit_msaa_gen(pipe
, tgsi_tex
,
472 * Make a fragment shader that sets the output depth and stencil to depth
473 * and stencil values fetched from two multisample textures / samplers.
474 * The sizes of both textures should match (it should be one depth-stencil
476 * \param tex_target one of PIPE_TEXTURE_x
479 util_make_fs_blit_msaa_depthstencil(struct pipe_context
*pipe
,
482 static const char shader_templ
[] =
484 "DCL IN[0], GENERIC[0], LINEAR\n"
486 "DCL OUT[0], POSITION\n"
487 "DCL OUT[1], STENCIL\n"
490 "F2U TEMP[0], IN[0]\n"
491 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
492 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
495 const char *type
= tgsi_texture_names
[tgsi_tex
];
496 char text
[sizeof(shader_templ
)+100];
497 struct tgsi_token tokens
[1000];
498 struct pipe_shader_state state
= {tokens
};
500 assert(tgsi_tex
== TGSI_TEXTURE_2D_MSAA
||
501 tgsi_tex
== TGSI_TEXTURE_2D_ARRAY_MSAA
);
503 sprintf(text
, shader_templ
, type
, type
);
505 if (!tgsi_text_translate(text
, tokens
, Elements(tokens
))) {
510 tgsi_dump(state
.tokens
, 0);
513 return pipe
->create_fs_state(pipe
, &state
);