[PATCH 4/7] wined3d: Enable transform feedback if geometry shader with stream output is active.
Józef Kucia
jkucia at codeweavers.com
Thu Mar 30 07:09:21 CDT 2017
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
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 4e8569c..b29534d 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 3c666d6..3a99738 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;
--
2.10.2
More information about the wine-patches
mailing list