1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
28 #include "util/u_debug.h"
29 #include "pipe/p_shader_tokens.h"
30 #include "tgsi_parse.h"
31 #include "tgsi_util.h"
43 union pointer_hack ph
;
46 ph
.pointer
= unaligned
;
47 ph
.uint64
= (ph
.uint64
+ 15) & ~15;
52 tgsi_util_get_src_register_swizzle(
53 const struct tgsi_src_register
*reg
,
73 tgsi_util_get_full_src_register_swizzle(
74 const struct tgsi_full_src_register
*reg
,
77 return tgsi_util_get_src_register_swizzle(
83 tgsi_util_set_src_register_swizzle(
84 struct tgsi_src_register
*reg
,
90 reg
->SwizzleX
= swizzle
;
93 reg
->SwizzleY
= swizzle
;
96 reg
->SwizzleZ
= swizzle
;
99 reg
->SwizzleW
= swizzle
;
107 tgsi_util_get_full_src_register_sign_mode(
108 const struct tgsi_full_src_register
*reg
,
113 if( reg
->Register
.Absolute
) {
114 /* Consider only the post-abs negation. */
116 if( reg
->Register
.Negate
) {
117 sign_mode
= TGSI_UTIL_SIGN_SET
;
120 sign_mode
= TGSI_UTIL_SIGN_CLEAR
;
124 if( reg
->Register
.Negate
) {
125 sign_mode
= TGSI_UTIL_SIGN_TOGGLE
;
128 sign_mode
= TGSI_UTIL_SIGN_KEEP
;
136 tgsi_util_set_full_src_register_sign_mode(
137 struct tgsi_full_src_register
*reg
,
142 case TGSI_UTIL_SIGN_CLEAR
:
143 reg
->Register
.Negate
= 0;
144 reg
->Register
.Absolute
= 1;
147 case TGSI_UTIL_SIGN_SET
:
148 reg
->Register
.Absolute
= 1;
149 reg
->Register
.Negate
= 1;
152 case TGSI_UTIL_SIGN_TOGGLE
:
153 reg
->Register
.Negate
= 1;
154 reg
->Register
.Absolute
= 0;
157 case TGSI_UTIL_SIGN_KEEP
:
158 reg
->Register
.Negate
= 0;
159 reg
->Register
.Absolute
= 0;
168 * Determine which channels of the specificed src register are effectively
169 * used by this instruction.
172 tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction
*inst
,
175 const struct tgsi_full_src_register
*src
= &inst
->Src
[src_idx
];
176 unsigned write_mask
= inst
->Dst
[0].Register
.WriteMask
;
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
:
218 case TGSI_OPCODE_XOR
:
219 case TGSI_OPCODE_SAD
:
220 /* Channel-wise operations */
221 read_mask
= write_mask
;
224 case TGSI_OPCODE_EX2
:
225 case TGSI_OPCODE_LG2
:
226 case TGSI_OPCODE_RCC
:
227 read_mask
= TGSI_WRITEMASK_X
;
230 case TGSI_OPCODE_SCS
:
231 read_mask
= write_mask
& TGSI_WRITEMASK_XY
? TGSI_WRITEMASK_X
: 0;
234 case TGSI_OPCODE_EXP
:
235 case TGSI_OPCODE_LOG
:
236 read_mask
= write_mask
& TGSI_WRITEMASK_XYZ
? TGSI_WRITEMASK_X
: 0;
239 case TGSI_OPCODE_DP2A
:
240 read_mask
= src_idx
== 2 ? TGSI_WRITEMASK_X
: TGSI_WRITEMASK_XY
;
243 case TGSI_OPCODE_DP2
:
244 read_mask
= TGSI_WRITEMASK_XY
;
247 case TGSI_OPCODE_DP3
:
248 read_mask
= TGSI_WRITEMASK_XYZ
;
251 case TGSI_OPCODE_DP4
:
252 read_mask
= TGSI_WRITEMASK_XYZW
;
255 case TGSI_OPCODE_DPH
:
256 read_mask
= src_idx
== 0 ? TGSI_WRITEMASK_XYZ
: TGSI_WRITEMASK_XYZW
;
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
:
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
;
270 case TGSI_TEXTURE_SHADOW1D
:
271 read_mask
= TGSI_WRITEMASK_XZ
;
273 case TGSI_TEXTURE_2D
:
274 case TGSI_TEXTURE_RECT
:
275 read_mask
= TGSI_WRITEMASK_XY
;
277 case TGSI_TEXTURE_SHADOW2D
:
278 case TGSI_TEXTURE_SHADOWRECT
:
279 case TGSI_TEXTURE_3D
:
280 case TGSI_TEXTURE_CUBE
:
281 read_mask
= TGSI_WRITEMASK_XYZ
;
283 case TGSI_TEXTURE_1D_ARRAY
:
284 read_mask
= TGSI_WRITEMASK_XY
;
286 case TGSI_TEXTURE_2D_ARRAY
:
287 read_mask
= TGSI_WRITEMASK_XYZ
;
294 if (inst
->Instruction
.Opcode
!= TGSI_OPCODE_TEX
) {
295 read_mask
|= TGSI_WRITEMASK_W
;
298 /* A safe approximation */
299 read_mask
= TGSI_WRITEMASK_XYZW
;
304 /* Assume all channels are read */
305 read_mask
= TGSI_WRITEMASK_XYZW
;
310 for (chan
= 0; chan
< 4; ++chan
) {
311 if (read_mask
& (1 << chan
)) {
312 usage_mask
|= 1 << tgsi_util_get_full_src_register_swizzle(src
, chan
);