From: Henri Verbeet Subject: [PATCH 1/5] wined3d: Copy the shader byte-code before initialising the front-end. Message-Id: <1487833829-21692-1-git-send-email-hverbeet@codeweavers.com> Date: Thu, 23 Feb 2017 08:10:25 +0100 This fixes a regression introduced by commit 12f5887a2358b4f91a882eeac57c9f1dd28c50ba. Signed-off-by: Henri Verbeet --- 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(®_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