[PATCH 1/5] wined3d: Copy the shader byte-code before initialising the front-end.

Henri Verbeet hverbeet at codeweavers.com
Thu Feb 23 01:10:25 CST 2017


This fixes a regression introduced by commit
12f5887a2358b4f91a882eeac57c9f1dd28c50ba.

Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/shader.c | 88 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 58 insertions(+), 30 deletions(-)

diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 519d029..3b5d6ee 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -866,7 +866,7 @@ static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HAN
 /* Note that this does not count the loop register as an address register. */
 static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe,
         struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature *input_signature,
-        struct wined3d_shader_signature *output_signature, const DWORD *byte_code, DWORD constf_size)
+        struct wined3d_shader_signature *output_signature, DWORD constf_size)
 {
     struct wined3d_shader_signature_element input_signature_elements[max(MAX_ATTRIBS, MAX_REG_INPUT)];
     struct wined3d_shader_signature_element output_signature_elements[MAX_REG_OUTPUT];
@@ -1412,8 +1412,6 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
     if (shader_version.major < 2 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
         reg_maps->rt_mask |= (1u << 0);
 
-    shader->functionLength = ((const char *)ptr - (const char *)byte_code);
-
     if (input_signature->elements)
     {
         for (i = 0; i < input_signature->element_count; ++i)
@@ -2856,9 +2854,8 @@ const struct wined3d_shader_backend_ops none_shader_backend =
     shader_none_has_ffp_proj_control,
 };
 
-static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *byte_code,
-        size_t byte_code_size, enum wined3d_shader_byte_code_format format,
-        DWORD float_const_count, enum wined3d_shader_type type, unsigned int max_version)
+static HRESULT shader_set_function(struct wined3d_shader *shader, DWORD float_const_count,
+        enum wined3d_shader_type type, unsigned int max_version)
 {
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     const struct wined3d_shader_frontend *fe;
@@ -2866,24 +2863,12 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     unsigned int backend_version;
     const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
 
-    TRACE("shader %p, byte_code %p, byte_code_size %#lx, format %#x, "
-            "float_const_count %u, type %#x, max_version %u.\n",
-            shader, byte_code, (long)byte_code_size, format, float_const_count, type, max_version);
-
-    list_init(&shader->constantsF);
-    list_init(&shader->constantsB);
-    list_init(&shader->constantsI);
-    shader->lconst_inf_or_nan = FALSE;
-    list_init(&reg_maps->indexable_temps);
+    TRACE("shader %p, float_const_count %u, type %#x, max_version %u.\n",
+            shader, float_const_count, type, max_version);
 
-    if (!(fe = shader_select_frontend(format)))
-    {
-        FIXME("Unable to find frontend for shader.\n");
-        return WINED3DERR_INVALIDCALL;
-    }
-    shader->frontend = fe;
-    shader->frontend_data = fe->shader_init(byte_code, byte_code_size, &shader->output_signature);
-    if (!shader->frontend_data)
+    fe = shader->frontend;
+    if (!(shader->frontend_data = fe->shader_init(shader->function,
+            shader->functionLength, &shader->output_signature)))
     {
         FIXME("Failed to initialize frontend.\n");
         return WINED3DERR_INVALIDCALL;
@@ -2895,7 +2880,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
 
     /* Second pass: figure out which registers are used, what the semantics are, etc. */
     if (FAILED(hr = shader_get_registers_used(shader, fe, reg_maps, &shader->input_signature,
-            &shader->output_signature, byte_code, float_const_count)))
+            &shader->output_signature, float_const_count)))
         return hr;
 
     if (reg_maps->shader_version.type != type)
@@ -2939,10 +2924,6 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (!(shader->function = HeapAlloc(GetProcessHeap(), 0, shader->functionLength)))
-        return E_OUTOFMEMORY;
-    memcpy(shader->function, byte_code, shader->functionLength);
-
     return WINED3D_OK;
 }
 
@@ -3145,14 +3126,24 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
         void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     struct wined3d_shader_signature_element *e;
+    size_t byte_code_size;
     SIZE_T total, len;
     unsigned int i;
     HRESULT hr;
     char *ptr;
 
+    TRACE("byte_code %p, byte_code_size %#lx, format %#x, max_version %#x.\n",
+            desc->byte_code, (long)desc->byte_code_size, desc->format, desc->max_version);
+
     if (!desc->byte_code)
         return WINED3DERR_INVALIDCALL;
 
+    if (!(shader->frontend = shader_select_frontend(desc->format)))
+    {
+        FIXME("Unable to find frontend for shader.\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
     shader->ref = 1;
     shader->device = device;
     shader->parent = parent;
@@ -3194,10 +3185,47 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
     }
 
     list_init(&shader->linked_programs);
+    list_init(&shader->constantsF);
+    list_init(&shader->constantsB);
+    list_init(&shader->constantsI);
+    shader->lconst_inf_or_nan = FALSE;
+    list_init(&shader->reg_maps.indexable_temps);
     list_add_head(&device->shaders, &shader->shader_list_entry);
 
-    if (FAILED(hr = shader_set_function(shader, desc->byte_code, desc->byte_code_size,
-            desc->format, float_const_count, type, desc->max_version)))
+    byte_code_size = desc->byte_code_size;
+    if (byte_code_size == ~(size_t)0)
+    {
+        const struct wined3d_shader_frontend *fe = shader->frontend;
+        struct wined3d_shader_version shader_version;
+        struct wined3d_shader_instruction ins;
+        const DWORD *ptr;
+        void *fe_data;
+
+        if (!(fe_data = fe->shader_init(desc->byte_code, byte_code_size, &shader->output_signature)))
+        {
+            WARN("Failed to initialise frontend data.\n");
+            shader_cleanup(shader);
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        fe->shader_read_header(fe_data, &ptr, &shader_version);
+        while (!fe->shader_is_end(fe_data, &ptr))
+            fe->shader_read_instruction(fe_data, &ptr, &ins);
+
+        fe->shader_free(fe_data);
+
+        byte_code_size = (ptr - desc->byte_code) * sizeof(*ptr);
+    }
+
+    if (!(shader->function = HeapAlloc(GetProcessHeap(), 0, byte_code_size)))
+    {
+        shader_cleanup(shader);
+        return E_OUTOFMEMORY;
+    }
+    memcpy(shader->function, desc->byte_code, byte_code_size);
+    shader->functionLength = byte_code_size;
+
+    if (FAILED(hr = shader_set_function(shader, float_const_count, type, desc->max_version)))
     {
         WARN("Failed to set function, hr %#x.\n", hr);
         shader_cleanup(shader);
-- 
2.1.4




More information about the wine-patches mailing list