Commit 3d883c64 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Only store unique stream output descriptions.

This allows us to compare them by pointer. Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 10bfc47a
...@@ -176,6 +176,13 @@ ULONG CDECL wined3d_device_incref(struct wined3d_device *device) ...@@ -176,6 +176,13 @@ ULONG CDECL wined3d_device_incref(struct wined3d_device *device)
return refcount; return refcount;
} }
static void device_free_so_desc(struct wine_rb_entry *entry, void *context)
{
struct wined3d_so_desc_entry *s = WINE_RB_ENTRY_VALUE(entry, struct wined3d_so_desc_entry, entry);
heap_free(s);
}
static void device_leftover_sampler(struct wine_rb_entry *entry, void *context) static void device_leftover_sampler(struct wine_rb_entry *entry, void *context)
{ {
struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry); struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
...@@ -242,6 +249,7 @@ void wined3d_device_cleanup(struct wined3d_device *device) ...@@ -242,6 +249,7 @@ void wined3d_device_cleanup(struct wined3d_device *device)
wine_rb_destroy(&device->rasterizer_states, device_leftover_rasterizer_state, NULL); wine_rb_destroy(&device->rasterizer_states, device_leftover_rasterizer_state, NULL);
wine_rb_destroy(&device->blend_states, device_leftover_blend_state, NULL); wine_rb_destroy(&device->blend_states, device_leftover_blend_state, NULL);
wine_rb_destroy(&device->depth_stencil_states, device_leftover_depth_stencil_state, NULL); wine_rb_destroy(&device->depth_stencil_states, device_leftover_depth_stencil_state, NULL);
wine_rb_destroy(&device->so_descs, device_free_so_desc, NULL);
wined3d_decref(device->wined3d); wined3d_decref(device->wined3d);
device->wined3d = NULL; device->wined3d = NULL;
...@@ -5686,6 +5694,49 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso ...@@ -5686,6 +5694,49 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
TRACE("Resource released.\n"); TRACE("Resource released.\n");
} }
static int wined3d_so_desc_compare(const void *key, const struct wine_rb_entry *entry)
{
const struct wined3d_stream_output_desc *desc = &WINE_RB_ENTRY_VALUE(entry,
struct wined3d_so_desc_entry, entry)->desc;
const struct wined3d_stream_output_desc *k = key;
unsigned int i;
int ret;
if ((ret = (k->element_count - desc->element_count)))
return ret;
if ((ret = (k->buffer_stride_count - desc->buffer_stride_count)))
return ret;
if ((ret = (k->rasterizer_stream_idx - desc->rasterizer_stream_idx)))
return ret;
for (i = 0; i < k->element_count; ++i)
{
const struct wined3d_stream_output_element *b = &desc->elements[i];
const struct wined3d_stream_output_element *a = &k->elements[i];
if ((ret = (a->stream_idx - b->stream_idx)))
return ret;
if ((ret = strcmp(a->semantic_name, b->semantic_name)))
return ret;
if ((ret = (a->semantic_idx - b->semantic_idx)))
return ret;
if ((ret = (a->component_idx - b->component_idx)))
return ret;
if ((ret = (a->component_count - b->component_count)))
return ret;
if ((ret = (a->output_slot - b->output_slot)))
return ret;
}
for (i = 0; i < k->buffer_stride_count; ++i)
{
if ((ret = (k->buffer_strides[i] - desc->buffer_strides[i])))
return ret;
}
return 0;
}
static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry *entry) static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry *entry)
{ {
const struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry); const struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
...@@ -5773,6 +5824,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined ...@@ -5773,6 +5824,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
fragment_pipeline = adapter->fragment_pipe; fragment_pipeline = adapter->fragment_pipe;
wine_rb_init(&device->so_descs, wined3d_so_desc_compare);
wine_rb_init(&device->samplers, wined3d_sampler_compare); wine_rb_init(&device->samplers, wined3d_sampler_compare);
wine_rb_init(&device->rasterizer_states, wined3d_rasterizer_state_compare); wine_rb_init(&device->rasterizer_states, wined3d_rasterizer_state_compare);
wine_rb_init(&device->blend_states, wined3d_blend_state_compare); wine_rb_init(&device->blend_states, wined3d_blend_state_compare);
...@@ -5788,6 +5840,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined ...@@ -5788,6 +5840,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined
wine_rb_destroy(&device->rasterizer_states, NULL, NULL); wine_rb_destroy(&device->rasterizer_states, NULL, NULL);
wine_rb_destroy(&device->blend_states, NULL, NULL); wine_rb_destroy(&device->blend_states, NULL, NULL);
wine_rb_destroy(&device->depth_stencil_states, NULL, NULL); wine_rb_destroy(&device->depth_stencil_states, NULL, NULL);
wine_rb_destroy(&device->so_descs, NULL, NULL);
wined3d_decref(device->wined3d); wined3d_decref(device->wined3d);
return hr; return hr;
} }
...@@ -5815,6 +5868,7 @@ err: ...@@ -5815,6 +5868,7 @@ err:
wine_rb_destroy(&device->rasterizer_states, NULL, NULL); wine_rb_destroy(&device->rasterizer_states, NULL, NULL);
wine_rb_destroy(&device->blend_states, NULL, NULL); wine_rb_destroy(&device->blend_states, NULL, NULL);
wine_rb_destroy(&device->depth_stencil_states, NULL, NULL); wine_rb_destroy(&device->depth_stencil_states, NULL, NULL);
wine_rb_destroy(&device->so_descs, NULL, NULL);
wined3d_decref(device->wined3d); wined3d_decref(device->wined3d);
return hr; return hr;
} }
......
...@@ -859,7 +859,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_stri ...@@ -859,7 +859,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_stri
const char **varyings, unsigned int *varying_count, char *strings, unsigned int *strings_length, const char **varyings, unsigned int *varying_count, char *strings, unsigned int *strings_length,
GLenum buffer_mode, struct wined3d_shader *shader) GLenum buffer_mode, struct wined3d_shader *shader)
{ {
const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc; const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
unsigned int buffer_idx, count, length, highest_output_slot, stride; unsigned int buffer_idx, count, length, highest_output_slot, stride;
unsigned int i, register_idx, component_idx; unsigned int i, register_idx, component_idx;
BOOL have_varyings_to_record = FALSE; BOOL have_varyings_to_record = FALSE;
...@@ -948,7 +948,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_stri ...@@ -948,7 +948,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_stri
static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl *context_gl, static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl *context_gl,
struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader) struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader)
{ {
const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc; const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
const struct wined3d_gl_info *gl_info = context_gl->gl_info; const struct wined3d_gl_info *gl_info = context_gl->gl_info;
struct wined3d_string_buffer *buffer; struct wined3d_string_buffer *buffer;
unsigned int i, count, length; unsigned int i, count, length;
...@@ -956,7 +956,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl ...@@ -956,7 +956,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl
char *strings; char *strings;
GLenum mode; GLenum mode;
if (!so_desc->element_count) if (!so_desc)
return; return;
if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3]) if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
...@@ -1005,7 +1005,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl ...@@ -1005,7 +1005,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context_gl
if (!shader_glsl_generate_transform_feedback_varyings(buffer, NULL, &count, NULL, &length, mode, shader)) if (!shader_glsl_generate_transform_feedback_varyings(buffer, NULL, &count, NULL, &length, mode, shader))
{ {
FIXME("No varyings to record, disabling transform feedback.\n"); FIXME("No varyings to record, disabling transform feedback.\n");
shader->u.gs.so_desc.element_count = 0; shader->u.gs.so_desc = NULL;
string_buffer_release(&priv->string_buffers, buffer); string_buffer_release(&priv->string_buffers, buffer);
return; return;
} }
...@@ -7217,7 +7217,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl ...@@ -7217,7 +7217,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
static void shader_glsl_generate_stream_output_setup(struct wined3d_string_buffer *buffer, static void shader_glsl_generate_stream_output_setup(struct wined3d_string_buffer *buffer,
const struct wined3d_shader *shader) const struct wined3d_shader *shader)
{ {
const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc; const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
unsigned int i, register_idx, component_idx; unsigned int i, register_idx, component_idx;
shader_addline(buffer, "out shader_in_out\n{\n"); shader_addline(buffer, "out shader_in_out\n{\n");
......
...@@ -3137,10 +3137,6 @@ static void shader_cleanup(struct wined3d_shader *shader) ...@@ -3137,10 +3137,6 @@ static void shader_cleanup(struct wined3d_shader *shader)
heap_free(shader->u.hs.phases.fork); heap_free(shader->u.hs.phases.fork);
heap_free(shader->u.hs.phases.join); heap_free(shader->u.hs.phases.join);
} }
else if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
{
heap_free((void *)shader->u.gs.so_desc.elements);
}
heap_free(shader->patch_constant_signature.elements); heap_free(shader->patch_constant_signature.elements);
heap_free(shader->output_signature.elements); heap_free(shader->output_signature.elements);
...@@ -3749,13 +3745,67 @@ BOOL shader_get_stream_output_register_info(const struct wined3d_shader *shader, ...@@ -3749,13 +3745,67 @@ BOOL shader_get_stream_output_register_info(const struct wined3d_shader *shader,
return TRUE; return TRUE;
} }
static HRESULT geometry_shader_init_so_desc(struct wined3d_geometry_shader *gs, struct wined3d_device *device,
const struct wined3d_stream_output_desc *so_desc)
{
struct wined3d_so_desc_entry *s;
struct wine_rb_entry *entry;
unsigned int i;
size_t size;
char *name;
if ((entry = wine_rb_get(&device->so_descs, so_desc)))
{
gs->so_desc = &WINE_RB_ENTRY_VALUE(entry, struct wined3d_so_desc_entry, entry)->desc;
return WINED3D_OK;
}
size = FIELD_OFFSET(struct wined3d_so_desc_entry, elements[so_desc->element_count]);
for (i = 0; i < so_desc->element_count; ++i)
{
const char *n = so_desc->elements[i].semantic_name;
if (n)
size += strlen(n) + 1;
}
if (!(s = heap_alloc(size)))
return E_OUTOFMEMORY;
s->desc = *so_desc;
memcpy(s->elements, so_desc->elements, so_desc->element_count * sizeof(*s->elements));
s->desc.elements = s->elements;
name = (char *)&s->elements[s->desc.element_count];
for (i = 0; i < so_desc->element_count; ++i)
{
struct wined3d_stream_output_element *e = &s->elements[i];
if (!e->semantic_name)
continue;
size = strlen(e->semantic_name) + 1;
memcpy(name, e->semantic_name, size);
e->semantic_name = name;
name += size;
}
if (wine_rb_put(&device->so_descs, &s->desc, &s->entry) == -1)
{
heap_free(s);
return E_FAIL;
}
gs->so_desc = &s->desc;
return WINED3D_OK;
}
static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader, static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
const struct wined3d_stream_output_desc *so_desc) const struct wined3d_stream_output_desc *so_desc)
{ {
const struct wined3d_shader_frontend *fe = shader->frontend; const struct wined3d_shader_frontend *fe = shader->frontend;
const struct wined3d_shader_signature_element *output; const struct wined3d_shader_signature_element *output;
unsigned int i, component_idx, register_idx, mask; unsigned int i, component_idx, register_idx, mask;
struct wined3d_stream_output_element *elements;
struct wined3d_shader_version shader_version; struct wined3d_shader_version shader_version;
const DWORD *ptr; const DWORD *ptr;
void *fe_data; void *fe_data;
...@@ -3795,16 +3845,9 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader, ...@@ -3795,16 +3845,9 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return hr; return hr;
} }
if (!(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
return E_OUTOFMEMORY;
shader->u.gs.so_desc = *so_desc;
shader->u.gs.so_desc.elements = elements;
memcpy(elements, so_desc->elements, so_desc->element_count * sizeof(*elements));
for (i = 0; i < so_desc->element_count; ++i) for (i = 0; i < so_desc->element_count; ++i)
{ {
struct wined3d_stream_output_element *e = &elements[i]; const struct wined3d_stream_output_element *e = &so_desc->elements[i];
if (!e->semantic_name) if (!e->semantic_name)
continue; continue;
...@@ -3816,8 +3859,6 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader, ...@@ -3816,8 +3859,6 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return E_INVALIDARG; return E_INVALIDARG;
} }
e->semantic_name = output->semantic_name;
mask = ((1u << e->component_count) - 1) << component_idx; mask = ((1u << e->component_count) - 1) << component_idx;
if ((output->mask & 0xff & mask) != mask) if ((output->mask & 0xff & mask) != mask)
{ {
...@@ -3827,6 +3868,12 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader, ...@@ -3827,6 +3868,12 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
} }
} }
if (FAILED(hr = geometry_shader_init_so_desc(&shader->u.gs, shader->device, so_desc)))
{
WARN("Failed to initialise stream output description, hr %#x.\n", hr);
return hr;
}
return WINED3D_OK; return WINED3D_OK;
} }
......
...@@ -283,15 +283,17 @@ static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_sh ...@@ -283,15 +283,17 @@ static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_sh
memset(iface, 0, sizeof(*iface)); memset(iface, 0, sizeof(*iface));
iface->vkd3d_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO; iface->vkd3d_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
if (shader_type == WINED3D_SHADER_TYPE_GEOMETRY && shader->u.gs.so_desc.element_count) if (shader_type == WINED3D_SHADER_TYPE_GEOMETRY && shader->u.gs.so_desc)
{ {
const struct wined3d_stream_output_desc *so_desc = shader->u.gs.so_desc;
iface->xfb_info.type = VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO; iface->xfb_info.type = VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO;
iface->xfb_info.next = NULL; iface->xfb_info.next = NULL;
iface->xfb_info.elements = (const struct vkd3d_shader_transform_feedback_element *)shader->u.gs.so_desc.elements; iface->xfb_info.elements = (const struct vkd3d_shader_transform_feedback_element *)so_desc->elements;
iface->xfb_info.element_count = shader->u.gs.so_desc.element_count; iface->xfb_info.element_count = so_desc->element_count;
iface->xfb_info.buffer_strides = shader->u.gs.so_desc.buffer_strides; iface->xfb_info.buffer_strides = so_desc->buffer_strides;
iface->xfb_info.buffer_stride_count = shader->u.gs.so_desc.buffer_stride_count; iface->xfb_info.buffer_stride_count = so_desc->buffer_stride_count;
iface->vkd3d_interface.next = &iface->xfb_info; iface->vkd3d_interface.next = &iface->xfb_info;
} }
......
...@@ -3671,6 +3671,13 @@ struct wined3d_dummy_textures ...@@ -3671,6 +3671,13 @@ struct wined3d_dummy_textures
* wined3d_device_create() ignores it. */ * wined3d_device_create() ignores it. */
#define WINED3DCREATE_MULTITHREADED 0x00000004 #define WINED3DCREATE_MULTITHREADED 0x00000004
struct wined3d_so_desc_entry
{
struct wine_rb_entry entry;
struct wined3d_stream_output_desc desc;
struct wined3d_stream_output_element elements[1];
};
struct wined3d_device struct wined3d_device
{ {
LONG ref; LONG ref;
...@@ -3715,6 +3722,7 @@ struct wined3d_device ...@@ -3715,6 +3722,7 @@ struct wined3d_device
struct list resources; /* a linked list to track resources created by the device */ struct list resources; /* a linked list to track resources created by the device */
struct list shaders; /* a linked list to track shaders (pixel and vertex) */ struct list shaders; /* a linked list to track shaders (pixel and vertex) */
struct wine_rb_tree so_descs;
struct wine_rb_tree samplers, rasterizer_states, blend_states, depth_stencil_states; struct wine_rb_tree samplers, rasterizer_states, blend_states, depth_stencil_states;
/* Render Target Support */ /* Render Target Support */
...@@ -5327,7 +5335,7 @@ struct wined3d_geometry_shader ...@@ -5327,7 +5335,7 @@ struct wined3d_geometry_shader
unsigned int vertices_out; unsigned int vertices_out;
unsigned int instance_count; unsigned int instance_count;
struct wined3d_stream_output_desc so_desc; const struct wined3d_stream_output_desc *so_desc;
}; };
struct wined3d_pixel_shader struct wined3d_pixel_shader
...@@ -5723,7 +5731,7 @@ static inline BOOL use_transform_feedback(const struct wined3d_state *state) ...@@ -5723,7 +5731,7 @@ static inline BOOL use_transform_feedback(const struct wined3d_state *state)
if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY])) if (!(shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]))
return FALSE; return FALSE;
return shader->u.gs.so_desc.element_count; return !!shader->u.gs.so_desc;
} }
static inline void context_apply_state(struct wined3d_context *context, static inline void context_apply_state(struct wined3d_context *context,
...@@ -5787,8 +5795,8 @@ static inline BOOL can_use_texture_swizzle(const struct wined3d_d3d_info *d3d_in ...@@ -5787,8 +5795,8 @@ static inline BOOL can_use_texture_swizzle(const struct wined3d_d3d_info *d3d_in
static inline BOOL is_rasterization_disabled(const struct wined3d_shader *geometry_shader) static inline BOOL is_rasterization_disabled(const struct wined3d_shader *geometry_shader)
{ {
return geometry_shader return geometry_shader && geometry_shader->u.gs.so_desc
&& geometry_shader->u.gs.so_desc.rasterizer_stream_idx == WINED3D_NO_RASTERIZER_STREAM; && geometry_shader->u.gs.so_desc->rasterizer_stream_idx == WINED3D_NO_RASTERIZER_STREAM;
} }
static inline DWORD wined3d_extract_bits(const DWORD *bitstream, static inline DWORD wined3d_extract_bits(const DWORD *bitstream,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment