[PATCH v3 1/3] wined3d: Implement dual source blending.

Zebediah Figura z.figura12 at gmail.com
Tue Mar 17 18:05:06 CDT 2020


Based on a patch by Michael Müller.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/wined3d/context.c         |  2 ++
 dlls/wined3d/glsl_shader.c     | 19 ++++++++++++++++---
 dlls/wined3d/shader.c          |  2 ++
 dlls/wined3d/state.c           | 27 +++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |  9 ++++++---
 5 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index d9e3dfaa50..633d5176ba 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -3444,6 +3444,8 @@ static uint32_t find_draw_buffers_mask(const struct wined3d_context_gl *context_
 
     rt_mask = ps ? ps->reg_maps.rt_mask : 1;
     rt_mask &= (1u << gl_info->limits.buffers) - 1;
+    if (state->blend_state && state->blend_state->dual_source)
+        rt_mask = 1;
 
     mask = rt_mask;
     while (mask)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 4a2fbce553..2c2ba33488 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -7772,7 +7772,10 @@ static GLuint shader_glsl_generate_fragment_shader(const struct wined3d_context_
     {
         const struct wined3d_shader_signature *output_signature = &shader->output_signature;
 
-        shader_addline(buffer, "vec4 ps_out[%u];\n", gl_info->limits.buffers);
+        if (args->dual_source_blend)
+            shader_addline(buffer, "vec4 ps_out[2];\n");
+        else
+            shader_addline(buffer, "vec4 ps_out[%u];\n", gl_info->limits.buffers);
         if (output_signature->element_count)
         {
             for (i = 0; i < output_signature->element_count; ++i)
@@ -7787,7 +7790,12 @@ static GLuint shader_glsl_generate_fragment_shader(const struct wined3d_context_
                     continue;
                 }
                 if (shader_glsl_use_explicit_attrib_location(gl_info))
-                    shader_addline(buffer, "layout(location = %u) ", output->semantic_idx);
+                {
+                    if (args->dual_source_blend)
+                        shader_addline(buffer, "layout(location = 0, index = %u) ", output->semantic_idx);
+                    else
+                        shader_addline(buffer, "layout(location = %u) ", output->semantic_idx);
+                }
                 shader_addline(buffer, "out %s4 color_out%u;\n",
                         component_type_info[output->component_type].glsl_vector_type, output->semantic_idx);
             }
@@ -7800,7 +7808,12 @@ static GLuint shader_glsl_generate_fragment_shader(const struct wined3d_context_
             {
                 i = wined3d_bit_scan(&mask);
                 if (shader_glsl_use_explicit_attrib_location(gl_info))
-                    shader_addline(buffer, "layout(location = %u) ", i);
+                {
+                    if (args->dual_source_blend)
+                        shader_addline(buffer, "layout(location = 0, index = %u) ", i);
+                    else
+                        shader_addline(buffer, "layout(location = %u) ", i);
+                }
                 shader_addline(buffer, "out vec4 color_out%u;\n", i);
             }
         }
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index d9ef1a96e2..3e2a756757 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -4167,6 +4167,8 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
         if (rtv && rtv->format->id == WINED3DFMT_A8_UNORM && !is_identity_fixup(rtv->format->color_fixup))
             args->rt_alpha_swizzle |= 1u << i;
     }
+
+    args->dual_source_blend = state->blend_state && state->blend_state->dual_source;
 }
 
 static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 6289317936..fb55bfe0f3 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -74,6 +74,11 @@ void * CDECL wined3d_blend_state_get_parent(const struct wined3d_blend_state *st
     return state->parent;
 }
 
+static BOOL is_dual_source(enum wined3d_blend state)
+{
+    return state >= WINED3D_BLEND_SRC1COLOR && state <= WINED3D_BLEND_INVSRC1ALPHA;
+}
+
 HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device,
         const struct wined3d_blend_state_desc *desc, void *parent,
         const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state)
