Module: wine Branch: master Commit: 2e3300fa59d9792a5578e64929777277ee9a685d URL: http://source.winehq.org/git/wine.git/?a=commit;h=2e3300fa59d9792a5578e64929...
Author: Józef Kucia jkucia@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@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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;