Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2010 VMware. |
||
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 | |||
29 | #include "util/u_math.h" |
||
30 | #include "util/u_memory.h" |
||
31 | #include "util/u_simple_list.h" |
||
32 | #include "os/os_time.h" |
||
33 | #include "gallivm/lp_bld_arit.h" |
||
34 | #include "gallivm/lp_bld_const.h" |
||
35 | #include "gallivm/lp_bld_debug.h" |
||
36 | #include "gallivm/lp_bld_init.h" |
||
37 | #include "gallivm/lp_bld_logic.h" |
||
38 | #include "gallivm/lp_bld_intr.h" |
||
39 | #include "gallivm/lp_bld_flow.h" |
||
40 | #include "gallivm/lp_bld_type.h" |
||
41 | |||
42 | #include "lp_perf.h" |
||
43 | #include "lp_debug.h" |
||
44 | #include "lp_flush.h" |
||
45 | #include "lp_screen.h" |
||
46 | #include "lp_context.h" |
||
47 | #include "lp_state.h" |
||
48 | #include "lp_state_fs.h" |
||
49 | #include "lp_state_setup.h" |
||
50 | |||
51 | |||
52 | |||
53 | /* currently organized to interpolate full float[4] attributes even |
||
54 | * when some elements are unused. Later, can pack vertex data more |
||
55 | * closely. |
||
56 | */ |
||
57 | |||
58 | |||
59 | struct lp_setup_args |
||
60 | { |
||
61 | /* Function arguments: |
||
62 | */ |
||
63 | LLVMValueRef v0; |
||
64 | LLVMValueRef v1; |
||
65 | LLVMValueRef v2; |
||
66 | LLVMValueRef facing; /* boolean */ |
||
67 | LLVMValueRef a0; |
||
68 | LLVMValueRef dadx; |
||
69 | LLVMValueRef dady; |
||
70 | |||
71 | /* Derived: |
||
72 | */ |
||
73 | LLVMValueRef x0_center; |
||
74 | LLVMValueRef y0_center; |
||
75 | LLVMValueRef dy20_ooa; |
||
76 | LLVMValueRef dy01_ooa; |
||
77 | LLVMValueRef dx20_ooa; |
||
78 | LLVMValueRef dx01_ooa; |
||
79 | }; |
||
80 | |||
81 | |||
82 | |||
83 | static LLVMTypeRef |
||
84 | type4f(struct gallivm_state *gallivm) |
||
85 | { |
||
86 | return LLVMVectorType(LLVMFloatTypeInContext(gallivm->context), 4); |
||
87 | } |
||
88 | |||
89 | |||
90 | /* Equivalent of _mm_setr_ps(a,b,c,d) |
||
91 | */ |
||
92 | static LLVMValueRef |
||
93 | vec4f(struct gallivm_state *gallivm, |
||
94 | LLVMValueRef a, LLVMValueRef b, LLVMValueRef c, LLVMValueRef d, |
||
95 | const char *name) |
||
96 | { |
||
97 | LLVMBuilderRef bld = gallivm->builder; |
||
98 | LLVMValueRef i0 = lp_build_const_int32(gallivm, 0); |
||
99 | LLVMValueRef i1 = lp_build_const_int32(gallivm, 1); |
||
100 | LLVMValueRef i2 = lp_build_const_int32(gallivm, 2); |
||
101 | LLVMValueRef i3 = lp_build_const_int32(gallivm, 3); |
||
102 | |||
103 | LLVMValueRef res = LLVMGetUndef(type4f(gallivm)); |
||
104 | |||
105 | res = LLVMBuildInsertElement(bld, res, a, i0, ""); |
||
106 | res = LLVMBuildInsertElement(bld, res, b, i1, ""); |
||
107 | res = LLVMBuildInsertElement(bld, res, c, i2, ""); |
||
108 | res = LLVMBuildInsertElement(bld, res, d, i3, name); |
||
109 | |||
110 | return res; |
||
111 | } |
||
112 | |||
113 | /* Equivalent of _mm_set1_ps(a) |
||
114 | */ |
||
115 | static LLVMValueRef |
||
116 | vec4f_from_scalar(struct gallivm_state *gallivm, |
||
117 | LLVMValueRef a, |
||
118 | const char *name) |
||
119 | { |
||
120 | LLVMBuilderRef bld = gallivm->builder; |
||
121 | LLVMValueRef res = LLVMGetUndef(type4f(gallivm)); |
||
122 | int i; |
||
123 | |||
124 | for(i = 0; i < 4; ++i) { |
||
125 | LLVMValueRef index = lp_build_const_int32(gallivm, i); |
||
126 | res = LLVMBuildInsertElement(bld, res, a, index, i == 3 ? name : ""); |
||
127 | } |
||
128 | |||
129 | return res; |
||
130 | } |
||
131 | |||
132 | static void |
||
133 | store_coef(struct gallivm_state *gallivm, |
||
134 | struct lp_setup_args *args, |
||
135 | unsigned slot, |
||
136 | LLVMValueRef a0, |
||
137 | LLVMValueRef dadx, |
||
138 | LLVMValueRef dady) |
||
139 | { |
||
140 | LLVMBuilderRef builder = gallivm->builder; |
||
141 | LLVMValueRef idx = lp_build_const_int32(gallivm, slot); |
||
142 | |||
143 | LLVMBuildStore(builder, |
||
144 | a0, |
||
145 | LLVMBuildGEP(builder, args->a0, &idx, 1, "")); |
||
146 | |||
147 | LLVMBuildStore(builder, |
||
148 | dadx, |
||
149 | LLVMBuildGEP(builder, args->dadx, &idx, 1, "")); |
||
150 | |||
151 | LLVMBuildStore(builder, |
||
152 | dady, |
||
153 | LLVMBuildGEP(builder, args->dady, &idx, 1, "")); |
||
154 | } |
||
155 | |||
156 | |||
157 | |||
158 | static void |
||
159 | emit_constant_coef4(struct gallivm_state *gallivm, |
||
160 | struct lp_setup_args *args, |
||
161 | unsigned slot, |
||
162 | LLVMValueRef vert) |
||
163 | { |
||
164 | LLVMValueRef zero = lp_build_const_float(gallivm, 0.0); |
||
165 | LLVMValueRef zerovec = vec4f_from_scalar(gallivm, zero, "zero"); |
||
166 | store_coef(gallivm, args, slot, vert, zerovec, zerovec); |
||
167 | } |
||
168 | |||
169 | |||
170 | |||
171 | /** |
||
172 | * Setup the fragment input attribute with the front-facing value. |
||
173 | * \param frontface is the triangle front facing? |
||
174 | */ |
||
175 | static void |
||
176 | emit_facing_coef(struct gallivm_state *gallivm, |
||
177 | struct lp_setup_args *args, |
||
178 | unsigned slot ) |
||
179 | { |
||
180 | LLVMBuilderRef builder = gallivm->builder; |
||
181 | LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context); |
||
182 | LLVMValueRef a0_0 = args->facing; |
||
183 | LLVMValueRef a0_0f = LLVMBuildSIToFP(builder, a0_0, float_type, ""); |
||
184 | LLVMValueRef zero = lp_build_const_float(gallivm, 0.0); |
||
185 | LLVMValueRef a0 = vec4f(gallivm, a0_0f, zero, zero, zero, "facing"); |
||
186 | LLVMValueRef zerovec = vec4f_from_scalar(gallivm, zero, "zero"); |
||
187 | |||
188 | store_coef(gallivm, args, slot, a0, zerovec, zerovec); |
||
189 | } |
||
190 | |||
191 | |||
192 | static LLVMValueRef |
||
193 | vert_attrib(struct gallivm_state *gallivm, |
||
194 | LLVMValueRef vert, |
||
195 | int attr, |
||
196 | int elem, |
||
197 | const char *name) |
||
198 | { |
||
199 | LLVMBuilderRef b = gallivm->builder; |
||
200 | LLVMValueRef idx[2]; |
||
201 | idx[0] = lp_build_const_int32(gallivm, attr); |
||
202 | idx[1] = lp_build_const_int32(gallivm, elem); |
||
203 | return LLVMBuildLoad(b, LLVMBuildGEP(b, vert, idx, 2, ""), name); |
||
204 | } |
||
205 | |||
206 | |||
207 | static void |
||
208 | lp_twoside(struct gallivm_state *gallivm, |
||
209 | struct lp_setup_args *args, |
||
210 | const struct lp_setup_variant_key *key, |
||
211 | int bcolor_slot, |
||
212 | LLVMValueRef attribv[3]) |
||
213 | { |
||
214 | LLVMBuilderRef b = gallivm->builder; |
||
215 | LLVMValueRef a0_back, a1_back, a2_back; |
||
216 | LLVMValueRef idx2 = lp_build_const_int32(gallivm, bcolor_slot); |
||
217 | |||
218 | LLVMValueRef facing = args->facing; |
||
219 | LLVMValueRef front_facing = LLVMBuildICmp(b, LLVMIntEQ, facing, lp_build_const_int32(gallivm, 0), ""); /** need i1 for if condition */ |
||
220 | |||
221 | a0_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx2, 1, ""), "v0a_back"); |
||
222 | a1_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx2, 1, ""), "v1a_back"); |
||
223 | a2_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx2, 1, ""), "v2a_back"); |
||
224 | |||
225 | /* Possibly swap the front and back attrib values, |
||
226 | * |
||
227 | * Prefer select to if so we don't have to worry about phis or |
||
228 | * allocas. |
||
229 | */ |
||
230 | attribv[0] = LLVMBuildSelect(b, front_facing, a0_back, attribv[0], ""); |
||
231 | attribv[1] = LLVMBuildSelect(b, front_facing, a1_back, attribv[1], ""); |
||
232 | attribv[2] = LLVMBuildSelect(b, front_facing, a2_back, attribv[2], ""); |
||
233 | |||
234 | } |
||
235 | |||
236 | static void |
||
237 | lp_do_offset_tri(struct gallivm_state *gallivm, |
||
238 | struct lp_setup_args *args, |
||
239 | const struct lp_setup_variant_key *key, |
||
240 | LLVMValueRef inv_det, |
||
241 | LLVMValueRef dxyz01, |
||
242 | LLVMValueRef dxyz20, |
||
243 | LLVMValueRef attribv[3]) |
||
244 | { |
||
245 | LLVMBuilderRef b = gallivm->builder; |
||
246 | struct lp_build_context bld; |
||
247 | struct lp_build_context flt_scalar_bld; |
||
248 | LLVMValueRef zoffset, mult; |
||
249 | LLVMValueRef z0_new, z1_new, z2_new; |
||
250 | LLVMValueRef dzdxdzdy, dzdx, dzdy, dzxyz20, dyzzx01, dyzzx01_dzxyz20, dzx01_dyz20; |
||
251 | LLVMValueRef z0z1, z0z1z2; |
||
252 | LLVMValueRef max, max_value, res12; |
||
253 | LLVMValueRef shuffles[4]; |
||
254 | LLVMTypeRef shuf_type = LLVMInt32TypeInContext(gallivm->context); |
||
255 | LLVMValueRef onei = lp_build_const_int32(gallivm, 1); |
||
256 | LLVMValueRef zeroi = lp_build_const_int32(gallivm, 0); |
||
257 | LLVMValueRef twoi = lp_build_const_int32(gallivm, 2); |
||
258 | LLVMValueRef threei = lp_build_const_int32(gallivm, 3); |
||
259 | |||
260 | /* (res12) = cross(e,f).xy */ |
||
261 | shuffles[0] = twoi; |
||
262 | shuffles[1] = zeroi; |
||
263 | shuffles[2] = onei; |
||
264 | shuffles[3] = twoi; |
||
265 | dzxyz20 = LLVMBuildShuffleVector(b, dxyz20, dxyz20, LLVMConstVector(shuffles, 4), ""); |
||
266 | |||
267 | shuffles[0] = onei; |
||
268 | shuffles[1] = twoi; |
||
269 | shuffles[2] = twoi; |
||
270 | shuffles[3] = zeroi; |
||
271 | dyzzx01 = LLVMBuildShuffleVector(b, dxyz01, dxyz01, LLVMConstVector(shuffles, 4), ""); |
||
272 | |||
273 | dyzzx01_dzxyz20 = LLVMBuildFMul(b, dzxyz20, dyzzx01, "dyzzx01_dzxyz20"); |
||
274 | |||
275 | shuffles[0] = twoi; |
||
276 | shuffles[1] = threei; |
||
277 | shuffles[2] = LLVMGetUndef(shuf_type); |
||
278 | shuffles[3] = LLVMGetUndef(shuf_type); |
||
279 | dzx01_dyz20 = LLVMBuildShuffleVector(b, dyzzx01_dzxyz20, dyzzx01_dzxyz20, |
||
280 | LLVMConstVector(shuffles, 4), ""); |
||
281 | |||
282 | res12 = LLVMBuildFSub(b, dyzzx01_dzxyz20, dzx01_dyz20, "res12"); |
||
283 | |||
284 | /* dzdx = fabsf(res1 * inv_det), dydx = fabsf(res2 * inv_det)*/ |
||
285 | lp_build_context_init(&bld, gallivm, lp_type_float_vec(32, 128)); |
||
286 | dzdxdzdy = LLVMBuildFMul(b, res12, inv_det, "dzdxdzdy"); |
||
287 | dzdxdzdy = lp_build_abs(&bld, dzdxdzdy); |
||
288 | |||
289 | dzdx = LLVMBuildExtractElement(b, dzdxdzdy, zeroi, ""); |
||
290 | dzdy = LLVMBuildExtractElement(b, dzdxdzdy, onei, ""); |
||
291 | |||
292 | /* zoffset = pgon_offset_units + MAX2(dzdx, dzdy) * pgon_offset_scale */ |
||
293 | max = LLVMBuildFCmp(b, LLVMRealUGT, dzdx, dzdy, ""); |
||
294 | max_value = LLVMBuildSelect(b, max, dzdx, dzdy, "max"); |
||
295 | |||
296 | mult = LLVMBuildFMul(b, max_value, |
||
297 | lp_build_const_float(gallivm, key->pgon_offset_scale), ""); |
||
298 | zoffset = LLVMBuildFAdd(b, |
||
299 | lp_build_const_float(gallivm, key->pgon_offset_units), |
||
300 | mult, "zoffset"); |
||
301 | |||
302 | lp_build_context_init(&flt_scalar_bld, gallivm, lp_type_float_vec(32, 32)); |
||
303 | if (key->pgon_offset_clamp > 0) { |
||
304 | zoffset = lp_build_min(&flt_scalar_bld, |
||
305 | lp_build_const_float(gallivm, key->pgon_offset_clamp), |
||
306 | zoffset); |
||
307 | } |
||
308 | else if (key->pgon_offset_clamp < 0) { |
||
309 | zoffset = lp_build_max(&flt_scalar_bld, |
||
310 | lp_build_const_float(gallivm, key->pgon_offset_clamp), |
||
311 | zoffset); |
||
312 | } |
||
313 | |||
314 | /* yuck */ |
||
315 | shuffles[0] = twoi; |
||
316 | shuffles[1] = lp_build_const_int32(gallivm, 6); |
||
317 | shuffles[2] = LLVMGetUndef(shuf_type); |
||
318 | shuffles[3] = LLVMGetUndef(shuf_type); |
||
319 | z0z1 = LLVMBuildShuffleVector(b, attribv[0], attribv[1], LLVMConstVector(shuffles, 4), ""); |
||
320 | shuffles[0] = zeroi; |
||
321 | shuffles[1] = onei; |
||
322 | shuffles[2] = lp_build_const_int32(gallivm, 6); |
||
323 | shuffles[3] = LLVMGetUndef(shuf_type); |
||
324 | z0z1z2 = LLVMBuildShuffleVector(b, z0z1, attribv[2], LLVMConstVector(shuffles, 4), ""); |
||
325 | zoffset = vec4f_from_scalar(gallivm, zoffset, ""); |
||
326 | |||
327 | /* clamp and do offset */ |
||
328 | /* |
||
329 | * FIXME I suspect the clamp (is that even right to always clamp to fixed |
||
330 | * 0.0/1.0?) should really be per fragment? |
||
331 | */ |
||
332 | z0z1z2 = lp_build_clamp(&bld, LLVMBuildFAdd(b, z0z1z2, zoffset, ""), bld.zero, bld.one); |
||
333 | |||
334 | /* insert into args->a0.z, a1.z, a2.z: |
||
335 | */ |
||
336 | z0_new = LLVMBuildExtractElement(b, z0z1z2, zeroi, ""); |
||
337 | z1_new = LLVMBuildExtractElement(b, z0z1z2, onei, ""); |
||
338 | z2_new = LLVMBuildExtractElement(b, z0z1z2, twoi, ""); |
||
339 | attribv[0] = LLVMBuildInsertElement(b, attribv[0], z0_new, twoi, ""); |
||
340 | attribv[1] = LLVMBuildInsertElement(b, attribv[1], z1_new, twoi, ""); |
||
341 | attribv[2] = LLVMBuildInsertElement(b, attribv[2], z2_new, twoi, ""); |
||
342 | } |
||
343 | |||
344 | static void |
||
345 | load_attribute(struct gallivm_state *gallivm, |
||
346 | struct lp_setup_args *args, |
||
347 | const struct lp_setup_variant_key *key, |
||
348 | unsigned vert_attr, |
||
349 | LLVMValueRef attribv[3]) |
||
350 | { |
||
351 | LLVMBuilderRef b = gallivm->builder; |
||
352 | LLVMValueRef idx = lp_build_const_int32(gallivm, vert_attr); |
||
353 | |||
354 | /* Load the vertex data |
||
355 | */ |
||
356 | attribv[0] = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a"); |
||
357 | attribv[1] = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a"); |
||
358 | attribv[2] = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a"); |
||
359 | |||
360 | |||
361 | /* Potentially modify it according to twoside, etc: |
||
362 | */ |
||
363 | if (key->twoside) { |
||
364 | if (vert_attr == key->color_slot && key->bcolor_slot >= 0) |
||
365 | lp_twoside(gallivm, args, key, key->bcolor_slot, attribv); |
||
366 | else if (vert_attr == key->spec_slot && key->bspec_slot >= 0) |
||
367 | lp_twoside(gallivm, args, key, key->bspec_slot, attribv); |
||
368 | } |
||
369 | } |
||
370 | |||
371 | static void |
||
372 | emit_coef4( struct gallivm_state *gallivm, |
||
373 | struct lp_setup_args *args, |
||
374 | unsigned slot, |
||
375 | LLVMValueRef a0, |
||
376 | LLVMValueRef a1, |
||
377 | LLVMValueRef a2) |
||
378 | { |
||
379 | LLVMBuilderRef b = gallivm->builder; |
||
380 | LLVMValueRef dy20_ooa = args->dy20_ooa; |
||
381 | LLVMValueRef dy01_ooa = args->dy01_ooa; |
||
382 | LLVMValueRef dx20_ooa = args->dx20_ooa; |
||
383 | LLVMValueRef dx01_ooa = args->dx01_ooa; |
||
384 | LLVMValueRef x0_center = args->x0_center; |
||
385 | LLVMValueRef y0_center = args->y0_center; |
||
386 | |||
387 | LLVMValueRef da01 = LLVMBuildFSub(b, a0, a1, "da01"); |
||
388 | LLVMValueRef da20 = LLVMBuildFSub(b, a2, a0, "da20"); |
||
389 | |||
390 | /* Calculate dadx (vec4f) |
||
391 | */ |
||
392 | LLVMValueRef da01_dy20_ooa = LLVMBuildFMul(b, da01, dy20_ooa, "da01_dy20_ooa"); |
||
393 | LLVMValueRef da20_dy01_ooa = LLVMBuildFMul(b, da20, dy01_ooa, "da20_dy01_ooa"); |
||
394 | LLVMValueRef dadx = LLVMBuildFSub(b, da01_dy20_ooa, da20_dy01_ooa, "dadx"); |
||
395 | |||
396 | /* Calculate dady (vec4f) |
||
397 | */ |
||
398 | LLVMValueRef da01_dx20_ooa = LLVMBuildFMul(b, da01, dx20_ooa, "da01_dx20_ooa"); |
||
399 | LLVMValueRef da20_dx01_ooa = LLVMBuildFMul(b, da20, dx01_ooa, "da20_dx01_ooa"); |
||
400 | LLVMValueRef dady = LLVMBuildFSub(b, da20_dx01_ooa, da01_dx20_ooa, "dady"); |
||
401 | |||
402 | /* Calculate a0 - the attribute value at the origin |
||
403 | */ |
||
404 | LLVMValueRef dadx_x0 = LLVMBuildFMul(b, dadx, x0_center, "dadx_x0"); |
||
405 | LLVMValueRef dady_y0 = LLVMBuildFMul(b, dady, y0_center, "dady_y0"); |
||
406 | LLVMValueRef attr_v0 = LLVMBuildFAdd(b, dadx_x0, dady_y0, "attr_v0"); |
||
407 | LLVMValueRef attr_0 = LLVMBuildFSub(b, a0, attr_v0, "attr_0"); |
||
408 | |||
409 | store_coef(gallivm, args, slot, attr_0, dadx, dady); |
||
410 | } |
||
411 | |||
412 | |||
413 | static void |
||
414 | emit_linear_coef( struct gallivm_state *gallivm, |
||
415 | struct lp_setup_args *args, |
||
416 | unsigned slot, |
||
417 | LLVMValueRef attribv[3]) |
||
418 | { |
||
419 | /* nothing to do anymore */ |
||
420 | emit_coef4(gallivm, |
||
421 | args, slot, |
||
422 | attribv[0], |
||
423 | attribv[1], |
||
424 | attribv[2]); |
||
425 | } |
||
426 | |||
427 | |||
428 | /** |
||
429 | * Compute a0, dadx and dady for a perspective-corrected interpolant, |
||
430 | * for a triangle. |
||
431 | * We basically multiply the vertex value by 1/w before computing |
||
432 | * the plane coefficients (a0, dadx, dady). |
||
433 | * Later, when we compute the value at a particular fragment position we'll |
||
434 | * divide the interpolated value by the interpolated W at that fragment. |
||
435 | */ |
||
436 | static void |
||
437 | apply_perspective_corr( struct gallivm_state *gallivm, |
||
438 | struct lp_setup_args *args, |
||
439 | unsigned slot, |
||
440 | LLVMValueRef attribv[3]) |
||
441 | { |
||
442 | LLVMBuilderRef b = gallivm->builder; |
||
443 | |||
444 | /* premultiply by 1/w (v[0][3] is always 1/w): |
||
445 | */ |
||
446 | LLVMValueRef v0_oow = vec4f_from_scalar(gallivm, vert_attrib(gallivm, args->v0, 0, 3, ""), "v0_oow"); |
||
447 | LLVMValueRef v1_oow = vec4f_from_scalar(gallivm, vert_attrib(gallivm, args->v1, 0, 3, ""), "v1_oow"); |
||
448 | LLVMValueRef v2_oow = vec4f_from_scalar(gallivm, vert_attrib(gallivm, args->v2, 0, 3, ""), "v2_oow"); |
||
449 | |||
450 | attribv[0] = LLVMBuildFMul(b, attribv[0], v0_oow, "v0_oow_v0a"); |
||
451 | attribv[1] = LLVMBuildFMul(b, attribv[1], v1_oow, "v1_oow_v1a"); |
||
452 | attribv[2] = LLVMBuildFMul(b, attribv[2], v2_oow, "v2_oow_v2a"); |
||
453 | } |
||
454 | |||
455 | |||
456 | static void |
||
457 | emit_position_coef( struct gallivm_state *gallivm, |
||
458 | struct lp_setup_args *args, |
||
459 | int slot, |
||
460 | LLVMValueRef attribv[3]) |
||
461 | { |
||
462 | emit_linear_coef(gallivm, args, slot, attribv); |
||
463 | } |
||
464 | |||
465 | |||
466 | /** |
||
467 | * Applys cylindrical wrapping to vertex attributes if enabled. |
||
468 | * Input coordinates must be in [0, 1] range, otherwise results are undefined. |
||
469 | * |
||
470 | * @param cyl_wrap TGSI_CYLINDRICAL_WRAP_x flags |
||
471 | */ |
||
472 | static void |
||
473 | emit_apply_cyl_wrap(struct gallivm_state *gallivm, |
||
474 | struct lp_setup_args *args, |
||
475 | uint cyl_wrap, |
||
476 | LLVMValueRef attribv[3]) |
||
477 | |||
478 | { |
||
479 | LLVMBuilderRef builder = gallivm->builder; |
||
480 | struct lp_type type = lp_float32_vec4_type(); |
||
481 | LLVMTypeRef float_vec_type = lp_build_vec_type(gallivm, type); |
||
482 | LLVMValueRef pos_half; |
||
483 | LLVMValueRef neg_half; |
||
484 | LLVMValueRef cyl_mask; |
||
485 | LLVMValueRef offset; |
||
486 | LLVMValueRef delta; |
||
487 | LLVMValueRef one; |
||
488 | |||
489 | if (!cyl_wrap) |
||
490 | return; |
||
491 | |||
492 | /* Constants */ |
||
493 | pos_half = lp_build_const_vec(gallivm, type, +0.5f); |
||
494 | neg_half = lp_build_const_vec(gallivm, type, -0.5f); |
||
495 | cyl_mask = lp_build_const_mask_aos(gallivm, type, cyl_wrap, 4); |
||
496 | |||
497 | one = lp_build_const_vec(gallivm, type, 1.0f); |
||
498 | one = LLVMBuildBitCast(builder, one, lp_build_int_vec_type(gallivm, type), ""); |
||
499 | one = LLVMBuildAnd(builder, one, cyl_mask, ""); |
||
500 | |||
501 | /* Edge v0 -> v1 */ |
||
502 | delta = LLVMBuildFSub(builder, attribv[1], attribv[0], ""); |
||
503 | |||
504 | offset = lp_build_compare(gallivm, type, PIPE_FUNC_GREATER, delta, pos_half); |
||
505 | offset = LLVMBuildAnd(builder, offset, one, ""); |
||
506 | offset = LLVMBuildBitCast(builder, offset, float_vec_type, ""); |
||
507 | attribv[0] = LLVMBuildFAdd(builder, attribv[0], offset, ""); |
||
508 | |||
509 | offset = lp_build_compare(gallivm, type, PIPE_FUNC_LESS, delta, neg_half); |
||
510 | offset = LLVMBuildAnd(builder, offset, one, ""); |
||
511 | offset = LLVMBuildBitCast(builder, offset, float_vec_type, ""); |
||
512 | attribv[1] = LLVMBuildFAdd(builder, attribv[1], offset, ""); |
||
513 | |||
514 | /* Edge v1 -> v2 */ |
||
515 | delta = LLVMBuildFSub(builder, attribv[2], attribv[1], ""); |
||
516 | |||
517 | offset = lp_build_compare(gallivm, type, PIPE_FUNC_GREATER, delta, pos_half); |
||
518 | offset = LLVMBuildAnd(builder, offset, one, ""); |
||
519 | offset = LLVMBuildBitCast(builder, offset, float_vec_type, ""); |
||
520 | attribv[1] = LLVMBuildFAdd(builder, attribv[1], offset, ""); |
||
521 | |||
522 | offset = lp_build_compare(gallivm, type, PIPE_FUNC_LESS, delta, neg_half); |
||
523 | offset = LLVMBuildAnd(builder, offset, one, ""); |
||
524 | offset = LLVMBuildBitCast(builder, offset, float_vec_type, ""); |
||
525 | attribv[2] = LLVMBuildFAdd(builder, attribv[2], offset, ""); |
||
526 | |||
527 | /* Edge v2 -> v0 */ |
||
528 | delta = LLVMBuildFSub(builder, attribv[0], attribv[2], ""); |
||
529 | |||
530 | offset = lp_build_compare(gallivm, type, PIPE_FUNC_GREATER, delta, pos_half); |
||
531 | offset = LLVMBuildAnd(builder, offset, one, ""); |
||
532 | offset = LLVMBuildBitCast(builder, offset, float_vec_type, ""); |
||
533 | attribv[2] = LLVMBuildFAdd(builder, attribv[2], offset, ""); |
||
534 | |||
535 | offset = lp_build_compare(gallivm, type, PIPE_FUNC_LESS, delta, neg_half); |
||
536 | offset = LLVMBuildAnd(builder, offset, one, ""); |
||
537 | offset = LLVMBuildBitCast(builder, offset, float_vec_type, ""); |
||
538 | attribv[0] = LLVMBuildFAdd(builder, attribv[0], offset, ""); |
||
539 | } |
||
540 | |||
541 | |||
542 | /** |
||
543 | * Compute the inputs-> dadx, dady, a0 values. |
||
544 | */ |
||
545 | static void |
||
546 | emit_tri_coef( struct gallivm_state *gallivm, |
||
547 | const struct lp_setup_variant_key *key, |
||
548 | struct lp_setup_args *args) |
||
549 | { |
||
550 | unsigned slot; |
||
551 | |||
552 | LLVMValueRef attribs[3]; |
||
553 | |||
554 | /* setup interpolation for all the remaining attributes: |
||
555 | */ |
||
556 | for (slot = 0; slot < key->num_inputs; slot++) { |
||
557 | switch (key->inputs[slot].interp) { |
||
558 | case LP_INTERP_CONSTANT: |
||
559 | load_attribute(gallivm, args, key, key->inputs[slot].src_index, attribs); |
||
560 | if (key->flatshade_first) { |
||
561 | emit_constant_coef4(gallivm, args, slot+1, attribs[0]); |
||
562 | } |
||
563 | else { |
||
564 | emit_constant_coef4(gallivm, args, slot+1, attribs[2]); |
||
565 | } |
||
566 | break; |
||
567 | |||
568 | case LP_INTERP_LINEAR: |
||
569 | load_attribute(gallivm, args, key, key->inputs[slot].src_index, attribs); |
||
570 | emit_apply_cyl_wrap(gallivm, args, key->inputs[slot].cyl_wrap, attribs); |
||
571 | emit_linear_coef(gallivm, args, slot+1, attribs); |
||
572 | break; |
||
573 | |||
574 | case LP_INTERP_PERSPECTIVE: |
||
575 | load_attribute(gallivm, args, key, key->inputs[slot].src_index, attribs); |
||
576 | emit_apply_cyl_wrap(gallivm, args, key->inputs[slot].cyl_wrap, attribs); |
||
577 | apply_perspective_corr(gallivm, args, slot+1, attribs); |
||
578 | emit_linear_coef(gallivm, args, slot+1, attribs); |
||
579 | break; |
||
580 | |||
581 | case LP_INTERP_POSITION: |
||
582 | /* |
||
583 | * The generated pixel interpolators will pick up the coeffs from |
||
584 | * slot 0. |
||
585 | */ |
||
586 | break; |
||
587 | |||
588 | case LP_INTERP_FACING: |
||
589 | emit_facing_coef(gallivm, args, slot+1); |
||
590 | break; |
||
591 | |||
592 | default: |
||
593 | assert(0); |
||
594 | } |
||
595 | } |
||
596 | } |
||
597 | |||
598 | |||
599 | /* XXX: generic code: |
||
600 | */ |
||
601 | static void |
||
602 | set_noalias(LLVMBuilderRef builder, |
||
603 | LLVMValueRef function, |
||
604 | const LLVMTypeRef *arg_types, |
||
605 | int nr_args) |
||
606 | { |
||
607 | int i; |
||
608 | for(i = 0; i < nr_args; ++i) |
||
609 | if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) |
||
610 | LLVMAddAttribute(LLVMGetParam(function, i), |
||
611 | LLVMNoAliasAttribute); |
||
612 | } |
||
613 | |||
614 | static void |
||
615 | init_args(struct gallivm_state *gallivm, |
||
616 | const struct lp_setup_variant_key *key, |
||
617 | struct lp_setup_args *args) |
||
618 | { |
||
619 | LLVMBuilderRef b = gallivm->builder; |
||
620 | LLVMTypeRef shuf_type = LLVMInt32TypeInContext(gallivm->context); |
||
621 | LLVMValueRef onef = lp_build_const_float(gallivm, 1.0); |
||
622 | LLVMValueRef onei = lp_build_const_int32(gallivm, 1); |
||
623 | LLVMValueRef zeroi = lp_build_const_int32(gallivm, 0); |
||
624 | LLVMValueRef pixel_center, xy0_center, dxy01, dxy20, dyx20; |
||
625 | LLVMValueRef e, f, ef, ooa; |
||
626 | LLVMValueRef shuffles[4]; |
||
627 | LLVMValueRef attr_pos[3]; |
||
628 | struct lp_type typef4 = lp_type_float_vec(32, 128); |
||
629 | |||
630 | /* The internal position input is in slot zero: |
||
631 | */ |
||
632 | load_attribute(gallivm, args, key, 0, attr_pos); |
||
633 | |||
634 | pixel_center = lp_build_const_vec(gallivm, typef4, |
||
635 | key->pixel_center_half ? 0.5 : 0.0); |
||
636 | |||
637 | /* |
||
638 | * xy are first two elems in v0a/v1a/v2a but just use vec4 arit |
||
639 | * also offset_tri uses actually xyz in them |
||
640 | */ |
||
641 | xy0_center = LLVMBuildFSub(b, attr_pos[0], pixel_center, "xy0_center" ); |
||
642 | |||
643 | dxy01 = LLVMBuildFSub(b, attr_pos[0], attr_pos[1], "dxy01"); |
||
644 | dxy20 = LLVMBuildFSub(b, attr_pos[2], attr_pos[0], "dxy20"); |
||
645 | |||
646 | shuffles[0] = onei; |
||
647 | shuffles[1] = zeroi; |
||
648 | shuffles[2] = LLVMGetUndef(shuf_type); |
||
649 | shuffles[3] = LLVMGetUndef(shuf_type); |
||
650 | |||
651 | dyx20 = LLVMBuildShuffleVector(b, dxy20, dxy20, LLVMConstVector(shuffles, 4), ""); |
||
652 | |||
653 | ef = LLVMBuildFMul(b, dxy01, dyx20, "ef"); |
||
654 | e = LLVMBuildExtractElement(b, ef, zeroi, ""); |
||
655 | f = LLVMBuildExtractElement(b, ef, onei, ""); |
||
656 | |||
657 | ooa = LLVMBuildFDiv(b, onef, LLVMBuildFSub(b, e, f, ""), "ooa"); |
||
658 | |||
659 | ooa = vec4f_from_scalar(gallivm, ooa, ""); |
||
660 | |||
661 | /* tri offset calc shares a lot of arithmetic, do it here */ |
||
662 | if (key->pgon_offset_scale != 0.0f || key->pgon_offset_units != 0.0f) { |
||
663 | lp_do_offset_tri(gallivm, args, key, ooa, dxy01, dxy20, attr_pos); |
||
664 | } |
||
665 | |||
666 | dxy20 = LLVMBuildFMul(b, dxy20, ooa, ""); |
||
667 | dxy01 = LLVMBuildFMul(b, dxy01, ooa, ""); |
||
668 | |||
669 | args->dy20_ooa = lp_build_extract_broadcast(gallivm, typef4, typef4, dxy20, onei); |
||
670 | args->dy01_ooa = lp_build_extract_broadcast(gallivm, typef4, typef4, dxy01, onei); |
||
671 | |||
672 | args->dx20_ooa = lp_build_extract_broadcast(gallivm, typef4, typef4, dxy20, zeroi); |
||
673 | args->dx01_ooa = lp_build_extract_broadcast(gallivm, typef4, typef4, dxy01, zeroi); |
||
674 | |||
675 | args->x0_center = lp_build_extract_broadcast(gallivm, typef4, typef4, xy0_center, zeroi); |
||
676 | args->y0_center = lp_build_extract_broadcast(gallivm, typef4, typef4, xy0_center, onei); |
||
677 | |||
678 | /* might want to merge that with other coef emit in the future */ |
||
679 | emit_position_coef(gallivm, args, 0, attr_pos); |
||
680 | } |
||
681 | |||
682 | /** |
||
683 | * Generate the runtime callable function for the coefficient calculation. |
||
684 | * |
||
685 | */ |
||
686 | static struct lp_setup_variant * |
||
687 | generate_setup_variant(struct lp_setup_variant_key *key, |
||
688 | struct llvmpipe_context *lp) |
||
689 | { |
||
690 | struct lp_setup_variant *variant = NULL; |
||
691 | struct gallivm_state *gallivm; |
||
692 | struct lp_setup_args args; |
||
693 | char func_name[256]; |
||
694 | LLVMTypeRef vec4f_type; |
||
695 | LLVMTypeRef func_type; |
||
696 | LLVMTypeRef arg_types[7]; |
||
697 | LLVMBasicBlockRef block; |
||
698 | LLVMBuilderRef builder; |
||
699 | int64_t t0 = 0, t1; |
||
700 | |||
701 | if (0) |
||
702 | goto fail; |
||
703 | |||
704 | variant = CALLOC_STRUCT(lp_setup_variant); |
||
705 | if (variant == NULL) |
||
706 | goto fail; |
||
707 | |||
708 | variant->gallivm = gallivm = gallivm_create(); |
||
709 | if (!variant->gallivm) { |
||
710 | goto fail; |
||
711 | } |
||
712 | |||
713 | builder = gallivm->builder; |
||
714 | |||
715 | if (LP_DEBUG & DEBUG_COUNTERS) { |
||
716 | t0 = os_time_get(); |
||
717 | } |
||
718 | |||
719 | memcpy(&variant->key, key, key->size); |
||
720 | variant->list_item_global.base = variant; |
||
721 | |||
722 | util_snprintf(func_name, sizeof(func_name), "fs%u_setup%u", |
||
723 | 0, |
||
724 | variant->no); |
||
725 | |||
726 | /* Currently always deal with full 4-wide vertex attributes from |
||
727 | * the vertices. |
||
728 | */ |
||
729 | |||
730 | vec4f_type = LLVMVectorType(LLVMFloatTypeInContext(gallivm->context), 4); |
||
731 | |||
732 | arg_types[0] = LLVMPointerType(vec4f_type, 0); /* v0 */ |
||
733 | arg_types[1] = LLVMPointerType(vec4f_type, 0); /* v1 */ |
||
734 | arg_types[2] = LLVMPointerType(vec4f_type, 0); /* v2 */ |
||
735 | arg_types[3] = LLVMInt32TypeInContext(gallivm->context); /* facing */ |
||
736 | arg_types[4] = LLVMPointerType(vec4f_type, 0); /* a0, aligned */ |
||
737 | arg_types[5] = LLVMPointerType(vec4f_type, 0); /* dadx, aligned */ |
||
738 | arg_types[6] = LLVMPointerType(vec4f_type, 0); /* dady, aligned */ |
||
739 | |||
740 | func_type = LLVMFunctionType(LLVMVoidTypeInContext(gallivm->context), |
||
741 | arg_types, Elements(arg_types), 0); |
||
742 | |||
743 | variant->function = LLVMAddFunction(gallivm->module, func_name, func_type); |
||
744 | if (!variant->function) |
||
745 | goto fail; |
||
746 | |||
747 | LLVMSetFunctionCallConv(variant->function, LLVMCCallConv); |
||
748 | |||
749 | args.v0 = LLVMGetParam(variant->function, 0); |
||
750 | args.v1 = LLVMGetParam(variant->function, 1); |
||
751 | args.v2 = LLVMGetParam(variant->function, 2); |
||
752 | args.facing = LLVMGetParam(variant->function, 3); |
||
753 | args.a0 = LLVMGetParam(variant->function, 4); |
||
754 | args.dadx = LLVMGetParam(variant->function, 5); |
||
755 | args.dady = LLVMGetParam(variant->function, 6); |
||
756 | |||
757 | lp_build_name(args.v0, "in_v0"); |
||
758 | lp_build_name(args.v1, "in_v1"); |
||
759 | lp_build_name(args.v2, "in_v2"); |
||
760 | lp_build_name(args.facing, "in_facing"); |
||
761 | lp_build_name(args.a0, "out_a0"); |
||
762 | lp_build_name(args.dadx, "out_dadx"); |
||
763 | lp_build_name(args.dady, "out_dady"); |
||
764 | |||
765 | /* |
||
766 | * Function body |
||
767 | */ |
||
768 | block = LLVMAppendBasicBlockInContext(gallivm->context, |
||
769 | variant->function, "entry"); |
||
770 | LLVMPositionBuilderAtEnd(builder, block); |
||
771 | |||
772 | set_noalias(builder, variant->function, arg_types, Elements(arg_types)); |
||
773 | init_args(gallivm, &variant->key, &args); |
||
774 | emit_tri_coef(gallivm, &variant->key, &args); |
||
775 | |||
776 | LLVMBuildRetVoid(builder); |
||
777 | |||
778 | gallivm_verify_function(gallivm, variant->function); |
||
779 | |||
780 | gallivm_compile_module(gallivm); |
||
781 | |||
782 | variant->jit_function = (lp_jit_setup_triangle) |
||
783 | gallivm_jit_function(gallivm, variant->function); |
||
784 | if (!variant->jit_function) |
||
785 | goto fail; |
||
786 | |||
787 | /* |
||
788 | * Update timing information: |
||
789 | */ |
||
790 | if (LP_DEBUG & DEBUG_COUNTERS) { |
||
791 | t1 = os_time_get(); |
||
792 | LP_COUNT_ADD(llvm_compile_time, t1 - t0); |
||
793 | LP_COUNT_ADD(nr_llvm_compiles, 1); |
||
794 | } |
||
795 | |||
796 | return variant; |
||
797 | |||
798 | fail: |
||
799 | if (variant) { |
||
800 | if (variant->function) { |
||
801 | gallivm_free_function(gallivm, |
||
802 | variant->function, |
||
803 | variant->jit_function); |
||
804 | } |
||
805 | if (variant->gallivm) { |
||
806 | gallivm_destroy(variant->gallivm); |
||
807 | } |
||
808 | FREE(variant); |
||
809 | } |
||
810 | |||
811 | return NULL; |
||
812 | } |
||
813 | |||
814 | |||
815 | |||
816 | static void |
||
817 | lp_make_setup_variant_key(struct llvmpipe_context *lp, |
||
818 | struct lp_setup_variant_key *key) |
||
819 | { |
||
820 | struct lp_fragment_shader *fs = lp->fs; |
||
821 | unsigned i; |
||
822 | |||
823 | assert(sizeof key->inputs[0] == sizeof(uint)); |
||
824 | |||
825 | key->num_inputs = fs->info.base.num_inputs; |
||
826 | key->flatshade_first = lp->rasterizer->flatshade_first; |
||
827 | key->pixel_center_half = lp->rasterizer->half_pixel_center; |
||
828 | key->twoside = lp->rasterizer->light_twoside; |
||
829 | key->size = Offset(struct lp_setup_variant_key, |
||
830 | inputs[key->num_inputs]); |
||
831 | |||
832 | key->color_slot = lp->color_slot [0]; |
||
833 | key->bcolor_slot = lp->bcolor_slot[0]; |
||
834 | key->spec_slot = lp->color_slot [1]; |
||
835 | key->bspec_slot = lp->bcolor_slot[1]; |
||
836 | assert(key->color_slot == lp->color_slot [0]); |
||
837 | assert(key->bcolor_slot == lp->bcolor_slot[0]); |
||
838 | assert(key->spec_slot == lp->color_slot [1]); |
||
839 | assert(key->bspec_slot == lp->bcolor_slot[1]); |
||
840 | |||
841 | key->pgon_offset_units = (float) (lp->rasterizer->offset_units * lp->mrd); |
||
842 | key->pgon_offset_scale = lp->rasterizer->offset_scale; |
||
843 | key->pgon_offset_clamp = lp->rasterizer->offset_clamp; |
||
844 | key->pad = 0; |
||
845 | memcpy(key->inputs, fs->inputs, key->num_inputs * sizeof key->inputs[0]); |
||
846 | for (i = 0; i < key->num_inputs; i++) { |
||
847 | if (key->inputs[i].interp == LP_INTERP_COLOR) { |
||
848 | if (lp->rasterizer->flatshade) |
||
849 | key->inputs[i].interp = LP_INTERP_CONSTANT; |
||
850 | else |
||
851 | key->inputs[i].interp = LP_INTERP_PERSPECTIVE; |
||
852 | } |
||
853 | } |
||
854 | |||
855 | } |
||
856 | |||
857 | |||
858 | static void |
||
859 | remove_setup_variant(struct llvmpipe_context *lp, |
||
860 | struct lp_setup_variant *variant) |
||
861 | { |
||
862 | if (gallivm_debug & GALLIVM_DEBUG_IR) { |
||
863 | debug_printf("llvmpipe: del setup_variant #%u total %u\n", |
||
864 | variant->no, lp->nr_setup_variants); |
||
865 | } |
||
866 | |||
867 | if (variant->function) { |
||
868 | gallivm_free_function(variant->gallivm, |
||
869 | variant->function, |
||
870 | variant->jit_function); |
||
871 | } |
||
872 | |||
873 | if (variant->gallivm) { |
||
874 | gallivm_destroy(variant->gallivm); |
||
875 | } |
||
876 | |||
877 | remove_from_list(&variant->list_item_global); |
||
878 | lp->nr_setup_variants--; |
||
879 | FREE(variant); |
||
880 | } |
||
881 | |||
882 | |||
883 | |||
884 | /* When the number of setup variants exceeds a threshold, cull a |
||
885 | * fraction (currently a quarter) of them. |
||
886 | */ |
||
887 | static void |
||
888 | cull_setup_variants(struct llvmpipe_context *lp) |
||
889 | { |
||
890 | struct pipe_context *pipe = &lp->pipe; |
||
891 | int i; |
||
892 | |||
893 | /* |
||
894 | * XXX: we need to flush the context until we have some sort of reference |
||
895 | * counting in fragment shaders as they may still be binned |
||
896 | * Flushing alone might not be sufficient we need to wait on it too. |
||
897 | */ |
||
898 | llvmpipe_finish(pipe, __FUNCTION__); |
||
899 | |||
900 | for (i = 0; i < LP_MAX_SETUP_VARIANTS / 4; i++) { |
||
901 | struct lp_setup_variant_list_item *item; |
||
902 | if (is_empty_list(&lp->setup_variants_list)) { |
||
903 | break; |
||
904 | } |
||
905 | item = last_elem(&lp->setup_variants_list); |
||
906 | assert(item); |
||
907 | assert(item->base); |
||
908 | remove_setup_variant(lp, item->base); |
||
909 | } |
||
910 | } |
||
911 | |||
912 | |||
913 | /** |
||
914 | * Update fragment/vertex shader linkage state. This is called just |
||
915 | * prior to drawing something when some fragment-related state has |
||
916 | * changed. |
||
917 | */ |
||
918 | void |
||
919 | llvmpipe_update_setup(struct llvmpipe_context *lp) |
||
920 | { |
||
921 | struct lp_setup_variant_key *key = &lp->setup_variant.key; |
||
922 | struct lp_setup_variant *variant = NULL; |
||
923 | struct lp_setup_variant_list_item *li; |
||
924 | |||
925 | lp_make_setup_variant_key(lp, key); |
||
926 | |||
927 | foreach(li, &lp->setup_variants_list) { |
||
928 | if(li->base->key.size == key->size && |
||
929 | memcmp(&li->base->key, key, key->size) == 0) { |
||
930 | variant = li->base; |
||
931 | break; |
||
932 | } |
||
933 | } |
||
934 | |||
935 | if (variant) { |
||
936 | move_to_head(&lp->setup_variants_list, &variant->list_item_global); |
||
937 | } |
||
938 | else { |
||
939 | if (lp->nr_setup_variants >= LP_MAX_SETUP_VARIANTS) { |
||
940 | cull_setup_variants(lp); |
||
941 | } |
||
942 | |||
943 | variant = generate_setup_variant(key, lp); |
||
944 | if (variant) { |
||
945 | insert_at_head(&lp->setup_variants_list, &variant->list_item_global); |
||
946 | lp->nr_setup_variants++; |
||
947 | llvmpipe_variant_count++; |
||
948 | } |
||
949 | } |
||
950 | |||
951 | lp_setup_set_setup_variant(lp->setup, |
||
952 | variant); |
||
953 | } |
||
954 | |||
955 | void |
||
956 | lp_delete_setup_variants(struct llvmpipe_context *lp) |
||
957 | { |
||
958 | struct lp_setup_variant_list_item *li; |
||
959 | li = first_elem(&lp->setup_variants_list); |
||
960 | while(!at_end(&lp->setup_variants_list, li)) { |
||
961 | struct lp_setup_variant_list_item *next = next_elem(li); |
||
962 | remove_setup_variant(lp, li->base); |
||
963 | li = next; |
||
964 | } |
||
965 | } |
||
966 | |||
967 | void |
||
968 | lp_dump_setup_coef( const struct lp_setup_variant_key *key, |
||
969 | const float (*sa0)[4], |
||
970 | const float (*sdadx)[4], |
||
971 | const float (*sdady)[4]) |
||
972 | { |
||
973 | int i, slot; |
||
974 | |||
975 | for (i = 0; i < TGSI_NUM_CHANNELS; i++) { |
||
976 | float a0 = sa0 [0][i]; |
||
977 | float dadx = sdadx[0][i]; |
||
978 | float dady = sdady[0][i]; |
||
979 | |||
980 | debug_printf("POS.%c: a0 = %f, dadx = %f, dady = %f\n", |
||
981 | "xyzw"[i], |
||
982 | a0, dadx, dady); |
||
983 | } |
||
984 | |||
985 | for (slot = 0; slot < key->num_inputs; slot++) { |
||
986 | unsigned usage_mask = key->inputs[slot].usage_mask; |
||
987 | for (i = 0; i < TGSI_NUM_CHANNELS; i++) { |
||
988 | if (usage_mask & (1 << i)) { |
||
989 | float a0 = sa0 [1 + slot][i]; |
||
990 | float dadx = sdadx[1 + slot][i]; |
||
991 | float dady = sdady[1 + slot][i]; |
||
992 | |||
993 | debug_printf("IN[%u].%c: a0 = %f, dadx = %f, dady = %f\n", |
||
994 | slot, |
||
995 | "xyzw"[i], |
||
996 | a0, dadx, dady); |
||
997 | } |
||
998 | } |
||
999 | } |
||
1000 | }><>>>>>>>>>> |