=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: wined3d: Enable transform feedback if geometry shader with stream output is active.

Alexandre Julliard julliard at winehq.org
Thu Mar 30 15:18:02 CDT 2017


Module: wine
Branch: master
Commit: 2e3300fa59d9792a5578e64929777277ee9a685d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2e3300fa59d9792a5578e64929777277ee9a685d

Author: Józef Kucia <jkucia at codeweavers.com>
Date:   Thu Mar 30 14:09:21 2017 +0200

wined3d: Enable transform feedback if geometry shader with stream output is active.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3d11/tests/d3d11.c       |  1 -
 dlls/wined3d/buffer.c          | 22 +++++++++++++++++-----
 dlls/wined3d/drawprim.c        | 25 +++++++++++++++++++++++++
 dlls/wined3d/state.c           |  7 +++++++
 dlls/wined3d/wined3d_private.h |  3 ++-
 5 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 07a9f25..c44afb4 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -11489,7 +11489,6 @@ static void test_index_buffer_offset(void)
     for (i = 0; i < ARRAY_SIZE(expected_data); ++i)
     {
         data = get_readback_vec4(&rb, i, 0);
-        todo_wine
         ok(compare_vec4(data, &expected_data[i], 0)
                 || broken(is_nvidia_device(device) && !(i % 2) && compare_vec4(data, &broken_result, 0)),
                 "Got unexpected result {%.8e, %.8e, %.8e, %.8e} at %u.\n",
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index cb3cbbd..ba8b004 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -144,7 +144,7 @@ static void buffer_bind(struct wined3d_buffer *buffer, struct wined3d_context *c
 }
 
 /* Context activation is done by the caller. */
-static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, const struct wined3d_context *context)
+static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, struct wined3d_context *context)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_resource *resource = &buffer->resource;
@@ -152,10 +152,6 @@ static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, const st
     if (!buffer->buffer_object)
         return;
 
-    GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object));
-    checkGLcall("glDeleteBuffers");
-    buffer->buffer_object = 0;
-
     /* The stream source state handler might have read the memory of the
      * vertex buffer already and got the memory in the vbo which is not
      * valid any longer. Dirtify the stream source to force a reload. This
@@ -177,9 +173,25 @@ static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, const st
             device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE));
         }
         if (buffer->bind_flags & WINED3D_BIND_STREAM_OUTPUT)
+        {
             device_invalidate_state(resource->device, STATE_STREAM_OUTPUT);
+            if (context->transform_feedback_active)
+            {
+                /* We have to make sure that transform feedback is not active
+                 * when deleting a potentially bound transform feedback buffer.
+                 * This may happen when the device is being destroyed. */
+                WARN("Deleting buffer object for buffer %p, disabling transform feedback.\n", buffer);
+                GL_EXTCALL(glEndTransformFeedback());
+                checkGLcall("glEndTransformFeedback");
+                context->transform_feedback_active = 0;
+            }
+        }
     }
 
+    GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object));
+    checkGLcall("glDeleteBuffers");
+    buffer->buffer_object = 0;
+
     if (buffer->query)
     {
         wined3d_event_query_destroy(buffer->query);
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 05a6380..e055361 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -406,6 +406,14 @@ static void remove_vbos(struct wined3d_context *context,
     }
 }
 
+static BOOL use_transform_feedback(const struct wined3d_state *state)
+{
+    const struct wined3d_shader *shader;
+    if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]))
+        return FALSE;
+    return shader->u.gs.so_desc.element_count;
+}
+
 /* Routine common to the draw primitive and draw indexed primitive routines */
 void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state,
         int base_vertex_idx, unsigned int start_idx, unsigned int index_count,
@@ -439,6 +447,13 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
     }
     gl_info = context->gl_info;
 
+    if (context->transform_feedback_active && !use_transform_feedback(state))
+    {
+        GL_EXTCALL(glEndTransformFeedback());
+        checkGLcall("glEndTransformFeedback");
+        context->transform_feedback_active = 0;
+    }
+
     for (i = 0; i < gl_info->limits.buffers; ++i)
     {
         struct wined3d_texture *rt;
@@ -549,6 +564,16 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
         }
     }
 
+    if (use_transform_feedback(state) && !context->transform_feedback_active)
+    {
+        const struct wined3d_shader *shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
+        GLenum primitive_mode = gl_primitive_type_from_d3d(shader->u.gs.output_type);
+
+        GL_EXTCALL(glBeginTransformFeedback(primitive_mode));
+        checkGLcall("glBeginTransformFeedback");
+        context->transform_feedback_active = 1;
+    }
+
     if (context->use_immediate_mode_draw || emulation)
         draw_primitive_immediate_mode(context, state, stream_info, idx_data,
                 idx_size, base_vertex_idx, start_idx, index_count, instance_count);
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 2b846ae..dedde1e 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4982,6 +4982,13 @@ static void state_so(struct wined3d_context *context, const struct wined3d_state
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
 
+    if (context->transform_feedback_active)
+    {
+        GL_EXTCALL(glEndTransformFeedback());
+        checkGLcall("glEndTransformFeedback");
+        context->transform_feedback_active = 0;
+    }
+
     for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
     {
         if (!(buffer = state->stream_output[i].buffer))
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4bd38f6..2f90efd 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1689,7 +1689,8 @@ struct wined3d_context
     DWORD update_compute_unordered_access_view_bindings : 1;
     DWORD uses_uavs : 1;
     DWORD destroy_delayed : 1;
-    DWORD padding : 9;
+    DWORD transform_feedback_active : 1;
+    DWORD padding : 8;
     DWORD last_swizzle_map; /* MAX_ATTRIBS, 16 */
     DWORD shader_update_mask;
     DWORD constant_update_mask;




More information about the wine-cvs mailing list