i965: Implement a drirc workaround for broken dual color blending.
authorKenneth Graunke <kenneth@whitecape.org>
Thu, 21 Jan 2016 01:33:14 +0000 (17:33 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Fri, 22 Jan 2016 22:14:26 +0000 (14:14 -0800)
OpenGL's dual color blending feature was specified so that an
implementation could support both multiple render targets (MRT) and
dual source blending.  Fragment shader outputs specify both "location"
(the render target number) and "index" (either color 0 or 1).

I believe DirectX only has the notion of "location" - if using dual
color blending, location 0 or 1 will specify the operands.  If not,
then location means the render target index.  The two features can't
be used together.

As such, some applications mistakenly try to use <loc = 0, index = 0>
and <loc = 1, index = 0> in a shader used for dual color blending with
a single render target, rather than the correct <loc = 0, index = 0>
and <loc = 0, index = 1>.

In particular, Unigine Heaven 4.0 and Valley 1.0 suffer from this bug.
Unigine is aware of the problem, and quickly developed a fix, but has
not bothered to change the download link on their website to a working
copy in over a year.  People were still using the broken version and
complaining.  We tried working around this by disabling dual color
blending, but that apparently hurts performance, and people were once
again unhappy.

On i965, dual source blending is achieved by using different framebuffer
write messages than normal rendering.  So, we have to compile different
code for the two cases.  We're not being pedantic: we actually have to
know in order to function.

Normally, dual source blending is detectable in the shader: if a shader
has an output with index = 1, then it's meant for blending, not MRT.
With the broken inputs, they're indistinguishable, so we can only tell
by looking at the current GL state.

This patch implements a new drirc workaround:

   export dual_color_blend_by_location=true

which makes the i965 driver detect when OpenGL state is configured for
dual source blending, and recompile the fragment shader to use the right
messages.  In that case, we allow either location = 1 or index = 1 to
specify the second source for the blending equations.

It also re-enables GL_ARB_blend_func_extended for Unigine.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92233
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/mesa/drivers/dri/common/drirc
src/mesa/drivers/dri/common/xmlpool/t_options.h
src/mesa/drivers/dri/i965/brw_compiler.h
src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_fs_nir.cpp
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/intel_screen.c

index e1874c3f1dce81770deefa8bf57b446872385c79..183a1dcabe8a29d4014c0e4c939dc6332780b978 100644 (file)
@@ -37,26 +37,26 @@ TODO: document the other workarounds.
 
         <application name="Unigine Heaven (32-bit)" executable="heaven_x86">
             <option name="allow_glsl_extension_directive_midshader" value="true" />
-            <!-- remove disable_blend_func_extended if 4.1 ever comes out -->
-            <option name="disable_blend_func_extended" value="true" />
+            <!-- remove dual_color_blend_by_location if 4.1 ever comes out -->
+            <option name="dual_color_blend_by_location" value="true" />
        </application>
 
         <application name="Unigine Heaven (64-bit)" executable="heaven_x64">
             <option name="allow_glsl_extension_directive_midshader" value="true" />
-            <!-- remove disable_blend_func_extended if 4.1 ever comes out -->
-            <option name="disable_blend_func_extended" value="true" />
+            <!-- remove dual_color_blend_by_location if 4.1 ever comes out -->
+            <option name="dual_color_blend_by_location" value="true" />
        </application>
 
         <application name="Unigine Valley (32-bit)" executable="valley_x86">
             <option name="allow_glsl_extension_directive_midshader" value="true" />
-            <!-- remove disable_blend_func_extended if 1.1 ever comes out -->
-            <option name="disable_blend_func_extended" value="true" />
+            <!-- remove dual_color_blend_by_location if 1.1 ever comes out -->
+            <option name="dual_color_blend_by_location" value="true" />
        </application>
 
         <application name="Unigine Valley (64-bit)" executable="valley_x64">
             <option name="allow_glsl_extension_directive_midshader" value="true" />
-            <!-- remove disable_blend_func_extended if 1.1 ever comes out -->
-            <option name="disable_blend_func_extended" value="true" />
+            <!-- remove dual_color_blend_by_location if 1.1 ever comes out -->
+            <option name="dual_color_blend_by_location" value="true" />
        </application>
 
         <application name="Unigine OilRush (32-bit)" executable="OilRush_x86">
index 4e5a7217ee2f1f106a094c3b004075fc9120ef81..55e926b239e68af2b4df4a0db949b35a47664894 100644 (file)
@@ -90,6 +90,11 @@ DRI_CONF_OPT_BEGIN_B(disable_blend_func_extended, def) \
         DRI_CONF_DESC(en,gettext("Disable dual source blending")) \
 DRI_CONF_OPT_END
 
+#define DRI_CONF_DUAL_COLOR_BLEND_BY_LOCATION(def) \
+DRI_CONF_OPT_BEGIN_B(dual_color_blend_by_location, def) \
+        DRI_CONF_DESC(en,gettext("Identify dual color blending sources by location rather than index")) \
+DRI_CONF_OPT_END
+
 #define DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS(def) \
 DRI_CONF_OPT_BEGIN_B(disable_glsl_line_continuations, def) \
         DRI_CONF_DESC(en,gettext("Disable backslash-based line continuations in GLSL source")) \
index 224ddb14ed1b0580abfd7508f54a9b3ad4527463..748ffe58b0c0a664b553fcefb3bb93af55f4b1e5 100644 (file)
@@ -246,6 +246,7 @@ struct brw_wm_prog_key {
    bool compute_sample_id:1;
    unsigned line_aa:2;
    bool high_quality_derivatives:1;
+   bool force_dual_color_blend:1;
 
    uint16_t drawable_height;
    uint64_t input_slots_valid;
index 9ba33396d3627cd3b78939e06f51d65f4360346e..1032e5a8175f2e8dcf41897537beea8437ba6436 100644 (file)
@@ -750,6 +750,9 @@ brw_process_driconf_options(struct brw_context *brw)
 
    ctx->Const.AllowGLSLExtensionDirectiveMidShader =
       driQueryOptionb(options, "allow_glsl_extension_directive_midshader");
+
+   brw->dual_color_blend_by_location =
+      driQueryOptionb(options, "dual_color_blend_by_location");
 }
 
 GLboolean
index 2a29dfe5eecb036e9558ee0306ca36c314a7dbb8..55d6723eab7511eb3bc4c300742c9685cc86eb8a 100644 (file)
@@ -836,6 +836,7 @@ struct brw_context
    bool always_flush_cache;
    bool disable_throttling;
    bool precompile;
+   bool dual_color_blend_by_location;
 
    driOptionCache optionCache;
    /** @} */
index d7bcc1c5374998c214d5ece788683176d2ee4849..f9df2a4e3b6a8c11bf9ebde77b94f0ca2b4f5d6f 100644 (file)
@@ -130,7 +130,11 @@ fs_visitor::nir_setup_outputs()
          break;
       }
       case MESA_SHADER_FRAGMENT:
