diff --git a/dlls/d3d10core/d3d10core_private.h b/dlls/d3d10core/d3d10core_private.h index 80eafe23c5d..845ddab544a 100644 --- a/dlls/d3d10core/d3d10core_private.h +++ b/dlls/d3d10core/d3d10core_private.h @@ -50,6 +50,7 @@ struct d3d10_device; struct d3d10_shader_info { const DWORD *shader_code; + struct wined3d_shader_signature *input_signature; struct wined3d_shader_signature *output_signature; }; diff --git a/dlls/d3d10core/shader.c b/dlls/d3d10core/shader.c index 62f1e97fec6..10000544290 100644 --- a/dlls/d3d10core/shader.c +++ b/dlls/d3d10core/shader.c @@ -29,11 +29,16 @@ static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void * struct d3d10_shader_info *shader_info = ctx; HRESULT hr; - switch(tag) + switch (tag) { + case TAG_ISGN: + if (FAILED(hr = shader_parse_signature(data, data_size, shader_info->input_signature))) + return hr; + break; + case TAG_OSGN: - hr = shader_parse_signature(data, data_size, shader_info->output_signature); - if (FAILED(hr)) return hr; + if (FAILED(hr = shader_parse_signature(data, data_size, shader_info->output_signature))) + return hr; break; case TAG_SHDR: @@ -53,6 +58,7 @@ static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, st HRESULT hr; shader_info->shader_code = NULL; + memset(shader_info->input_signature, 0, sizeof(*shader_info->input_signature)); memset(shader_info->output_signature, 0, sizeof(*shader_info->output_signature)); hr = parse_dxbc(dxbc, dxbc_length, shdr_handler, shader_info); @@ -61,6 +67,7 @@ static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, st if (FAILED(hr)) { ERR("Failed to parse shader, hr %#x\n", hr); + shader_free_signature(shader_info->input_signature); shader_free_signature(shader_info->output_signature); } @@ -243,22 +250,30 @@ HRESULT d3d10_vertex_shader_init(struct d3d10_vertex_shader *shader, struct d3d1 const void *byte_code, SIZE_T byte_code_length) { struct wined3d_shader_signature output_signature; + struct wined3d_shader_signature input_signature; struct d3d10_shader_info shader_info; + struct wined3d_shader_desc desc; HRESULT hr; shader->ID3D10VertexShader_iface.lpVtbl = &d3d10_vertex_shader_vtbl; shader->refcount = 1; + shader_info.input_signature = &input_signature; shader_info.output_signature = &output_signature; - hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info); - if (FAILED(hr)) + if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info))) { ERR("Failed to extract shader, hr %#x.\n", hr); return hr; } - hr = wined3d_shader_create_vs(device->wined3d_device, shader_info.shader_code, - &output_signature, shader, &d3d10_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader, 4); + desc.byte_code = shader_info.shader_code; + desc.input_signature = &input_signature; + desc.output_signature = &output_signature; + desc.max_version = 4; + + hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader, + &d3d10_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader); + shader_free_signature(&input_signature); shader_free_signature(&output_signature); if (FAILED(hr)) { @@ -391,22 +406,30 @@ HRESULT d3d10_geometry_shader_init(struct d3d10_geometry_shader *shader, struct const void *byte_code, SIZE_T byte_code_length) { struct wined3d_shader_signature output_signature; + struct wined3d_shader_signature input_signature; struct d3d10_shader_info shader_info; + struct wined3d_shader_desc desc; HRESULT hr; shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl; shader->refcount = 1; + shader_info.input_signature = &input_signature; shader_info.output_signature = &output_signature; - hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info); - if (FAILED(hr)) + if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info))) { ERR("Failed to extract shader, hr %#x.\n", hr); return hr; } - hr = wined3d_shader_create_gs(device->wined3d_device, shader_info.shader_code, - &output_signature, shader, &d3d10_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader, 4); + desc.byte_code = shader_info.shader_code; + desc.input_signature = &input_signature; + desc.output_signature = &output_signature; + desc.max_version = 4; + + hr = wined3d_shader_create_gs(device->wined3d_device, &desc, shader, + &d3d10_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader); + shader_free_signature(&input_signature); shader_free_signature(&output_signature); if (FAILED(hr)) { @@ -554,22 +577,30 @@ HRESULT d3d10_pixel_shader_init(struct d3d10_pixel_shader *shader, struct d3d10_ const void *byte_code, SIZE_T byte_code_length) { struct wined3d_shader_signature output_signature; + struct wined3d_shader_signature input_signature; struct d3d10_shader_info shader_info; + struct wined3d_shader_desc desc; HRESULT hr; shader->ID3D10PixelShader_iface.lpVtbl = &d3d10_pixel_shader_vtbl; shader->refcount = 1; + shader_info.input_signature = &input_signature; shader_info.output_signature = &output_signature; - hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info); - if (FAILED(hr)) + if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info))) { ERR("Failed to extract shader, hr %#x.\n", hr); return hr; } - hr = wined3d_shader_create_ps(device->wined3d_device, shader_info.shader_code, - &output_signature, shader, &d3d10_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader, 4); + desc.byte_code = shader_info.shader_code; + desc.input_signature = &input_signature; + desc.output_signature = &output_signature; + desc.max_version = 4; + + hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader, + &d3d10_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader); + shader_free_signature(&input_signature); shader_free_signature(&output_signature); if (FAILED(hr)) { diff --git a/dlls/d3d8/shader.c b/dlls/d3d8/shader.c index 7d61fd6fb2a..a0bb3179c07 100644 --- a/dlls/d3d8/shader.c +++ b/dlls/d3d8/shader.c @@ -111,11 +111,19 @@ HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_d if (byte_code) { - if (usage) FIXME("Usage %#x not implemented.\n", usage); + struct wined3d_shader_desc desc; + + if (usage) + FIXME("Usage %#x not implemented.\n", usage); + + desc.byte_code = byte_code; + desc.input_signature = NULL; + desc.output_signature = NULL; + desc.max_version = 1; wined3d_mutex_lock(); - hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL /* output signature */, - shader, &d3d8_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 1); + hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader, + &d3d8_vertexshader_wined3d_parent_ops, &shader->wined3d_shader); wined3d_mutex_unlock(); if (FAILED(hr)) { @@ -152,13 +160,19 @@ static const struct wined3d_parent_ops d3d8_pixelshader_wined3d_parent_ops = HRESULT d3d8_pixel_shader_init(struct d3d8_pixel_shader *shader, struct d3d8_device *device, const DWORD *byte_code, DWORD shader_handle) { + struct wined3d_shader_desc desc; HRESULT hr; shader->handle = shader_handle; + desc.byte_code = byte_code; + desc.input_signature = NULL; + desc.output_signature = NULL; + desc.max_version = 1; + wined3d_mutex_lock(); - hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader, - &d3d8_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 1); + hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader, + &d3d8_pixelshader_wined3d_parent_ops, &shader->wined3d_shader); wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/dlls/d3d9/shader.c b/dlls/d3d9/shader.c index e65f485b2e3..0c2c881a9ae 100644 --- a/dlls/d3d9/shader.c +++ b/dlls/d3d9/shader.c @@ -136,14 +136,20 @@ static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops = HRESULT vertexshader_init(struct d3d9_vertexshader *shader, struct d3d9_device *device, const DWORD *byte_code) { + struct wined3d_shader_desc desc; HRESULT hr; shader->refcount = 1; shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl; + desc.byte_code = byte_code; + desc.input_signature = NULL; + desc.output_signature = NULL; + desc.max_version = 3; + wined3d_mutex_lock(); - hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL, - shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 3); + hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader, + &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader); wined3d_mutex_unlock(); if (FAILED(hr)) { @@ -280,14 +286,20 @@ static const struct wined3d_parent_ops d3d9_pixelshader_wined3d_parent_ops = HRESULT pixelshader_init(struct d3d9_pixelshader *shader, struct d3d9_device *device, const DWORD *byte_code) { + struct wined3d_shader_desc desc; HRESULT hr; shader->refcount = 1; shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl; + desc.byte_code = byte_code; + desc.input_signature = NULL; + desc.output_signature = NULL; + desc.max_version = 3; + wined3d_mutex_lock(); - hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader, - &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 3); + hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader, + &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader); wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 230b82c60c6..7a98dd85092 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -1978,8 +1978,7 @@ BOOL vshader_get_input(const struct wined3d_shader *shader, } static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_device *device, - const DWORD *byte_code, const struct wined3d_shader_signature *output_signature, - void *parent, const struct wined3d_parent_ops *parent_ops, unsigned int max_version) + const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) { struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; unsigned int i; @@ -1987,12 +1986,12 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d WORD map; const DWORD vs_uniform_count = device->adapter->d3d_info.limits.vs_uniform_count; - if (!byte_code) return WINED3DERR_INVALIDCALL; + if (!desc->byte_code) + return WINED3DERR_INVALIDCALL; shader_init(shader, device, parent, parent_ops); - hr = shader_set_function(shader, byte_code, output_signature, vs_uniform_count, - WINED3D_SHADER_TYPE_VERTEX, max_version); - if (FAILED(hr)) + if (FAILED(hr = shader_set_function(shader, desc->byte_code, desc->output_signature, + vs_uniform_count, WINED3D_SHADER_TYPE_VERTEX, desc->max_version))) { WARN("Failed to set function, hr %#x.\n", hr); shader_cleanup(shader); @@ -2010,16 +2009,16 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d shader->u.vs.attributes[i].usage_idx = shader->input_signature[i].semantic_idx; } - if (output_signature) + if (desc->output_signature) { struct wined3d_shader_signature_element *e; SIZE_T total, len; char *ptr; total = 0; - for (i = 0; i < output_signature->element_count; ++i) + for (i = 0; i < desc->output_signature->element_count; ++i) { - e = &output_signature->elements[i]; + e = &desc->output_signature->elements[i]; len = strlen(e->semantic_name); if (len >= ~(SIZE_T)0 - total) { @@ -2037,9 +2036,9 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d } ptr = shader->signature_strings; - for (i = 0; i < output_signature->element_count; ++i) + for (i = 0; i < desc->output_signature->element_count; ++i) { - e = &output_signature->elements[i]; + e = &desc->output_signature->elements[i]; reg_maps->output_registers |= 1 << e->register_idx; shader->output_signature[e->register_idx] = *e; @@ -2057,15 +2056,13 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d } static HRESULT geometryshader_init(struct wined3d_shader *shader, struct wined3d_device *device, - const DWORD *byte_code, const struct wined3d_shader_signature *output_signature, - void *parent, const struct wined3d_parent_ops *parent_ops, unsigned int max_version) + const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) { HRESULT hr; shader_init(shader, device, parent, parent_ops); - hr = shader_set_function(shader, byte_code, output_signature, 0, - WINED3D_SHADER_TYPE_GEOMETRY, max_version); - if (FAILED(hr)) + if (FAILED(hr = shader_set_function(shader, desc->byte_code, desc->output_signature, + 0, WINED3D_SHADER_TYPE_GEOMETRY, desc->max_version))) { WARN("Failed to set function, hr %#x.\n", hr); shader_cleanup(shader); @@ -2252,20 +2249,19 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 } static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_device *device, - const DWORD *byte_code, const struct wined3d_shader_signature *output_signature, - void *parent, const struct wined3d_parent_ops *parent_ops, unsigned int max_version) + const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; unsigned int i, highest_reg_used = 0, num_regs_used = 0; HRESULT hr; const DWORD ps_uniform_count = device->adapter->d3d_info.limits.ps_uniform_count; - if (!byte_code) return WINED3DERR_INVALIDCALL; + if (!desc->byte_code) + return WINED3DERR_INVALIDCALL; shader_init(shader, device, parent, parent_ops); - hr = shader_set_function(shader, byte_code, output_signature, ps_uniform_count, - WINED3D_SHADER_TYPE_PIXEL, max_version); - if (FAILED(hr)) + if (FAILED(hr = shader_set_function(shader, desc->byte_code, desc->output_signature, + ps_uniform_count, WINED3D_SHADER_TYPE_PIXEL, desc->max_version))) { WARN("Failed to set function, hr %#x.\n", hr); shader_cleanup(shader); @@ -2314,6 +2310,46 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de shader->load_local_constsF = shader->lconst_inf_or_nan; + if (desc->input_signature) + { + struct wined3d_shader_signature_element *e; + SIZE_T total, len; + char *ptr; + + total = 0; + for (i = 0; i < desc->input_signature->element_count; ++i) + { + e = &desc->input_signature->elements[i]; + len = strlen(e->semantic_name); + if (len >= ~(SIZE_T)0 - total) + { + shader_cleanup(shader); + return E_OUTOFMEMORY; + } + + total += len + 1; + } + + if (!(shader->signature_strings = HeapAlloc(GetProcessHeap(), 0, total))) + { + shader_cleanup(shader); + return E_OUTOFMEMORY; + } + ptr = shader->signature_strings; + + for (i = 0; i < desc->input_signature->element_count; ++i) + { + e = &desc->input_signature->elements[i]; + shader->reg_maps.input_registers |= 1 << e->register_idx; + shader->input_signature[e->register_idx] = *e; + + len = strlen(e->semantic_name); + memcpy(ptr, e->semantic_name, len + 1); + shader->output_signature[e->register_idx].semantic_name = ptr; + ptr += len + 1; + } + } + return WINED3D_OK; } @@ -2347,22 +2383,20 @@ void pixelshader_update_samplers(struct wined3d_shader *shader, WORD tex_types) } } -HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const DWORD *byte_code, - const struct wined3d_shader_signature *output_signature, void *parent, - const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version) +HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const struct wined3d_shader_desc *desc, + void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader) { struct wined3d_shader *object; HRESULT hr; - TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n", - device, byte_code, output_signature, parent, parent_ops, shader); + TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", + device, desc, parent, parent_ops, shader); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; - hr = geometryshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version); - if (FAILED(hr)) + if (FAILED(hr = geometryshader_init(object, device, desc, parent, parent_ops))) { WARN("Failed to initialize geometry shader, hr %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); @@ -2375,22 +2409,20 @@ HRESULT CDECL wined3d_shader_create_gs(struct wined3d_device *device, const DWOR return WINED3D_OK; } -HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const DWORD *byte_code, - const struct wined3d_shader_signature *output_signature, void *parent, - const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version) +HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const struct wined3d_shader_desc *desc, + void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader) { struct wined3d_shader *object; HRESULT hr; - TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n", - device, byte_code, output_signature, parent, parent_ops, shader); + TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", + device, desc, parent, parent_ops, shader); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; - hr = pixelshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version); - if (FAILED(hr)) + if (FAILED(hr = pixelshader_init(object, device, desc, parent, parent_ops))) { WARN("Failed to initialize pixel shader, hr %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); @@ -2403,22 +2435,20 @@ HRESULT CDECL wined3d_shader_create_ps(struct wined3d_device *device, const DWOR return WINED3D_OK; } -HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const DWORD *byte_code, - const struct wined3d_shader_signature *output_signature, void *parent, - const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version) +HRESULT CDECL wined3d_shader_create_vs(struct wined3d_device *device, const struct wined3d_shader_desc *desc, + void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader) { struct wined3d_shader *object; HRESULT hr; - TRACE("device %p, byte_code %p, output_signature %p, parent %p, parent_ops %p, shader %p.\n", - device, byte_code, output_signature, parent, parent_ops, shader); + TRACE("device %p, desc %p, parent %p, parent_ops %p, shader %p.\n", + device, desc, parent, parent_ops, shader); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) return E_OUTOFMEMORY; - hr = vertexshader_init(object, device, byte_code, output_signature, parent, parent_ops, max_version); - if (FAILED(hr)) + if (FAILED(hr = vertexshader_init(object, device, desc, parent, parent_ops))) { WARN("Failed to initialize vertex shader, hr %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index e7652244b92..97852775cfa 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1972,6 +1972,14 @@ struct wined3d_shader_signature struct wined3d_shader_signature_element *elements; }; +struct wined3d_shader_desc +{ + const DWORD *byte_code; + const struct wined3d_shader_signature *input_signature; + const struct wined3d_shader_signature *output_signature; + unsigned int max_version; +}; + struct wined3d_parent_ops { void (__stdcall *wined3d_object_destroyed)(void *parent); @@ -2411,15 +2419,12 @@ ULONG __cdecl wined3d_sampler_decref(struct wined3d_sampler *sampler); void * __cdecl wined3d_sampler_get_parent(const struct wined3d_sampler *sampler); ULONG __cdecl wined3d_sampler_incref(struct wined3d_sampler *sampler); -HRESULT __cdecl wined3d_shader_create_gs(struct wined3d_device *device, const DWORD *byte_code, - const struct wined3d_shader_signature *output_signature, void *parent, - const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version); -HRESULT __cdecl wined3d_shader_create_ps(struct wined3d_device *device, const DWORD *byte_code, - const struct wined3d_shader_signature *output_signature, void *parent, - const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version); -HRESULT __cdecl wined3d_shader_create_vs(struct wined3d_device *device, const DWORD *byte_code, - const struct wined3d_shader_signature *output_signature, void *parent, - const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader, unsigned int max_version); +HRESULT __cdecl wined3d_shader_create_gs(struct wined3d_device *device, const struct wined3d_shader_desc *desc, + void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader); +HRESULT __cdecl wined3d_shader_create_ps(struct wined3d_device *device, const struct wined3d_shader_desc *desc, + void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader); +HRESULT __cdecl wined3d_shader_create_vs(struct wined3d_device *device, const struct wined3d_shader_desc *desc, + void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader **shader); ULONG __cdecl wined3d_shader_decref(struct wined3d_shader *shader); HRESULT __cdecl wined3d_shader_get_byte_code(const struct wined3d_shader *shader, void *byte_code, UINT *byte_code_size);