@@ -92,6 +97,12 @@ HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device,
     object->parent_ops = parent_ops;
     object->device = device;
 
+    object->dual_source = desc->rt[0].enable
+            && (is_dual_source(desc->rt[0].src)
+            || is_dual_source(desc->rt[0].dst)
+            || is_dual_source(desc->rt[0].src_alpha)
+            || is_dual_source(desc->rt[0].dst_alpha));
+
     TRACE("Created blend state %p.\n", object);
     *state = object;
 
@@ -650,6 +661,7 @@ static void blend_db2(struct wined3d_context *context, const struct wined3d_stat
     GLenum src_blend, dst_blend, src_blend_alpha, dst_blend_alpha;
     const struct wined3d_blend_state *b = state->blend_state;
     const struct wined3d_format *rt_format;
+    BOOL dual_source = b && b->dual_source;
     unsigned int i;
 
     if (b && b->desc.alpha_to_coverage)
@@ -658,6 +670,13 @@ static void blend_db2(struct wined3d_context *context, const struct wined3d_stat
         gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
     checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
 
+    if (context->last_was_dual_source_blend != dual_source)
+    {
+        /* Dual source blending changes the location of the output varyings. */
+        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
+        context->last_was_dual_source_blend = dual_source;
+    }
+
     if (!b || !b->desc.independent)
     {
         blend(context, state, state_id);
@@ -708,6 +727,7 @@ static void blend_dbb(struct wined3d_context *context, const struct wined3d_stat
 {
     const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
     const struct wined3d_blend_state *b = state->blend_state;
+    BOOL dual_source = b && b->dual_source;
     unsigned int i;
 
     if (b && b->desc.alpha_to_coverage)
@@ -716,6 +736,13 @@ static void blend_dbb(struct wined3d_context *context, const struct wined3d_stat
         gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
     checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
 
+    if (context->last_was_dual_source_blend != dual_source)
+    {
+        /* Dual source blending changes the location of the output varyings. */
+        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
+        context->last_was_dual_source_blend = dual_source;
+    }
+
     if (!b || !b->desc.independent)
     {
         blend(context, state, state_id);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9240b0e455..f8ee3c6446 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1394,7 +1394,8 @@ struct ps_compile_args
     DWORD alpha_test_func : 3;
     DWORD render_offscreen : 1;
     DWORD rt_alpha_swizzle : 8; /* MAX_RENDER_TARGET_VIEWS, 8 */
-    DWORD padding : 18;
+    DWORD dual_source_blend : 1;
+    DWORD padding : 17;
 };
 
 enum fog_src_type
@@ -1954,7 +1955,7 @@ struct wined3d_context
     DWORD last_was_ffp_blit : 1;
     DWORD last_was_blit : 1;
     DWORD last_was_ckey : 1;
-    DWORD namedArraysLoaded : 1;
+    DWORD last_was_dual_source_blend : 1;
     DWORD texShaderBumpMap : 8;         /* WINED3D_MAX_TEXTURES, 8 */
     DWORD lastWasPow2Texture : 8;       /* WINED3D_MAX_TEXTURES, 8 */
     DWORD fixed_function_usage_map : 8; /* WINED3D_MAX_TEXTURES, 8 */
@@ -1971,7 +1972,8 @@ struct wined3d_context
     DWORD destroyed : 1;
     DWORD destroy_delayed : 1;
     DWORD clip_distance_mask : 8; /* WINED3D_MAX_CLIP_DISTANCES, 8 */
-    DWORD padding : 14;
+    DWORD namedArraysLoaded : 1;
+    DWORD padding : 13;
 
     DWORD constant_update_mask;
     DWORD numbered_array_mask;
@@ -3140,6 +3142,7 @@ struct wined3d_blend_state
 {
     LONG refcount;
     struct wined3d_blend_state_desc desc;
+    BOOL dual_source;
 
     void *parent;
     const struct wined3d_parent_ops *parent_ops;
-- 
2.25.1




More information about the wine-devel mailing list