1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 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 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 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 "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 */ 59void * 60util_make_vertex_passthrough_shader(struct pipe_context *pipe, 61 uint num_attribs, 62 const enum tgsi_semantic *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, false, NULL); 70} 71 72void * 73util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, 74 uint num_attribs, 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) 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 if (layered) { 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); 107 108 ureg_MOV(ureg, ureg_writemask(layer, TGSI_WRITEMASK_X), 109 ureg_scalar(instance_id, TGSI_SWIZZLE_X)); 110 } 111 112 ureg_END( ureg ); 113 114 return ureg_create_shader_with_so_and_destroy( ureg, pipe, so ); 115} 116 117 118void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe) 119{ 120 const enum tgsi_semantic semantic_names[] = {TGSI_SEMANTIC_POSITION, 121 TGSI_SEMANTIC_GENERIC}; 122 const unsigned semantic_indices[] = {0, 0}; 123 124 return util_make_vertex_passthrough_shader_with_so(pipe, 2, semantic_names, 125 semantic_indices, false, 126 true, NULL); 127} 128 129/** 130 * Takes position and color, and outputs position, color, and instance id. 131 */ 132void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe) 133{ 134 static const char text[] = 135 "VERT\n" 136 "DCL IN[0]\n" 137 "DCL IN[1]\n" 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" 142 143 "MOV OUT[0], IN[0]\n" 144 "MOV OUT[1], IN[1]\n" 145 "MOV OUT[2].x, SV[0].xxxx\n" 146 "END\n"; 147 struct tgsi_token tokens[1000]; 148 struct pipe_shader_state state = {0}; 149 150 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 151 assert(0); 152 return NULL; 153 } 154 pipe_shader_state_from_tgsi(&state, tokens); 155 return pipe->create_vs_state(pipe, &state); 156} 157 158/** 159 * Takes position, color, and target layer, and emits vertices on that target 160 * layer, with the specified color. 161 */ 162void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe) 163{ 164 static const char text[] = 165 "GEOM\n" 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" 177 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" 181 "EMIT IMM[0].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" 185 "EMIT IMM[0].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" 189 "EMIT IMM[0].xxxx\n" 190 "END\n"; 191 struct tgsi_token tokens[1000]; 192 struct pipe_shader_state state = {0}; 193 194 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 195 assert(0); 196 return NULL; 197 } 198 pipe_shader_state_from_tgsi(&state, tokens); 199 return pipe->create_gs_state(pipe, &state); 200} 201 202static void 203ureg_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) 207{ 208 if (use_txf) { 209 struct ureg_dst temp = ureg_DECL_temporary(ureg); 210 211 ureg_F2I(ureg, temp, coord); 212 213 if (load_level_zero) 214 ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler); 215 else 216 ureg_TXF(ureg, out, tex_target, ureg_src(temp), sampler); 217 } else { 218 if (load_level_zero) 219 ureg_TEX_LZ(ureg, out, tex_target, coord, sampler); 220 else 221 ureg_TEX(ureg, out, tex_target, coord, sampler); 222 } 223} 224 225/** 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] 231 * END; 232 * 233 * \param tex_target one of PIPE_TEXTURE_x 234 */ 235void * 236util_make_fragment_tex_shader_xrbias(struct pipe_context *pipe, 237 enum tgsi_texture_type tex_target) 238{ 239 struct ureg_program *ureg; 240 struct ureg_src sampler; 241 struct ureg_src coord; 242 struct ureg_dst temp; 243 struct ureg_dst out; 244 struct ureg_src imm; 245 enum tgsi_return_type stype = TGSI_RETURN_TYPE_FLOAT; 246 247 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 248 if (!ureg) 249 return NULL; 250 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); 259 260 ureg_TEX(ureg, temp, tex_target, coord, sampler); 261 ureg_MAD(ureg, ureg_writemask(temp, TGSI_WRITEMASK_XYZ), 262 ureg_src(temp), 263 ureg_scalar(imm, TGSI_SWIZZLE_X), 264 ureg_scalar(imm, TGSI_SWIZZLE_Y)); 265 ureg_MOV(ureg, out, ureg_src(temp)); 266 ureg_END(ureg); 267 268 return ureg_create_shader_and_destroy(ureg, pipe); 269} 270 271 272/** 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] 279 * END; 280 * 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 284 */ 285void * 286util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, 287 enum tgsi_texture_type tex_target, 288 enum tgsi_interpolate_mode interp_mode, 289 unsigned writemask, 290 enum tgsi_return_type stype, 291 enum tgsi_return_type dtype, 292 bool load_level_zero, 293 bool use_txf) 294{ 295 struct ureg_program *ureg; 296 struct ureg_src sampler; 297 struct ureg_src tex; 298 struct ureg_dst temp; 299 struct ureg_dst out; 300 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); 304 305 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 306 if (!ureg) 307 return NULL; 308 309 sampler = ureg_DECL_sampler( ureg, 0 ); 310 311 ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype); 312 313 tex = ureg_DECL_fs_input( ureg, 314 TGSI_SEMANTIC_GENERIC, 0, 315 interp_mode ); 316 317 out = ureg_DECL_output( ureg, 318 TGSI_SEMANTIC_COLOR, 319 0 ); 320 321 temp = ureg_DECL_temporary(ureg); 322 323 if (writemask != TGSI_WRITEMASK_XYZW) { 324 struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); 325 326 ureg_MOV(ureg, temp, imm); 327 } 328 329 if (tex_target == TGSI_TEXTURE_BUFFER) 330 ureg_TXF(ureg, 331 ureg_writemask(temp, writemask), 332 tex_target, tex, sampler); 333 else 334 ureg_load_tex(ureg, ureg_writemask(temp, writemask), tex, sampler, 335 tex_target, load_level_zero, use_txf); 336 337 if (stype != dtype) { 338 if (stype == TGSI_RETURN_TYPE_SINT) { 339 assert(dtype == TGSI_RETURN_TYPE_UINT); 340 341 ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0)); 342 } else { 343 assert(stype == TGSI_RETURN_TYPE_UINT); 344 assert(dtype == TGSI_RETURN_TYPE_SINT); 345 346 ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1)); 347 } 348 } 349 350 ureg_MOV(ureg, out, ureg_src(temp)); 351 352 ureg_END( ureg ); 353 354 return ureg_create_shader_and_destroy( ureg, pipe ); 355} 356 357 358/** 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 362 */ 363void * 364util_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, 370 bool use_txf) 371{ 372 return util_make_fragment_tex_shader_writemask( pipe, 373 tex_target, 374 interp_mode, 375 TGSI_WRITEMASK_XYZW, 376 stype, dtype, load_level_zero, 377 use_txf); 378} 379 380 381/** 382 * Make a simple fragment texture shader which reads the texture unit 0 and 1 383 * and writes it as depth and stencil, respectively. 384 */ 385void * 386util_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) 389{ 390 struct ureg_program *ureg; 391 struct ureg_src depth_sampler, stencil_sampler, coord; 392 struct ureg_dst depth, stencil, tmp; 393 394 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 395 if (!ureg) 396 return NULL; 397 398 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, 399 TGSI_INTERPOLATE_LINEAR); 400 tmp = ureg_DECL_temporary(ureg); 401 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); 409 410 ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord, 411 depth_sampler, tex_target, load_level_zero, use_txf); 412 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)); 416 } 417 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); 425 426 ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord, 427 stencil_sampler, tex_target, load_level_zero, use_txf); 428 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)); 432 } 433 434 ureg_END(ureg); 435 436 return ureg_create_shader_and_destroy(ureg, pipe); 437} 438 439 440/** 441 * Make simple fragment color pass-through shader that replicates OUT[0] 442 * to all bound colorbuffers. 443 */ 444void * 445util_make_fragment_passthrough_shader(struct pipe_context *pipe, 446 int input_semantic, 447 int input_interpolate, 448 boolean write_all_cbufs) 449{ 450 static const char shader_templ[] = 451 "FRAG\n" 452 "%s" 453 "DCL IN[0], %s[0], %s\n" 454 "DCL OUT[0], COLOR[0]\n" 455 456 "MOV OUT[0], IN[0]\n" 457 "END\n"; 458 459 char text[sizeof(shader_templ)+100]; 460 struct tgsi_token tokens[1000]; 461 struct pipe_shader_state state = {0}; 462 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]); 467 468 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 469 assert(0); 470 return NULL; 471 } 472 pipe_shader_state_from_tgsi(&state, tokens); 473#if 0 474 tgsi_dump(state.tokens, 0); 475#endif 476 477 return pipe->create_fs_state(pipe, &state); 478} 479 480 481void * 482util_make_empty_fragment_shader(struct pipe_context *pipe) 483{ 484 struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT); 485 if (!ureg) 486 return NULL; 487 488 ureg_END(ureg); 489 return ureg_create_shader_and_destroy(ureg, pipe); 490} 491 492 493/** 494 * Make a fragment shader that copies the input color to N output colors. 495 */ 496void * 497util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, 498 int input_semantic, 499 int input_interpolate) 500{ 501 struct ureg_program *ureg; 502 struct ureg_src src; 503 struct ureg_dst dst[PIPE_MAX_COLOR_BUFS]; 504 int i; 505 506 assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); 507 508 ureg = ureg_create( PIPE_SHADER_FRAGMENT ); 509 if (!ureg) 510 return NULL; 511 512 src = ureg_DECL_fs_input( ureg, input_semantic, 0, 513 input_interpolate ); 514 515 for (i = 0; i < num_cbufs; i++) 516 dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i ); 517 518 for (i = 0; i < num_cbufs; i++) 519 ureg_MOV( ureg, dst[i], src ); 520 521 ureg_END( ureg ); 522 523 return ureg_create_shader_and_destroy( ureg, pipe ); 524} 525 526 527static void * 528util_make_fs_blit_msaa_gen(struct pipe_context *pipe, 529 enum tgsi_texture_type tgsi_tex, 530 bool sample_shading, 531 const char *samp_type, 532 const char *output_semantic, 533 const char *output_mask, 534 const char *conversion_decl, 535 const char *conversion) 536{ 537 static const char shader_templ[] = 538 "FRAG\n" 539 "DCL IN[0], GENERIC[0], LINEAR\n" 540 "DCL SAMP[0]\n" 541 "DCL SVIEW[0], %s, %s\n" 542 "DCL OUT[0], %s\n" 543 "DCL TEMP[0]\n" 544 "%s" 545 "%s" 546 547 "F2U TEMP[0], IN[0]\n" 548 "%s" 549 "TXF TEMP[0], TEMP[0], SAMP[0], %s\n" 550 "%s" 551 "MOV OUT[0]%s, TEMP[0]\n" 552 "END\n"; 553 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}; 558 559 assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || 560 tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); 561 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); 566 567 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 568 puts(text); 569 assert(0); 570 return NULL; 571 } 572 pipe_shader_state_from_tgsi(&state, tokens); 573#if 0 574 tgsi_dump(state.tokens, 0); 575#endif 576 577 return pipe->create_fs_state(pipe, &state); 578} 579 580 581/** 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 585 */ 586void * 587util_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, 591 bool sample_shading) 592{ 593 const char *samp_type; 594 const char *conversion_decl = ""; 595 const char *conversion = ""; 596 597 if (stype == TGSI_RETURN_TYPE_UINT) { 598 samp_type = "UINT"; 599 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"; 603 } 604 } else if (stype == TGSI_RETURN_TYPE_SINT) { 605 samp_type = "SINT"; 606 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"; 610 } 611 } else { 612 assert(dtype == TGSI_RETURN_TYPE_FLOAT); 613 samp_type = "FLOAT"; 614 } 615 616 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, samp_type, 617 "COLOR[0]", "", conversion_decl, 618 conversion); 619} 620 621 622/** 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 626 */ 627void * 628util_make_fs_blit_msaa_depth(struct pipe_context *pipe, 629 enum tgsi_texture_type tgsi_tex, 630 bool sample_shading) 631{ 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"); 635} 636 637 638/** 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 642 */ 643void * 644util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, 645 enum tgsi_texture_type tgsi_tex, 646 bool sample_shading) 647{ 648 return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "UINT", 649 "STENCIL", ".y", "", 650 "MOV TEMP[0].y, TEMP[0].xxxx\n"); 651} 652 653 654/** 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 658 * texture). 659 * \param tex_target one of PIPE_TEXTURE_x 660 */ 661void * 662util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, 663 enum tgsi_texture_type tgsi_tex, 664 bool sample_shading) 665{ 666 static const char shader_templ[] = 667 "FRAG\n" 668 "DCL IN[0], GENERIC[0], LINEAR\n" 669 "DCL SAMP[0..1]\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" 674 "DCL TEMP[0]\n" 675 "%s" 676 677 "F2U TEMP[0], IN[0]\n" 678 "%s" 679 "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n" 680 "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n" 681 "END\n"; 682 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}; 687 688 assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || 689 tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); 690 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" : "", 694 type, type); 695 696 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 697 assert(0); 698 return NULL; 699 } 700 pipe_shader_state_from_tgsi(&state, tokens); 701#if 0 702 tgsi_dump(state.tokens, 0); 703#endif 704 705 return pipe->create_fs_state(pipe, &state); 706} 707 708 709void * 710util_make_fs_msaa_resolve(struct pipe_context *pipe, 711 enum tgsi_texture_type tgsi_tex, unsigned nr_samples, 712 enum tgsi_return_type stype) 713{ 714 struct ureg_program *ureg; 715 struct ureg_src sampler, coord; 716 struct ureg_dst out, tmp_sum, tmp_coord, tmp; 717 unsigned i; 718 719 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 720 if (!ureg) 721 return NULL; 722 723 /* Declarations. */ 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); 732 733 /* Instructions. */ 734 ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0)); 735 ureg_F2U(ureg, tmp_coord, coord); 736 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); 742 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)); 747 748 /* Add it to the sum.*/ 749 ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp)); 750 } 751 752 /* Calculate the average and return. */ 753 ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum), 754 ureg_imm1f(ureg, 1.0 / nr_samples)); 755 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)); 760 else 761 ureg_MOV(ureg, out, ureg_src(tmp_sum)); 762 763 ureg_END(ureg); 764 765 return ureg_create_shader_and_destroy(ureg, pipe); 766} 767 768 769void * 770util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, 771 enum tgsi_texture_type tgsi_tex, 772 unsigned nr_samples, 773 enum tgsi_return_type stype) 774{ 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]; 779 unsigned i, c; 780 781 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 782 if (!ureg) 783 return NULL; 784 785 /* Declarations. */ 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); 798 799 /* Instructions. */ 800 for (c = 0; c < 4; c++) 801 ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0)); 802 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 */ 811 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); 818 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)); 823 824 /* Add it to the sum.*/ 825 ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp)); 826 } 827 } 828 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)); 833 834 /* Take the 4 average values and apply a standard bilinear filter. */ 835 ureg_FRC(ureg, tmp, coord); 836 837 ureg_LRP(ureg, top, 838 ureg_scalar(ureg_src(tmp), 0), 839 ureg_src(tmp_sum[1]), 840 ureg_src(tmp_sum[0])); 841 842 ureg_LRP(ureg, bottom, 843 ureg_scalar(ureg_src(tmp), 0), 844 ureg_src(tmp_sum[3]), 845 ureg_src(tmp_sum[2])); 846 847 ureg_LRP(ureg, tmp, 848 ureg_scalar(ureg_src(tmp), 1), 849 ureg_src(bottom), 850 ureg_src(top)); 851 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)); 857 else 858 ureg_MOV(ureg, out, ureg_src(tmp)); 859 860 ureg_END(ureg); 861 862 return ureg_create_shader_and_destroy(ureg, pipe); 863} 864 865void * 866util_make_geometry_passthrough_shader(struct pipe_context *pipe, 867 uint num_attribs, 868 const ubyte *semantic_names, 869 const ubyte *semantic_indexes) 870{ 871 static const unsigned zero[4] = {0, 0, 0, 0}; 872 873 struct ureg_program *ureg; 874 struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS]; 875 struct ureg_src src[PIPE_MAX_SHADER_INPUTS]; 876 struct ureg_src imm; 877 878 unsigned i; 879 880 ureg = ureg_create(PIPE_SHADER_GEOMETRY); 881 if (!ureg) 882 return NULL; 883 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); 889 890 /** 891 * Loop over all the attribs and declare the corresponding 892 * declarations in the geometry shader 893 */ 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]); 899 } 900 901 /* MOV dst[i] src[i] */ 902 for (i = 0; i < num_attribs; i++) { 903 ureg_MOV(ureg, dst[i], src[i]); 904 } 905 906 /* EMIT IMM[0] */ 907 ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0); 908 909 /* END */ 910 ureg_END(ureg); 911 912 return ureg_create_shader_and_destroy(ureg, pipe); 913} 914 915 916/** 917 * Blit from color to ZS or from ZS to color in a manner that is equivalent 918 * to memcpy. 919 * 920 * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24). 921 * 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. 924 * OR 925 * A color sampler is used to load a color value, which is unpacked and 926 * written to depth and stencil shader outputs. 927 */ 928void * 929util_make_fs_pack_color_zs(struct pipe_context *pipe, 930 enum tgsi_texture_type tex_target, 931 enum pipe_format zs_format, 932 bool dst_is_color) 933{ 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; 937 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 */ 943 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; 949 950 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 951 if (!ureg) 952 return NULL; 953 954 coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, 955 TGSI_INTERPOLATE_LINEAR); 956 957 if (dst_is_color) { 958 /* Load depth. */ 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); 965 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); 969 970 /* Pack to Z24. */ 971 if (is_z24) { 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), 975 TGSI_WRITEMASK_XY); 976 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)); 980 981 if (z24_is_high) 982 ureg_SHL(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 8)); 983 else 984 ureg_AND(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 0xffffff)); 985 } 986 987 if (has_stencil) { 988 /* Load stencil. */ 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); 995 996 stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); 997 ureg_load_tex(ureg, stencil, coord, stencil_sampler, tex_target, 998 true, true); 999 1000 /* Pack stencil into depth. */ 1001 if (is_z24) { 1002 if (!z24_is_high) 1003 ureg_SHL(ureg, stencil, ureg_src(stencil), ureg_imm1u(ureg, 24)); 1004 1005 ureg_OR(ureg, depth_x, ureg_src(depth), ureg_src(stencil)); 1006 } 1007 } 1008 1009 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 1010 1011 if (is_z24) { 1012 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_X), ureg_src(depth)); 1013 } else { 1014 /* Z32_S8X24 */ 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)); 1018 } 1019 } else { 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); 1026 1027 color = ureg_DECL_temporary(ureg); 1028 ureg_load_tex(ureg, color, coord, color_sampler, tex_target, true, true); 1029 1030 depth = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); 1031 stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); 1032 1033 if (is_z24) { 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), 1037 TGSI_WRITEMASK_XY); 1038 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)); 1045 } else { 1046 /* depth = color.x; (Z32_S8X24) */ 1047 ureg_MOV(ureg, depth, ureg_src(color)); 1048 } 1049 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)); 1053 1054 if (has_stencil) { 1055 if (is_z24) { 1056 ureg_UBFE(ureg, stencil, ureg_src(color), 1057 ureg_imm1u(ureg, z24_is_high ? 0 : 24), 1058 ureg_imm1u(ureg, 8)); 1059 } else { 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)); 1065 } 1066 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)); 1070 } 1071 } 1072 1073 ureg_END(ureg); 1074 1075 return ureg_create_shader_and_destroy(ureg, pipe); 1076} 1077 1078 1079/** 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. 1083 */ 1084void * 1085util_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) 1093{ 1094 unsigned i, j; 1095 unsigned num_regs; 1096 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]; 1102 1103 ureg = ureg_create(PIPE_SHADER_TESS_CTRL); 1104 1105 if (!ureg) 1106 return NULL; 1107 1108 ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, vertices_per_patch); 1109 1110 num_regs = 0; 1111 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]) { 1126 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], 1132 0, 1); 1133 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); 1138 } 1139 1140 num_regs++; 1141 break; 1142 } 1143 } 1144 break; 1145 default: 1146 break; 1147 } 1148 } 1149 1150 dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSOUTER, 1151 num_regs); 1152 src[num_regs] = ureg_DECL_constant(ureg, 0); 1153 num_regs++; 1154 dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSINNER, 1155 num_regs); 1156 src[num_regs] = ureg_DECL_constant(ureg, 1); 1157 num_regs++; 1158 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)); 1166 } 1167 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], 1172 addr_x, 0)); 1173 ureg_MOV(ureg, ureg_dst_dimension_indirect(dst[i], 1174 addr_x, 0), ureg_src(temp)); 1175 } 1176 else 1177 ureg_MOV(ureg, dst[i], src[i]); 1178 } 1179 1180 ureg_END(ureg); 1181 1182 return ureg_create_shader_and_destroy(ureg, pipe); 1183} 1184 1185void * 1186util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src) 1187{ 1188 static const char shader_templ[] = 1189 "FRAG\n" 1190 "DCL IN[0], GENERIC[0], LINEAR\n" 1191 "DCL SAMP[0]\n" 1192 "DCL SVIEW[0], %s, UINT\n" 1193 "DCL CONST[0][0]\n" 1194 "DCL TEMP[0]\n" 1195 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" 1202 "END\n"; 1203 1204 char text[sizeof(shader_templ)+100]; 1205 struct tgsi_token tokens[1000]; 1206 struct pipe_shader_state state = { 0 }; 1207 1208 enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA : 1209 TGSI_TEXTURE_2D; 1210 1211 sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex], tgsi_texture_names[tgsi_tex]); 1212 1213 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 1214 assert(0); 1215 return NULL; 1216 } 1217 1218 pipe_shader_state_from_tgsi(&state, tokens); 1219 1220 return pipe->create_fs_state(pipe, &state); 1221} 1222 1223void * 1224util_make_fs_clear_all_cbufs(struct pipe_context *pipe) 1225{ 1226 static const char text[] = 1227 "FRAG\n" 1228 "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" 1229 "DCL OUT[0], COLOR[0]\n" 1230 "DCL CONST[0][0]\n" 1231 1232 "MOV OUT[0], CONST[0][0]\n" 1233 "END\n"; 1234 1235 struct tgsi_token tokens[1000]; 1236 struct pipe_shader_state state = { 0 }; 1237 1238 if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { 1239 assert(0); 1240 return NULL; 1241 } 1242 1243 pipe_shader_state_from_tgsi(&state, tokens); 1244 1245 return pipe->create_fs_state(pipe, &state); 1246} 1247