1 /************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * All Rights Reserved. 5 * Copyright 2009 Marek Olk <maraeo (at) 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 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. 26 * 27 **************************************************************************/ 28 29 /** 30 * @file 31 * Simple vertex/fragment shader generators. 32 * 33 * @author Brian Paul 34 Marek Olk 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 "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 */ 50 51 52 53 /** 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 58 */ 59 void * 60 util_make_vertex_passthrough_shader(struct pipe_context *pipe, 61 uint num_attribs, 62 const uint *semantic_names, 63 const uint *semantic_indexes, 64 bool window_space) 65 { 66 return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs, 67 semantic_names, 68 semantic_indexes, 69 window_space, NULL); 70 } 71 72 void * 73 util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, 74 uint num_attribs, 75 const uint *semantic_names, 76 const uint *semantic_indexes, 77 bool window_space, 78 const struct pipe_stream_output_info *so) 79 { 80 struct ureg_program *ureg; 81 uint i; 82 83 ureg = ureg_create( PIPE_SHADER_VERTEX ); 84 if (!ureg) 85 return NULL; 86 87 if (window_space) 88 ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); 89 90 for (i = 0; i < num_attribs; i++) { 91 struct ureg_src src; 92 struct ureg_dst dst; 93 94 src = ureg_DECL_vs_input( ureg, i ); 95 96 dst = ureg_DECL_output( ureg, 97 semantic_names[i], 98 semantic_indexes[i]); 99 100 ureg_MOV( ureg, dst, src ); 101 } 102 103 ureg_END( ureg ); 104 105 return ureg_create_shader_with_so_and_destroy( ureg, pipe, so ); 106 } 107 108 109 void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe) 110 { 111 static const char text[] = 112 "VERT\n" 113 "DCL IN[0]\n" 114 "DCL IN[1]\n" 115 "DCL SV[0], INSTANCEID\n" 116 "DCL OUT[0], POSITION\n" 117 "DCL OUT[1], GENERIC[0]\n" 118 "DCL OUT[2], LAYER\n" 119 120 "MOV OUT[0], IN[0]\n" 121 "MOV OUT[1], IN[1]\n" 122 "MOV OUT[2], SV[0]\n" 123 "END\n"; 124 struct tgsi_token tokens[1000]; 125 struct pipe_shader_state state; 126 127 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 128 assert(0); 129 return NULL; 130 } 131 pipe_shader_state_from_tgsi(&state, tokens); 132 return pipe->create_vs_state(pipe, &state); 133 } 134 135 /** 136 * Takes position and color, and outputs position, color, and instance id. 137 */ 138 void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe) 139 { 140 static const char text[] = 141 "VERT\n" 142 "DCL IN[0]\n" 143 "DCL IN[1]\n" 144 "DCL SV[0], INSTANCEID\n" 145 "DCL OUT[0], POSITION\n" 146 "DCL OUT[1], GENERIC[0]\n" 147 "DCL OUT[2], GENERIC[1]\n" 148 149 "MOV OUT[0], IN[0]\n" 150 "MOV OUT[1], IN[1]\n" 151 "MOV OUT[2].x, SV[0].xxxx\n" 152 "END\n"; 153 struct tgsi_token tokens[1000]; 154 struct pipe_shader_state state; 155 156 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 157 assert(0); 158 return NULL; 159 } 160 pipe_shader_state_from_tgsi(&state, tokens); 161 return pipe->create_vs_state(pipe, &state); 162 } 163 164 /** 165 * Takes position, color, and target layer, and emits vertices on that target 166 * layer, with the specified color. 167 */ 168 void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe) 169 { 170 static const char text[] = 171 "GEOM\n" 172 "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n" 173 "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n" 174 "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n" 175 "PROPERTY GS_INVOCATIONS 1\n" 176 "DCL IN[][0], POSITION\n" /* position */ 177 "DCL IN[][1], GENERIC[0]\n" /* color */ 178 "DCL IN[][2], GENERIC[1]\n" /* vs invocation */ 179 "DCL OUT[0], POSITION\n" 180 "DCL OUT[1], GENERIC[0]\n" 181 "DCL OUT[2], LAYER\n" 182 "IMM[0] INT32 {0, 0, 0, 0}\n" 183 184 "MOV OUT[0], IN[0][0]\n" 185 "MOV OUT[1], IN[0][1]\n" 186 "MOV OUT[2].x, IN[0][2].xxxx\n" 187 "EMIT IMM[0].xxxx\n" 188 "MOV OUT[0], IN[1][0]\n" 189 "MOV OUT[1], IN[1][1]\n" 190 "MOV OUT[2].x, IN[1][2].xxxx\n" 191 "EMIT IMM[0].xxxx\n" 192 "MOV OUT[0], IN[2][0]\n" 193 "MOV OUT[1], IN[2][1]\n" 194 "MOV OUT[2].x, IN[2][2].xxxx\n" 195 "EMIT IMM[0].xxxx\n" 196 "END\n"; 197 struct tgsi_token tokens[1000]; 198 struct pipe_shader_state state; 199 200 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 201 assert(0); 202 return NULL; 203 } 204 pipe_shader_state_from_tgsi(&state, tokens); 205 return pipe->create_gs_state(pipe, &state); 206 } 207 208 /** 209 * Make simple fragment texture shader: 210 * IMM {0,0,0,1} // (if writemask != 0xf) 211 * MOV TEMP[0], IMM[0] // (if writemask != 0xf) 212 * TEX TEMP[0].writemask, IN[0], SAMP[0], 2D; 213 * .. optional SINT <-> UINT clamping .. 214 * MOV OUT[0], TEMP[0] 215 * END; 216 * 217 * \param tex_target one of PIPE_TEXTURE_x 218 * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE 219 * \param writemask mask of TGSI_WRITEMASK_x 220 */ 221 void * 222 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, 223 unsigned tex_target, 224 unsigned interp_mode, 225 unsigned writemask, 226 enum tgsi_return_type stype, 227 enum tgsi_return_type dtype) 228 { 229 struct ureg_program *ureg; 230 struct ureg_src sampler; 231 struct ureg_src tex; 232 struct ureg_dst temp; 233 struct ureg_dst out; 234 235 assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT)); 236 assert(interp_mode == TGSI_INTERPOLATE_LINEAR || 237 interp_mode == TGSI_INTERPOLATE_PERSPECTIVE); 238 239 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 240 if (!ureg) 241 return NULL; 242 243 sampler = ureg_DECL_sampler( ureg, 0 ); 244 245 ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype); 246 247 tex = ureg_DECL_fs_input( ureg, 248 TGSI_SEMANTIC_GENERIC, 0, 249 interp_mode ); 250 251 out = ureg_DECL_output( ureg, 252 TGSI_SEMANTIC_COLOR, 253 0 ); 254 255 temp = ureg_DECL_temporary(ureg); 256 257 if (writemask != TGSI_WRITEMASK_XYZW) { 258 struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 259 260 ureg_MOV( ureg, out, imm ); 261 } 262 263 if (tex_target == TGSI_TEXTURE_BUFFER) 264 ureg_TXF(ureg, 265 ureg_writemask(temp, writemask), 266 tex_target, tex, sampler); 267 else 268 ureg_TEX(ureg, 269 ureg_writemask(temp, writemask), 270 tex_target, tex, sampler); 271 272 if (stype != dtype) { 273 if (stype == TGSI_RETURN_TYPE_SINT) { 274 assert(dtype == TGSI_RETURN_TYPE_UINT); 275 276 ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0)); 277 } else { 278 assert(stype == TGSI_RETURN_TYPE_UINT); 279 assert(dtype == TGSI_RETURN_TYPE_SINT); 280 281 ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1)); 282 } 283 } 284 285 ureg_MOV(ureg, out, ureg_src(temp)); 286 287 ureg_END( ureg ); 288 289 return ureg_create_shader_and_destroy( ureg, pipe ); 290 } 291 292 293 /** 294 * Make a simple fragment shader that sets the output color to a color 295 * taken from a texture. 296 * \param tex_target one of PIPE_TEXTURE_x 297 */ 298 void * 299 util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, 300 unsigned interp_mode, 301 enum tgsi_return_type stype, 302 enum tgsi_return_type dtype) 303 { 304 return util_make_fragment_tex_shader_writemask( pipe, 305 tex_target, 306 interp_mode, 307 TGSI_WRITEMASK_XYZW, 308 stype, dtype ); 309 } 310 311 312 /** 313 * Make a simple fragment texture shader which reads an X component from 314 * a texture and writes it as depth. 315 */ 316 void * 317 util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, 318 unsigned tex_target, 319 unsigned interp_mode) 320 { 321 struct ureg_program *ureg; 322 struct ureg_src sampler; 323 struct ureg_src tex; 324 struct ureg_dst out, depth; 325 struct ureg_src imm; 326 327 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 328 if (!ureg) 329 return NULL; 330 331 sampler = ureg_DECL_sampler( ureg, 0 ); 332 333 ureg_DECL_sampler_view(ureg, 0, tex_target, 334 TGSI_RETURN_TYPE_FLOAT, 335 TGSI_RETURN_TYPE_FLOAT, 336 TGSI_RETURN_TYPE_FLOAT, 337 TGSI_RETURN_TYPE_FLOAT); 338 339 tex = ureg_DECL_fs_input( ureg, 340 TGSI_SEMANTIC_GENERIC, 0, 341 interp_mode ); 342 343 out = ureg_DECL_output( ureg, 344 TGSI_SEMANTIC_COLOR, 345 0 ); 346 347 depth = ureg_DECL_output( ureg, 348 TGSI_SEMANTIC_POSITION, 349 0 ); 350 351 imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 352 353 ureg_MOV( ureg, out, imm ); 354 355 ureg_TEX( ureg, 356 ureg_writemask(depth, TGSI_WRITEMASK_Z), 357 tex_target, tex, sampler ); 358 ureg_END( ureg ); 359 360 return ureg_create_shader_and_destroy( ureg, pipe ); 361 } 362 363 364 /** 365 * Make a simple fragment texture shader which reads the texture unit 0 and 1 366 * and writes it as depth and stencil, respectively. 367 */ 368 void * 369 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe, 370 unsigned tex_target, 371 unsigned interp_mode) 372 { 373 struct ureg_program *ureg; 374 struct ureg_src depth_sampler, stencil_sampler; 375 struct ureg_src tex; 376 struct ureg_dst out, depth, stencil; 377 struct ureg_src imm; 378 379 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 380 if (!ureg) 381 return NULL; 382 383 depth_sampler = ureg_DECL_sampler( ureg, 0 ); 384 ureg_DECL_sampler_view(ureg, 0, tex_target, 385 TGSI_RETURN_TYPE_FLOAT, 386 TGSI_RETURN_TYPE_FLOAT, 387 TGSI_RETURN_TYPE_FLOAT, 388 TGSI_RETURN_TYPE_FLOAT); 389 stencil_sampler = ureg_DECL_sampler( ureg, 1 ); 390 ureg_DECL_sampler_view(ureg, 0, tex_target, 391 TGSI_RETURN_TYPE_UINT, 392 TGSI_RETURN_TYPE_UINT, 393 TGSI_RETURN_TYPE_UINT, 394 TGSI_RETURN_TYPE_UINT); 395 396 tex = ureg_DECL_fs_input( ureg, 397 TGSI_SEMANTIC_GENERIC, 0, 398 interp_mode ); 399 400 out = ureg_DECL_output( ureg, 401 TGSI_SEMANTIC_COLOR, 402 0 ); 403 404 depth = ureg_DECL_output( ureg, 405 TGSI_SEMANTIC_POSITION, 406 0 ); 407 408 stencil = ureg_DECL_output( ureg, 409 TGSI_SEMANTIC_STENCIL, 410 0 ); 411 412 imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 413 414 ureg_MOV( ureg, out, imm ); 415 416 ureg_TEX( ureg, 417 ureg_writemask(depth, TGSI_WRITEMASK_Z), 418 tex_target, tex, depth_sampler ); 419 ureg_TEX( ureg, 420 ureg_writemask(stencil, TGSI_WRITEMASK_Y), 421 tex_target, tex, stencil_sampler ); 422 ureg_END( ureg ); 423 424 return ureg_create_shader_and_destroy( ureg, pipe ); 425 } 426 427 428 /** 429 * Make a simple fragment texture shader which reads a texture and writes it 430 * as stencil. 431 */ 432 void * 433 util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, 434 unsigned tex_target, 435 unsigned interp_mode) 436 { 437 struct ureg_program *ureg; 438 struct ureg_src stencil_sampler; 439 struct ureg_src tex; 440 struct ureg_dst out, stencil; 441 struct ureg_src imm; 442 443 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 444 if (!ureg) 445 return NULL; 446 447 stencil_sampler = ureg_DECL_sampler( ureg, 0 ); 448 449 ureg_DECL_sampler_view(ureg, 0, tex_target, 450 TGSI_RETURN_TYPE_UINT, 451 TGSI_RETURN_TYPE_UINT, 452 TGSI_RETURN_TYPE_UINT, 453 TGSI_RETURN_TYPE_UINT); 454 455 tex = ureg_DECL_fs_input( ureg, 456 TGSI_SEMANTIC_GENERIC, 0, 457 interp_mode ); 458 459 out = ureg_DECL_output( ureg, 460 TGSI_SEMANTIC_COLOR, 461 0 ); 462 463 stencil = ureg_DECL_output( ureg, 464 TGSI_SEMANTIC_STENCIL, 465 0 ); 466 467 imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 468 469 ureg_MOV( ureg, out, imm ); 470 471 ureg_TEX( ureg, 472 ureg_writemask(stencil, TGSI_WRITEMASK_Y), 473 tex_target, tex, stencil_sampler ); 474 ureg_END( ureg ); 475 476 return ureg_create_shader_and_destroy( ureg, pipe ); 477 } 478 479 480 /** 481 * Make simple fragment color pass-through shader that replicates OUT[0] 482 * to all bound colorbuffers. 483 */ 484 void * 485 util_make_fragment_passthrough_shader(struct pipe_context *pipe, 486 int input_semantic, 487 int input_interpolate, 488 boolean write_all_cbufs) 489 { 490 static const char shader_templ[] = 491 "FRAG\n" 492 "%s" 493 "DCL IN[0], %s[0], %s\n" 494 "DCL OUT[0], COLOR[0]\n" 495 496 "MOV OUT[0], IN[0]\n" 497 "END\n"; 498 499 char text[sizeof(shader_templ)+100]; 500 struct tgsi_token tokens[1000]; 501 struct pipe_shader_state state; 502 503 sprintf(text, shader_templ, 504 write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "", 505 tgsi_semantic_names[input_semantic], 506 tgsi_interpolate_names[input_interpolate]); 507 508 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 509 assert(0); 510 return NULL; 511 } 512 pipe_shader_state_from_tgsi(&state, tokens); 513 #if 0 514 tgsi_dump(state.tokens, 0); 515 #endif 516 517 return pipe->create_fs_state(pipe, &state); 518 } 519 520 521 void * 522 util_make_empty_fragment_shader(struct pipe_context *pipe) 523 { 524 struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT); 525 if (!ureg) 526 return NULL; 527 528 ureg_END(ureg); 529 return ureg_create_shader_and_destroy(ureg, pipe); 530 } 531 532 533 /** 534 * Make a fragment shader that copies the input color to N output colors. 535 */ 536 void * 537 util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, 538 int input_semantic, 539 int input_interpolate) 540 { 541 struct ureg_program *ureg; 542 struct ureg_src src; 543 struct ureg_dst dst[PIPE_MAX_COLOR_BUFS]; 544 int i; 545 546 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 547 548 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 549 if (!ureg) 550 return NULL; 551 552 src = ureg_DECL_fs_input( ureg, input_semantic, 0, 553 input_interpolate ); 554 555 for (i = 0; i < num_cbufs; i++) 556 dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i ); 557 558 for (i = 0; i < num_cbufs; i++) 559 ureg_MOV( ureg, dst[i], src ); 560 561 ureg_END( ureg ); 562 563 return ureg_create_shader_and_destroy( ureg, pipe ); 564 } 565 566 567 static void * 568 util_make_fs_blit_msaa_gen(struct pipe_context *pipe, 569 unsigned tgsi_tex, 570 const char *samp_type, 571 const char *output_semantic, 572 const char *output_mask, 573 const char *conversion_decl, 574 const char *conversion) 575 { 576 static const char shader_templ[] = 577 "FRAG\n" 578 "DCL IN[0], GENERIC[0], LINEAR\n" 579 "DCL SAMP[0]\n" 580 "DCL SVIEW[0], %s, %s\n" 581 "DCL OUT[0], %s\n" 582 "DCL TEMP[0]\n" 583 "%s" 584 585 "F2U TEMP[0], IN[0]\n" 586 "TXF TEMP[0], TEMP[0], SAMP[0], %s\n" 587 "%s" 588 "MOV OUT[0]%s, TEMP[0]\n" 589 "END\n"; 590 591 const char *type = tgsi_texture_names[tgsi_tex]; 592 char text[sizeof(shader_templ)+100]; 593 struct tgsi_token tokens[1000]; 594 struct pipe_shader_state state; 595 596 assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || 597 tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); 598 599 util_snprintf(text, sizeof(text), shader_templ, type, samp_type, 600 output_semantic, conversion_decl, type, conversion, output_mask); 601 602 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 603 puts(text); 604 assert(0); 605 return NULL; 606 } 607 pipe_shader_state_from_tgsi(&state, tokens); 608 #if 0 609 tgsi_dump(state.tokens, 0); 610 #endif 611 612 return pipe->create_fs_state(pipe, &state); 613 } 614 615 616 /** 617 * Make a fragment shader that sets the output color to a color 618 * fetched from a multisample texture. 619 * \param tex_target one of PIPE_TEXTURE_x 620 */ 621 void * 622 util_make_fs_blit_msaa_color(struct pipe_context *pipe, 623 unsigned tgsi_tex, 624 enum tgsi_return_type stype, 625 enum tgsi_return_type dtype) 626 { 627 const char *samp_type; 628 const char *conversion_decl = ""; 629 const char *conversion = ""; 630 631 if (stype == TGSI_RETURN_TYPE_UINT) { 632 samp_type = "UINT"; 633 634 if (dtype == TGSI_RETURN_TYPE_SINT) { 635 conversion_decl = "IMM[0] UINT32 {2147483647, 0, 0, 0}\n"; 636 conversion = "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n"; 637 } 638 } else if (stype == TGSI_RETURN_TYPE_SINT) { 639 samp_type = "SINT"; 640 641 if (dtype == TGSI_RETURN_TYPE_UINT) { 642 conversion_decl = "IMM[0] INT32 {0, 0, 0, 0}\n"; 643 conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n"; 644 } 645 } else { 646 assert(dtype == TGSI_RETURN_TYPE_FLOAT); 647 samp_type = "FLOAT"; 648 } 649 650 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, samp_type, 651 "COLOR[0]", "", conversion_decl, 652 conversion); 653 } 654 655 656 /** 657 * Make a fragment shader that sets the output depth to a depth value 658 * fetched from a multisample texture. 659 * \param tex_target one of PIPE_TEXTURE_x 660 */ 661 void * 662 util_make_fs_blit_msaa_depth(struct pipe_context *pipe, 663 unsigned tgsi_tex) 664 { 665 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "FLOAT", 666 "POSITION", ".z", "", ""); 667 } 668 669 670 /** 671 * Make a fragment shader that sets the output stencil to a stencil value 672 * fetched from a multisample texture. 673 * \param tex_target one of PIPE_TEXTURE_x 674 */ 675 void * 676 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, 677 unsigned tgsi_tex) 678 { 679 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "UINT", 680 "STENCIL", ".y", "", ""); 681 } 682 683 684 /** 685 * Make a fragment shader that sets the output depth and stencil to depth 686 * and stencil values fetched from two multisample textures / samplers. 687 * The sizes of both textures should match (it should be one depth-stencil 688 * texture). 689 * \param tex_target one of PIPE_TEXTURE_x 690 */ 691 void * 692 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, 693 unsigned tgsi_tex) 694 { 695 static const char shader_templ[] = 696 "FRAG\n" 697 "DCL IN[0], GENERIC[0], LINEAR\n" 698 "DCL SAMP[0..1]\n" 699 "DCL SVIEW[0..1], %s, FLOAT\n" 700 "DCL OUT[0], POSITION\n" 701 "DCL OUT[1], STENCIL\n" 702 "DCL TEMP[0]\n" 703 704 "F2U TEMP[0], IN[0]\n" 705 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n" 706 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n" 707 "END\n"; 708 709 const char *type = tgsi_texture_names[tgsi_tex]; 710 char text[sizeof(shader_templ)+100]; 711 struct tgsi_token tokens[1000]; 712 struct pipe_shader_state state; 713 714 assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || 715 tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); 716 717 sprintf(text, shader_templ, type, type, type); 718 719 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 720 assert(0); 721 return NULL; 722 } 723 pipe_shader_state_from_tgsi(&state, tokens); 724 #if 0 725 tgsi_dump(state.tokens, 0); 726 #endif 727 728 return pipe->create_fs_state(pipe, &state); 729 } 730 731 732 void * 733 util_make_fs_msaa_resolve(struct pipe_context *pipe, 734 unsigned tgsi_tex, unsigned nr_samples, 735 enum tgsi_return_type stype) 736 { 737 struct ureg_program *ureg; 738 struct ureg_src sampler, coord; 739 struct ureg_dst out, tmp_sum, tmp_coord, tmp; 740 unsigned i; 741 742 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 743 if (!ureg) 744 return NULL; 745 746 /* Declarations. */ 747 sampler = ureg_DECL_sampler(ureg, 0); 748 ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype); 749 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, 750 TGSI_INTERPOLATE_LINEAR); 751 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 752 tmp_sum = ureg_DECL_temporary(ureg); 753 tmp_coord = ureg_DECL_temporary(ureg); 754 tmp = ureg_DECL_temporary(ureg); 755 756 /* Instructions. */ 757 ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0)); 758 ureg_F2U(ureg, tmp_coord, coord); 759 760 for (i = 0; i < nr_samples; i++) { 761 /* Read one sample. */ 762 ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W), 763 ureg_imm1u(ureg, i)); 764 ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler); 765 766 if (stype == TGSI_RETURN_TYPE_UINT) 767 ureg_U2F(ureg, tmp, ureg_src(tmp)); 768 else if (stype == TGSI_RETURN_TYPE_SINT) 769 ureg_I2F(ureg, tmp, ureg_src(tmp)); 770 771 /* Add it to the sum.*/ 772 ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp)); 773 } 774 775 /* Calculate the average and return. */ 776 ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum), 777 ureg_imm1f(ureg, 1.0 / nr_samples)); 778 779 if (stype == TGSI_RETURN_TYPE_UINT) 780 ureg_F2U(ureg, out, ureg_src(tmp_sum)); 781 else if (stype == TGSI_RETURN_TYPE_SINT) 782 ureg_F2I(ureg, out, ureg_src(tmp_sum)); 783 else 784 ureg_MOV(ureg, out, ureg_src(tmp_sum)); 785 786 ureg_END(ureg); 787 788 return ureg_create_shader_and_destroy(ureg, pipe); 789 } 790 791 792 void * 793 util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, 794 unsigned tgsi_tex, unsigned nr_samples, 795 enum tgsi_return_type stype) 796 { 797 struct ureg_program *ureg; 798 struct ureg_src sampler, coord; 799 struct ureg_dst out, tmp, top, bottom; 800 struct ureg_dst tmp_coord[4], tmp_sum[4]; 801 unsigned i, c; 802 803 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 804 if (!ureg) 805 return NULL; 806 807 /* Declarations. */ 808 sampler = ureg_DECL_sampler(ureg, 0); 809 ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype); 810 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, 811 TGSI_INTERPOLATE_LINEAR); 812 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 813 for (c = 0; c < 4; c++) 814 tmp_sum[c] = ureg_DECL_temporary(ureg); 815 for (c = 0; c < 4; c++) 816 tmp_coord[c] = ureg_DECL_temporary(ureg); 817 tmp = ureg_DECL_temporary(ureg); 818 top = ureg_DECL_temporary(ureg); 819 bottom = ureg_DECL_temporary(ureg); 820 821 /* Instructions. */ 822 for (c = 0; c < 4; c++) 823 ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0)); 824 825 /* Get 4 texture coordinates for the bilinear filter. */ 826 ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */ 827 ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]), 828 ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */ 829 ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]), 830 ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */ 831 ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]), 832 ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */ 833 834 for (i = 0; i < nr_samples; i++) { 835 for (c = 0; c < 4; c++) { 836 /* Read one sample. */ 837 ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W), 838 ureg_imm1u(ureg, i)); 839 ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler); 840 841 if (stype == TGSI_RETURN_TYPE_UINT) 842 ureg_U2F(ureg, tmp, ureg_src(tmp)); 843 else if (stype == TGSI_RETURN_TYPE_SINT) 844 ureg_I2F(ureg, tmp, ureg_src(tmp)); 845 846 /* Add it to the sum.*/ 847 ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp)); 848 } 849 } 850 851 /* Calculate the average. */ 852 for (c = 0; c < 4; c++) 853 ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), 854 ureg_imm1f(ureg, 1.0 / nr_samples)); 855 856 /* Take the 4 average values and apply a standard bilinear filter. */ 857 ureg_FRC(ureg, tmp, coord); 858 859 ureg_LRP(ureg, top, 860 ureg_scalar(ureg_src(tmp), 0), 861 ureg_src(tmp_sum[1]), 862 ureg_src(tmp_sum[0])); 863 864 ureg_LRP(ureg, bottom, 865 ureg_scalar(ureg_src(tmp), 0), 866 ureg_src(tmp_sum[3]), 867 ureg_src(tmp_sum[2])); 868 869 ureg_LRP(ureg, tmp, 870 ureg_scalar(ureg_src(tmp), 1), 871 ureg_src(bottom), 872 ureg_src(top)); 873 874 /* Convert to the texture format and return. */ 875 if (stype == TGSI_RETURN_TYPE_UINT) 876 ureg_F2U(ureg, out, ureg_src(tmp)); 877 else if (stype == TGSI_RETURN_TYPE_SINT) 878 ureg_F2I(ureg, out, ureg_src(tmp)); 879 else 880 ureg_MOV(ureg, out, ureg_src(tmp)); 881 882 ureg_END(ureg); 883 884 return ureg_create_shader_and_destroy(ureg, pipe); 885 } 886 887 void * 888 util_make_geometry_passthrough_shader(struct pipe_context *pipe, 889 uint num_attribs, 890 const ubyte *semantic_names, 891 const ubyte *semantic_indexes) 892 { 893 static const unsigned zero[4] = {0, 0, 0, 0}; 894 895 struct ureg_program *ureg; 896 struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS]; 897 struct ureg_src src[PIPE_MAX_SHADER_INPUTS]; 898 struct ureg_src imm; 899 900 unsigned i; 901 902 ureg = ureg_create(PIPE_SHADER_GEOMETRY); 903 if (!ureg) 904 return NULL; 905 906 ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS); 907 ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS); 908 ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1); 909 ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1); 910 imm = ureg_DECL_immediate_uint(ureg, zero, 4); 911 912 /** 913 * Loop over all the attribs and declare the corresponding 914 * declarations in the geometry shader 915 */ 916 for (i = 0; i < num_attribs; i++) { 917 src[i] = ureg_DECL_input(ureg, semantic_names[i], 918 semantic_indexes[i], 0, 1); 919 src[i] = ureg_src_dimension(src[i], 0); 920 dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]); 921 } 922 923 /* MOV dst[i] src[i] */ 924 for (i = 0; i < num_attribs; i++) { 925 ureg_MOV(ureg, dst[i], src[i]); 926 } 927 928 /* EMIT IMM[0] */ 929 ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1); 930 931 /* END */ 932 ureg_END(ureg); 933 934 return ureg_create_shader_and_destroy(ureg, pipe); 935 } 936 937