1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "ir.h"
25 #include "ir_builder.h"
26 #include "ir_optimization.h"
27 #include "ir_hierarchical_visitor.h"
28 #include "program/prog_instruction.h"
29 #include "program/prog_statevars.h"
30 #include "util/bitscan.h"
31 #include "builtin_functions.h"
32 #include "main/mtypes.h"
33
34 using namespace ir_builder;
35
36 #define imm1(x) new(mem_ctx) ir_constant((float) (x), 1)
37 #define imm3(x) new(mem_ctx) ir_constant((float) (x), 3)
38
39 static ir_rvalue *
blend_multiply(ir_variable * src,ir_variable * dst)40 blend_multiply(ir_variable *src, ir_variable *dst)
41 {
42 /* f(Cs,Cd) = Cs*Cd */
43 return mul(src, dst);
44 }
45
46 static ir_rvalue *
blend_screen(ir_variable * src,ir_variable * dst)47 blend_screen(ir_variable *src, ir_variable *dst)
48 {
49 /* f(Cs,Cd) = Cs+Cd-Cs*Cd */
50 return sub(add(src, dst), mul(src, dst));
51 }
52
53 static ir_rvalue *
blend_overlay(ir_variable * src,ir_variable * dst)54 blend_overlay(ir_variable *src, ir_variable *dst)
55 {
56 void *mem_ctx = ralloc_parent(src);
57
58 /* f(Cs,Cd) = 2*Cs*Cd, if Cd <= 0.5
59 * 1-2*(1-Cs)*(1-Cd), otherwise
60 */
61 ir_rvalue *rule_1 = mul(imm3(2), mul(src, dst));
62 ir_rvalue *rule_2 =
63 sub(imm3(1), mul(imm3(2), mul(sub(imm3(1), src), sub(imm3(1), dst))));
64 return csel(lequal(dst, imm3(0.5f)), rule_1, rule_2);
65 }
66
67 static ir_rvalue *
blend_darken(ir_variable * src,ir_variable * dst)68 blend_darken(ir_variable *src, ir_variable *dst)
69 {
70 /* f(Cs,Cd) = min(Cs,Cd) */
71 return min2(src, dst);
72 }
73
74 static ir_rvalue *
blend_lighten(ir_variable * src,ir_variable * dst)75 blend_lighten(ir_variable *src, ir_variable *dst)
76 {
77 /* f(Cs,Cd) = max(Cs,Cd) */
78 return max2(src, dst);
79 }
80
81 static ir_rvalue *
blend_colordodge(ir_variable * src,ir_variable * dst)82 blend_colordodge(ir_variable *src, ir_variable *dst)
83 {
84 void *mem_ctx = ralloc_parent(src);
85
86 /* f(Cs,Cd) =
87 * 0, if Cd <= 0
88 * min(1,Cd/(1-Cs)), if Cd > 0 and Cs < 1
89 * 1, if Cd > 0 and Cs >= 1
90 */
91 return csel(lequal(dst, imm3(0)), imm3(0),
92 csel(gequal(src, imm3(1)), imm3(1),
93 min2(imm3(1), div(dst, sub(imm3(1), src)))));
94 }
95
96 static ir_rvalue *
blend_colorburn(ir_variable * src,ir_variable * dst)97 blend_colorburn(ir_variable *src, ir_variable *dst)
98 {
99 void *mem_ctx = ralloc_parent(src);
100
101 /* f(Cs,Cd) =
102 * 1, if Cd >= 1
103 * 1 - min(1,(1-Cd)/Cs), if Cd < 1 and Cs > 0
104 * 0, if Cd < 1 and Cs <= 0
105 */
106 return csel(gequal(dst, imm3(1)), imm3(1),
107 csel(lequal(src, imm3(0)), imm3(0),
108 sub(imm3(1), min2(imm3(1), div(sub(imm3(1), dst), src)))));
109 }
110
111 static ir_rvalue *
blend_hardlight(ir_variable * src,ir_variable * dst)112 blend_hardlight(ir_variable *src, ir_variable *dst)
113 {
114 void *mem_ctx = ralloc_parent(src);
115
116 /* f(Cs,Cd) = 2*Cs*Cd, if Cs <= 0.5
117 * 1-2*(1-Cs)*(1-Cd), otherwise
118 */
119 ir_rvalue *rule_1 = mul(imm3(2), mul(src, dst));
120 ir_rvalue *rule_2 =
121 sub(imm3(1), mul(imm3(2), mul(sub(imm3(1), src), sub(imm3(1), dst))));
122 return csel(lequal(src, imm3(0.5f)), rule_1, rule_2);
123 }
124
125 static ir_rvalue *
blend_softlight(ir_variable * src,ir_variable * dst)126 blend_softlight(ir_variable *src, ir_variable *dst)
127 {
128 void *mem_ctx = ralloc_parent(src);
129
130 /* f(Cs,Cd) =
131 * Cd-(1-2*Cs)*Cd*(1-Cd),
132 * if Cs <= 0.5
133 * Cd+(2*Cs-1)*Cd*((16*Cd-12)*Cd+3),
134 * if Cs > 0.5 and Cd <= 0.25
135 * Cd+(2*Cs-1)*(sqrt(Cd)-Cd),
136 * if Cs > 0.5 and Cd > 0.25
137 *
138 * We can simplify this to
139 *
140 * f(Cs,Cd) = Cd+(2*Cs-1)*g(Cs,Cd) where
141 * g(Cs,Cd) = Cd*Cd-Cd if Cs <= 0.5
142 * Cd*((16*Cd-12)*Cd+3) if Cs > 0.5 and Cd <= 0.25
143 * sqrt(Cd)-Cd, otherwise
144 */
145 ir_rvalue *factor_1 = mul(dst, sub(imm3(1), dst));
146 ir_rvalue *factor_2 =
147 mul(dst, add(mul(sub(mul(imm3(16), dst), imm3(12)), dst), imm3(3)));
148 ir_rvalue *factor_3 = sub(sqrt(dst), dst);
149 ir_rvalue *factor = csel(lequal(src, imm3(0.5f)), factor_1,
150 csel(lequal(dst, imm3(0.25f)),
151 factor_2, factor_3));
152 return add(dst, mul(sub(mul(imm3(2), src), imm3(1)), factor));
153 }
154
155 static ir_rvalue *
blend_difference(ir_variable * src,ir_variable * dst)156 blend_difference(ir_variable *src, ir_variable *dst)
157 {
158 return abs(sub(dst, src));
159 }
160
161 static ir_rvalue *
blend_exclusion(ir_variable * src,ir_variable * dst)162 blend_exclusion(ir_variable *src, ir_variable *dst)
163 {
164 void *mem_ctx = ralloc_parent(src);
165
166 return add(src, sub(dst, mul(imm3(2), mul(src, dst))));
167 }
168
169 /* Return the minimum of a vec3's components */
170 static ir_rvalue *
minv3(ir_variable * v)171 minv3(ir_variable *v)
172 {
173 return min2(min2(swizzle_x(v), swizzle_y(v)), swizzle_z(v));
174 }
175
176 /* Return the maximum of a vec3's components */
177 static ir_rvalue *
maxv3(ir_variable * v)178 maxv3(ir_variable *v)
179 {
180 return max2(max2(swizzle_x(v), swizzle_y(v)), swizzle_z(v));
181 }
182
183 static ir_rvalue *
lumv3(ir_variable * c)184 lumv3(ir_variable *c)
185 {
186 ir_constant_data data;
187 data.f[0] = 0.30;
188 data.f[1] = 0.59;
189 data.f[2] = 0.11;
190
191 void *mem_ctx = ralloc_parent(c);
192
193 /* dot(c, vec3(0.30, 0.59, 0.11)) */
194 return dot(c, new(mem_ctx) ir_constant(glsl_type::vec3_type, &data));
195 }
196
197 static ir_rvalue *
satv3(ir_variable * c)198 satv3(ir_variable *c)
199 {
200 return sub(maxv3(c), minv3(c));
201 }
202
203 /* Take the base RGB color <cbase> and override its luminosity with that
204 * of the RGB color <clum>.
205 *
206 * This follows the equations given in the ES 3.2 (June 15th, 2016)
207 * specification. Revision 16 of GL_KHR_blend_equation_advanced and
208 * revision 9 of GL_NV_blend_equation_advanced specify a different set
209 * of equations. Older revisions match ES 3.2's text, and dEQP expects
210 * the ES 3.2 rules implemented here.
211 */
212 static void
set_lum(ir_factory * f,ir_variable * color,ir_variable * cbase,ir_variable * clum)213 set_lum(ir_factory *f,
214 ir_variable *color,
215 ir_variable *cbase,
216 ir_variable *clum)
217 {
218 void *mem_ctx = f->mem_ctx;
219 f->emit(assign(color, add(cbase, sub(lumv3(clum), lumv3(cbase)))));
220
221 ir_variable *llum = f->make_temp(glsl_type::float_type, "__blend_lum");
222 ir_variable *mincol = f->make_temp(glsl_type::float_type, "__blend_mincol");
223 ir_variable *maxcol = f->make_temp(glsl_type::float_type, "__blend_maxcol");
224
225 f->emit(assign(llum, lumv3(color)));
226 f->emit(assign(mincol, minv3(color)));
227 f->emit(assign(maxcol, maxv3(color)));
228
229 f->emit(if_tree(less(mincol, imm1(0)),
230 assign(color, add(llum, div(mul(sub(color, llum), llum),
231 sub(llum, mincol)))),
232 if_tree(greater(maxcol, imm1(1)),
233 assign(color, add(llum, div(mul(sub(color, llum),
234 sub(imm3(1), llum)),
235 sub(maxcol, llum)))))));
236
237 }
238
239 /* Take the base RGB color <cbase> and override its saturation with
240 * that of the RGB color <csat>. The override the luminosity of the
241 * result with that of the RGB color <clum>.
242 */
243 static void
set_lum_sat(ir_factory * f,ir_variable * color,ir_variable * cbase,ir_variable * csat,ir_variable * clum)244 set_lum_sat(ir_factory *f,
245 ir_variable *color,
246 ir_variable *cbase,
247 ir_variable *csat,
248 ir_variable *clum)
249 {
250 void *mem_ctx = f->mem_ctx;
251
252 ir_rvalue *minbase = minv3(cbase);
253 ir_rvalue *ssat = satv3(csat);
254
255 ir_variable *sbase = f->make_temp(glsl_type::float_type, "__blend_sbase");
256 f->emit(assign(sbase, satv3(cbase)));
257
258 /* Equivalent (modulo rounding errors) to setting the
259 * smallest (R,G,B) component to 0, the largest to <ssat>,
260 * and interpolating the "middle" component based on its
261 * original value relative to the smallest/largest.
262 */
263 f->emit(if_tree(greater(sbase, imm1(0)),
264 assign(color, div(mul(sub(cbase, minbase), ssat), sbase)),
265 assign(color, imm3(0))));
266 set_lum(f, color, color, clum);
267 }
268
269 static ir_rvalue *
is_mode(ir_variable * mode,enum gl_advanced_blend_mode q)270 is_mode(ir_variable *mode, enum gl_advanced_blend_mode q)
271 {
272 return equal(mode, new(ralloc_parent(mode)) ir_constant(unsigned(q)));
273 }
274
275 static ir_variable *
calc_blend_result(ir_factory f,ir_variable * mode,ir_variable * fb,ir_rvalue * blend_src,GLbitfield blend_qualifiers)276 calc_blend_result(ir_factory f,
277 ir_variable *mode,
278 ir_variable *fb,
279 ir_rvalue *blend_src,
280 GLbitfield blend_qualifiers)
281 {
282 void *mem_ctx = f.mem_ctx;
283 ir_variable *result = f.make_temp(glsl_type::vec4_type, "__blend_result");
284
285 /* Save blend_src to a temporary so we can reference it multiple times. */
286 ir_variable *src = f.make_temp(glsl_type::vec4_type, "__blend_src");
287 f.emit(assign(src, blend_src));
288
289 /* If we're not doing advanced blending, just write the original value. */
290 ir_if *if_blending = new(mem_ctx) ir_if(is_mode(mode, BLEND_NONE));
291 f.emit(if_blending);
292 if_blending->then_instructions.push_tail(assign(result, src));
293
294 f.instructions = &if_blending->else_instructions;
295
296 /* (Rs', Gs', Bs') =
297 * (0, 0, 0), if As == 0
298 * (Rs/As, Gs/As, Bs/As), otherwise
299 */
300 ir_variable *src_rgb = f.make_temp(glsl_type::vec3_type, "__blend_src_rgb");
301 ir_variable *src_alpha = f.make_temp(glsl_type::float_type, "__blend_src_a");
302
303 /* (Rd', Gd', Bd') =
304 * (0, 0, 0), if Ad == 0
305 * (Rd/Ad, Gd/Ad, Bd/Ad), otherwise
306 */
307 ir_variable *dst_rgb = f.make_temp(glsl_type::vec3_type, "__blend_dst_rgb");
308 ir_variable *dst_alpha = f.make_temp(glsl_type::float_type, "__blend_dst_a");
309
310 f.emit(assign(dst_alpha, swizzle_w(fb)));
311 f.emit(if_tree(equal(dst_alpha, imm1(0)),
312 assign(dst_rgb, imm3(0)),
313 assign(dst_rgb, csel(equal(swizzle_xyz(fb),
314 swizzle(fb, SWIZZLE_WWWW, 3)),
315 imm3(1),
316 div(swizzle_xyz(fb), dst_alpha)))));
317
318 f.emit(assign(src_alpha, swizzle_w(src)));
319 f.emit(if_tree(equal(src_alpha, imm1(0)),
320 assign(src_rgb, imm3(0)),
321 assign(src_rgb, csel(equal(swizzle_xyz(src),
322 swizzle(src, SWIZZLE_WWWW, 3)),
323 imm3(1),
324 div(swizzle_xyz(src), src_alpha)))));
325
326 ir_variable *factor = f.make_temp(glsl_type::vec3_type, "__blend_factor");
327
328 ir_factory casefactory = f;
329
330 unsigned choices = blend_qualifiers;
331 while (choices) {
332 enum gl_advanced_blend_mode choice = (enum gl_advanced_blend_mode)u_bit_scan(&choices);
333
334 ir_if *iff = new(mem_ctx) ir_if(is_mode(mode, choice));
335 casefactory.emit(iff);
336 casefactory.instructions = &iff->then_instructions;
337
338 ir_rvalue *val = NULL;
339
340 switch (choice) {
341 case BLEND_MULTIPLY:
342 val = blend_multiply(src_rgb, dst_rgb);
343 break;
344 case BLEND_SCREEN:
345 val = blend_screen(src_rgb, dst_rgb);
346 break;
347 case BLEND_OVERLAY:
348 val = blend_overlay(src_rgb, dst_rgb);
349 break;
350 case BLEND_DARKEN:
351 val = blend_darken(src_rgb, dst_rgb);
352 break;
353 case BLEND_LIGHTEN:
354 val = blend_lighten(src_rgb, dst_rgb);
355 break;
356 case BLEND_COLORDODGE:
357 val = blend_colordodge(src_rgb, dst_rgb);
358 break;
359 case BLEND_COLORBURN:
360 val = blend_colorburn(src_rgb, dst_rgb);
361 break;
362 case BLEND_HARDLIGHT:
363 val = blend_hardlight(src_rgb, dst_rgb);
364 break;
365 case BLEND_SOFTLIGHT:
366 val = blend_softlight(src_rgb, dst_rgb);
367 break;
368 case BLEND_DIFFERENCE:
369 val = blend_difference(src_rgb, dst_rgb);
370 break;
371 case BLEND_EXCLUSION:
372 val = blend_exclusion(src_rgb, dst_rgb);
373 break;
374 case BLEND_HSL_HUE:
375 set_lum_sat(&casefactory, factor, src_rgb, dst_rgb, dst_rgb);
376 break;
377 case BLEND_HSL_SATURATION:
378 set_lum_sat(&casefactory, factor, dst_rgb, src_rgb, dst_rgb);
379 break;
380 case BLEND_HSL_COLOR:
381 set_lum(&casefactory, factor, src_rgb, dst_rgb);
382 break;
383 case BLEND_HSL_LUMINOSITY:
384 set_lum(&casefactory, factor, dst_rgb, src_rgb);
385 break;
386 case BLEND_NONE:
387 unreachable("not real cases");
388 }
389
390 if (val)
391 casefactory.emit(assign(factor, val));
392
393 casefactory.instructions = &iff->else_instructions;
394 }
395
396 /* p0(As,Ad) = As*Ad
397 * p1(As,Ad) = As*(1-Ad)
398 * p2(As,Ad) = Ad*(1-As)
399 */
400 ir_variable *p0 = f.make_temp(glsl_type::float_type, "__blend_p0");
401 ir_variable *p1 = f.make_temp(glsl_type::float_type, "__blend_p1");
402 ir_variable *p2 = f.make_temp(glsl_type::float_type, "__blend_p2");
403
404 f.emit(assign(p0, mul(src_alpha, dst_alpha)));
405 f.emit(assign(p1, mul(src_alpha, sub(imm1(1), dst_alpha))));
406 f.emit(assign(p2, mul(dst_alpha, sub(imm1(1), src_alpha))));
407
408 /* R = f(Rs',Rd')*p0(As,Ad) + Y*Rs'*p1(As,Ad) + Z*Rd'*p2(As,Ad)
409 * G = f(Gs',Gd')*p0(As,Ad) + Y*Gs'*p1(As,Ad) + Z*Gd'*p2(As,Ad)
410 * B = f(Bs',Bd')*p0(As,Ad) + Y*Bs'*p1(As,Ad) + Z*Bd'*p2(As,Ad)
411 * A = X*p0(As,Ad) + Y*p1(As,Ad) + Z*p2(As,Ad)
412 *
413 * <X, Y, Z> is always <1, 1, 1>, so we can ignore it.
414 *
415 * In vector form, this is:
416 * RGB = factor * p0 + Cs * p1 + Cd * p2
417 * A = p0 + p1 + p2
418 */
419 f.emit(assign(result,
420 add(add(mul(factor, p0), mul(src_rgb, p1)), mul(dst_rgb, p2)),
421 WRITEMASK_XYZ));
422 f.emit(assign(result, add(add(p0, p1), p2), WRITEMASK_W));
423
424 return result;
425 }
426
427 /**
428 * Dereference var, or var[0] if it's an array.
429 */
430 static ir_dereference *
deref_output(ir_variable * var)431 deref_output(ir_variable *var)
432 {
433 void *mem_ctx = ralloc_parent(var);
434
435 ir_dereference *val = new(mem_ctx) ir_dereference_variable(var);
436 if (val->type->is_array()) {
437 ir_constant *index = new(mem_ctx) ir_constant(0);
438 val = new(mem_ctx) ir_dereference_array(val, index);
439 }
440
441 return val;
442 }
443
444 static ir_function_signature *
get_main(gl_linked_shader * sh)445 get_main(gl_linked_shader *sh)
446 {
447 ir_function_signature *sig = NULL;
448 /* We can't use _mesa_get_main_function_signature() because we don't
449 * have a symbol table at this point. Just go find main() by hand.
450 */
451 foreach_in_list(ir_instruction, ir, sh->ir) {
452 ir_function *f = ir->as_function();
453 if (f && strcmp(f->name, "main") == 0) {
454 exec_list void_parameters;
455 sig = f->matching_signature(NULL, &void_parameters, false);
456 break;
457 }
458 }
459 assert(sig != NULL); /* main() must exist */
460 return sig;
461 }
462
463 bool
lower_blend_equation_advanced(struct gl_linked_shader * sh,bool coherent)464 lower_blend_equation_advanced(struct gl_linked_shader *sh, bool coherent)
465 {
466 if (sh->Program->sh.fs.BlendSupport == 0)
467 return false;
468
469 /* Lower early returns in main() so there's a single exit point
470 * where we can insert our lowering code.
471 */
472 do_lower_jumps(sh->ir, false, false, true, false, false);
473
474 void *mem_ctx = ralloc_parent(sh->ir);
475
476 ir_variable *fb = new(mem_ctx) ir_variable(glsl_type::vec4_type,
477 "__blend_fb_fetch",
478 ir_var_shader_out);
479 fb->data.location = FRAG_RESULT_DATA0;
480 fb->data.read_only = 1;
481 fb->data.fb_fetch_output = 1;
482 fb->data.memory_coherent = coherent;
483 fb->data.how_declared = ir_var_hidden;
484
485 ir_variable *mode = new(mem_ctx) ir_variable(glsl_type::uint_type,
486 "gl_AdvancedBlendModeMESA",
487 ir_var_uniform);
488 mode->data.how_declared = ir_var_hidden;
489 mode->allocate_state_slots(1);
490 ir_state_slot *slot0 = &mode->get_state_slots()[0];
491 slot0->swizzle = SWIZZLE_XXXX;
492 slot0->tokens[0] = STATE_INTERNAL;
493 slot0->tokens[1] = STATE_ADVANCED_BLENDING_MODE;
494 for (int i = 2; i < STATE_LENGTH; i++)
495 slot0->tokens[i] = 0;
496
497 sh->ir->push_head(fb);
498 sh->ir->push_head(mode);
499
500 /* Gather any output variables referring to render target 0.
501 *
502 * ARB_enhanced_layouts irritatingly allows the shader to specify
503 * multiple output variables for the same render target, each of
504 * which writes a subset of the components, starting at location_frac.
505 * The variables can't overlap, thankfully.
506 */
507 ir_variable *outputs[4] = { NULL, NULL, NULL, NULL };
508 foreach_in_list(ir_instruction, ir, sh->ir) {
509 ir_variable *var = ir->as_variable();
510 if (!var || var->data.mode != ir_var_shader_out)
511 continue;
512
513 if (var->data.location == FRAG_RESULT_DATA0 ||
514 var->data.location == FRAG_RESULT_COLOR) {
515 const int components = var->type->without_array()->vector_elements;
516
517 for (int i = 0; i < components; i++) {
518 outputs[var->data.location_frac + i] = var;
519 }
520 }
521 }
522
523 /* Combine values written to outputs into a single RGBA blend source.
524 * We assign <0, 0, 0, 1> to any components with no corresponding output.
525 */
526 ir_rvalue *blend_source;
527 if (outputs[0] && outputs[0]->type->without_array()->vector_elements == 4) {
528 blend_source = deref_output(outputs[0]);
529 } else {
530 ir_rvalue *blend_comps[4];
531 for (int i = 0; i < 4; i++) {
532 ir_variable *var = outputs[i];
533 if (var) {
534 blend_comps[i] = swizzle(deref_output(outputs[i]),
535 i - outputs[i]->data.location_frac, 1);
536 } else {
537 blend_comps[i] = new(mem_ctx) ir_constant(i < 3 ? 0.0f : 1.0f);
538 }
539 }
540
541 blend_source =
542 new(mem_ctx) ir_expression(ir_quadop_vector, glsl_type::vec4_type,
543 blend_comps[0], blend_comps[1],
544 blend_comps[2], blend_comps[3]);
545 }
546
547 ir_function_signature *main = get_main(sh);
548 ir_factory f(&main->body, mem_ctx);
549
550 ir_variable *result_dest =
551 calc_blend_result(f, mode, fb, blend_source,
552 sh->Program->sh.fs.BlendSupport);
553
554 /* Copy the result back to the original values. It would be simpler
555 * to demote the program's output variables, and create a new vec4
556 * output for our result, but this pass runs before we create the
557 * ARB_program_interface_query resource list. So we have to leave
558 * the original outputs in place and use them.
559 */
560 for (int i = 0; i < 4; i++) {
561 if (!outputs[i])
562 continue;
563
564 f.emit(assign(deref_output(outputs[i]), swizzle(result_dest, i, 1),
565 1 << i));
566 }
567
568 validate_ir_tree(sh->ir);
569 return true;
570 }
571