-         if (var->data.index > 0) {
+         if (key->force_dual_color_blend &&
+             var->data.location == FRAG_RESULT_DATA1) {
+            this->dual_src_output = reg;
+            this->do_dual_src = true;
+         } else if (var->data.index > 0) {
             assert(var->data.location == FRAG_RESULT_DATA0);
             assert(var->data.index == 1);
             this->dual_src_output = reg;
index 39d644ea63ae1e25d6871b50fb7e62b7f192be3e..78846dc37900d028dbe538d01c16d0f3bbfa7d07 100644 (file)
@@ -515,6 +515,10 @@ brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
    /* _NEW_BUFFERS */
    key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers;
 
+   /* _NEW_COLOR */
+   key->force_dual_color_blend = brw->dual_color_blend_by_location &&
+      (ctx->Color.BlendEnabled & 1) && ctx->Color.Blend[0]._UsesDualSrc;
+
    /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */
    key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
       (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled);
index e1e1e62d26a6047709130260730462722ecc3f05..bca783aea86cab13840cd285a672ec771936b191 100644 (file)
@@ -79,6 +79,7 @@ DRI_CONF_BEGIN
       DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false")
       DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false")
       DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false")
+      DRI_CONF_DUAL_COLOR_BLEND_BY_LOCATION("false")
       DRI_CONF_ALLOW_GLSL_EXTENSION_DIRECTIVE_MIDSHADER("false")
 
       DRI_CONF_OPT_BEGIN_B(shader_precompile, "true")