1/* 2 Copyright (C) Intel Corp. 2006. All Rights Reserved. 3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to 4 develop this 3D driver. 5 6 Permission is hereby granted, free of charge, to any person obtaining 7 a copy of this software and associated documentation files (the 8 "Software"), to deal in the Software without restriction, including 9 without limitation the rights to use, copy, modify, merge, publish, 10 distribute, sublicense, and/or sell copies of the Software, and to 11 permit persons to whom the Software is furnished to do so, subject to 12 the following conditions: 13 14 The above copyright notice and this permission notice (including the 15 next paragraph) shall be included in all copies or substantial 16 portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 26 **********************************************************************/ 27 /* 28 * Authors: 29 * Keith Whitwell <keith@tungstengraphics.com> 30 */ 31 32 33#include "main/macros.h" 34#include "brw_context.h" 35#include "brw_wm.h" 36 37static bool 38can_do_pln(struct intel_context *intel, const struct brw_reg *deltas) 39{ 40 struct brw_context *brw = brw_context(&intel->ctx); 41 42 if (!brw->has_pln) 43 return false; 44 45 if (deltas[1].nr != deltas[0].nr + 1) 46 return false; 47 48 if (intel->gen < 6 && ((deltas[0].nr & 1) != 0)) 49 return false; 50 51 return true; 52} 53 54/* Return the SrcReg index of the channels that can be immediate float operands 55 * instead of usage of PROGRAM_CONSTANT values through push/pull. 56 */ 57bool 58brw_wm_arg_can_be_immediate(enum prog_opcode opcode, int arg) 59{ 60 int opcode_array[] = { 61 [OPCODE_ADD] = 2, 62 [OPCODE_CMP] = 3, 63 [OPCODE_DP3] = 2, 64 [OPCODE_DP4] = 2, 65 [OPCODE_DPH] = 2, 66 [OPCODE_MAX] = 2, 67 [OPCODE_MIN] = 2, 68 [OPCODE_MOV] = 1, 69 [OPCODE_MUL] = 2, 70 [OPCODE_SEQ] = 2, 71 [OPCODE_SGE] = 2, 72 [OPCODE_SGT] = 2, 73 [OPCODE_SLE] = 2, 74 [OPCODE_SLT] = 2, 75 [OPCODE_SNE] = 2, 76 [OPCODE_SWZ] = 1, 77 [OPCODE_XPD] = 2, 78 }; 79 80 /* These opcodes get broken down in a way that allow two 81 * args to be immediates. 82 */ 83 if (opcode == OPCODE_MAD || opcode == OPCODE_LRP) { 84 if (arg == 1 || arg == 2) 85 return true; 86 } 87 88 if (opcode > ARRAY_SIZE(opcode_array)) 89 return false; 90 91 return arg == opcode_array[opcode] - 1; 92} 93 94/** 95 * Computes the screen-space x,y position of the pixels. 96 * 97 * This will be used by emit_delta_xy() or emit_wpos_xy() for 98 * interpolation of attributes.. 99 * 100 * Payload R0: 101 * 102 * R0.0 -- pixel mask, one bit for each of 4 pixels in 4 tiles, 103 * corresponding to each of the 16 execution channels. 104 * R0.1..8 -- ? 105 * R1.0 -- triangle vertex 0.X 106 * R1.1 -- triangle vertex 0.Y 107 * R1.2 -- tile 0 x,y coords (2 packed uwords) 108 * R1.3 -- tile 1 x,y coords (2 packed uwords) 109 * R1.4 -- tile 2 x,y coords (2 packed uwords) 110 * R1.5 -- tile 3 x,y coords (2 packed uwords) 111 * R1.6 -- ? 112 * R1.7 -- ? 113 * R1.8 -- ? 114 */ 115void emit_pixel_xy(struct brw_wm_compile *c, 116 const struct brw_reg *dst, 117 GLuint mask) 118{ 119 struct brw_compile *p = &c->func; 120 struct brw_reg r1 = brw_vec1_grf(1, 0); 121 struct brw_reg r1_uw = retype(r1, BRW_REGISTER_TYPE_UW); 122 struct brw_reg dst0_uw, dst1_uw; 123 124 brw_push_insn_state(p); 125 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 126 127 if (c->dispatch_width == 16) { 128 dst0_uw = vec16(retype(dst[0], BRW_REGISTER_TYPE_UW)); 129 dst1_uw = vec16(retype(dst[1], BRW_REGISTER_TYPE_UW)); 130 } else { 131 dst0_uw = vec8(retype(dst[0], BRW_REGISTER_TYPE_UW)); 132 dst1_uw = vec8(retype(dst[1], BRW_REGISTER_TYPE_UW)); 133 } 134 135 /* Calculate pixel centers by adding 1 or 0 to each of the 136 * micro-tile coordinates passed in r1. 137 */ 138 if (mask & WRITEMASK_X) { 139 brw_ADD(p, 140 dst0_uw, 141 stride(suboffset(r1_uw, 4), 2, 4, 0), 142 brw_imm_v(0x10101010)); 143 } 144 145 if (mask & WRITEMASK_Y) { 146 brw_ADD(p, 147 dst1_uw, 148 stride(suboffset(r1_uw,5), 2, 4, 0), 149 brw_imm_v(0x11001100)); 150 } 151 brw_pop_insn_state(p); 152} 153 154/** 155 * Computes the screen-space x,y distance of the pixels from the start 156 * vertex. 157 * 158 * This will be used in linterp or pinterp with the start vertex value 159 * and the Cx, Cy, and C0 coefficients passed in from the setup engine 160 * to produce interpolated attribute values. 161 */ 162void emit_delta_xy(struct brw_compile *p, 163 const struct brw_reg *dst, 164 GLuint mask, 165 const struct brw_reg *arg0) 166{ 167 struct intel_context *intel = &p->brw->intel; 168 struct brw_reg r1 = brw_vec1_grf(1, 0); 169 170 if (mask == 0) 171 return; 172 173 assert(mask == WRITEMASK_XY); 174 175 if (intel->gen >= 6) { 176 /* XXX Gen6 WM doesn't have Xstart/Ystart in payload r1.0/r1.1. 177 Just add them with 0.0 for dst reg.. */ 178 r1 = brw_imm_v(0x00000000); 179 brw_ADD(p, 180 dst[0], 181 retype(arg0[0], BRW_REGISTER_TYPE_UW), 182 r1); 183 brw_ADD(p, 184 dst[1], 185 retype(arg0[1], BRW_REGISTER_TYPE_UW), 186 r1); 187 return; 188 } 189 190 /* Calc delta X,Y by subtracting origin in r1 from the pixel 191 * centers produced by emit_pixel_xy(). 192 */ 193 brw_ADD(p, 194 dst[0], 195 retype(arg0[0], BRW_REGISTER_TYPE_UW), 196 negate(r1)); 197 brw_ADD(p, 198 dst[1], 199 retype(arg0[1], BRW_REGISTER_TYPE_UW), 200 negate(suboffset(r1,1))); 201} 202 203/** 204 * Computes the pixel offset from the window origin for gl_FragCoord(). 205 */ 206void emit_wpos_xy(struct brw_wm_compile *c, 207 const struct brw_reg *dst, 208 GLuint mask, 209 const struct brw_reg *arg0) 210{ 211 struct brw_compile *p = &c->func; 212 struct intel_context *intel = &p->brw->intel; 213 struct brw_reg delta_x = retype(arg0[0], BRW_REGISTER_TYPE_W); 214 struct brw_reg delta_y = retype(arg0[1], BRW_REGISTER_TYPE_W); 215 216 if (mask & WRITEMASK_X) { 217 if (intel->gen >= 6) { 218 struct brw_reg delta_x_f = retype(delta_x, BRW_REGISTER_TYPE_F); 219 brw_MOV(p, delta_x_f, delta_x); 220 delta_x = delta_x_f; 221 } 222 223 if (c->fp->program.PixelCenterInteger) { 224 /* X' = X */ 225 brw_MOV(p, dst[0], delta_x); 226 } else { 227 /* X' = X + 0.5 */ 228 brw_ADD(p, dst[0], delta_x, brw_imm_f(0.5)); 229 } 230 } 231 232 if (mask & WRITEMASK_Y) { 233 if (intel->gen >= 6) { 234 struct brw_reg delta_y_f = retype(delta_y, BRW_REGISTER_TYPE_F); 235 brw_MOV(p, delta_y_f, delta_y); 236 delta_y = delta_y_f; 237 } 238 239 if (c->fp->program.OriginUpperLeft) { 240 if (c->fp->program.PixelCenterInteger) { 241 /* Y' = Y */ 242 brw_MOV(p, dst[1], delta_y); 243 } else { 244 brw_ADD(p, dst[1], delta_y, brw_imm_f(0.5)); 245 } 246 } else { 247 float center_offset = c->fp->program.PixelCenterInteger ? 0.0 : 0.5; 248 249 /* Y' = (height - 1) - Y + center */ 250 brw_ADD(p, dst[1], negate(delta_y), 251 brw_imm_f(c->key.drawable_height - 1 + center_offset)); 252 } 253 } 254} 255 256 257void emit_pixel_w(struct brw_wm_compile *c, 258 const struct brw_reg *dst, 259 GLuint mask, 260 const struct brw_reg *arg0, 261 const struct brw_reg *deltas) 262{ 263 struct brw_compile *p = &c->func; 264 struct intel_context *intel = &p->brw->intel; 265 struct brw_reg src; 266 struct brw_reg temp_dst; 267 268 if (intel->gen >= 6) 269 temp_dst = dst[3]; 270 else 271 temp_dst = brw_message_reg(2); 272 273 assert(intel->gen < 6); 274 275 /* Don't need this if all you are doing is interpolating color, for 276 * instance. 277 */ 278 if (mask & WRITEMASK_W) { 279 struct brw_reg interp3 = brw_vec1_grf(arg0[0].nr+1, 4); 280 281 /* Calc 1/w - just linterp wpos[3] optimized by putting the 282 * result straight into a message reg. 283 */ 284 if (can_do_pln(intel, deltas)) { 285 brw_PLN(p, temp_dst, interp3, deltas[0]); 286 } else { 287 brw_LINE(p, brw_null_reg(), interp3, deltas[0]); 288 brw_MAC(p, temp_dst, suboffset(interp3, 1), deltas[1]); 289 } 290 291 /* Calc w */ 292 if (intel->gen >= 6) 293 src = temp_dst; 294 else 295 src = brw_null_reg(); 296 297 if (c->dispatch_width == 16) { 298 brw_math_16(p, dst[3], 299 BRW_MATH_FUNCTION_INV, 300 2, src, 301 BRW_MATH_PRECISION_FULL); 302 } else { 303 brw_math(p, dst[3], 304 BRW_MATH_FUNCTION_INV, 305 2, src, 306 BRW_MATH_DATA_VECTOR, 307 BRW_MATH_PRECISION_FULL); 308 } 309 } 310} 311 312void emit_linterp(struct brw_compile *p, 313 const struct brw_reg *dst, 314 GLuint mask, 315 const struct brw_reg *arg0, 316 const struct brw_reg *deltas) 317{ 318 struct intel_context *intel = &p->brw->intel; 319 struct brw_reg interp[4]; 320 GLuint nr = arg0[0].nr; 321 GLuint i; 322 323 interp[0] = brw_vec1_grf(nr, 0); 324 interp[1] = brw_vec1_grf(nr, 4); 325 interp[2] = brw_vec1_grf(nr+1, 0); 326 interp[3] = brw_vec1_grf(nr+1, 4); 327 328 for (i = 0; i < 4; i++) { 329 if (mask & (1<<i)) { 330 if (intel->gen >= 6) { 331 brw_PLN(p, dst[i], interp[i], brw_vec8_grf(2, 0)); 332 } else if (can_do_pln(intel, deltas)) { 333 brw_PLN(p, dst[i], interp[i], deltas[0]); 334 } else { 335 brw_LINE(p, brw_null_reg(), interp[i], deltas[0]); 336 brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]); 337 } 338 } 339 } 340} 341 342 343void emit_pinterp(struct brw_compile *p, 344 const struct brw_reg *dst, 345 GLuint mask, 346 const struct brw_reg *arg0, 347 const struct brw_reg *deltas, 348 const struct brw_reg *w) 349{ 350 struct intel_context *intel = &p->brw->intel; 351 struct brw_reg interp[4]; 352 GLuint nr = arg0[0].nr; 353 GLuint i; 354 355 if (intel->gen >= 6) { 356 emit_linterp(p, dst, mask, arg0, interp); 357 return; 358 } 359 360 interp[0] = brw_vec1_grf(nr, 0); 361 interp[1] = brw_vec1_grf(nr, 4); 362 interp[2] = brw_vec1_grf(nr+1, 0); 363 interp[3] = brw_vec1_grf(nr+1, 4); 364 365 for (i = 0; i < 4; i++) { 366 if (mask & (1<<i)) { 367 if (can_do_pln(intel, deltas)) { 368 brw_PLN(p, dst[i], interp[i], deltas[0]); 369 } else { 370 brw_LINE(p, brw_null_reg(), interp[i], deltas[0]); 371 brw_MAC(p, dst[i], suboffset(interp[i],1), deltas[1]); 372 } 373 } 374 } 375 for (i = 0; i < 4; i++) { 376 if (mask & (1<<i)) { 377 brw_MUL(p, dst[i], dst[i], w[3]); 378 } 379 } 380} 381 382 383void emit_cinterp(struct brw_compile *p, 384 const struct brw_reg *dst, 385 GLuint mask, 386 const struct brw_reg *arg0) 387{ 388 struct brw_reg interp[4]; 389 GLuint nr = arg0[0].nr; 390 GLuint i; 391 392 interp[0] = brw_vec1_grf(nr, 0); 393 interp[1] = brw_vec1_grf(nr, 4); 394 interp[2] = brw_vec1_grf(nr+1, 0); 395 interp[3] = brw_vec1_grf(nr+1, 4); 396 397 for (i = 0; i < 4; i++) { 398 if (mask & (1<<i)) { 399 brw_MOV(p, dst[i], suboffset(interp[i],3)); /* TODO: optimize away like other moves */ 400 } 401 } 402} 403 404/* Sets the destination channels to 1.0 or 0.0 according to glFrontFacing. */ 405void emit_frontfacing(struct brw_compile *p, 406 const struct brw_reg *dst, 407 GLuint mask) 408{ 409 struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD); 410 GLuint i; 411 412 if (!(mask & WRITEMASK_XYZW)) 413 return; 414 415 for (i = 0; i < 4; i++) { 416 if (mask & (1<<i)) { 417 brw_MOV(p, dst[i], brw_imm_f(0.0)); 418 } 419 } 420 421 /* bit 31 is "primitive is back face", so checking < (1 << 31) gives 422 * us front face 423 */ 424 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, r1_6ud, brw_imm_ud(1 << 31)); 425 for (i = 0; i < 4; i++) { 426 if (mask & (1<<i)) { 427 brw_MOV(p, dst[i], brw_imm_f(1.0)); 428 } 429 } 430 brw_set_predicate_control_flag_value(p, 0xff); 431} 432 433/* For OPCODE_DDX and OPCODE_DDY, per channel of output we've got input 434 * looking like: 435 * 436 * arg0: ss0.tl ss0.tr ss0.bl ss0.br ss1.tl ss1.tr ss1.bl ss1.br 437 * 438 * and we're trying to produce: 439 * 440 * DDX DDY 441 * dst: (ss0.tr - ss0.tl) (ss0.tl - ss0.bl) 442 * (ss0.tr - ss0.tl) (ss0.tr - ss0.br) 443 * (ss0.br - ss0.bl) (ss0.tl - ss0.bl) 444 * (ss0.br - ss0.bl) (ss0.tr - ss0.br) 445 * (ss1.tr - ss1.tl) (ss1.tl - ss1.bl) 446 * (ss1.tr - ss1.tl) (ss1.tr - ss1.br) 447 * (ss1.br - ss1.bl) (ss1.tl - ss1.bl) 448 * (ss1.br - ss1.bl) (ss1.tr - ss1.br) 449 * 450 * and add another set of two more subspans if in 16-pixel dispatch mode. 451 * 452 * For DDX, it ends up being easy: width = 2, horiz=0 gets us the same result 453 * for each pair, and vertstride = 2 jumps us 2 elements after processing a 454 * pair. But for DDY, it's harder, as we want to produce the pairs swizzled 455 * between each other. We could probably do it like ddx and swizzle the right 456 * order later, but bail for now and just produce 457 * ((ss0.tl - ss0.bl)x4 (ss1.tl - ss1.bl)x4) 458 * 459 * The negate_value boolean is used to negate the d/dy computation for FBOs, 460 * since they place the origin at the upper left instead of the lower left. 461 */ 462void emit_ddxy(struct brw_compile *p, 463 const struct brw_reg *dst, 464 GLuint mask, 465 bool is_ddx, 466 const struct brw_reg *arg0, 467 bool negate_value) 468{ 469 int i; 470 struct brw_reg src0, src1; 471 472 if (mask & SATURATE) 473 brw_set_saturate(p, 1); 474 for (i = 0; i < 4; i++ ) { 475 if (mask & (1<<i)) { 476 if (is_ddx) { 477 src0 = brw_reg(arg0[i].file, arg0[i].nr, 1, 478 BRW_REGISTER_TYPE_F, 479 BRW_VERTICAL_STRIDE_2, 480 BRW_WIDTH_2, 481 BRW_HORIZONTAL_STRIDE_0, 482 BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); 483 src1 = brw_reg(arg0[i].file, arg0[i].nr, 0, 484 BRW_REGISTER_TYPE_F, 485 BRW_VERTICAL_STRIDE_2, 486 BRW_WIDTH_2, 487 BRW_HORIZONTAL_STRIDE_0, 488 BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); 489 } else { 490 src0 = brw_reg(arg0[i].file, arg0[i].nr, 0, 491 BRW_REGISTER_TYPE_F, 492 BRW_VERTICAL_STRIDE_4, 493 BRW_WIDTH_4, 494 BRW_HORIZONTAL_STRIDE_0, 495 BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); 496 src1 = brw_reg(arg0[i].file, arg0[i].nr, 2, 497 BRW_REGISTER_TYPE_F, 498 BRW_VERTICAL_STRIDE_4, 499 BRW_WIDTH_4, 500 BRW_HORIZONTAL_STRIDE_0, 501 BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); 502 } 503 if (negate_value) 504 brw_ADD(p, dst[i], src1, negate(src0)); 505 else 506 brw_ADD(p, dst[i], src0, negate(src1)); 507 } 508 } 509 if (mask & SATURATE) 510 brw_set_saturate(p, 0); 511} 512 513void emit_alu1(struct brw_compile *p, 514 struct brw_instruction *(*func)(struct brw_compile *, 515 struct brw_reg, 516 struct brw_reg), 517 const struct brw_reg *dst, 518 GLuint mask, 519 const struct brw_reg *arg0) 520{ 521 GLuint i; 522 523 if (mask & SATURATE) 524 brw_set_saturate(p, 1); 525 526 for (i = 0; i < 4; i++) { 527 if (mask & (1<<i)) { 528 func(p, dst[i], arg0[i]); 529 } 530 } 531 532 if (mask & SATURATE) 533 brw_set_saturate(p, 0); 534} 535 536 537void emit_alu2(struct brw_compile *p, 538 struct brw_instruction *(*func)(struct brw_compile *, 539 struct brw_reg, 540 struct brw_reg, 541 struct brw_reg), 542 const struct brw_reg *dst, 543 GLuint mask, 544 const struct brw_reg *arg0, 545 const struct brw_reg *arg1) 546{ 547 GLuint i; 548 549 if (mask & SATURATE) 550 brw_set_saturate(p, 1); 551 552 for (i = 0; i < 4; i++) { 553 if (mask & (1<<i)) { 554 func(p, dst[i], arg0[i], arg1[i]); 555 } 556 } 557 558 if (mask & SATURATE) 559 brw_set_saturate(p, 0); 560} 561 562 563void emit_mad(struct brw_compile *p, 564 const struct brw_reg *dst, 565 GLuint mask, 566 const struct brw_reg *arg0, 567 const struct brw_reg *arg1, 568 const struct brw_reg *arg2) 569{ 570 GLuint i; 571 572 for (i = 0; i < 4; i++) { 573 if (mask & (1<<i)) { 574 brw_MUL(p, dst[i], arg0[i], arg1[i]); 575 576 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 577 brw_ADD(p, dst[i], dst[i], arg2[i]); 578 brw_set_saturate(p, 0); 579 } 580 } 581} 582 583void emit_lrp(struct brw_compile *p, 584 const struct brw_reg *dst, 585 GLuint mask, 586 const struct brw_reg *arg0, 587 const struct brw_reg *arg1, 588 const struct brw_reg *arg2) 589{ 590 GLuint i; 591 592 /* Uses dst as a temporary: 593 */ 594 for (i = 0; i < 4; i++) { 595 if (mask & (1<<i)) { 596 /* Can I use the LINE instruction for this? 597 */ 598 brw_ADD(p, dst[i], negate(arg0[i]), brw_imm_f(1.0)); 599 brw_MUL(p, brw_null_reg(), dst[i], arg2[i]); 600 601 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 602 brw_MAC(p, dst[i], arg0[i], arg1[i]); 603 brw_set_saturate(p, 0); 604 } 605 } 606} 607 608void emit_sop(struct brw_compile *p, 609 const struct brw_reg *dst, 610 GLuint mask, 611 GLuint cond, 612 const struct brw_reg *arg0, 613 const struct brw_reg *arg1) 614{ 615 GLuint i; 616 617 for (i = 0; i < 4; i++) { 618 if (mask & (1<<i)) { 619 brw_push_insn_state(p); 620 brw_CMP(p, brw_null_reg(), cond, arg0[i], arg1[i]); 621 brw_set_predicate_control(p, BRW_PREDICATE_NONE); 622 brw_MOV(p, dst[i], brw_imm_f(0)); 623 brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); 624 brw_MOV(p, dst[i], brw_imm_f(1.0)); 625 brw_pop_insn_state(p); 626 } 627 } 628} 629 630static void emit_slt( struct brw_compile *p, 631 const struct brw_reg *dst, 632 GLuint mask, 633 const struct brw_reg *arg0, 634 const struct brw_reg *arg1 ) 635{ 636 emit_sop(p, dst, mask, BRW_CONDITIONAL_L, arg0, arg1); 637} 638 639static void emit_sle( struct brw_compile *p, 640 const struct brw_reg *dst, 641 GLuint mask, 642 const struct brw_reg *arg0, 643 const struct brw_reg *arg1 ) 644{ 645 emit_sop(p, dst, mask, BRW_CONDITIONAL_LE, arg0, arg1); 646} 647 648static void emit_sgt( struct brw_compile *p, 649 const struct brw_reg *dst, 650 GLuint mask, 651 const struct brw_reg *arg0, 652 const struct brw_reg *arg1 ) 653{ 654 emit_sop(p, dst, mask, BRW_CONDITIONAL_G, arg0, arg1); 655} 656 657static void emit_sge( struct brw_compile *p, 658 const struct brw_reg *dst, 659 GLuint mask, 660 const struct brw_reg *arg0, 661 const struct brw_reg *arg1 ) 662{ 663 emit_sop(p, dst, mask, BRW_CONDITIONAL_GE, arg0, arg1); 664} 665 666static void emit_seq( struct brw_compile *p, 667 const struct brw_reg *dst, 668 GLuint mask, 669 const struct brw_reg *arg0, 670 const struct brw_reg *arg1 ) 671{ 672 emit_sop(p, dst, mask, BRW_CONDITIONAL_EQ, arg0, arg1); 673} 674 675static void emit_sne( struct brw_compile *p, 676 const struct brw_reg *dst, 677 GLuint mask, 678 const struct brw_reg *arg0, 679 const struct brw_reg *arg1 ) 680{ 681 emit_sop(p, dst, mask, BRW_CONDITIONAL_NEQ, arg0, arg1); 682} 683 684void emit_cmp(struct brw_compile *p, 685 const struct brw_reg *dst, 686 GLuint mask, 687 const struct brw_reg *arg0, 688 const struct brw_reg *arg1, 689 const struct brw_reg *arg2) 690{ 691 GLuint i; 692 693 for (i = 0; i < 4; i++) { 694 if (mask & (1<<i)) { 695 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], brw_imm_f(0)); 696 697 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 698 brw_SEL(p, dst[i], arg1[i], arg2[i]); 699 brw_set_saturate(p, 0); 700 brw_set_predicate_control_flag_value(p, 0xff); 701 } 702 } 703} 704 705void emit_sign(struct brw_compile *p, 706 const struct brw_reg *dst, 707 GLuint mask, 708 const struct brw_reg *arg0) 709{ 710 GLuint i; 711 712 for (i = 0; i < 4; i++) { 713 if (mask & (1<<i)) { 714 brw_MOV(p, dst[i], brw_imm_f(0.0)); 715 716 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], brw_imm_f(0)); 717 brw_MOV(p, dst[i], brw_imm_f(-1.0)); 718 brw_set_predicate_control(p, BRW_PREDICATE_NONE); 719 720 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_G, arg0[i], brw_imm_f(0)); 721 brw_MOV(p, dst[i], brw_imm_f(1.0)); 722 brw_set_predicate_control(p, BRW_PREDICATE_NONE); 723 } 724 } 725} 726 727void emit_max(struct brw_compile *p, 728 const struct brw_reg *dst, 729 GLuint mask, 730 const struct brw_reg *arg0, 731 const struct brw_reg *arg1) 732{ 733 GLuint i; 734 735 for (i = 0; i < 4; i++) { 736 if (mask & (1<<i)) { 737 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_GE, arg0[i], arg1[i]); 738 739 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 740 brw_SEL(p, dst[i], arg0[i], arg1[i]); 741 brw_set_saturate(p, 0); 742 brw_set_predicate_control_flag_value(p, 0xff); 743 } 744 } 745} 746 747void emit_min(struct brw_compile *p, 748 const struct brw_reg *dst, 749 GLuint mask, 750 const struct brw_reg *arg0, 751 const struct brw_reg *arg1) 752{ 753 GLuint i; 754 755 for (i = 0; i < 4; i++) { 756 if (mask & (1<<i)) { 757 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, arg0[i], arg1[i]); 758 759 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 760 brw_SEL(p, dst[i], arg0[i], arg1[i]); 761 brw_set_saturate(p, 0); 762 brw_set_predicate_control_flag_value(p, 0xff); 763 } 764 } 765} 766 767 768void emit_dp2(struct brw_compile *p, 769 const struct brw_reg *dst, 770 GLuint mask, 771 const struct brw_reg *arg0, 772 const struct brw_reg *arg1) 773{ 774 int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1; 775 776 if (!(mask & WRITEMASK_XYZW)) 777 return; /* Do not emit dead code */ 778 779 assert(is_power_of_two(mask & WRITEMASK_XYZW)); 780 781 brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]); 782 783 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 784 brw_MAC(p, dst[dst_chan], arg0[1], arg1[1]); 785 brw_set_saturate(p, 0); 786} 787 788 789void emit_dp3(struct brw_compile *p, 790 const struct brw_reg *dst, 791 GLuint mask, 792 const struct brw_reg *arg0, 793 const struct brw_reg *arg1) 794{ 795 int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1; 796 797 if (!(mask & WRITEMASK_XYZW)) 798 return; /* Do not emit dead code */ 799 800 assert(is_power_of_two(mask & WRITEMASK_XYZW)); 801 802 brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]); 803 brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]); 804 805 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 806 brw_MAC(p, dst[dst_chan], arg0[2], arg1[2]); 807 brw_set_saturate(p, 0); 808} 809 810 811void emit_dp4(struct brw_compile *p, 812 const struct brw_reg *dst, 813 GLuint mask, 814 const struct brw_reg *arg0, 815 const struct brw_reg *arg1) 816{ 817 int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1; 818 819 if (!(mask & WRITEMASK_XYZW)) 820 return; /* Do not emit dead code */ 821 822 assert(is_power_of_two(mask & WRITEMASK_XYZW)); 823 824 brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]); 825 brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]); 826 brw_MAC(p, brw_null_reg(), arg0[2], arg1[2]); 827 828 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 829 brw_MAC(p, dst[dst_chan], arg0[3], arg1[3]); 830 brw_set_saturate(p, 0); 831} 832 833 834void emit_dph(struct brw_compile *p, 835 const struct brw_reg *dst, 836 GLuint mask, 837 const struct brw_reg *arg0, 838 const struct brw_reg *arg1) 839{ 840 const int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1; 841 842 if (!(mask & WRITEMASK_XYZW)) 843 return; /* Do not emit dead code */ 844 845 assert(is_power_of_two(mask & WRITEMASK_XYZW)); 846 847 brw_MUL(p, brw_null_reg(), arg0[0], arg1[0]); 848 brw_MAC(p, brw_null_reg(), arg0[1], arg1[1]); 849 brw_MAC(p, dst[dst_chan], arg0[2], arg1[2]); 850 851 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 852 brw_ADD(p, dst[dst_chan], dst[dst_chan], arg1[3]); 853 brw_set_saturate(p, 0); 854} 855 856 857void emit_xpd(struct brw_compile *p, 858 const struct brw_reg *dst, 859 GLuint mask, 860 const struct brw_reg *arg0, 861 const struct brw_reg *arg1) 862{ 863 GLuint i; 864 865 assert((mask & WRITEMASK_W) != WRITEMASK_W); 866 867 for (i = 0 ; i < 3; i++) { 868 if (mask & (1<<i)) { 869 GLuint i2 = (i+2)%3; 870 GLuint i1 = (i+1)%3; 871 872 brw_MUL(p, brw_null_reg(), negate(arg0[i2]), arg1[i1]); 873 874 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 875 brw_MAC(p, dst[i], arg0[i1], arg1[i2]); 876 brw_set_saturate(p, 0); 877 } 878 } 879} 880 881 882void emit_math1(struct brw_wm_compile *c, 883 GLuint function, 884 const struct brw_reg *dst, 885 GLuint mask, 886 const struct brw_reg *arg0) 887{ 888 struct brw_compile *p = &c->func; 889 struct intel_context *intel = &p->brw->intel; 890 int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1; 891 struct brw_reg src; 892 893 if (!(mask & WRITEMASK_XYZW)) 894 return; /* Do not emit dead code */ 895 896 assert(is_power_of_two(mask & WRITEMASK_XYZW)); 897 898 if (intel->gen >= 6 && ((arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0 || 899 arg0[0].file != BRW_GENERAL_REGISTER_FILE) || 900 arg0[0].negate || arg0[0].abs)) { 901 /* Gen6 math requires that source and dst horizontal stride be 1, 902 * and that the argument be in the GRF. 903 * 904 * The hardware ignores source modifiers (negate and abs) on math 905 * instructions, so we also move to a temp to set those up. 906 */ 907 src = dst[dst_chan]; 908 brw_MOV(p, src, arg0[0]); 909 } else { 910 src = arg0[0]; 911 } 912 913 /* Send two messages to perform all 16 operations: 914 */ 915 brw_push_insn_state(p); 916 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 917 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 918 brw_math(p, 919 dst[dst_chan], 920 function, 921 2, 922 src, 923 BRW_MATH_DATA_VECTOR, 924 BRW_MATH_PRECISION_FULL); 925 926 if (c->dispatch_width == 16) { 927 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); 928 brw_math(p, 929 offset(dst[dst_chan],1), 930 function, 931 3, 932 sechalf(src), 933 BRW_MATH_DATA_VECTOR, 934 BRW_MATH_PRECISION_FULL); 935 } 936 brw_pop_insn_state(p); 937} 938 939 940void emit_math2(struct brw_wm_compile *c, 941 GLuint function, 942 const struct brw_reg *dst, 943 GLuint mask, 944 const struct brw_reg *arg0, 945 const struct brw_reg *arg1) 946{ 947 struct brw_compile *p = &c->func; 948 struct intel_context *intel = &p->brw->intel; 949 int dst_chan = ffs(mask & WRITEMASK_XYZW) - 1; 950 951 if (!(mask & WRITEMASK_XYZW)) 952 return; /* Do not emit dead code */ 953 954 assert(is_power_of_two(mask & WRITEMASK_XYZW)); 955 956 brw_push_insn_state(p); 957 958 /* math can only operate on up to a vec8 at a time, so in 959 * dispatch_width==16 we have to do the second half manually. 960 */ 961 if (intel->gen >= 6) { 962 struct brw_reg src0 = arg0[0]; 963 struct brw_reg src1 = arg1[0]; 964 struct brw_reg temp_dst = dst[dst_chan]; 965 966 if (arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0) { 967 brw_MOV(p, temp_dst, src0); 968 src0 = temp_dst; 969 } 970 971 if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) { 972 /* This is a heinous hack to get a temporary register for use 973 * in case both arg0 and arg1 are constants. Why you're 974 * doing exponentiation on constant values in the shader, we 975 * don't know. 976 * 977 * max_wm_grf is almost surely less than the maximum GRF, and 978 * gen6 doesn't care about the number of GRFs used in a 979 * shader like pre-gen6 did. 980 */ 981 struct brw_reg temp = brw_vec8_grf(c->max_wm_grf, 0); 982 brw_MOV(p, temp, src1); 983 src1 = temp; 984 } 985 986 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 987 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 988 brw_math2(p, 989 temp_dst, 990 function, 991 src0, 992 src1); 993 if (c->dispatch_width == 16) { 994 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); 995 brw_math2(p, 996 sechalf(temp_dst), 997 function, 998 sechalf(src0), 999 sechalf(src1)); 1000 } 1001 } else { 1002 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1003 brw_MOV(p, brw_message_reg(3), arg1[0]); 1004 if (c->dispatch_width == 16) { 1005 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); 1006 brw_MOV(p, brw_message_reg(5), sechalf(arg1[0])); 1007 } 1008 1009 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 1010 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1011 brw_math(p, 1012 dst[dst_chan], 1013 function, 1014 2, 1015 arg0[0], 1016 BRW_MATH_DATA_VECTOR, 1017 BRW_MATH_PRECISION_FULL); 1018 1019 /* Send two messages to perform all 16 operations: 1020 */ 1021 if (c->dispatch_width == 16) { 1022 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); 1023 brw_math(p, 1024 offset(dst[dst_chan],1), 1025 function, 1026 4, 1027 sechalf(arg0[0]), 1028 BRW_MATH_DATA_VECTOR, 1029 BRW_MATH_PRECISION_FULL); 1030 } 1031 } 1032 brw_pop_insn_state(p); 1033} 1034 1035 1036void emit_tex(struct brw_wm_compile *c, 1037 struct brw_reg *dst, 1038 GLuint dst_flags, 1039 struct brw_reg *arg, 1040 struct brw_reg depth_payload, 1041 GLuint tex_idx, 1042 GLuint sampler, 1043 bool shadow) 1044{ 1045 struct brw_compile *p = &c->func; 1046 struct intel_context *intel = &p->brw->intel; 1047 struct brw_reg dst_retyped; 1048 GLuint cur_mrf = 2, response_length; 1049 GLuint i, nr_texcoords; 1050 GLuint emit; 1051 GLuint msg_type; 1052 GLuint mrf_per_channel; 1053 GLuint simd_mode; 1054 1055 if (c->dispatch_width == 16) { 1056 mrf_per_channel = 2; 1057 response_length = 8; 1058 dst_retyped = retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW); 1059 simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; 1060 } else { 1061 mrf_per_channel = 1; 1062 response_length = 4; 1063 dst_retyped = retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW); 1064 simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8; 1065 } 1066 1067 /* How many input regs are there? 1068 */ 1069 switch (tex_idx) { 1070 case TEXTURE_1D_INDEX: 1071 emit = WRITEMASK_X; 1072 nr_texcoords = 1; 1073 break; 1074 case TEXTURE_2D_INDEX: 1075 case TEXTURE_1D_ARRAY_INDEX: 1076 case TEXTURE_RECT_INDEX: 1077 case TEXTURE_EXTERNAL_INDEX: 1078 emit = WRITEMASK_XY; 1079 nr_texcoords = 2; 1080 break; 1081 case TEXTURE_3D_INDEX: 1082 case TEXTURE_2D_ARRAY_INDEX: 1083 case TEXTURE_CUBE_INDEX: 1084 emit = WRITEMASK_XYZ; 1085 nr_texcoords = 3; 1086 break; 1087 default: 1088 /* unexpected target */ 1089 abort(); 1090 } 1091 1092 /* Pre-Ironlake, the 8-wide sampler always took u,v,r. */ 1093 if (intel->gen < 5 && c->dispatch_width == 8) 1094 nr_texcoords = 3; 1095 1096 if (shadow) { 1097 if (intel->gen < 7) { 1098 /* For shadow comparisons, we have to supply u,v,r. */ 1099 nr_texcoords = 3; 1100 } else { 1101 /* On Ivybridge, the shadow comparitor comes first. Just load it. */ 1102 brw_MOV(p, brw_message_reg(cur_mrf), arg[2]); 1103 cur_mrf += mrf_per_channel; 1104 } 1105 } 1106 1107 /* Emit the texcoords. */ 1108 for (i = 0; i < nr_texcoords; i++) { 1109 if (c->key.tex.gl_clamp_mask[i] & (1 << sampler)) 1110 brw_set_saturate(p, true); 1111 1112 if (emit & (1<<i)) 1113 brw_MOV(p, brw_message_reg(cur_mrf), arg[i]); 1114 else 1115 brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0)); 1116 cur_mrf += mrf_per_channel; 1117 1118 brw_set_saturate(p, false); 1119 } 1120 1121 /* Fill in the shadow comparison reference value. */ 1122 if (shadow && intel->gen < 7) { 1123 if (intel->gen >= 5) { 1124 /* Fill in the cube map array index value. */ 1125 brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0)); 1126 cur_mrf += mrf_per_channel; 1127 } else if (c->dispatch_width == 8) { 1128 /* Fill in the LOD bias value. */ 1129 brw_MOV(p, brw_message_reg(cur_mrf), brw_imm_f(0)); 1130 cur_mrf += mrf_per_channel; 1131 } 1132 brw_MOV(p, brw_message_reg(cur_mrf), arg[2]); 1133 cur_mrf += mrf_per_channel; 1134 } 1135 1136 if (intel->gen >= 5) { 1137 if (shadow) 1138 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_COMPARE; 1139 else 1140 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE; 1141 } else { 1142 /* Note that G45 and older determines shadow compare and dispatch width 1143 * from message length for most messages. 1144 */ 1145 if (c->dispatch_width == 16 && shadow) 1146 msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE; 1147 else 1148 msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE; 1149 } 1150 1151 brw_SAMPLE(p, 1152 dst_retyped, 1153 1, 1154 retype(depth_payload, BRW_REGISTER_TYPE_UW), 1155 SURF_INDEX_TEXTURE(sampler), 1156 sampler, 1157 dst_flags & WRITEMASK_XYZW, 1158 msg_type, 1159 response_length, 1160 cur_mrf - 1, 1161 1, 1162 simd_mode, 1163 BRW_SAMPLER_RETURN_FORMAT_FLOAT32); 1164} 1165 1166 1167void emit_txb(struct brw_wm_compile *c, 1168 struct brw_reg *dst, 1169 GLuint dst_flags, 1170 struct brw_reg *arg, 1171 struct brw_reg depth_payload, 1172 GLuint tex_idx, 1173 GLuint sampler) 1174{ 1175 struct brw_compile *p = &c->func; 1176 struct intel_context *intel = &p->brw->intel; 1177 GLuint msgLength; 1178 GLuint msg_type; 1179 GLuint mrf_per_channel; 1180 GLuint response_length; 1181 struct brw_reg dst_retyped; 1182 1183 /* The G45 and older chipsets don't support 8-wide dispatch for LOD biased 1184 * samples, so we'll use the 16-wide instruction, leave the second halves 1185 * undefined, and trust the execution mask to keep the undefined pixels 1186 * from mattering. 1187 */ 1188 if (c->dispatch_width == 16 || intel->gen < 5) { 1189 if (intel->gen >= 5) 1190 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS; 1191 else 1192 msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS; 1193 mrf_per_channel = 2; 1194 dst_retyped = retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW); 1195 response_length = 8; 1196 } else { 1197 msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS; 1198 mrf_per_channel = 1; 1199 dst_retyped = retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW); 1200 response_length = 4; 1201 } 1202 1203 /* Shadow ignored for txb. */ 1204 switch (tex_idx) { 1205 case TEXTURE_1D_INDEX: 1206 brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]); 1207 brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), brw_imm_f(0)); 1208 brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), brw_imm_f(0)); 1209 break; 1210 case TEXTURE_2D_INDEX: 1211 case TEXTURE_RECT_INDEX: 1212 case TEXTURE_EXTERNAL_INDEX: 1213 brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]); 1214 brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), arg[1]); 1215 brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), brw_imm_f(0)); 1216 break; 1217 case TEXTURE_3D_INDEX: 1218 case TEXTURE_CUBE_INDEX: 1219 brw_MOV(p, brw_message_reg(2 + 0 * mrf_per_channel), arg[0]); 1220 brw_MOV(p, brw_message_reg(2 + 1 * mrf_per_channel), arg[1]); 1221 brw_MOV(p, brw_message_reg(2 + 2 * mrf_per_channel), arg[2]); 1222 break; 1223 default: 1224 /* unexpected target */ 1225 abort(); 1226 } 1227 1228 brw_MOV(p, brw_message_reg(2 + 3 * mrf_per_channel), arg[3]); 1229 msgLength = 2 + 4 * mrf_per_channel - 1; 1230 1231 brw_SAMPLE(p, 1232 dst_retyped, 1233 1, 1234 retype(depth_payload, BRW_REGISTER_TYPE_UW), 1235 SURF_INDEX_TEXTURE(sampler), 1236 sampler, 1237 dst_flags & WRITEMASK_XYZW, 1238 msg_type, 1239 response_length, 1240 msgLength, 1241 1, 1242 BRW_SAMPLER_SIMD_MODE_SIMD16, 1243 BRW_SAMPLER_RETURN_FORMAT_FLOAT32); 1244} 1245 1246 1247static void emit_lit(struct brw_wm_compile *c, 1248 const struct brw_reg *dst, 1249 GLuint mask, 1250 const struct brw_reg *arg0) 1251{ 1252 struct brw_compile *p = &c->func; 1253 1254 assert((mask & WRITEMASK_XW) == 0); 1255 1256 if (mask & WRITEMASK_Y) { 1257 brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); 1258 brw_MOV(p, dst[1], arg0[0]); 1259 brw_set_saturate(p, 0); 1260 } 1261 1262 if (mask & WRITEMASK_Z) { 1263 emit_math2(c, BRW_MATH_FUNCTION_POW, 1264 &dst[2], 1265 WRITEMASK_X | (mask & SATURATE), 1266 &arg0[1], 1267 &arg0[3]); 1268 } 1269 1270 /* Ordinarily you'd use an iff statement to skip or shortcircuit 1271 * some of the POW calculations above, but 16-wide iff statements 1272 * seem to lock c1 hardware, so this is a nasty workaround: 1273 */ 1274 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_LE, arg0[0], brw_imm_f(0)); 1275 { 1276 if (mask & WRITEMASK_Y) 1277 brw_MOV(p, dst[1], brw_imm_f(0)); 1278 1279 if (mask & WRITEMASK_Z) 1280 brw_MOV(p, dst[2], brw_imm_f(0)); 1281 } 1282 brw_set_predicate_control(p, BRW_PREDICATE_NONE); 1283} 1284 1285 1286/* Kill pixel - set execution mask to zero for those pixels which 1287 * fail. 1288 */ 1289static void emit_kil( struct brw_wm_compile *c, 1290 struct brw_reg *arg0) 1291{ 1292 struct brw_compile *p = &c->func; 1293 struct intel_context *intel = &p->brw->intel; 1294 struct brw_reg pixelmask; 1295 GLuint i, j; 1296 1297 if (intel->gen >= 6) 1298 pixelmask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW); 1299 else 1300 pixelmask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW); 1301 1302 for (i = 0; i < 4; i++) { 1303 /* Check if we've already done the comparison for this reg 1304 * -- common when someone does KIL TEMP.wwww. 1305 */ 1306 for (j = 0; j < i; j++) { 1307 if (memcmp(&arg0[j], &arg0[i], sizeof(arg0[0])) == 0) 1308 break; 1309 } 1310 if (j != i) 1311 continue; 1312 1313 brw_push_insn_state(p); 1314 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_GE, arg0[i], brw_imm_f(0)); 1315 brw_set_predicate_control_flag_value(p, 0xff); 1316 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1317 brw_AND(p, pixelmask, brw_flag_reg(), pixelmask); 1318 brw_pop_insn_state(p); 1319 } 1320} 1321 1322static void fire_fb_write( struct brw_wm_compile *c, 1323 GLuint base_reg, 1324 GLuint nr, 1325 GLuint target, 1326 GLuint eot ) 1327{ 1328 struct brw_compile *p = &c->func; 1329 struct intel_context *intel = &p->brw->intel; 1330 uint32_t msg_control; 1331 1332 /* Pass through control information: 1333 * 1334 * Gen6 has done m1 mov in emit_fb_write() for current SIMD16 case. 1335 */ 1336/* mov (8) m1.0<1>:ud r1.0<8;8,1>:ud { Align1 NoMask } */ 1337 if (intel->gen < 6) 1338 { 1339 brw_push_insn_state(p); 1340 brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */ 1341 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1342 brw_MOV(p, 1343 brw_message_reg(base_reg + 1), 1344 brw_vec8_grf(1, 0)); 1345 brw_pop_insn_state(p); 1346 } 1347 1348 if (c->dispatch_width == 16) 1349 msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE; 1350 else 1351 msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01; 1352 1353 /* Send framebuffer write message: */ 1354/* send (16) null.0<1>:uw m0 r0.0<8;8,1>:uw 0x85a04000:ud { Align1 EOT } */ 1355 brw_fb_WRITE(p, 1356 c->dispatch_width, 1357 base_reg, 1358 retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW), 1359 msg_control, 1360 target, 1361 nr, 1362 0, 1363 eot, 1364 true); 1365} 1366 1367 1368static void emit_aa( struct brw_wm_compile *c, 1369 struct brw_reg *arg1, 1370 GLuint reg ) 1371{ 1372 struct brw_compile *p = &c->func; 1373 GLuint comp = c->aa_dest_stencil_reg / 2; 1374 GLuint off = c->aa_dest_stencil_reg % 2; 1375 struct brw_reg aa = offset(arg1[comp], off); 1376 1377 brw_push_insn_state(p); 1378 brw_set_compression_control(p, BRW_COMPRESSION_NONE); /* ?? */ 1379 brw_MOV(p, brw_message_reg(reg), aa); 1380 brw_pop_insn_state(p); 1381} 1382 1383 1384/* Post-fragment-program processing. Send the results to the 1385 * framebuffer. 1386 * \param arg0 the fragment color 1387 * \param arg1 the pass-through depth value 1388 * \param arg2 the shader-computed depth value 1389 */ 1390void emit_fb_write(struct brw_wm_compile *c, 1391 struct brw_reg *arg0, 1392 struct brw_reg *arg1, 1393 struct brw_reg *arg2, 1394 GLuint target, 1395 GLuint eot) 1396{ 1397 struct brw_compile *p = &c->func; 1398 struct brw_context *brw = p->brw; 1399 struct intel_context *intel = &brw->intel; 1400 GLuint nr = 2; 1401 GLuint channel; 1402 1403 /* Reserve a space for AA - may not be needed: 1404 */ 1405 if (c->aa_dest_stencil_reg) 1406 nr += 1; 1407 1408 /* I don't really understand how this achieves the color interleave 1409 * (ie RGBARGBA) in the result: [Do the saturation here] 1410 */ 1411 brw_push_insn_state(p); 1412 1413 if (c->key.clamp_fragment_color) 1414 brw_set_saturate(p, 1); 1415 1416 for (channel = 0; channel < 4; channel++) { 1417 if (intel->gen >= 6) { 1418 /* gen6 SIMD16 single source DP write looks like: 1419 * m + 0: r0 1420 * m + 1: r1 1421 * m + 2: g0 1422 * m + 3: g1 1423 * m + 4: b0 1424 * m + 5: b1 1425 * m + 6: a0 1426 * m + 7: a1 1427 */ 1428 if (c->dispatch_width == 16) { 1429 brw_MOV(p, brw_message_reg(nr + channel * 2), arg0[channel]); 1430 } else { 1431 brw_MOV(p, brw_message_reg(nr + channel), arg0[channel]); 1432 } 1433 } else if (c->dispatch_width == 16 && brw->has_compr4) { 1434 /* pre-gen6 SIMD16 single source DP write looks like: 1435 * m + 0: r0 1436 * m + 1: g0 1437 * m + 2: b0 1438 * m + 3: a0 1439 * m + 4: r1 1440 * m + 5: g1 1441 * m + 6: b1 1442 * m + 7: a1 1443 * 1444 * By setting the high bit of the MRF register number, we indicate 1445 * that we want COMPR4 mode - instead of doing the usual destination 1446 * + 1 for the second half we get destination + 4. 1447 */ 1448 brw_MOV(p, 1449 brw_message_reg(nr + channel + BRW_MRF_COMPR4), 1450 arg0[channel]); 1451 } else { 1452 /* mov (8) m2.0<1>:ud r28.0<8;8,1>:ud { Align1 } */ 1453 /* mov (8) m6.0<1>:ud r29.0<8;8,1>:ud { Align1 SecHalf } */ 1454 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1455 brw_MOV(p, 1456 brw_message_reg(nr + channel), 1457 arg0[channel]); 1458 1459 if (c->dispatch_width == 16) { 1460 brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); 1461 brw_MOV(p, 1462 brw_message_reg(nr + channel + 4), 1463 sechalf(arg0[channel])); 1464 } 1465 } 1466 } 1467 1468 brw_set_saturate(p, 0); 1469 1470 /* skip over the regs populated above: 1471 */ 1472 if (c->dispatch_width == 16) 1473 nr += 8; 1474 else 1475 nr += 4; 1476 1477 brw_pop_insn_state(p); 1478 1479 if (c->source_depth_to_render_target) 1480 { 1481 if (c->computes_depth) 1482 brw_MOV(p, brw_message_reg(nr), arg2[2]); 1483 else 1484 brw_MOV(p, brw_message_reg(nr), arg1[1]); /* ? */ 1485 1486 nr += 2; 1487 } 1488 1489 if (c->dest_depth_reg) 1490 { 1491 GLuint comp = c->dest_depth_reg / 2; 1492 GLuint off = c->dest_depth_reg % 2; 1493 1494 if (off != 0) { 1495 brw_push_insn_state(p); 1496 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1497 1498 brw_MOV(p, brw_message_reg(nr), offset(arg1[comp],1)); 1499 /* 2nd half? */ 1500 brw_MOV(p, brw_message_reg(nr+1), arg1[comp+1]); 1501 brw_pop_insn_state(p); 1502 } 1503 else { 1504 brw_MOV(p, brw_message_reg(nr), arg1[comp]); 1505 } 1506 nr += 2; 1507 } 1508 1509 if (intel->gen >= 6) { 1510 /* Load the message header. There's no implied move from src0 1511 * to the base mrf on gen6. 1512 */ 1513 brw_push_insn_state(p); 1514 brw_set_mask_control(p, BRW_MASK_DISABLE); 1515 brw_MOV(p, retype(brw_message_reg(0), BRW_REGISTER_TYPE_UD), 1516 retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); 1517 brw_pop_insn_state(p); 1518 1519 if (target != 0) { 1520 brw_MOV(p, retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, 1521 0, 1522 2), BRW_REGISTER_TYPE_UD), 1523 brw_imm_ud(target)); 1524 } 1525 } 1526 1527 if (!c->runtime_check_aads_emit) { 1528 if (c->aa_dest_stencil_reg) 1529 emit_aa(c, arg1, 2); 1530 1531 fire_fb_write(c, 0, nr, target, eot); 1532 } 1533 else { 1534 struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD)); 1535 struct brw_reg ip = brw_ip_reg(); 1536 int jmp; 1537 1538 brw_set_compression_control(p, BRW_COMPRESSION_NONE); 1539 brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); 1540 brw_AND(p, 1541 v1_null_ud, 1542 get_element_ud(brw_vec8_grf(1,0), 6), 1543 brw_imm_ud(1<<26)); 1544 1545 jmp = brw_JMPI(p, ip, ip, brw_imm_w(0)) - p->store; 1546 { 1547 emit_aa(c, arg1, 2); 1548 fire_fb_write(c, 0, nr, target, eot); 1549 /* note - thread killed in subroutine */ 1550 } 1551 brw_land_fwd_jump(p, jmp); 1552 1553 /* ELSE: Shuffle up one register to fill in the hole left for AA: 1554 */ 1555 fire_fb_write(c, 1, nr-1, target, eot); 1556 } 1557} 1558 1559/** 1560 * Move a GPR to scratch memory. 1561 */ 1562static void emit_spill( struct brw_wm_compile *c, 1563 struct brw_reg reg, 1564 GLuint slot ) 1565{ 1566 struct brw_compile *p = &c->func; 1567 1568 /* 1569 mov (16) m2.0<1>:ud r2.0<8;8,1>:ud { Align1 Compr } 1570 */ 1571 brw_MOV(p, brw_message_reg(2), reg); 1572 1573 /* 1574 mov (1) r0.2<1>:d 0x00000080:d { Align1 NoMask } 1575 send (16) null.0<1>:uw m1 r0.0<8;8,1>:uw 0x053003ff:ud { Align1 } 1576 */ 1577 brw_oword_block_write_scratch(p, brw_message_reg(1), 2, slot); 1578} 1579 1580 1581/** 1582 * Load a GPR from scratch memory. 1583 */ 1584static void emit_unspill( struct brw_wm_compile *c, 1585 struct brw_reg reg, 1586 GLuint slot ) 1587{ 1588 struct brw_compile *p = &c->func; 1589 1590 /* Slot 0 is the undef value. 1591 */ 1592 if (slot == 0) { 1593 brw_MOV(p, reg, brw_imm_f(0)); 1594 return; 1595 } 1596 1597 /* 1598 mov (1) r0.2<1>:d 0x000000c0:d { Align1 NoMask } 1599 send (16) r110.0<1>:uw m1 r0.0<8;8,1>:uw 0x041243ff:ud { Align1 } 1600 */ 1601 1602 brw_oword_block_read(p, vec16(reg), brw_message_reg(1), 2, slot); 1603} 1604 1605 1606/** 1607 * Retrieve up to 4 GEN4 register pairs for the given wm reg: 1608 * Args with unspill_reg != 0 will be loaded from scratch memory. 1609 */ 1610static void get_argument_regs( struct brw_wm_compile *c, 1611 struct brw_wm_ref *arg[], 1612 struct brw_reg *regs ) 1613{ 1614 GLuint i; 1615 1616 for (i = 0; i < 4; i++) { 1617 if (arg[i]) { 1618 if (arg[i]->unspill_reg) 1619 emit_unspill(c, 1620 brw_vec8_grf(arg[i]->unspill_reg, 0), 1621 arg[i]->value->spill_slot); 1622 1623 regs[i] = arg[i]->hw_reg; 1624 } 1625 else { 1626 regs[i] = brw_null_reg(); 1627 } 1628 } 1629} 1630 1631 1632/** 1633 * For values that have a spill_slot!=0, write those regs to scratch memory. 1634 */ 1635static void spill_values( struct brw_wm_compile *c, 1636 struct brw_wm_value *values, 1637 GLuint nr ) 1638{ 1639 GLuint i; 1640 1641 for (i = 0; i < nr; i++) 1642 if (values[i].spill_slot) 1643 emit_spill(c, values[i].hw_reg, values[i].spill_slot); 1644} 1645 1646 1647/* Emit the fragment program instructions here. 1648 */ 1649void brw_wm_emit( struct brw_wm_compile *c ) 1650{ 1651 struct brw_compile *p = &c->func; 1652 struct intel_context *intel = &p->brw->intel; 1653 GLuint insn; 1654 1655 brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); 1656 if (intel->gen >= 6) 1657 brw_set_acc_write_control(p, 1); 1658 1659 /* Check if any of the payload regs need to be spilled: 1660 */ 1661 spill_values(c, c->payload.depth, 4); 1662 spill_values(c, c->creg, c->nr_creg); 1663 spill_values(c, c->payload.input_interp, FRAG_ATTRIB_MAX); 1664 1665 1666 for (insn = 0; insn < c->nr_insns; insn++) { 1667 1668 struct brw_wm_instruction *inst = &c->instruction[insn]; 1669 struct brw_reg args[3][4], dst[4]; 1670 GLuint i, dst_flags; 1671 1672 /* Get argument regs: 1673 */ 1674 for (i = 0; i < 3; i++) 1675 get_argument_regs(c, inst->src[i], args[i]); 1676 1677 /* Get dest regs: 1678 */ 1679 for (i = 0; i < 4; i++) 1680 if (inst->dst[i]) 1681 dst[i] = inst->dst[i]->hw_reg; 1682 else 1683 dst[i] = brw_null_reg(); 1684 1685 /* Flags 1686 */ 1687 dst_flags = inst->writemask; 1688 if (inst->saturate) 1689 dst_flags |= SATURATE; 1690 1691 switch (inst->opcode) { 1692 /* Generated instructions for calculating triangle interpolants: 1693 */ 1694 case WM_PIXELXY: 1695 emit_pixel_xy(c, dst, dst_flags); 1696 break; 1697 1698 case WM_DELTAXY: 1699 emit_delta_xy(p, dst, dst_flags, args[0]); 1700 break; 1701 1702 case WM_WPOSXY: 1703 emit_wpos_xy(c, dst, dst_flags, args[0]); 1704 break; 1705 1706 case WM_PIXELW: 1707 emit_pixel_w(c, dst, dst_flags, args[0], args[1]); 1708 break; 1709 1710 case WM_LINTERP: 1711 emit_linterp(p, dst, dst_flags, args[0], args[1]); 1712 break; 1713 1714 case WM_PINTERP: 1715 emit_pinterp(p, dst, dst_flags, args[0], args[1], args[2]); 1716 break; 1717 1718 case WM_CINTERP: 1719 emit_cinterp(p, dst, dst_flags, args[0]); 1720 break; 1721 1722 case WM_FB_WRITE: 1723 emit_fb_write(c, args[0], args[1], args[2], inst->target, inst->eot); 1724 break; 1725 1726 case WM_FRONTFACING: 1727 emit_frontfacing(p, dst, dst_flags); 1728 break; 1729 1730 /* Straightforward arithmetic: 1731 */ 1732 case OPCODE_ADD: 1733 emit_alu2(p, brw_ADD, dst, dst_flags, args[0], args[1]); 1734 break; 1735 1736 case OPCODE_FRC: 1737 emit_alu1(p, brw_FRC, dst, dst_flags, args[0]); 1738 break; 1739 1740 case OPCODE_FLR: 1741 emit_alu1(p, brw_RNDD, dst, dst_flags, args[0]); 1742 break; 1743 1744 case OPCODE_DDX: 1745 emit_ddxy(p, dst, dst_flags, true, args[0], false); 1746 break; 1747 1748 case OPCODE_DDY: 1749 /* Make sure fp->program.UsesDFdy flag got set (otherwise there's no 1750 * guarantee that c->key.render_to_fbo is set). 1751 */ 1752 assert(c->fp->program.UsesDFdy); 1753 emit_ddxy(p, dst, dst_flags, false, args[0], c->key.render_to_fbo); 1754 break; 1755 1756 case OPCODE_DP2: 1757 emit_dp2(p, dst, dst_flags, args[0], args[1]); 1758 break; 1759 1760 case OPCODE_DP3: 1761 emit_dp3(p, dst, dst_flags, args[0], args[1]); 1762 break; 1763 1764 case OPCODE_DP4: 1765 emit_dp4(p, dst, dst_flags, args[0], args[1]); 1766 break; 1767 1768 case OPCODE_DPH: 1769 emit_dph(p, dst, dst_flags, args[0], args[1]); 1770 break; 1771 1772 case OPCODE_TRUNC: 1773 for (i = 0; i < 4; i++) { 1774 if (dst_flags & (1<<i)) { 1775 brw_RNDZ(p, dst[i], args[0][i]); 1776 } 1777 } 1778 break; 1779 1780 case OPCODE_LRP: 1781 emit_lrp(p, dst, dst_flags, args[0], args[1], args[2]); 1782 break; 1783 1784 case OPCODE_MAD: 1785 emit_mad(p, dst, dst_flags, args[0], args[1], args[2]); 1786 break; 1787 1788 case OPCODE_MOV: 1789 case OPCODE_SWZ: 1790 emit_alu1(p, brw_MOV, dst, dst_flags, args[0]); 1791 break; 1792 1793 case OPCODE_MUL: 1794 emit_alu2(p, brw_MUL, dst, dst_flags, args[0], args[1]); 1795 break; 1796 1797 case OPCODE_XPD: 1798 emit_xpd(p, dst, dst_flags, args[0], args[1]); 1799 break; 1800 1801 /* Higher math functions: 1802 */ 1803 case OPCODE_RCP: 1804 emit_math1(c, BRW_MATH_FUNCTION_INV, dst, dst_flags, args[0]); 1805 break; 1806 1807 case OPCODE_RSQ: 1808 emit_math1(c, BRW_MATH_FUNCTION_RSQ, dst, dst_flags, args[0]); 1809 break; 1810 1811 case OPCODE_SIN: 1812 emit_math1(c, BRW_MATH_FUNCTION_SIN, dst, dst_flags, args[0]); 1813 break; 1814 1815 case OPCODE_COS: 1816 emit_math1(c, BRW_MATH_FUNCTION_COS, dst, dst_flags, args[0]); 1817 break; 1818 1819 case OPCODE_EX2: 1820 emit_math1(c, BRW_MATH_FUNCTION_EXP, dst, dst_flags, args[0]); 1821 break; 1822 1823 case OPCODE_LG2: 1824 emit_math1(c, BRW_MATH_FUNCTION_LOG, dst, dst_flags, args[0]); 1825 break; 1826 1827 case OPCODE_SCS: 1828 /* There is an scs math function, but it would need some 1829 * fixup for 16-element execution. 1830 */ 1831 if (dst_flags & WRITEMASK_X) 1832 emit_math1(c, BRW_MATH_FUNCTION_COS, dst, (dst_flags&SATURATE)|WRITEMASK_X, args[0]); 1833 if (dst_flags & WRITEMASK_Y) 1834 emit_math1(c, BRW_MATH_FUNCTION_SIN, dst+1, (dst_flags&SATURATE)|WRITEMASK_X, args[0]); 1835 break; 1836 1837 case OPCODE_POW: 1838 emit_math2(c, BRW_MATH_FUNCTION_POW, dst, dst_flags, args[0], args[1]); 1839 break; 1840 1841 /* Comparisons: 1842 */ 1843 case OPCODE_CMP: 1844 emit_cmp(p, dst, dst_flags, args[0], args[1], args[2]); 1845 break; 1846 1847 case OPCODE_MAX: 1848 emit_max(p, dst, dst_flags, args[0], args[1]); 1849 break; 1850 1851 case OPCODE_MIN: 1852 emit_min(p, dst, dst_flags, args[0], args[1]); 1853 break; 1854 1855 case OPCODE_SLT: 1856 emit_slt(p, dst, dst_flags, args[0], args[1]); 1857 break; 1858 1859 case OPCODE_SLE: 1860 emit_sle(p, dst, dst_flags, args[0], args[1]); 1861 break; 1862 case OPCODE_SGT: 1863 emit_sgt(p, dst, dst_flags, args[0], args[1]); 1864 break; 1865 case OPCODE_SGE: 1866 emit_sge(p, dst, dst_flags, args[0], args[1]); 1867 break; 1868 case OPCODE_SEQ: 1869 emit_seq(p, dst, dst_flags, args[0], args[1]); 1870 break; 1871 case OPCODE_SNE: 1872 emit_sne(p, dst, dst_flags, args[0], args[1]); 1873 break; 1874 1875 case OPCODE_SSG: 1876 emit_sign(p, dst, dst_flags, args[0]); 1877 break; 1878 1879 case OPCODE_LIT: 1880 emit_lit(c, dst, dst_flags, args[0]); 1881 break; 1882 1883 /* Texturing operations: 1884 */ 1885 case OPCODE_TEX: 1886 emit_tex(c, dst, dst_flags, args[0], c->payload.depth[0].hw_reg, 1887 inst->tex_idx, inst->tex_unit, 1888 inst->tex_shadow); 1889 break; 1890 1891 case OPCODE_TXB: 1892 emit_txb(c, dst, dst_flags, args[0], c->payload.depth[0].hw_reg, 1893 inst->tex_idx, inst->tex_unit); 1894 break; 1895 1896 case OPCODE_KIL: 1897 emit_kil(c, args[0]); 1898 break; 1899 1900 default: 1901 printf("Unsupported opcode %i (%s) in fragment shader\n", 1902 inst->opcode, inst->opcode < MAX_OPCODE ? 1903 _mesa_opcode_string(inst->opcode) : 1904 "unknown"); 1905 } 1906 1907 for (i = 0; i < 4; i++) 1908 if (inst->dst[i] && inst->dst[i]->spill_slot) 1909 emit_spill(c, 1910 inst->dst[i]->hw_reg, 1911 inst->dst[i]->spill_slot); 1912 } 1913 1914 /* Only properly tested on ILK */ 1915 if (p->brw->intel.gen == 5) { 1916 brw_remove_duplicate_mrf_moves(p); 1917 if (c->dispatch_width == 16) 1918 brw_remove_grf_to_mrf_moves(p); 1919 } 1920 1921 if (unlikely(INTEL_DEBUG & DEBUG_WM)) { 1922 int i; 1923 1924 printf("wm-native:\n"); 1925 for (i = 0; i < p->nr_insn; i++) 1926 brw_disasm(stdout, &p->store[i], p->brw->intel.gen); 1927 printf("\n"); 1928 } 1929} 1930 1931