Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 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_CUBE_ARRAY: |
||
289 | case TGSI_TEXTURE_SHADOWCUBE: |
||
290 | case TGSI_TEXTURE_2D_ARRAY_MSAA: |
||
291 | case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||
292 | read_mask = TGSI_WRITEMASK_XYZW; |
||
293 | break; |
||
294 | default: |
||
295 | assert(0); |
||
296 | read_mask = 0; |
||
297 | } |
||
298 | |||
299 | if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) { |
||
300 | read_mask |= TGSI_WRITEMASK_W; |
||
301 | } |
||
302 | } else { |
||
303 | /* A safe approximation */ |
||
304 | read_mask = TGSI_WRITEMASK_XYZW; |
||
305 | } |
||
306 | break; |
||
307 | |||
308 | default: |
||
309 | /* Assume all channels are read */ |
||
310 | read_mask = TGSI_WRITEMASK_XYZW; |
||
311 | break; |
||
312 | } |
||
313 | |||
314 | usage_mask = 0; |
||
315 | for (chan = 0; chan < 4; ++chan) { |
||
316 | if (read_mask & (1 << chan)) { |
||
317 | usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan); |
||
318 | } |
||
319 | } |
||
320 | |||
321 | return usage_mask; |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * Convert a tgsi_ind_register into a tgsi_src_register |
||
326 | */ |
||
327 | struct tgsi_src_register |
||
328 | tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg) |
||
329 | { |
||
330 | struct tgsi_src_register src = { 0 }; |
||
331 | |||
332 | src.File = reg->File; |
||
333 | src.Index = reg->Index; |
||
334 | src.SwizzleX = reg->Swizzle; |
||
335 | src.SwizzleY = reg->Swizzle; |
||
336 | src.SwizzleZ = reg->Swizzle; |
||
337 | src.SwizzleW = reg->Swizzle; |
||
338 | |||
339 | return src; |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Return the dimension of the texture coordinates (layer included for array |
||
344 | * textures), as well as the location of the shadow reference value or the |
||
345 | * sample index. |
||
346 | */ |
||
347 | int |
||
348 | tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample) |
||
349 | { |
||
350 | int dim; |
||
351 | |||
352 | /* |
||
353 | * Depending on the texture target, (src0.xyzw, src1.x) is interpreted |
||
354 | * differently: |
||
355 | * |
||
356 | * (s, X, X, X, X), for BUFFER |
||
357 | * (s, X, X, X, X), for 1D |
||
358 | * (s, t, X, X, X), for 2D, RECT |
||
359 | * (s, t, r, X, X), for 3D, CUBE |
||
360 | * |
||
361 | * (s, layer, X, X, X), for 1D_ARRAY |
||
362 | * (s, t, layer, X, X), for 2D_ARRAY |
||
363 | * (s, t, r, layer, X), for CUBE_ARRAY |
||
364 | * |
||
365 | * (s, X, shadow, X, X), for SHADOW1D |
||
366 | * (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT |
||
367 | * (s, t, r, shadow, X), for SHADOWCUBE |
||
368 | * |
||
369 | * (s, layer, shadow, X, X), for SHADOW1D_ARRAY |
||
370 | * (s, t, layer, shadow, X), for SHADOW2D_ARRAY |
||
371 | * (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY |
||
372 | * |
||
373 | * (s, t, sample, X, X), for 2D_MSAA |
||
374 | * (s, t, layer, sample, X), for 2D_ARRAY_MSAA |
||
375 | */ |
||
376 | switch (tgsi_tex) { |
||
377 | case TGSI_TEXTURE_BUFFER: |
||
378 | case TGSI_TEXTURE_1D: |
||
379 | case TGSI_TEXTURE_SHADOW1D: |
||
380 | dim = 1; |
||
381 | break; |
||
382 | case TGSI_TEXTURE_2D: |
||
383 | case TGSI_TEXTURE_RECT: |
||
384 | case TGSI_TEXTURE_1D_ARRAY: |
||
385 | case TGSI_TEXTURE_SHADOW2D: |
||
386 | case TGSI_TEXTURE_SHADOWRECT: |
||
387 | case TGSI_TEXTURE_SHADOW1D_ARRAY: |
||
388 | case TGSI_TEXTURE_2D_MSAA: |
||
389 | dim = 2; |
||
390 | break; |
||
391 | case TGSI_TEXTURE_3D: |
||
392 | case TGSI_TEXTURE_CUBE: |
||
393 | case TGSI_TEXTURE_2D_ARRAY: |
||
394 | case TGSI_TEXTURE_SHADOWCUBE: |
||
395 | case TGSI_TEXTURE_SHADOW2D_ARRAY: |
||
396 | case TGSI_TEXTURE_2D_ARRAY_MSAA: |
||
397 | dim = 3; |
||
398 | break; |
||
399 | case TGSI_TEXTURE_CUBE_ARRAY: |
||
400 | case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||
401 | dim = 4; |
||
402 | break; |
||
403 | default: |
||
404 | assert(!"unknown texture target"); |
||
405 | dim = 0; |
||
406 | break; |
||
407 | } |
||
408 | |||
409 | if (shadow_or_sample) { |
||
410 | switch (tgsi_tex) { |
||
411 | case TGSI_TEXTURE_SHADOW1D: |
||
412 | /* there is a gap */ |
||
413 | *shadow_or_sample = 2; |
||
414 | break; |
||
415 | case TGSI_TEXTURE_SHADOW2D: |
||
416 | case TGSI_TEXTURE_SHADOWRECT: |
||
417 | case TGSI_TEXTURE_SHADOWCUBE: |
||
418 | case TGSI_TEXTURE_SHADOW1D_ARRAY: |
||
419 | case TGSI_TEXTURE_SHADOW2D_ARRAY: |
||
420 | case TGSI_TEXTURE_SHADOWCUBE_ARRAY: |
||
421 | case TGSI_TEXTURE_2D_MSAA: |
||
422 | case TGSI_TEXTURE_2D_ARRAY_MSAA: |
||
423 | *shadow_or_sample = dim; |
||
424 | break; |
||
425 | default: |
||
426 | /* no shadow nor sample */ |
||
427 | *shadow_or_sample = -1; |
||
428 | break; |
||
429 | } |
||
430 | } |
||
431 | |||
432 | return dim; |
||
433 | }><>><>> |