tgsi_util.c revision 7ec681f3
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_info.h" 31#include "tgsi_parse.h" 32#include "tgsi_util.h" 33#include "tgsi_exec.h" 34#include "util/bitscan.h" 35 36union pointer_hack 37{ 38 void *pointer; 39 uint64_t uint64; 40}; 41 42void * 43tgsi_align_128bit(void *unaligned) 44{ 45 union pointer_hack ph; 46 47 ph.uint64 = 0; 48 ph.pointer = unaligned; 49 ph.uint64 = (ph.uint64 + 15) & ~15; 50 return ph.pointer; 51} 52 53unsigned 54tgsi_util_get_src_register_swizzle(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 73unsigned 74tgsi_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(®->Register, component); 79} 80 81 82void 83tgsi_util_set_src_register_swizzle(struct tgsi_src_register *reg, 84 unsigned swizzle, 85 unsigned component) 86{ 87 switch (component) { 88 case 0: 89 reg->SwizzleX = swizzle; 90 break; 91 case 1: 92 reg->SwizzleY = swizzle; 93 break; 94 case 2: 95 reg->SwizzleZ = swizzle; 96 break; 97 case 3: 98 reg->SwizzleW = swizzle; 99 break; 100 default: 101 assert(0); 102 } 103} 104 105 106/** 107 * Determine which channels of the specificed src register are effectively 108 * used by this instruction. 109 */ 110unsigned 111tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst, 112 unsigned src_idx) 113{ 114 const struct tgsi_full_src_register *src = &inst->Src[src_idx]; 115 unsigned write_mask = inst->Dst[0].Register.WriteMask; 116 unsigned read_mask; 117 unsigned usage_mask; 118 unsigned chan; 119 120 switch (inst->Instruction.Opcode) { 121 case TGSI_OPCODE_IF: 122 case TGSI_OPCODE_UIF: 123 case TGSI_OPCODE_EMIT: 124 case TGSI_OPCODE_ENDPRIM: 125 case TGSI_OPCODE_RCP: 126 case TGSI_OPCODE_RSQ: 127 case TGSI_OPCODE_SQRT: 128 case TGSI_OPCODE_EX2: 129 case TGSI_OPCODE_LG2: 130 case TGSI_OPCODE_SIN: 131 case TGSI_OPCODE_COS: 132 case TGSI_OPCODE_POW: /* reads src0.x and src1.x */ 133 case TGSI_OPCODE_UP2H: 134 case TGSI_OPCODE_UP2US: 135 case TGSI_OPCODE_UP4B: 136 case TGSI_OPCODE_UP4UB: 137 case TGSI_OPCODE_MEMBAR: 138 case TGSI_OPCODE_BALLOT: 139 read_mask = TGSI_WRITEMASK_X; 140 break; 141 142 case TGSI_OPCODE_DP2: 143 case TGSI_OPCODE_PK2H: 144 case TGSI_OPCODE_PK2US: 145 case TGSI_OPCODE_DFRACEXP: 146 case TGSI_OPCODE_F2D: 147 case TGSI_OPCODE_I2D: 148 case TGSI_OPCODE_U2D: 149 case TGSI_OPCODE_F2U64: 150 case TGSI_OPCODE_F2I64: 151 case TGSI_OPCODE_U2I64: 152 case TGSI_OPCODE_I2I64: 153 case TGSI_OPCODE_TXQS: /* bindless handle possible */ 154 case TGSI_OPCODE_RESQ: /* bindless handle possible */ 155 read_mask = TGSI_WRITEMASK_XY; 156 break; 157 158 case TGSI_OPCODE_TXQ: 159 if (src_idx == 0) 160 read_mask = TGSI_WRITEMASK_X; 161 else 162 read_mask = TGSI_WRITEMASK_XY; /* bindless handle possible */ 163 break; 164 165 case TGSI_OPCODE_DP3: 166 read_mask = TGSI_WRITEMASK_XYZ; 167 break; 168 169 case TGSI_OPCODE_DSEQ: 170 case TGSI_OPCODE_DSNE: 171 case TGSI_OPCODE_DSLT: 172 case TGSI_OPCODE_DSGE: 173 case TGSI_OPCODE_DP4: 174 case TGSI_OPCODE_PK4B: 175 case TGSI_OPCODE_PK4UB: 176 case TGSI_OPCODE_D2F: 177 case TGSI_OPCODE_D2I: 178 case TGSI_OPCODE_D2U: 179 case TGSI_OPCODE_I2F: 180 case TGSI_OPCODE_U2F: 181 case TGSI_OPCODE_U64SEQ: 182 case TGSI_OPCODE_U64SNE: 183 case TGSI_OPCODE_U64SLT: 184 case TGSI_OPCODE_U64SGE: 185 case TGSI_OPCODE_U642F: 186 case TGSI_OPCODE_I64SLT: 187 case TGSI_OPCODE_I64SGE: 188 case TGSI_OPCODE_I642F: 189 read_mask = TGSI_WRITEMASK_XYZW; 190 break; 191 192 case TGSI_OPCODE_LIT: 193 read_mask = write_mask & TGSI_WRITEMASK_YZ ? 194 TGSI_WRITEMASK_XY | TGSI_WRITEMASK_W : 0; 195 break; 196 197 case TGSI_OPCODE_EXP: 198 case TGSI_OPCODE_LOG: 199 read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0; 200 break; 201 202 case TGSI_OPCODE_DST: 203 if (src_idx == 0) 204 read_mask = TGSI_WRITEMASK_YZ; 205 else 206 read_mask = TGSI_WRITEMASK_YW; 207 break; 208 209 case TGSI_OPCODE_DLDEXP: 210 if (src_idx == 0) { 211 read_mask = write_mask; 212 } else { 213 read_mask = 214 (write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0) | 215 (write_mask & TGSI_WRITEMASK_ZW ? TGSI_WRITEMASK_Z : 0); 216 } 217 break; 218 219 case TGSI_OPCODE_READ_INVOC: 220 if (src_idx == 0) 221 read_mask = write_mask; 222 else 223 read_mask = TGSI_WRITEMASK_X; 224 break; 225 226 case TGSI_OPCODE_FBFETCH: 227 read_mask = 0; /* not a real register read */ 228 break; 229 230 case TGSI_OPCODE_TEX: 231 case TGSI_OPCODE_TEX_LZ: 232 case TGSI_OPCODE_TXF_LZ: 233 case TGSI_OPCODE_TXF: 234 case TGSI_OPCODE_TXB: 235 case TGSI_OPCODE_TXL: 236 case TGSI_OPCODE_TXP: 237 case TGSI_OPCODE_TXD: 238 case TGSI_OPCODE_TEX2: 239 case TGSI_OPCODE_TXB2: 240 case TGSI_OPCODE_TXL2: 241 case TGSI_OPCODE_LODQ: 242 case TGSI_OPCODE_TG4: { 243 unsigned dim_layer = 244 tgsi_util_get_texture_coord_dim(inst->Texture.Texture); 245 unsigned dim_layer_shadow, dim; 246 247 /* Add shadow. */ 248 if (tgsi_is_shadow_target(inst->Texture.Texture)) { 249 dim_layer_shadow = dim_layer + 1; 250 if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D) 251 dim_layer_shadow = 3; 252 } else { 253 dim_layer_shadow = dim_layer; 254 } 255 256 /* Remove layer. */ 257 if (tgsi_is_array_sampler(inst->Texture.Texture)) 258 dim = dim_layer - 1; 259 else 260 dim = dim_layer; 261 262 read_mask = TGSI_WRITEMASK_XY; /* bindless handle in the last operand */ 263 264 switch (src_idx) { 265 case 0: 266 if (inst->Instruction.Opcode == TGSI_OPCODE_LODQ) 267 read_mask = u_bit_consecutive(0, dim); 268 else 269 read_mask = u_bit_consecutive(0, dim_layer_shadow) & 0xf; 270 271 if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D) 272 read_mask &= ~TGSI_WRITEMASK_Y; 273 274 if (inst->Instruction.Opcode == TGSI_OPCODE_TXF || 275 inst->Instruction.Opcode == TGSI_OPCODE_TXB || 276 inst->Instruction.Opcode == TGSI_OPCODE_TXL || 277 inst->Instruction.Opcode == TGSI_OPCODE_TXP) 278 read_mask |= TGSI_WRITEMASK_W; 279 break; 280 281 case 1: 282 if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) 283 read_mask = u_bit_consecutive(0, dim); 284 else if (inst->Instruction.Opcode == TGSI_OPCODE_TEX2 || 285 inst->Instruction.Opcode == TGSI_OPCODE_TXB2 || 286 inst->Instruction.Opcode == TGSI_OPCODE_TXL2 || 287 inst->Instruction.Opcode == TGSI_OPCODE_TG4) 288 read_mask = TGSI_WRITEMASK_X; 289 break; 290 291 case 2: 292 if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) 293 read_mask = u_bit_consecutive(0, dim); 294 break; 295 } 296 break; 297 } 298 299 case TGSI_OPCODE_LOAD: 300 if (src_idx == 0) { 301 read_mask = TGSI_WRITEMASK_XY; /* bindless handle possible */ 302 } else { 303 unsigned dim = tgsi_util_get_texture_coord_dim(inst->Memory.Texture); 304 read_mask = u_bit_consecutive(0, dim); 305 } 306 break; 307 308 case TGSI_OPCODE_STORE: 309 if (src_idx == 0) { 310 unsigned dim = tgsi_util_get_texture_coord_dim(inst->Memory.Texture); 311 read_mask = u_bit_consecutive(0, dim); 312 } else { 313 read_mask = TGSI_WRITEMASK_XYZW; 314 } 315 break; 316 317 case TGSI_OPCODE_ATOMUADD: 318 case TGSI_OPCODE_ATOMXCHG: 319 case TGSI_OPCODE_ATOMCAS: 320 case TGSI_OPCODE_ATOMAND: 321 case TGSI_OPCODE_ATOMOR: 322 case TGSI_OPCODE_ATOMXOR: 323 case TGSI_OPCODE_ATOMUMIN: 324 case TGSI_OPCODE_ATOMUMAX: 325 case TGSI_OPCODE_ATOMIMIN: 326 case TGSI_OPCODE_ATOMIMAX: 327 case TGSI_OPCODE_ATOMFADD: 328 if (src_idx == 0) { 329 read_mask = TGSI_WRITEMASK_XY; /* bindless handle possible */ 330 } else if (src_idx == 1) { 331 unsigned dim = tgsi_util_get_texture_coord_dim(inst->Memory.Texture); 332 read_mask = u_bit_consecutive(0, dim); 333 } else { 334 read_mask = TGSI_WRITEMASK_XYZW; 335 } 336 break; 337 338 case TGSI_OPCODE_INTERP_CENTROID: 339 case TGSI_OPCODE_INTERP_SAMPLE: 340 case TGSI_OPCODE_INTERP_OFFSET: 341 if (src_idx == 0) 342 read_mask = write_mask; 343 else if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET) 344 read_mask = TGSI_WRITEMASK_XY; /* offset */ 345 else 346 read_mask = TGSI_WRITEMASK_X; /* sample */ 347 break; 348 349 default: 350 if (tgsi_get_opcode_info(inst->Instruction.Opcode)->output_mode == 351 TGSI_OUTPUT_COMPONENTWISE) 352 read_mask = write_mask; 353 else 354 read_mask = TGSI_WRITEMASK_XYZW; /* assume all channels are read */ 355 break; 356 } 357 358 usage_mask = 0; 359 for (chan = 0; chan < 4; ++chan) { 360 if (read_mask & (1 << chan)) { 361 usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan); 362 } 363 } 364 365 return usage_mask; 366} 367 368/** 369 * Convert a tgsi_ind_register into a tgsi_src_register 370 */ 371struct tgsi_src_register 372tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg) 373{ 374 struct tgsi_src_register src = { 0 }; 375 376 src.File = reg->File; 377 src.Index = reg->Index; 378 src.SwizzleX = reg->Swizzle; 379 src.SwizzleY = reg->Swizzle; 380 src.SwizzleZ = reg->Swizzle; 381 src.SwizzleW = reg->Swizzle; 382 383 return src; 384} 385 386/** 387 * Return the dimension of the texture coordinates (layer included for array 388 * textures), as well as the location of the shadow reference value or the 389 * sample index. 390 */ 391int 392tgsi_util_get_texture_coord_dim(enum tgsi_texture_type tgsi_tex) 393{ 394 /* 395 * Depending on the texture target, (src0.xyzw, src1.x) is interpreted 396 * differently: 397 * 398 * (s, X, X, X, X), for BUFFER 399 * (s, X, X, X, X), for 1D 400 * (s, t, X, X, X), for 2D, RECT 401 * (s, t, r, X, X), for 3D, CUBE 402 * 403 * (s, layer, X, X, X), for 1D_ARRAY 404 * (s, t, layer, X, X), for 2D_ARRAY 405 * (s, t, r, layer, X), for CUBE_ARRAY 406 * 407 * (s, X, shadow, X, X), for SHADOW1D 408 * (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT 409 * (s, t, r, shadow, X), for SHADOWCUBE 410 * 411 * (s, layer, shadow, X, X), for SHADOW1D_ARRAY 412 * (s, t, layer, shadow, X), for SHADOW2D_ARRAY 413 * (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY 414 * 415 * (s, t, sample, X, X), for 2D_MSAA 416 * (s, t, layer, sample, X), for 2D_ARRAY_MSAA 417 */ 418 switch (tgsi_tex) { 419 case TGSI_TEXTURE_BUFFER: 420 case TGSI_TEXTURE_1D: 421 case TGSI_TEXTURE_SHADOW1D: 422 return 1; 423 case TGSI_TEXTURE_2D: 424 case TGSI_TEXTURE_RECT: 425 case TGSI_TEXTURE_1D_ARRAY: 426 case TGSI_TEXTURE_SHADOW2D: 427 case TGSI_TEXTURE_SHADOWRECT: 428 case TGSI_TEXTURE_SHADOW1D_ARRAY: 429 case TGSI_TEXTURE_2D_MSAA: 430 return 2; 431 case TGSI_TEXTURE_3D: 432 case TGSI_TEXTURE_CUBE: 433 case TGSI_TEXTURE_2D_ARRAY: 434 case TGSI_TEXTURE_SHADOWCUBE: 435 case TGSI_TEXTURE_SHADOW2D_ARRAY: 436 case TGSI_TEXTURE_2D_ARRAY_MSAA: 437 return 3; 438 case TGSI_TEXTURE_CUBE_ARRAY: 439 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 440 return 4; 441 default: 442 assert(!"unknown texture target"); 443 return 0; 444 } 445} 446 447 448/** 449 * Given a TGSI_TEXTURE_x target, return register component where the 450 * shadow reference/distance coordinate is found. Typically, components 451 * 0 and 1 are the (s,t) texcoords and component 2 or 3 hold the shadow 452 * reference value. But if we return 4, it means the reference value is 453 * found in the 0th component of the second coordinate argument to the 454 * TEX2 instruction. 455 */ 456int 457tgsi_util_get_shadow_ref_src_index(enum tgsi_texture_type tgsi_tex) 458{ 459 switch (tgsi_tex) { 460 case TGSI_TEXTURE_SHADOW1D: 461 case TGSI_TEXTURE_SHADOW2D: 462 case TGSI_TEXTURE_SHADOWRECT: 463 case TGSI_TEXTURE_SHADOW1D_ARRAY: 464 return 2; 465 case TGSI_TEXTURE_SHADOWCUBE: 466 case TGSI_TEXTURE_SHADOW2D_ARRAY: 467 case TGSI_TEXTURE_2D_MSAA: 468 case TGSI_TEXTURE_2D_ARRAY_MSAA: 469 return 3; 470 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 471 return 4; 472 default: 473 /* no shadow nor sample */ 474 return -1; 475 } 476} 477 478 479bool 480tgsi_is_shadow_target(enum tgsi_texture_type target) 481{ 482 switch (target) { 483 case TGSI_TEXTURE_SHADOW1D: 484 case TGSI_TEXTURE_SHADOW2D: 485 case TGSI_TEXTURE_SHADOWRECT: 486 case TGSI_TEXTURE_SHADOW1D_ARRAY: 487 case TGSI_TEXTURE_SHADOW2D_ARRAY: 488 case TGSI_TEXTURE_SHADOWCUBE: 489 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 490 return TRUE; 491 default: 492 return FALSE; 493 } 494} 495