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