1 /************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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 33 union pointer_hack 34 { 35 void *pointer; 36 uint64_t uint64; 37 }; 38 39 void * 40 tgsi_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 51 unsigned 52 tgsi_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 72 unsigned 73 tgsi_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 82 void 83 tgsi_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 106 unsigned 107 tgsi_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 135 void 136 tgsi_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 */ 171 unsigned 172 tgsi_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 /* Channel-wise operations */ 221 read_mask = write_mask; 222 break; 223 224 case TGSI_OPCODE_EX2: 225 case TGSI_OPCODE_LG2: 226 case TGSI_OPCODE_RCC: 227 read_mask = TGSI_WRITEMASK_X; 228 break; 229 230 case TGSI_OPCODE_SCS: 231 read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0; 232 break; 233 234 case TGSI_OPCODE_EXP: 235 case TGSI_OPCODE_LOG: 236 read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0; 237 break; 238 239 case TGSI_OPCODE_DP2A: 240 read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY; 241 break; 242 243 case TGSI_OPCODE_DP2: 244 read_mask = TGSI_WRITEMASK_XY; 245 break; 246 247 case TGSI_OPCODE_DP3: 248 read_mask = TGSI_WRITEMASK_XYZ; 249 break; 250 251 case TGSI_OPCODE_DP4: 252 read_mask = TGSI_WRITEMASK_XYZW; 253 break; 254 255 case TGSI_OPCODE_DPH: 256 read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW; 257 break; 258 259 case TGSI_OPCODE_TEX: 260 case TGSI_OPCODE_TXD: 261 case TGSI_OPCODE_TXB: 262 case TGSI_OPCODE_TXL: 263 case TGSI_OPCODE_TXP: 264 if (src_idx == 0) { 265 /* Note that the SHADOW variants use the Z component too */ 266 switch (inst->Texture.Texture) { 267 case TGSI_TEXTURE_1D: 268 read_mask = TGSI_WRITEMASK_X; 269 break; 270 case TGSI_TEXTURE_SHADOW1D: 271 read_mask = TGSI_WRITEMASK_XZ; 272 break; 273 case TGSI_TEXTURE_1D_ARRAY: 274 case TGSI_TEXTURE_2D: 275 case TGSI_TEXTURE_RECT: 276 read_mask = TGSI_WRITEMASK_XY; 277 break; 278 case TGSI_TEXTURE_SHADOW1D_ARRAY: 279 case TGSI_TEXTURE_SHADOW2D: 280 case TGSI_TEXTURE_SHADOWRECT: 281 case TGSI_TEXTURE_2D_ARRAY: 282 case TGSI_TEXTURE_3D: 283 case TGSI_TEXTURE_CUBE: 284 case TGSI_TEXTURE_2D_MSAA: 285 read_mask = TGSI_WRITEMASK_XYZ; 286 break; 287 case TGSI_TEXTURE_SHADOW2D_ARRAY: 288 case TGSI_TEXTURE_SHADOWCUBE: 289 case TGSI_TEXTURE_2D_ARRAY_MSAA: 290 read_mask = TGSI_WRITEMASK_XYZW; 291 break; 292 default: 293 assert(0); 294 read_mask = 0; 295 } 296 297 if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) { 298 read_mask |= TGSI_WRITEMASK_W; 299 } 300 } else { 301 /* A safe approximation */ 302 read_mask = TGSI_WRITEMASK_XYZW; 303 } 304 break; 305 306 default: 307 /* Assume all channels are read */ 308 read_mask = TGSI_WRITEMASK_XYZW; 309 break; 310 } 311 312 usage_mask = 0; 313 for (chan = 0; chan < 4; ++chan) { 314 if (read_mask & (1 << chan)) { 315 usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan); 316 } 317 } 318 319 return usage_mask; 320 } 321