u_simple_shaders.c revision bdaf0a085ba7b8af4cf858b31f701caf571b7c4f
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * Copyright 2009 Marek Olšák <maraeo@gmail.com> 6 * 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: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 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. 26 * 27 **************************************************************************/ 28 29/** 30 * @file 31 * Simple vertex/fragment shader generators. 32 * 33 * @author Brian Paul 34 Marek Olšák 35 */ 36 37 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 "tgsi/tgsi_ureg.h" 44 45 46 47/** 48 * Make simple vertex pass-through shader. 49 * \param num_attribs number of attributes to pass through 50 * \param semantic_names array of semantic names for each attribute 51 * \param semantic_indexes array of semantic indexes for each attribute 52 */ 53void * 54util_make_vertex_passthrough_shader(struct pipe_context *pipe, 55 uint num_attribs, 56 const uint *semantic_names, 57 const uint *semantic_indexes) 58{ 59 return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs, 60 semantic_names, 61 semantic_indexes, NULL); 62} 63 64void * 65util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, 66 uint num_attribs, 67 const uint *semantic_names, 68 const uint *semantic_indexes, 69 const struct pipe_stream_output_info *so) 70{ 71 struct ureg_program *ureg; 72 uint i; 73 74 ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); 75 if (ureg == NULL) 76 return NULL; 77 78 for (i = 0; i < num_attribs; i++) { 79 struct ureg_src src; 80 struct ureg_dst dst; 81 82 src = ureg_DECL_vs_input( ureg, i ); 83 84 dst = ureg_DECL_output( ureg, 85 semantic_names[i], 86 semantic_indexes[i]); 87 88 ureg_MOV( ureg, dst, src ); 89 } 90 91 ureg_END( ureg ); 92 93 return ureg_create_shader_with_so_and_destroy( ureg, pipe, so ); 94} 95 96 97/** 98 * Make simple fragment texture shader: 99 * IMM {0,0,0,1} // (if writemask != 0xf) 100 * MOV OUT[0], IMM[0] // (if writemask != 0xf) 101 * TEX OUT[0].writemask, IN[0], SAMP[0], 2D; 102 * END; 103 * 104 * \param tex_target one of PIPE_TEXTURE_x 105 * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE 106 * \param writemask mask of TGSI_WRITEMASK_x 107 */ 108void * 109util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, 110 unsigned tex_target, 111 unsigned interp_mode, 112 unsigned writemask ) 113{ 114 struct ureg_program *ureg; 115 struct ureg_src sampler; 116 struct ureg_src tex; 117 struct ureg_dst out; 118 119 assert(interp_mode == TGSI_INTERPOLATE_LINEAR || 120 interp_mode == TGSI_INTERPOLATE_PERSPECTIVE); 121 122 ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); 123 if (ureg == NULL) 124 return NULL; 125 126 sampler = ureg_DECL_sampler( ureg, 0 ); 127 128 tex = ureg_DECL_fs_input( ureg, 129 TGSI_SEMANTIC_GENERIC, 0, 130 interp_mode ); 131 132 out = ureg_DECL_output( ureg, 133 TGSI_SEMANTIC_COLOR, 134 0 ); 135 136 if (writemask != TGSI_WRITEMASK_XYZW) { 137 struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 138 139 ureg_MOV( ureg, out, imm ); 140 } 141 142 ureg_TEX( ureg, 143 ureg_writemask(out, writemask), 144 tex_target, tex, sampler ); 145 ureg_END( ureg ); 146 147 return ureg_create_shader_and_destroy( ureg, pipe ); 148} 149 150 151/** 152 * Make a simple fragment shader that sets the output color to a color 153 * taken from a texture. 154 * \param tex_target one of PIPE_TEXTURE_x 155 */ 156void * 157util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, 158 unsigned interp_mode) 159{ 160 return util_make_fragment_tex_shader_writemask( pipe, 161 tex_target, 162 interp_mode, 163 TGSI_WRITEMASK_XYZW ); 164} 165 166 167/** 168 * Make a simple fragment texture shader which reads an X component from 169 * a texture and writes it as depth. 170 */ 171void * 172util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, 173 unsigned tex_target, 174 unsigned interp_mode) 175{ 176 struct ureg_program *ureg; 177 struct ureg_src sampler; 178 struct ureg_src tex; 179 struct ureg_dst out, depth; 180 struct ureg_src imm; 181 182 ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); 183 if (ureg == NULL) 184 return NULL; 185 186 sampler = ureg_DECL_sampler( ureg, 0 ); 187 188 tex = ureg_DECL_fs_input( ureg, 189 TGSI_SEMANTIC_GENERIC, 0, 190 interp_mode ); 191 192 out = ureg_DECL_output( ureg, 193 TGSI_SEMANTIC_COLOR, 194 0 ); 195 196 depth = ureg_DECL_output( ureg, 197 TGSI_SEMANTIC_POSITION, 198 0 ); 199 200 imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 201 202 ureg_MOV( ureg, out, imm ); 203 204 ureg_TEX( ureg, 205 ureg_writemask(depth, TGSI_WRITEMASK_Z), 206 tex_target, tex, sampler ); 207 ureg_END( ureg ); 208 209 return ureg_create_shader_and_destroy( ureg, pipe ); 210} 211 212 213/** 214 * Make a simple fragment texture shader which reads the texture unit 0 and 1 215 * and writes it as depth and stencil, respectively. 216 */ 217void * 218util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe, 219 unsigned tex_target, 220 unsigned interp_mode) 221{ 222 struct ureg_program *ureg; 223 struct ureg_src depth_sampler, stencil_sampler; 224 struct ureg_src tex; 225 struct ureg_dst out, depth, stencil; 226 struct ureg_src imm; 227 228 ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); 229 if (ureg == NULL) 230 return NULL; 231 232 depth_sampler = ureg_DECL_sampler( ureg, 0 ); 233 stencil_sampler = ureg_DECL_sampler( ureg, 1 ); 234 235 tex = ureg_DECL_fs_input( ureg, 236 TGSI_SEMANTIC_GENERIC, 0, 237 interp_mode ); 238 239 out = ureg_DECL_output( ureg, 240 TGSI_SEMANTIC_COLOR, 241 0 ); 242 243 depth = ureg_DECL_output( ureg, 244 TGSI_SEMANTIC_POSITION, 245 0 ); 246 247 stencil = ureg_DECL_output( ureg, 248 TGSI_SEMANTIC_STENCIL, 249 0 ); 250 251 imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 252 253 ureg_MOV( ureg, out, imm ); 254 255 ureg_TEX( ureg, 256 ureg_writemask(depth, TGSI_WRITEMASK_Z), 257 tex_target, tex, depth_sampler ); 258 ureg_TEX( ureg, 259 ureg_writemask(stencil, TGSI_WRITEMASK_Y), 260 tex_target, tex, stencil_sampler ); 261 ureg_END( ureg ); 262 263 return ureg_create_shader_and_destroy( ureg, pipe ); 264} 265 266 267/** 268 * Make a simple fragment texture shader which reads a texture and writes it 269 * as stencil. 270 */ 271void * 272util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, 273 unsigned tex_target, 274 unsigned interp_mode) 275{ 276 struct ureg_program *ureg; 277 struct ureg_src stencil_sampler; 278 struct ureg_src tex; 279 struct ureg_dst out, stencil; 280 struct ureg_src imm; 281 282 ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); 283 if (ureg == NULL) 284 return NULL; 285 286 stencil_sampler = ureg_DECL_sampler( ureg, 0 ); 287 288 tex = ureg_DECL_fs_input( ureg, 289 TGSI_SEMANTIC_GENERIC, 0, 290 interp_mode ); 291 292 out = ureg_DECL_output( ureg, 293 TGSI_SEMANTIC_COLOR, 294 0 ); 295 296 stencil = ureg_DECL_output( ureg, 297 TGSI_SEMANTIC_STENCIL, 298 0 ); 299 300 imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 301 302 ureg_MOV( ureg, out, imm ); 303 304 ureg_TEX( ureg, 305 ureg_writemask(stencil, TGSI_WRITEMASK_Y), 306 tex_target, tex, stencil_sampler ); 307 ureg_END( ureg ); 308 309 return ureg_create_shader_and_destroy( ureg, pipe ); 310} 311 312 313/** 314 * Make simple fragment color pass-through shader. 315 */ 316void * 317util_make_fragment_passthrough_shader(struct pipe_context *pipe) 318{ 319 return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR, 320 TGSI_INTERPOLATE_PERSPECTIVE); 321} 322 323 324/** 325 * Make a fragment shader that copies the input color to N output colors. 326 */ 327void * 328util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, 329 int input_semantic, 330 int input_interpolate) 331{ 332 struct ureg_program *ureg; 333 struct ureg_src src; 334 struct ureg_dst dst[PIPE_MAX_COLOR_BUFS]; 335 int i; 336 337 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 338 339 ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); 340 if (ureg == NULL) 341 return NULL; 342 343 src = ureg_DECL_fs_input( ureg, input_semantic, 0, 344 input_interpolate ); 345 346 for (i = 0; i < num_cbufs; i++) 347 dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i ); 348 349 for (i = 0; i < num_cbufs; i++) 350 ureg_MOV( ureg, dst[i], src ); 351 352 ureg_END( ureg ); 353 354 return ureg_create_shader_and_destroy( ureg, pipe ); 355} 356