• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2008-2009 Nicolai Haehnle.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "radeon_program_pair.h"
7 
8 #include "radeon_compiler_util.h"
9 
10 #include <stdlib.h>
11 
12 /**
13  * Return the source slot where we installed the given register access,
14  * or -1 if no slot was free anymore.
15  */
16 int
rc_pair_alloc_source(struct rc_pair_instruction * pair,unsigned int rgb,unsigned int alpha,rc_register_file file,unsigned int index)17 rc_pair_alloc_source(struct rc_pair_instruction *pair, unsigned int rgb, unsigned int alpha,
18                      rc_register_file file, unsigned int index)
19 {
20    int candidate = -1;
21    int candidate_quality = -1;
22    unsigned int alpha_used = 0;
23    unsigned int rgb_used = 0;
24    int i;
25 
26    if ((!rgb && !alpha) || file == RC_FILE_NONE)
27       return 0;
28 
29    /* Make sure only one presubtract operation is used per instruction. */
30    if (file == RC_FILE_PRESUB) {
31       if (rgb && pair->RGB.Src[RC_PAIR_PRESUB_SRC].Used &&
32           index != pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index) {
33          return -1;
34       }
35 
36       if (alpha && pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Used &&
37           index != pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) {
38          return -1;
39       }
40    }
41 
42    for (i = 0; i < 3; ++i) {
43       int q = 0;
44       if (rgb) {
45          if (pair->RGB.Src[i].Used) {
46             if (pair->RGB.Src[i].File != file || pair->RGB.Src[i].Index != index) {
47                rgb_used++;
48                continue;
49             }
50             q++;
51          }
52       }
53       if (alpha) {
54          if (pair->Alpha.Src[i].Used) {
55             if (pair->Alpha.Src[i].File != file || pair->Alpha.Src[i].Index != index) {
56                alpha_used++;
57                continue;
58             }
59             q++;
60          }
61       }
62       if (q > candidate_quality) {
63          candidate_quality = q;
64          candidate = i;
65       }
66    }
67 
68    if (file == RC_FILE_PRESUB) {
69       candidate = RC_PAIR_PRESUB_SRC;
70    } else if (candidate < 0 || (rgb && rgb_used > 2) || (alpha && alpha_used > 2)) {
71       return -1;
72    }
73 
74    /* candidate >= 0 */
75 
76    if (rgb) {
77       pair->RGB.Src[candidate].Used = 1;
78       pair->RGB.Src[candidate].File = file;
79       pair->RGB.Src[candidate].Index = index;
80       if (candidate == RC_PAIR_PRESUB_SRC) {
81          /* For registers with the RC_FILE_PRESUB file,
82           * the index stores the presubtract op. */
83          int src_regs = rc_presubtract_src_reg_count(index);
84          for (i = 0; i < src_regs; i++) {
85             pair->RGB.Src[i].Used = 1;
86          }
87       }
88    }
89    if (alpha) {
90       pair->Alpha.Src[candidate].Used = 1;
91       pair->Alpha.Src[candidate].File = file;
92       pair->Alpha.Src[candidate].Index = index;
93       if (candidate == RC_PAIR_PRESUB_SRC) {
94          /* For registers with the RC_FILE_PRESUB file,
95           * the index stores the presubtract op. */
96          int src_regs = rc_presubtract_src_reg_count(index);
97          for (i = 0; i < src_regs; i++) {
98             pair->Alpha.Src[i].Used = 1;
99          }
100       }
101    }
102 
103    return candidate;
104 }
105 
106 static void
pair_foreach_source_callback(struct rc_pair_instruction * pair,void * data,rc_pair_foreach_src_fn cb,unsigned int swz,unsigned int src)107 pair_foreach_source_callback(struct rc_pair_instruction *pair, void *data,
108                              rc_pair_foreach_src_fn cb, unsigned int swz, unsigned int src)
109 {
110    /* swz > 3 means that the swizzle is either not used, or a constant
111     * swizzle (e.g. 0, 1, 0.5). */
112    if (swz > 3)
113       return;
114 
115    if (swz == RC_SWIZZLE_W) {
116       if (src == RC_PAIR_PRESUB_SRC) {
117          unsigned int i;
118          unsigned int src_count =
119             rc_presubtract_src_reg_count(pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index);
120          for (i = 0; i < src_count; i++) {
121             cb(data, &pair->Alpha.Src[i]);
122          }
123       } else {
124          cb(data, &pair->Alpha.Src[src]);
125       }
126    } else {
127       if (src == RC_PAIR_PRESUB_SRC) {
128          unsigned int i;
129          unsigned int src_count =
130             rc_presubtract_src_reg_count(pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index);
131          for (i = 0; i < src_count; i++) {
132             cb(data, &pair->RGB.Src[i]);
133          }
134       } else {
135          cb(data, &pair->RGB.Src[src]);
136       }
137    }
138 }
139 
140 void
rc_pair_foreach_source_that_alpha_reads(struct rc_pair_instruction * pair,void * data,rc_pair_foreach_src_fn cb)141 rc_pair_foreach_source_that_alpha_reads(struct rc_pair_instruction *pair, void *data,
142                                         rc_pair_foreach_src_fn cb)
143 {
144    unsigned int i;
145    const struct rc_opcode_info *info = rc_get_opcode_info(pair->Alpha.Opcode);
146    for (i = 0; i < info->NumSrcRegs; i++) {
147       pair_foreach_source_callback(pair, data, cb, GET_SWZ(pair->Alpha.Arg[i].Swizzle, 0),
148                                    pair->Alpha.Arg[i].Source);
149    }
150 }
151 
152 void
rc_pair_foreach_source_that_rgb_reads(struct rc_pair_instruction * pair,void * data,rc_pair_foreach_src_fn cb)153 rc_pair_foreach_source_that_rgb_reads(struct rc_pair_instruction *pair, void *data,
154                                       rc_pair_foreach_src_fn cb)
155 {
156    unsigned int i;
157    const struct rc_opcode_info *info = rc_get_opcode_info(pair->RGB.Opcode);
158    for (i = 0; i < info->NumSrcRegs; i++) {
159       unsigned int chan;
160       unsigned int swz = RC_SWIZZLE_UNUSED;
161       /* Find a swizzle that is either X,Y,Z,or W.  We assume here
162        * that if one channel swizzles X,Y, or Z, then none of the
163        * other channels swizzle W, and vice-versa. */
164       for (chan = 0; chan < 4; chan++) {
165          swz = GET_SWZ(pair->RGB.Arg[i].Swizzle, chan);
166          if (swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y || swz == RC_SWIZZLE_Z ||
167              swz == RC_SWIZZLE_W)
168             continue;
169       }
170       pair_foreach_source_callback(pair, data, cb, swz, pair->RGB.Arg[i].Source);
171    }
172 }
173 
174 struct rc_pair_instruction_source *
rc_pair_get_src(struct rc_pair_instruction * pair_inst,struct rc_pair_instruction_arg * arg)175 rc_pair_get_src(struct rc_pair_instruction *pair_inst, struct rc_pair_instruction_arg *arg)
176 {
177    unsigned int type;
178 
179    type = rc_source_type_swz(arg->Swizzle);
180 
181    if (type & RC_SOURCE_RGB) {
182       return &pair_inst->RGB.Src[arg->Source];
183    } else if (type & RC_SOURCE_ALPHA) {
184       return &pair_inst->Alpha.Src[arg->Source];
185    } else {
186       return NULL;
187    }
188 }
189 
190 int
rc_pair_get_src_index(struct rc_pair_instruction * pair_inst,struct rc_pair_instruction_source * src)191 rc_pair_get_src_index(struct rc_pair_instruction *pair_inst, struct rc_pair_instruction_source *src)
192 {
193    int i;
194    for (i = 0; i < 3; i++) {
195       if (&pair_inst->RGB.Src[i] == src || &pair_inst->Alpha.Src[i] == src) {
196          return i;
197       }
198    }
199    return -1;
200 }
201