1 /************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * 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, sub license, 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 portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include "util/u_debug.h" 29 #include "pipe/p_shader_tokens.h" 30 #include "tgsi_parse.h" 31 #include "tgsi_util.h" 32 #include "tgsi_exec.h" 33 34 union pointer_hack 35 { 36 void *pointer; 37 uint64_t uint64; 38 }; 39 40 void * 41 tgsi_align_128bit( 42 void *unaligned ) 43 { 44 union pointer_hack ph; 45 46 ph.uint64 = 0; 47 ph.pointer = unaligned; 48 ph.uint64 = (ph.uint64 + 15) & ~15; 49 return ph.pointer; 50 } 51 52 unsigned 53 tgsi_util_get_src_register_swizzle( 54 const struct tgsi_src_register *reg, 55 unsigned component ) 56 { 57 switch (component) { 58 case TGSI_CHAN_X: 59 return reg->SwizzleX; 60 case TGSI_CHAN_Y: 61 return reg->SwizzleY; 62 case TGSI_CHAN_Z: 63 return reg->SwizzleZ; 64 case TGSI_CHAN_W: 65 return reg->SwizzleW; 66 default: 67 assert(0); 68 } 69 return 0; 70 } 71 72 73 unsigned 74 tgsi_util_get_full_src_register_swizzle( 75 const struct tgsi_full_src_register *reg, 76 unsigned component ) 77 { 78 return tgsi_util_get_src_register_swizzle( 79 ®->Register, 80 component ); 81 } 82 83 void 84 tgsi_util_set_src_register_swizzle( 85 struct tgsi_src_register *reg, 86 unsigned swizzle, 87 unsigned component ) 88 { 89 switch( component ) { 90 case 0: 91 reg->SwizzleX = swizzle; 92 break; 93 case 1: 94 reg->SwizzleY = swizzle; 95 break; 96 case 2: 97 reg->SwizzleZ = swizzle; 98 break; 99 case 3: 100 reg->SwizzleW = swizzle; 101 break; 102 default: 103 assert( 0 ); 104 } 105 } 106 107 unsigned 108 tgsi_util_get_full_src_register_sign_mode( 109 const struct tgsi_full_src_register *reg, 110 unsigned component ) 111 { 112 unsigned sign_mode; 113 114 if( reg->Register.Absolute ) { 115 /* Consider only the post-abs negation. */ 116 117 if( reg->Register.Negate ) { 118 sign_mode = TGSI_UTIL_SIGN_SET; 119 } 120 else { 121 sign_mode = TGSI_UTIL_SIGN_CLEAR; 122 } 123 } 124 else { 125 if( reg->Register.Negate ) { 126 sign_mode = TGSI_UTIL_SIGN_TOGGLE; 127 } 128 else { 129 sign_mode = TGSI_UTIL_SIGN_KEEP; 130 } 131 } 132 133 return sign_mode; 134 } 135 136 void 137 tgsi_util_set_full_src_register_sign_mode( 138 struct tgsi_full_src_register *reg, 139 unsigned sign_mode ) 140 { 141 switch (sign_mode) 142 { 143 case TGSI_UTIL_SIGN_CLEAR: 144 reg->Register.Negate = 0; 145 reg->Register.Absolute = 1; 146 break; 147 148 case TGSI_UTIL_SIGN_SET: 149 reg->Register.Absolute = 1; 150 reg->Register.Negate = 1; 151 break; 152 153 case TGSI_UTIL_SIGN_TOGGLE: 154 reg->Register.Negate = 1; 155 reg->Register.Absolute = 0; 156 break; 157 158 case TGSI_UTIL_SIGN_KEEP: 159 reg->Register.Negate = 0; 160 reg->Register.Absolute = 0; 161 break; 162 163 default: 164 assert( 0 ); 165 } 166 } 167 168 /** 169 * Determine which channels of the specificed src register are effectively 170 * used by this instruction. 171 */ 172 unsigned 173 tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, 174 unsigned src_idx) 175 { 176 const struct tgsi_full_src_register *src = &inst->Src[src_idx]; 177 unsigned write_mask = inst->Dst[0].Register.WriteMask; 178 unsigned read_mask; 179 unsigned usage_mask; 180 unsigned chan; 181 182 switch (inst->Instruction.Opcode) { 183 case TGSI_OPCODE_MOV: 184 case TGSI_OPCODE_ARL: 185 case TGSI_OPCODE_ARR: 186 case TGSI_OPCODE_RCP: 187 case TGSI_OPCODE_MUL: 188 case TGSI_OPCODE_DIV: 189 case TGSI_OPCODE_ADD: 190 case TGSI_OPCODE_MIN: 191 case TGSI_OPCODE_MAX: 192 case TGSI_OPCODE_SLT: 193 case TGSI_OPCODE_SGE: 194 case TGSI_OPCODE_MAD: 195 case TGSI_OPCODE_LRP: 196 case TGSI_OPCODE_FMA: 197 case TGSI_OPCODE_FRC: 198 case TGSI_OPCODE_CEIL: 199 case TGSI_OPCODE_CLAMP: 200 case TGSI_OPCODE_FLR: 201 case TGSI_OPCODE_ROUND: 202 case TGSI_OPCODE_POW: 203 case TGSI_OPCODE_COS: 204 case TGSI_OPCODE_SIN: 205 case TGSI_OPCODE_DDX: 206 case TGSI_OPCODE_DDY: 207 case TGSI_OPCODE_SEQ: 208 case TGSI_OPCODE_SGT: 209 case TGSI_OPCODE_SLE: 210 case TGSI_OPCODE_SNE: 211 case TGSI_OPCODE_SSG: 212 case TGSI_OPCODE_CMP: 213 case TGSI_OPCODE_TRUNC: 214 case TGSI_OPCODE_NOT: 215 case TGSI_OPCODE_AND: 216 case TGSI_OPCODE_OR: 217 case TGSI_OPCODE_XOR: 218 case TGSI_OPCODE_SAD: 219 case TGSI_OPCODE_FSEQ: 220 case TGSI_OPCODE_FSGE: 221 case TGSI_OPCODE_FSLT: 222 case TGSI_OPCODE_FSNE: 223 case TGSI_OPCODE_F2I: 224 case TGSI_OPCODE_IDIV: 225 case TGSI_OPCODE_IMAX: 226 case TGSI_OPCODE_IMIN: 227 case TGSI_OPCODE_INEG: 228 case TGSI_OPCODE_ISGE: 229 case TGSI_OPCODE_ISHR: 230 case TGSI_OPCODE_ISLT: 231 case TGSI_OPCODE_F2U: 232 case TGSI_OPCODE_U2F: 233 case TGSI_OPCODE_UADD: 234 case TGSI_OPCODE_UDIV: 235 case TGSI_OPCODE_UMAD: 236 case TGSI_OPCODE_UMAX: 237 case TGSI_OPCODE_UMIN: 238 case TGSI_OPCODE_UMOD: 239 case TGSI_OPCODE_UMUL: 240 case TGSI_OPCODE_USEQ: 241 case TGSI_OPCODE_USGE: 242 case TGSI_OPCODE_USHR: 243 case TGSI_OPCODE_USLT: 244 case TGSI_OPCODE_USNE: 245 case TGSI_OPCODE_IMUL_HI: 246 case TGSI_OPCODE_UMUL_HI: 247 case TGSI_OPCODE_DDX_FINE: 248 case TGSI_OPCODE_DDY_FINE: 249 /* Channel-wise operations */ 250 read_mask = write_mask; 251 break; 252 253 case TGSI_OPCODE_EX2: 254 case TGSI_OPCODE_LG2: 255 read_mask = TGSI_WRITEMASK_X; 256 break; 257 258 case TGSI_OPCODE_SCS: 259 read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0; 260 break; 261 262 case TGSI_OPCODE_EXP: 263 case TGSI_OPCODE_LOG: 264 read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0; 265 break; 266 267 case TGSI_OPCODE_DP2A: 268 read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY; 269 break; 270 271 case TGSI_OPCODE_DP2: 272 read_mask = TGSI_WRITEMASK_XY; 273 break; 274 275 case TGSI_OPCODE_DP3: 276 read_mask = TGSI_WRITEMASK_XYZ; 277 break; 278 279 case TGSI_OPCODE_DP4: 280 read_mask = TGSI_WRITEMASK_XYZW; 281 break; 282 283 case TGSI_OPCODE_DPH: 284 read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW; 285 break; 286 287 case TGSI_OPCODE_TEX: 288 case TGSI_OPCODE_TXD: 289 case TGSI_OPCODE_TXB: 290 case TGSI_OPCODE_TXL: 291 case TGSI_OPCODE_TXP: 292 if (src_idx == 0) { 293 /* Note that the SHADOW variants use the Z component too */ 294 switch (inst->Texture.Texture) { 295 case TGSI_TEXTURE_1D: 296 read_mask = TGSI_WRITEMASK_X; 297 break; 298 case TGSI_TEXTURE_SHADOW1D: 299 read_mask = TGSI_WRITEMASK_XZ; 300 break; 301 case TGSI_TEXTURE_1D_ARRAY: 302 case TGSI_TEXTURE_2D: 303 case TGSI_TEXTURE_RECT: 304 read_mask = TGSI_WRITEMASK_XY; 305 break; 306 case TGSI_TEXTURE_SHADOW1D_ARRAY: 307 case TGSI_TEXTURE_SHADOW2D: 308 case TGSI_TEXTURE_SHADOWRECT: 309 case TGSI_TEXTURE_2D_ARRAY: 310 case TGSI_TEXTURE_3D: 311 case TGSI_TEXTURE_CUBE: 312 case TGSI_TEXTURE_2D_MSAA: 313 read_mask = TGSI_WRITEMASK_XYZ; 314 break; 315 case TGSI_TEXTURE_SHADOW2D_ARRAY: 316 case TGSI_TEXTURE_CUBE_ARRAY: 317 case TGSI_TEXTURE_SHADOWCUBE: 318 case TGSI_TEXTURE_2D_ARRAY_MSAA: 319 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 320 read_mask = TGSI_WRITEMASK_XYZW; 321 break; 322 default: 323 assert(0); 324 read_mask = 0; 325 } 326 327 if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) { 328 read_mask |= TGSI_WRITEMASK_W; 329 } 330 } else { 331 /* A safe approximation */ 332 read_mask = TGSI_WRITEMASK_XYZW; 333 } 334 break; 335 336 default: 337 /* Assume all channels are read */ 338 read_mask = TGSI_WRITEMASK_XYZW; 339 break; 340 } 341 342 usage_mask = 0; 343 for (chan = 0; chan < 4; ++chan) { 344 if (read_mask & (1 << chan)) { 345 usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan); 346 } 347 } 348 349 return usage_mask; 350 } 351 352 /** 353 * Convert a tgsi_ind_register into a tgsi_src_register 354 */ 355 struct tgsi_src_register 356 tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg) 357 { 358 struct tgsi_src_register src = { 0 }; 359 360 src.File = reg->File; 361 src.Index = reg->Index; 362 src.SwizzleX = reg->Swizzle; 363 src.SwizzleY = reg->Swizzle; 364 src.SwizzleZ = reg->Swizzle; 365 src.SwizzleW = reg->Swizzle; 366 367 return src; 368 } 369 370 /** 371 * Return the dimension of the texture coordinates (layer included for array 372 * textures), as well as the location of the shadow reference value or the 373 * sample index. 374 */ 375 int 376 tgsi_util_get_texture_coord_dim(unsigned tgsi_tex) 377 { 378 /* 379 * Depending on the texture target, (src0.xyzw, src1.x) is interpreted 380 * differently: 381 * 382 * (s, X, X, X, X), for BUFFER 383 * (s, X, X, X, X), for 1D 384 * (s, t, X, X, X), for 2D, RECT 385 * (s, t, r, X, X), for 3D, CUBE 386 * 387 * (s, layer, X, X, X), for 1D_ARRAY 388 * (s, t, layer, X, X), for 2D_ARRAY 389 * (s, t, r, layer, X), for CUBE_ARRAY 390 * 391 * (s, X, shadow, X, X), for SHADOW1D 392 * (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT 393 * (s, t, r, shadow, X), for SHADOWCUBE 394 * 395 * (s, layer, shadow, X, X), for SHADOW1D_ARRAY 396 * (s, t, layer, shadow, X), for SHADOW2D_ARRAY 397 * (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY 398 * 399 * (s, t, sample, X, X), for 2D_MSAA 400 * (s, t, layer, sample, X), for 2D_ARRAY_MSAA 401 */ 402 switch (tgsi_tex) { 403 case TGSI_TEXTURE_BUFFER: 404 case TGSI_TEXTURE_1D: 405 case TGSI_TEXTURE_SHADOW1D: 406 return 1; 407 case TGSI_TEXTURE_2D: 408 case TGSI_TEXTURE_RECT: 409 case TGSI_TEXTURE_1D_ARRAY: 410 case TGSI_TEXTURE_SHADOW2D: 411 case TGSI_TEXTURE_SHADOWRECT: 412 case TGSI_TEXTURE_SHADOW1D_ARRAY: 413 case TGSI_TEXTURE_2D_MSAA: 414 return 2; 415 case TGSI_TEXTURE_3D: 416 case TGSI_TEXTURE_CUBE: 417 case TGSI_TEXTURE_2D_ARRAY: 418 case TGSI_TEXTURE_SHADOWCUBE: 419 case TGSI_TEXTURE_SHADOW2D_ARRAY: 420 case TGSI_TEXTURE_2D_ARRAY_MSAA: 421 return 3; 422 case TGSI_TEXTURE_CUBE_ARRAY: 423 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 424 return 4; 425 default: 426 assert(!"unknown texture target"); 427 return 0; 428 } 429 } 430 431 432 /** 433 * Given a TGSI_TEXTURE_x target, return the src register index for the 434 * shadow reference coordinate. 435 */ 436 int 437 tgsi_util_get_shadow_ref_src_index(unsigned tgsi_tex) 438 { 439 switch (tgsi_tex) { 440 case TGSI_TEXTURE_SHADOW1D: 441 case TGSI_TEXTURE_SHADOW2D: 442 case TGSI_TEXTURE_SHADOWRECT: 443 case TGSI_TEXTURE_SHADOW1D_ARRAY: 444 return 2; 445 case TGSI_TEXTURE_SHADOWCUBE: 446 case TGSI_TEXTURE_SHADOW2D_ARRAY: 447 case TGSI_TEXTURE_2D_MSAA: 448 case TGSI_TEXTURE_2D_ARRAY_MSAA: 449 return 3; 450 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 451 return 4; 452 default: 453 /* no shadow nor sample */ 454 return -1; 455 } 456 } 457 458 459 boolean 460 tgsi_is_shadow_target(unsigned target) 461 { 462 switch (target) { 463 case TGSI_TEXTURE_SHADOW1D: 464 case TGSI_TEXTURE_SHADOW2D: 465 case TGSI_TEXTURE_SHADOWRECT: 466 case TGSI_TEXTURE_SHADOW1D_ARRAY: 467 case TGSI_TEXTURE_SHADOW2D_ARRAY: 468 case TGSI_TEXTURE_SHADOWCUBE: 469 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 470 return TRUE; 471 default: 472 return FALSE; 473 } 474 } 475