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>
This commit is contained in:
Józef Kucia 2017-03-30 14:09:21 +02:00 committed by Alexandre Julliard
parent c8dc913c47
commit 2e3300fa59
5 changed files with 51 additions and 7 deletions

View File

@ -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",

View File

@ -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);

View File

@ -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);

View File

@ -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))

View File

@ -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;