forked from Mirrors/wine-wine
wined3d: Specify geometry shader outputs to record in stream output buffers.
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>oldstable
parent
d50745b7ae
commit
16ab203342
|
@ -727,6 +727,133 @@ static void shader_glsl_load_program_resources(const struct wined3d_context *con
|
|||
shader_glsl_load_samplers(context, priv, program_id, reg_maps);
|
||||
}
|
||||
|
||||
static void append_transform_feedback_varying(const char **varyings, unsigned int *varying_count,
|
||||
char **strings, unsigned int *strings_length, struct wined3d_string_buffer *buffer)
|
||||
{
|
||||
if (varyings && *strings)
|
||||
{
|
||||
char *ptr = *strings;
|
||||
|
||||
varyings[*varying_count] = ptr;
|
||||
|
||||
memcpy(ptr, buffer->buffer, buffer->content_size + 1);
|
||||
ptr += buffer->content_size + 1;
|
||||
|
||||
*strings = ptr;
|
||||
}
|
||||
|
||||
*strings_length += buffer->content_size + 1;
|
||||
++(*varying_count);
|
||||
}
|
||||
|
||||
static void shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc,
|
||||
struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count,
|
||||
char *strings, unsigned int *strings_length)
|
||||
{
|
||||
unsigned int i, j, buffer_idx, count, length, highest_output_slot;
|
||||
|
||||
count = length = 0;
|
||||
highest_output_slot = 0;
|
||||
for (buffer_idx = 0; buffer_idx < WINED3D_MAX_STREAM_OUTPUT_BUFFERS; ++buffer_idx)
|
||||
{
|
||||
for (i = 0; i < so_desc->element_count; ++i)
|
||||
{
|
||||
const struct wined3d_stream_output_element *e = &so_desc->elements[i];
|
||||
|
||||
highest_output_slot = max(highest_output_slot, e->output_slot);
|
||||
if (e->output_slot != buffer_idx)
|
||||
continue;
|
||||
|
||||
if (e->stream_idx)
|
||||
{
|
||||
FIXME("Unhandled stream %u.\n", e->stream_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
|
||||
{
|
||||
for (j = 0; j < e->component_count / 4; ++j)
|
||||
{
|
||||
string_buffer_sprintf(buffer, "gl_SkipComponents4");
|
||||
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
|
||||
}
|
||||
if (e->component_count % 4)
|
||||
{
|
||||
string_buffer_sprintf(buffer, "gl_SkipComponents%u", e->component_count % 4);
|
||||
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->component_idx || e->component_count != 4)
|
||||
{
|
||||
FIXME("Unsupported component range %u-%u.\n", e->component_idx, e->component_count);
|
||||
continue;
|
||||
}
|
||||
|
||||
string_buffer_sprintf(buffer, "ps_link[%u]", e->register_idx);
|
||||
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
|
||||
}
|
||||
|
||||
if (highest_output_slot <= buffer_idx)
|
||||
break;
|
||||
|
||||
string_buffer_sprintf(buffer, "gl_NextBuffer");
|
||||
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
|
||||
}
|
||||
|
||||
if (varying_count)
|
||||
*varying_count = count;
|
||||
if (strings_length)
|
||||
*strings_length = length;
|
||||
}
|
||||
|
||||
static void shader_glsl_init_transform_feedback(const struct wined3d_context *context,
|
||||
struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader)
|
||||
{
|
||||
const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
struct wined3d_string_buffer *buffer;
|
||||
unsigned int count, length;
|
||||
const char **varyings;
|
||||
char *strings;
|
||||
|
||||
if (!gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
|
||||
{
|
||||
FIXME("ARB_transform_feedback3 not supported by OpenGL implementation.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (so_desc->buffer_stride_count)
|
||||
FIXME("Ignoring buffer strides.\n");
|
||||
|
||||
buffer = string_buffer_get(&priv->string_buffers);
|
||||
|
||||
shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length);
|
||||
|
||||
if (!(varyings = wined3d_calloc(count, sizeof(*varyings))))
|
||||
{
|
||||
ERR("Out of memory.\n");
|
||||
string_buffer_release(&priv->string_buffers, buffer);
|
||||
return;
|
||||
}
|
||||
if (!(strings = wined3d_calloc(length, sizeof(*strings))))
|
||||
{
|
||||
ERR("Out of memory.\n");
|
||||
HeapFree(GetProcessHeap(), 0, varyings);
|
||||
string_buffer_release(&priv->string_buffers, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL);
|
||||
GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, GL_INTERLEAVED_ATTRIBS));
|
||||
checkGLcall("glTransformFeedbackVaryings");
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, varyings);
|
||||
HeapFree(GetProcessHeap(), 0, strings);
|
||||
string_buffer_release(&priv->string_buffers, buffer);
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants,
|
||||
const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
|
||||
|
@ -8994,6 +9121,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
|
|||
checkGLcall("glProgramParameteriARB");
|
||||
}
|
||||
|
||||
shader_glsl_init_transform_feedback(context, priv, program_id, gshader);
|
||||
|
||||
list_add_head(&gshader->linked_programs, &entry->gs.shader_entry);
|
||||
}
|
||||
|
||||
|
@ -9588,7 +9717,8 @@ static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct s
|
|||
&& gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS]
|
||||
&& gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE]
|
||||
&& gl_info->supported[ARB_SHADER_IMAGE_SIZE]
|
||||
&& gl_info->supported[ARB_SHADING_LANGUAGE_PACKING])
|
||||
&& gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]
|
||||
&& gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
|
||||
shader_model = 5;
|
||||
else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50) && gl_info->supported[WINED3D_GL_VERSION_3_2]
|
||||
&& gl_info->supported[ARB_SHADER_BIT_ENCODING] && gl_info->supported[ARB_SAMPLER_OBJECTS]
|
||||
|
|
|
@ -2813,6 +2813,9 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
|
|||
|
||||
static void shader_cleanup(struct wined3d_shader *shader)
|
||||
{
|
||||
if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
|
||||
HeapFree(GetProcessHeap(), 0, shader->u.gs.so_desc.elements);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, shader->output_signature.elements);
|
||||
HeapFree(GetProcessHeap(), 0, shader->input_signature.elements);
|
||||
HeapFree(GetProcessHeap(), 0, shader->signature_strings);
|
||||
|
@ -3399,9 +3402,27 @@ static HRESULT hull_shader_init(struct wined3d_shader *shader, struct wined3d_de
|
|||
}
|
||||
|
||||
static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
|
||||
const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
|
||||
const struct wined3d_shader_desc *desc, const struct wined3d_stream_output_desc *so_desc,
|
||||
void *parent, const struct wined3d_parent_ops *parent_ops)
|
||||
{
|
||||
return shader_init(shader, device, desc, 0, WINED3D_SHADER_TYPE_GEOMETRY, parent, parent_ops);
|
||||
HRESULT hr;
|
||||
|
||||
if (FAILED(hr = shader_init(shader, device, desc, 0, WINED3D_SHADER_TYPE_GEOMETRY, parent, parent_ops)))
|
||||
return hr;
|
||||
|
||||
if (so_desc)
|
||||
{
|
||||
struct wined3d_stream_output_desc *d = &shader->u.gs.so_desc;
|
||||
*d = *so_desc;
|
||||
if (!(d->elements = wined3d_calloc(so_desc->element_count, sizeof(*d->elements))))
|
||||
{
|
||||
shader_cleanup(shader);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
memcpy(d->elements, so_desc->elements, so_desc->element_count * sizeof(*d->elements));
|
||||
}
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
|
||||
|
@ -3797,13 +3818,10 @@ HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const stru
|
|||
TRACE("device %p, desc %p, so_desc %p, parent %p, parent_ops %p, shader %p.\n",
|
||||
device, desc, so_desc, parent, parent_ops, shader);
|
||||
|
||||
if (so_desc)
|
||||
FIXME("Stream output not supported.\n");
|
||||
|
||||
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (FAILED(hr = geometry_shader_init(object, device, desc, parent, parent_ops)))
|
||||
if (FAILED(hr = geometry_shader_init(object, device, desc, so_desc, parent, parent_ops)))
|
||||
{
|
||||
WARN("Failed to initialize geometry shader, hr %#x.\n", hr);
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
|
|
|
@ -3610,6 +3610,8 @@ struct wined3d_geometry_shader
|
|||
enum wined3d_primitive_type input_type;
|
||||
enum wined3d_primitive_type output_type;
|
||||
UINT vertices_out;
|
||||
|
||||
struct wined3d_stream_output_desc so_desc;
|
||||
};
|
||||
|
||||
struct wined3d_pixel_shader
|
||||
|
|
Loading…
Reference in New Issue