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