[Mesa-dev] [PATCH 11/16] glsl: Add a lowering pass to handle advanced blending modes.

Francisco Jerez currojerez at riseup.net
Thu Aug 18 22:13:44 UTC 2016


Kenneth Graunke <kenneth at whitecape.org> writes:

> Many GPUs cannot handle GL_KHR_blend_equation_advanced natively, and
> need to emulate it in the pixel shader.  This lowering pass implements
> all the necessary math for advanced blending.  It fetches the existing
> framebuffer value using the MESA_shader_framebuffer_fetch built-in
> variables, and the previous commit's state var uniform to select
> which equation to use.
>
> This is done at the GLSL IR level to make it easy for all drivers to
> implement the GL_KHR_blend_equation_advanced extension and share code.
>
> Drivers need to hook up MESA_shader_framebuffer_fetch functionality:
> 1. Hook up the fb_fetch_output variable
> 2. Implement BlendBarrier()
>
> Then to get KHR_blend_equation_advanced, they simply need to:
> 3. Disable hardware blending based on ctx->Color._AdvancedBlendEnabled
> 4. Call this lowering pass.
>
> Very little driver specific code should be required.
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/compiler/Makefile.sources                      |   1 +
>  src/compiler/glsl/ir_optimization.h                |   1 +
>  .../glsl/lower_blend_equation_advanced.cpp         | 523 +++++++++++++++++++++
>  3 files changed, 525 insertions(+)
>  create mode 100644 src/compiler/glsl/lower_blend_equation_advanced.cpp
>
> diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
> index 0ff9b23..fe26132 100644
> --- a/src/compiler/Makefile.sources
> +++ b/src/compiler/Makefile.sources
> @@ -77,6 +77,7 @@ LIBGLSL_FILES = \
>  	glsl/loop_analysis.h \
>  	glsl/loop_controls.cpp \
>  	glsl/loop_unroll.cpp \
> +	glsl/lower_blend_equation_advanced.cpp \
>  	glsl/lower_buffer_access.cpp \
>  	glsl/lower_buffer_access.h \
>  	glsl/lower_const_arrays_to_uniforms.cpp \
> diff --git a/src/compiler/glsl/ir_optimization.h b/src/compiler/glsl/ir_optimization.h
> index c29260a..3bd6928 100644
> --- a/src/compiler/glsl/ir_optimization.h
> +++ b/src/compiler/glsl/ir_optimization.h
> @@ -151,6 +151,7 @@ void optimize_dead_builtin_variables(exec_list *instructions,
>  bool lower_tess_level(gl_linked_shader *shader);
>  
>  bool lower_vertex_id(gl_linked_shader *shader);
> +bool lower_blend_equation_advanced(gl_linked_shader *shader);
>  
>  bool lower_subroutine(exec_list *instructions, struct _mesa_glsl_parse_state *state);
>  void propagate_invariance(exec_list *instructions);
> diff --git a/src/compiler/glsl/lower_blend_equation_advanced.cpp b/src/compiler/glsl/lower_blend_equation_advanced.cpp
> new file mode 100644
> index 0000000..91a11f3
> --- /dev/null
> +++ b/src/compiler/glsl/lower_blend_equation_advanced.cpp
> @@ -0,0 +1,523 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "ir.h"
> +#include "ir_builder.h"
> +#include "ir_optimization.h"
> +#include "ir_hierarchical_visitor.h"
> +#include "program/prog_instruction.h"
> +#include "program/prog_statevars.h"
> +#include "util/bitscan.h"
> +
> +namespace {
> +
> +using namespace ir_builder;
> +
> +class lower_blend_visitor : public ir_hierarchical_visitor {
> +public:
> +   explicit lower_blend_visitor(gl_linked_shader *sh)
> +      : sh(sh), mem_ctx(ralloc_parent(sh->ir)), progress(false)
> +   {
> +      fb = new(mem_ctx) ir_variable(glsl_type::vec4_type, "__blend_fb_fetch",
> +                                    ir_var_shader_out);
> +      fb->data.location = FRAG_RESULT_DATA0;
> +      fb->data.read_only = 1;
> +      fb->data.fb_fetch_output = 1;
> +

Does this variable need to be marked ir_var_hidden too?

> +      mode = new(mem_ctx) ir_variable(glsl_type::uint_type,
> +                                      "gl_AdvancedBlendModeMESA",
> +                                      ir_var_uniform);
> +      mode->data.how_declared = ir_var_hidden;
> +      mode->allocate_state_slots(1);
> +      ir_state_slot *slot0 = &mode->get_state_slots()[0];
> +      slot0->swizzle = SWIZZLE_XXXX;
> +      slot0->tokens[0] = STATE_INTERNAL;
> +      slot0->tokens[1] = STATE_ADVANCED_BLENDING_MODE;
> +      for (int i = 2; i < STATE_LENGTH; i++)
> +	 slot0->tokens[i] = 0;

The indentation of this line looks weird, tab gone astray?

> +   }
> +
> +   virtual ~lower_blend_visitor()
> +   {
> +   }
> +
> +   bool run()
> +   {
> +      sh->ir->push_head(fb);
> +      sh->ir->push_head(mode);
> +
> +      visit_list_elements(this, sh->ir);
> +      validate_ir_tree(sh->ir);
> +      return progress;
> +   }
> +
> +private:
> +   ir_visitor_status visit_enter(ir_assignment *ir);
> +
> +   ir_constant *imm1(float x)
> +   {
> +      return new(mem_ctx) ir_constant(x, 1);
> +   }
> +
> +   ir_constant *imm3(float x)
> +   {
> +      return new(mem_ctx) ir_constant(x, 3);
> +   }
> +
> +   gl_linked_shader *sh;
> +   void *mem_ctx;
> +   bool progress;
> +
> +   ir_variable *mode; /* uniform */
> +   ir_variable *fb;
> +
> +   void clip_color(ir_factory *f, ir_variable *color);
> +   void set_lum(ir_factory *f, ir_variable *color,
> +                ir_variable *cbase, ir_variable *clum);
> +   void set_lum_sat(ir_factory *f, ir_variable *color,
> +                    ir_variable *cbase, ir_variable *csat, ir_variable *clum);
> +
> +   void lower(ir_assignment *ir);
> +   ir_rvalue *is_mode(enum gl_blend_support_qualifier q);
> +   ir_rvalue *blend_multiply(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_screen(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_overlay(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_darken(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_lighten(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_colordodge(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_colorburn(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_hardlight(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_softlight(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_difference(ir_variable *src, ir_variable *dst);
> +   ir_rvalue *blend_exclusion(ir_variable *src, ir_variable *dst);
> +};
> +
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_multiply(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) = Cs*Cd */
> +   return mul(src, dst);
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_screen(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) = Cs+Cd-Cs*Cd */
> +   return sub(add(src, dst), mul(src, dst));
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_overlay(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) = 2*Cs*Cd, if Cd <= 0.5
> +    *            1-2*(1-Cs)*(1-Cd), otherwise
> +    */
> +   ir_rvalue *rule_1 = mul(imm3(2), mul(src, dst));
> +   ir_rvalue *rule_2 =
> +      sub(imm3(1), mul(imm3(2), mul(sub(imm3(1), src), sub(imm3(1), dst))));
> +   return csel(lequal(dst, imm3(0.5f)), rule_1, rule_2);
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_darken(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) = min(Cs,Cd) */
> +   return min2(src, dst);
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_lighten(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) = max(Cs,Cd) */
> +   return max2(src, dst);
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_colordodge(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) =
> +    *   0, if Cd <= 0
> +    *   min(1,Cd/(1-Cs)), if Cd > 0 and Cs < 1
> +    *   1, if Cd > 0 and Cs >= 1
> +    */
> +   return csel(lequal(dst, imm3(0)), imm3(0),
> +               csel(gequal(src, imm3(1)), imm3(1),
> +                    min2(imm3(1), div(dst, sub(imm3(1), src)))));
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_colorburn(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) =
> +    *   1, if Cd >= 1
> +    *   1 - min(1,(1-Cd)/Cs), if Cd < 1 and Cs > 0
> +    *   0, if Cd < 1 and Cs <= 0
> +    */
> +   return csel(gequal(dst, imm3(1)), imm3(1),
> +               csel(lequal(src, imm3(0)), imm3(0),
> +                    sub(imm3(1), min2(imm3(1), div(sub(imm3(1), dst), src)))));
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_hardlight(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) = 2*Cs*Cd, if Cs <= 0.5
> +    *            1-2*(1-Cs)*(1-Cd), otherwise
> +    */
> +   ir_rvalue *rule_1 = mul(imm3(2), mul(src, dst));
> +   ir_rvalue *rule_2 =
> +      sub(imm3(1), mul(imm3(2), mul(sub(imm3(1), src), sub(imm3(1), dst))));
> +   return csel(lequal(src, imm3(0.5f)), rule_1, rule_2);
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_softlight(ir_variable *src, ir_variable *dst)
> +{
> +   /* f(Cs,Cd) =
> +    *   Cd-(1-2*Cs)*Cd*(1-Cd),
> +    *     if Cs <= 0.5
> +    *   Cd+(2*Cs-1)*Cd*((16*Cd-12)*Cd+3),
> +    *     if Cs > 0.5 and Cd <= 0.25
> +    *   Cd+(2*Cs-1)*(sqrt(Cd)-Cd),
> +    *     if Cs > 0.5 and Cd > 0.25
> +    *
> +    * We can simplify this to
> +    *
> +    * f(Cs,Cd) = Cd+(2*Cs-1)*g(Cs,Cd) where
> +    * g(Cs,Cd) = Cd*Cd-Cd             if Cs <= 0.5
> +    *            Cd*((16*Cd-12)*Cd+3) if Cs > 0.5 and Cd <= 0.25
> +    *            sqrt(Cd)-Cd,         otherwise
> +    */
> +   ir_rvalue *factor_1 = mul(dst, sub(imm3(1), dst));
> +   ir_rvalue *factor_2 =
> +      mul(dst, add(mul(sub(mul(imm3(16), dst), imm3(12)), dst), imm3(3)));
> +   ir_rvalue *factor_3 = sub(sqrt(dst), dst);
> +   ir_rvalue *factor = csel(lequal(src, imm3(0.5f)), factor_1,
> +                            csel(lequal(dst, imm3(0.25f)),
> +                                        factor_2, factor_3));
> +   return add(dst, mul(sub(mul(imm3(2), src), imm3(1)), factor));
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_difference(ir_variable *src, ir_variable *dst)
> +{
> +   return abs(sub(dst, src));
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::blend_exclusion(ir_variable *src, ir_variable *dst)
> +{
> +   return add(src, sub(dst, mul(imm3(2), mul(src, dst))));
> +}
> +
> +/* Return the minimum of a vec3's components */
> +ir_rvalue *
> +minv3(ir_variable *v)
> +{
> +   return min2(min2(swizzle_x(v), swizzle_y(v)), swizzle_z(v));
> +}
> +
> +/* Return the maximum of a vec3's components */
> +ir_rvalue *
> +maxv3(ir_variable *v)
> +{
> +   return max2(max2(swizzle_x(v), swizzle_y(v)), swizzle_z(v));
> +}
> +
> +ir_rvalue *
> +lumv3(ir_variable *c)
> +{
> +   ir_constant_data data;
> +   data.f[0] = 0.30;
> +   data.f[1] = 0.59;
> +   data.f[2] = 0.11;
> +
> +   void *mem_ctx = ralloc_parent(c);
> +
> +   /* dot(c, vec3(0.30, 0.59, 0.11)) */
> +   return dot(c, new(mem_ctx) ir_constant(glsl_type::vec3_type, &data));
> +}
> +
> +ir_rvalue *
> +satv3(ir_variable *c)
> +{
> +   return sub(maxv3(c), minv3(c));
> +}
> +
> +/* If any color components are outside [0,1], adjust the color to
> + * get the components in range.
> + */
> +void
> +lower_blend_visitor::clip_color(ir_factory *f, ir_variable *color)
> +{
> +   ir_variable *lum = f->make_temp(glsl_type::float_type, "__blend_lum");
> +   ir_variable *mincol = f->make_temp(glsl_type::float_type, "__blend_mincol");
> +   ir_variable *maxcol = f->make_temp(glsl_type::float_type, "__blend_maxcol");
> +   ir_variable *tmp = f->make_temp(glsl_type::vec3_type, "__blend_clip_tmp");
> +
> +   f->emit(assign(lum, lumv3(color)));
> +   f->emit(assign(mincol, minv3(color)));
> +   f->emit(assign(maxcol, maxv3(color)));
> +   f->emit(assign(tmp, mul(sub(color, lum), lum)));
> +   f->emit(if_tree(less(mincol, imm1(0)),
> +                   assign(color, add(lum, div(tmp, sub(lum, mincol))))));
> +   f->emit(if_tree(greater(maxcol, imm1(1)),
> +                   assign(color, add(lum, div(tmp, sub(maxcol, lum))))));
> +}
> +
> +/* Take the base RGB color <cbase> and override its luminosity
> + * with that of the RGB color <clum>.
> + */
> +void
> +lower_blend_visitor::set_lum(ir_factory *f,
> +                             ir_variable *color,
> +                             ir_variable *cbase,
> +                             ir_variable *clum)
> +{
> +   f->emit(assign(color, add(cbase, sub(lumv3(clum), lumv3(cbase)))));
> +   clip_color(f, color);
> +}
> +
> +/* Take the base RGB color <cbase> and override its saturation with
> + * that of the RGB color <csat>.  The override the luminosity of the
> + * result with that of the RGB color <clum>.
> + */
> +void
> +lower_blend_visitor::set_lum_sat(ir_factory *f,
> +                                 ir_variable *color,
> +                                 ir_variable *cbase,
> +                                 ir_variable *csat,
> +                                 ir_variable *clum)
> +{
> +   ir_rvalue *minbase = minv3(cbase);
> +   ir_rvalue *ssat = satv3(csat);
> +
> +   ir_variable *sbase = f->make_temp(glsl_type::float_type, "__blend_sbase");
> +   f->emit(assign(sbase, satv3(cbase)));
> +
> +   /* Equivalent (modulo rounding errors) to setting the
> +    * smallest (R,G,B) component to 0, the largest to <ssat>,
> +    * and interpolating the "middle" component based on its
> +    * original value relative to the smallest/largest.
> +    */
> +   f->emit(if_tree(greater(sbase, imm1(0)),
> +                   assign(color, div(mul(sub(cbase, minbase), ssat), sbase)),
> +                   assign(color, imm3(0))));
> +   set_lum(f, color, color, clum);
> +}
> +
> +ir_visitor_status
> +lower_blend_visitor::visit_enter(ir_assignment *ir)
> +{
> +   ir_variable *lhs_var = ir->lhs->variable_referenced();
> +   if (lhs_var->data.mode == ir_var_shader_out) {
> +      lower(ir);
> +   }
> +
> +   return visit_continue_with_parent;
> +}
> +
> +ir_rvalue *
> +lower_blend_visitor::is_mode(enum gl_blend_support_qualifier q)
> +{
> +   return equal(mode, new(mem_ctx) ir_constant(unsigned(q)));
> +}
> +
> +void
> +lower_blend_visitor::lower(ir_assignment *ir)
> +{
> +   /* Skip whole array assignments to FS outputs.  This should only
> +    * happen for the multiple render target case, where advanced
> +    * blending isn't allowed.  However, if blending is disabled,
> +    * MRT is supposed to work normally, so we leave it untouched.
> +    */
> +   if (ir->rhs->type->is_array())
> +      return;
> +

I have doubts this is correct, it looks like a one-element array
fragment output (attached to color output zero) would be allowed by the
spec in combination with advanced blending, don't you need to handle
whole array assignments then?

> +   /* <mareko> Kayden: if the shader writes fewer components, the result is
> +    *          undefined I think
> +    * <Kayden> undefined \o/
> +    *
> +    * Skip non-vec4 values.
> +    */
> +   if (ir->rhs->type != glsl_type::vec4_type)
> +      return;
> +

Spec quotation?  ISTR it's allowed to use output types other than vec4
as long as the type matches the framebuffer format, and with
ARB_enhanced_layouts you can potentially have multiple output variables
mapping to different non-vec4 subsets of the same fragment output, so I
don't think this is quite right.

Other than that the lowering pass looks good to me.

> +   /* Save the RHS to a temporary so we can reference it multiple times */
> +   ir_variable *src =
> +      new(mem_ctx) ir_variable(glsl_type::vec4_type, "__blend_src",
> +                               ir_var_temporary);
> +   ir->insert_before(src);
> +   ir->insert_before(assign(src, ir->rhs));
> +
> +   ir_variable *result =
> +      new(mem_ctx) ir_variable(glsl_type::vec4_type, "__blend_result",
> +                               ir_var_temporary);
> +
> +   ir->insert_before(result);
> +
> +   ir->rhs = new(mem_ctx) ir_dereference_variable(result);
> +
> +   /* If we're not doing advanced blending, just write the original value. */
> +   ir_if *if_blending = new(mem_ctx) ir_if(is_mode(BLEND_NONE));
> +   ir->insert_before(if_blending);
> +   if_blending->then_instructions.push_tail(assign(result, src));
> +
> +   ir_factory f(&if_blending->else_instructions, mem_ctx);
> +
> +   /* (Rs', Gs', Bs') =
> +    *   (0, 0, 0),              if As == 0
> +    *   (Rs/As, Gs/As, Bs/As),  otherwise
> +    */
> +   ir_variable *src_rgb = f.make_temp(glsl_type::vec3_type, "__blend_src_rgb");
> +   ir_variable *src_alpha = f.make_temp(glsl_type::float_type, "__blend_src_a");
> +
> +   /* (Rd', Gd', Bd') =
> +    *   (0, 0, 0),              if Ad == 0
> +    *   (Rd/Ad, Gd/Ad, Bd/Ad),  otherwise
> +    */
> +   ir_variable *dst_rgb = f.make_temp(glsl_type::vec3_type, "__blend_dst_rgb");
> +   ir_variable *dst_alpha = f.make_temp(glsl_type::float_type, "__blend_dst_a");
> +
> +   f.emit(assign(dst_alpha, swizzle_w(fb)));
> +   f.emit(if_tree(equal(dst_alpha, imm1(0)),
> +                     assign(dst_rgb, imm3(0)),
> +                     assign(dst_rgb, div(swizzle_xyz(fb), dst_alpha))));
> +
> +   f.emit(assign(src_alpha, swizzle_w(src)));
> +   f.emit(if_tree(equal(src_alpha, imm1(0)),
> +                     assign(src_rgb, imm3(0)),
> +                     assign(src_rgb, div(swizzle_xyz(src), src_alpha))));
> +
> +   ir_variable *factor = f.make_temp(glsl_type::vec3_type, "__blend_factor");
> +
> +   ir_factory casefactory = f;
> +
> +   unsigned choices = sh->info.BlendSupport;
> +   while (choices) {
> +      enum gl_blend_support_qualifier q = (enum gl_blend_support_qualifier)
> +         (1u << u_bit_scan(&choices));
> +
> +      ir_if *iff = new(mem_ctx) ir_if(is_mode(q));
> +      casefactory.emit(iff);
> +      casefactory.instructions = &iff->then_instructions;
> +
> +      ir_rvalue *val = NULL;
> +
> +      switch (q) {
> +      case BLEND_MULTIPLY:
> +         val = blend_multiply(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_SCREEN:
> +         val = blend_screen(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_OVERLAY:
> +         val = blend_overlay(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_DARKEN:
> +         val = blend_darken(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_LIGHTEN:
> +         val = blend_lighten(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_COLORDODGE:
> +         val = blend_colordodge(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_COLORBURN:
> +         val = blend_colorburn(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_HARDLIGHT:
> +         val = blend_hardlight(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_SOFTLIGHT:
> +         val = blend_softlight(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_DIFFERENCE:
> +         val = blend_difference(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_EXCLUSION:
> +         val = blend_exclusion(src_rgb, dst_rgb);
> +         break;
> +      case BLEND_HSL_HUE:
> +         set_lum_sat(&casefactory, factor, src_rgb, dst_rgb, dst_rgb);
> +         break;
> +      case BLEND_HSL_SATURATION:
> +         set_lum_sat(&casefactory, factor, dst_rgb, src_rgb, dst_rgb);
> +         break;
> +      case BLEND_HSL_COLOR:
> +         set_lum(&casefactory, factor, src_rgb, dst_rgb);
> +         break;
> +      case BLEND_HSL_LUMINOSITY:
> +         set_lum(&casefactory, factor, dst_rgb, src_rgb);
> +         break;
> +      case BLEND_NONE:
> +      case BLEND_ALL:
> +         unreachable("not real cases");
> +      }
> +
> +      if (val)
> +         casefactory.emit(assign(factor, val));
> +
> +      casefactory.instructions = &iff->else_instructions;
> +   }
> +
> +   /* p0(As,Ad) = As*Ad
> +    * p1(As,Ad) = As*(1-Ad)
> +    * p2(As,Ad) = Ad*(1-As)
> +    */
> +   ir_variable *p0 = f.make_temp(glsl_type::float_type, "__blend_p0");
> +   ir_variable *p1 = f.make_temp(glsl_type::float_type, "__blend_p1");
> +   ir_variable *p2 = f.make_temp(glsl_type::float_type, "__blend_p2");
> +
> +   f.emit(assign(p0, mul(src_alpha, dst_alpha)));
> +   f.emit(assign(p1, mul(src_alpha, sub(imm1(1), dst_alpha))));
> +   f.emit(assign(p2, mul(dst_alpha, sub(imm1(1), src_alpha))));
> +
> +   /* R = f(Rs',Rd')*p0(As,Ad) + Y*Rs'*p1(As,Ad) + Z*Rd'*p2(As,Ad)
> +    * G = f(Gs',Gd')*p0(As,Ad) + Y*Gs'*p1(As,Ad) + Z*Gd'*p2(As,Ad)
> +    * B = f(Bs',Bd')*p0(As,Ad) + Y*Bs'*p1(As,Ad) + Z*Bd'*p2(As,Ad)
> +    * A =          X*p0(As,Ad) +     Y*p1(As,Ad) +     Z*p2(As,Ad)
> +    *
> +    * <X, Y, Z> is always <1, 1, 1>, so we can ignore it.
> +    *
> +    * In vector form, this is:
> +    * RGB = factor * p0 + Cs * p1 + Cd * p2
> +    *   A = p0 + p1 + p2
> +    */
> +   f.emit(assign(result,
> +                 add(add(mul(factor, p0), mul(src_rgb, p1)), mul(dst_rgb, p2)),
> +                 WRITEMASK_XYZ));
> +   f.emit(assign(result, add(add(p0, p1), p2), WRITEMASK_W));
> +}
> +
> +bool
> +lower_blend_equation_advanced(struct gl_linked_shader *sh)
> +{
> +   if (sh->info.BlendSupport == 0)
> +      return false;
> +
> +   lower_blend_visitor v(sh);
> +   return v.run();
> +}
> -- 
> 2.9.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 212 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160818/bbd4e816/attachment.sig>


More information about the mesa-dev mailing list