Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Mainly for vkd3d-shader backend.
--- dlls/d3d11/shader.c | 92 ++++------------------------------ dlls/wined3d/glsl_shader.c | 40 ++++++++------- dlls/wined3d/shader.c | 57 ++++++++++++++++++++- dlls/wined3d/wined3d_private.h | 1 + include/wine/wined3d.h | 6 +-- 5 files changed, 93 insertions(+), 103 deletions(-)
diff --git a/dlls/d3d11/shader.c b/dlls/d3d11/shader.c index 455ff9f7c8c8..259ac331dbfe 100644 --- a/dlls/d3d11/shader.c +++ b/dlls/d3d11/shader.c @@ -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); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index db6760ebc303..ba2c62165b53 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -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 { diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index e11a37cf078f..a52b9a1c83a9 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -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; }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 66a2ee4e418e..f44dccbe6c1e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4191,6 +4191,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 diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index e09e4e1fce2d..a58dd87ee7d0 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -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;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=47289
Your paranoid android.
=== debian9 (32 bit report) ===
d3d11: Unhandled exception: page fault on execute access to 0x00000000 in 32-bit code (0x00000000).
Report errors: d3d11:d3d11 crashed (c0000005)
=== debian9 (32 bit Chinese:China report) ===
d3d11: Unhandled exception: page fault on execute access to 0x00000000 in 32-bit code (0x00000000).
=== debian9 (32 bit WoW report) ===
d3d11: Unhandled exception: page fault on read access to 0x00000001 in 32-bit code (0x7ecf9f6d).
=== debian9 (64 bit WoW report) ===
d3d11: d3d11.c:5593: Test failed: Got unexpected hr 0x8876086a. d3d11.c:16715: Test failed: Got {-1.00787401e+00, 0.00000000e+00, 1.00000000e+00, 5.03937006e-01}, expected {-1.00000000e+00, 0.00000000e+00, 1.00000000e+00, 5.03937006e-01} at (0, 0), sub-resource 0.