[PATCH 2/2] wined3d: Do not convert SO declaration entries.

Józef Kucia jkucia at codeweavers.com
Thu Feb 7 11:26:19 CST 2019


Signed-off-by: Józef Kucia <jkucia at 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;
-- 
2.19.2




More information about the wine-devel mailing list