Commit c74c8800 authored by Józef Kucia's avatar Józef Kucia Committed by Alexandre Julliard

wined3d: Do not convert SO declaration entries.

parent 04ed44a5
......@@ -24,21 +24,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
static HRESULT osgn_handler(const char *data, DWORD data_size, DWORD tag, void *context)
{
struct wined3d_shader_signature *signature = context;
if (tag != TAG_OSGN && tag != TAG_OSG5)
return S_OK;
if (signature->elements)
{
FIXME("Multiple input signatures.\n");
shader_free_signature(signature);
}
return shader_parse_signature(tag, data, data_size, signature);
}
static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
{
size_t len, max_len;
......@@ -1073,18 +1058,14 @@ static const struct wined3d_parent_ops d3d_geometry_shader_wined3d_parent_ops =
d3d_geometry_shader_wined3d_object_destroyed,
};
static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_output_element *elements,
const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count,
const unsigned int *buffer_strides, unsigned int buffer_stride_count,
const struct wined3d_shader_signature *os, D3D_FEATURE_LEVEL feature_level)
static HRESULT validate_stream_output_entries(const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count,
const unsigned int *buffer_strides, unsigned int buffer_stride_count, D3D_FEATURE_LEVEL feature_level)
{
unsigned int i, j, mask;
unsigned int i, j;
for (i = 0; i < entry_count; ++i)
{
struct wined3d_stream_output_element *e = &elements[i];
const D3D11_SO_DECLARATION_ENTRY *f = &entries[i];
struct wined3d_shader_signature_element *output;
TRACE("Stream: %u, semantic: %s, semantic idx: %u, start component: %u, "
"component count %u, output slot %u.\n",
......@@ -1112,11 +1093,6 @@ static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_o
return E_INVALIDARG;
}
e->stream_idx = f->Stream;
e->component_idx = f->StartComponent;
e->component_count = f->ComponentCount;
e->output_slot = f->OutputSlot;
if (!f->SemanticName)
{
if (f->SemanticIndex)
......@@ -1129,10 +1105,8 @@ static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_o
WARN("Invalid stream output gap %u-%u.\n", f->StartComponent, f->ComponentCount);
return E_INVALIDARG;
}
e->register_idx = WINED3D_STREAM_OUTPUT_GAP;
}
else if ((output = shader_find_signature_element(os, f->SemanticName, f->SemanticIndex, f->Stream)))
else
{
if (f->StartComponent > 3 || f->ComponentCount > 4 || !f->ComponentCount
|| f->StartComponent + f->ComponentCount > 4)
......@@ -1140,29 +1114,6 @@ static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_o
WARN("Invalid component range %u-%u.\n", f->StartComponent, f->ComponentCount);
return E_INVALIDARG;
}
for (j = 0; j < 4; ++j)
{
if ((1u << j) & output->mask)
break;
}
e->component_idx += j;
mask = ((1u << e->component_count) - 1) << e->component_idx;
if ((output->mask & 0xff & mask) != mask)
{
WARN("Invalid component range %u-%u (mask %#x), output mask %#x.\n",
e->component_idx, e->component_count, mask, output->mask & 0xff);
return E_INVALIDARG;
}
e->register_idx = output->register_idx;
TRACE("Register idx: %u, register component idx %u, register mask %#x.\n",
e->register_idx, e->component_idx, mask);
}
else
{
WARN("Failed to find output signature element for stream output entry.\n");
return E_INVALIDARG;
}
}
......@@ -1255,7 +1206,6 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
unsigned int rasterizer_stream)
{
struct wined3d_stream_output_desc so_desc;
struct wined3d_shader_signature signature;
struct wined3d_shader_desc desc;
unsigned int i;
HRESULT hr;
......@@ -1292,40 +1242,22 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
}
}
if (FAILED(hr = validate_stream_output_entries(so_entries, so_entry_count,
buffer_strides, buffer_stride_count, device->feature_level)))
return hr;
desc.byte_code = byte_code;
desc.byte_code_size = byte_code_length;
memset(&so_desc, 0, sizeof(so_desc));
if (so_entries)
{
so_desc.elements = (const struct wined3d_stream_output_element *)so_entries;
so_desc.element_count = so_entry_count;
for (i = 0; i < min(buffer_stride_count, ARRAY_SIZE(so_desc.buffer_strides)); ++i)
so_desc.buffer_strides[i] = buffer_strides[i];
so_desc.buffer_stride_count = buffer_stride_count;
so_desc.rasterizer_stream_idx = rasterizer_stream;
if (!(so_desc.elements = heap_calloc(so_entry_count, sizeof(*so_desc.elements))))
{
ERR("Failed to allocate wined3d stream output element array memory.\n");
return E_OUTOFMEMORY;
}
memset(&signature, 0, sizeof(signature));
if (FAILED(hr = parse_dxbc(byte_code, byte_code_length, osgn_handler, &signature)))
{
ERR("Failed to parse input signature.\n");
heap_free(so_desc.elements);
return E_FAIL;
}
hr = wined3d_so_elements_from_d3d11_so_entries(so_desc.elements,
so_entries, so_entry_count, buffer_strides, buffer_stride_count,
&signature, device->feature_level);
shader_free_signature(&signature);
if (FAILED(hr))
{
heap_free(so_desc.elements);
return hr;
}
}
shader->ID3D11GeometryShader_iface.lpVtbl = &d3d11_geometry_shader_vtbl;
......@@ -1334,10 +1266,8 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader,
wined3d_mutex_lock();
wined3d_private_store_init(&shader->private_store);
hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL,
shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
heap_free(so_desc.elements);
if (FAILED(hr))
if (FAILED(hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL,
shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader)))
{
WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
wined3d_private_store_cleanup(&shader->private_store);
......
......@@ -818,9 +818,10 @@ static void append_transform_feedback_skip_components(const char **varyings,
}
}
static BOOL 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, GLenum buffer_mode)
static BOOL shader_glsl_generate_transform_feedback_varyings(struct wined3d_string_buffer *buffer,
const char **varyings, unsigned int *varying_count,
char *strings, unsigned int *strings_length, GLenum buffer_mode,
const struct wined3d_stream_output_desc *so_desc, const unsigned int *output_register_idx)
{
unsigned int i, buffer_idx, count, length, highest_output_slot, stride;
BOOL have_varyings_to_record = FALSE;
......@@ -847,7 +848,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3
stride += e->component_count;
if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
if (!e->semantic_name)
{
append_transform_feedback_skip_components(varyings, &count,
&strings, &length, buffer, e->component_count);
......@@ -865,12 +866,12 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3
}
string_buffer_sprintf(buffer, "shader_in_out.reg%u_%u_%u",
e->register_idx, e->component_idx, e->component_idx + e->component_count - 1);
output_register_idx[i], e->component_idx, e->component_idx + e->component_count - 1);
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
}
else
{
string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx);
string_buffer_sprintf(buffer, "shader_in_out.reg%u", output_register_idx[i]);
append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
}
......@@ -906,6 +907,7 @@ static BOOL shader_glsl_generate_transform_feedback_varyings(const struct wined3
static void shader_glsl_init_transform_feedback(const struct wined3d_context *context,
struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader)
{
const unsigned int *output_register_idx = shader->u.gs.output_register_idx;
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;
......@@ -927,7 +929,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
for (i = 0; i < so_desc->element_count; ++i)
{
if (so_desc->elements[i].register_idx == WINED3D_STREAM_OUTPUT_GAP)
if (!so_desc->elements[i].semantic_name)
{
FIXME("ARB_transform_feedback3 is needed for stream output gaps.\n");
return;
......@@ -960,7 +962,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
buffer = string_buffer_get(&priv->string_buffers);
if (!shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode))
if (!shader_glsl_generate_transform_feedback_varyings(buffer, NULL, &count, NULL, &length, mode, so_desc, output_register_idx))
{
FIXME("No varyings to record, disabling transform feedback.\n");
shader->u.gs.so_desc.element_count = 0;
......@@ -982,7 +984,7 @@ static void shader_glsl_init_transform_feedback(const struct wined3d_context *co
return;
}
shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL, mode);
shader_glsl_generate_transform_feedback_varyings(buffer, varyings, NULL, strings, NULL, mode, so_desc, output_register_idx);
GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, mode));
checkGLcall("glTransformFeedbackVaryings");
......@@ -7421,7 +7423,8 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
}
static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *priv,
const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc)
const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc,
const unsigned int *output_register_idx)
{
struct wined3d_string_buffer *buffer = &priv->shader_buffer;
unsigned int i;
......@@ -7436,7 +7439,7 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
FIXME("Unhandled stream %u.\n", e->stream_idx);
continue;
}
if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
if (!e->semantic_name)
continue;
if (e->component_idx || e->component_count != 4)
......@@ -7446,11 +7449,11 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
else
shader_addline(buffer, "vec%u", e->component_count);
shader_addline(buffer, " reg%u_%u_%u;\n",
e->register_idx, e->component_idx, e->component_idx + e->component_count - 1);
output_register_idx[i], e->component_idx, e->component_idx + e->component_count - 1);
}
else
{
shader_addline(buffer, "vec4 reg%u;\n", e->register_idx);
shader_addline(buffer, "vec4 reg%u;\n", output_register_idx[i]);
}
}
shader_addline(buffer, "} shader_out;\n");
......@@ -7466,7 +7469,7 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
FIXME("Unhandled stream %u.\n", e->stream_idx);
continue;
}
if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP)
if (!e->semantic_name)
continue;
if (e->component_idx || e->component_count != 4)
......@@ -7477,13 +7480,13 @@ static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *pr
write_mask = ((1u << e->component_count) - 1) << e->component_idx;
shader_glsl_write_mask_to_str(write_mask, str_mask);
shader_addline(buffer, "shader_out.reg%u_%u_%u = outputs[%u]%s;\n",
e->register_idx, e->component_idx, e->component_idx + e->component_count - 1,
e->register_idx, str_mask);
output_register_idx[i], e->component_idx, e->component_idx + e->component_count - 1,
output_register_idx[i], str_mask);
}
else
{
shader_addline(buffer, "shader_out.reg%u = outputs[%u];\n",
e->register_idx, e->register_idx);
output_register_idx[i], output_register_idx[i]);
}
}
shader_addline(buffer, "}\n");
......@@ -8529,7 +8532,8 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
if (is_rasterization_disabled(shader))
{
shader_glsl_generate_stream_output_setup(priv, shader, &shader->u.gs.so_desc);
shader_glsl_generate_stream_output_setup(priv, shader,
&shader->u.gs.so_desc, shader->u.gs.output_register_idx);
}
else
{
......
......@@ -3144,7 +3144,8 @@ static void shader_cleanup(struct wined3d_shader *shader)
}
else if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_GEOMETRY)
{
heap_free(shader->u.gs.so_desc.elements);
heap_free((void *)shader->u.gs.so_desc.elements);
heap_free(shader->u.gs.output_register_idx);
}
heap_free(shader->patch_constant_signature.elements);
......@@ -3728,12 +3729,31 @@ static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_
return WINED3D_OK;
}
static struct wined3d_shader_signature_element *shader_find_signature_element(const struct wined3d_shader_signature *s,
unsigned int stream_idx, const char *semantic_name, unsigned int semantic_idx)
{
struct wined3d_shader_signature_element *e = s->elements;
unsigned int i;
for (i = 0; i < s->element_count; ++i)
{
if (e[i].stream_idx == stream_idx
&& !strcasecmp(e[i].semantic_name, semantic_name)
&& e[i].semantic_idx == semantic_idx)
return &e[i];
}
return NULL;
}
static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
const struct wined3d_stream_output_desc *so_desc)
{
const struct wined3d_shader_frontend *fe = shader->frontend;
const struct wined3d_shader_signature_element *output;
struct wined3d_stream_output_element *elements;
struct wined3d_shader_version shader_version;
unsigned int i, j, mask;
const DWORD *ptr;
void *fe_data;
HRESULT hr;
......@@ -3772,6 +3792,9 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
return hr;
}
if (!(shader->u.gs.output_register_idx = heap_calloc(so_desc->element_count, sizeof(*shader->u.gs.output_register_idx))))
return E_OUTOFMEMORY;
if (!(elements = heap_calloc(so_desc->element_count, sizeof(*elements))))
return E_OUTOFMEMORY;
......@@ -3779,6 +3802,38 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
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)
{
struct wined3d_stream_output_element *e = &elements[i];
if (!e->semantic_name)
continue;
if (!(output = shader_find_signature_element(&shader->output_signature,
e->stream_idx, e->semantic_name, e->semantic_idx)))
{
WARN("Failed to find output signature element for stream output entry.\n");
return E_INVALIDARG;
}
e->semantic_name = output->semantic_name;
shader->u.gs.output_register_idx[i] = output->register_idx;
for (j = 0; j < 4; ++j)
{
if ((1u << j) & output->mask)
break;
}
e->component_idx += j;
mask = ((1u << e->component_count) - 1) << e->component_idx;
if ((output->mask & 0xff & mask) != mask)
{
WARN("Invalid component range %u-%u (mask %#x), output mask %#x.\n",
e->component_idx, e->component_count, mask, output->mask & 0xff);
return E_INVALIDARG;
}
}
return WINED3D_OK;
}
......
......@@ -4198,6 +4198,7 @@ struct wined3d_geometry_shader
unsigned int instance_count;
struct wined3d_stream_output_desc so_desc;
unsigned int *output_register_idx;
};
struct wined3d_pixel_shader
......
......@@ -1574,7 +1574,6 @@ enum wined3d_shader_type
#define WINED3D_OUTPUT_SLOT_UNUSED 0xfffffffe
#define WINED3D_MAX_STREAM_OUTPUT_BUFFERS 4
#define WINED3D_STREAM_OUTPUT_GAP 0xffffffff
#define WINED3D_NO_RASTERIZER_STREAM 0xffffffff
#define WINED3D_VIEW_BUFFER_RAW 0x00000001
......@@ -2060,7 +2059,8 @@ struct wined3d_shader_desc
struct wined3d_stream_output_element
{
unsigned int stream_idx;
unsigned int register_idx;
const char *semantic_name;
unsigned int semantic_idx;
BYTE component_idx;
BYTE component_count;
BYTE output_slot;
......@@ -2068,7 +2068,7 @@ struct wined3d_stream_output_element
struct wined3d_stream_output_desc
{
struct wined3d_stream_output_element *elements;
const struct wined3d_stream_output_element *elements;
unsigned int element_count;
unsigned int buffer_strides[WINED3D_MAX_STREAM_OUTPUT_BUFFERS];
unsigned int buffer_stride_count;
......
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