From 9a579a43b1769ca3de23062ffc93d994b065b82f Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 8 May 2009 17:44:25 +0200 Subject: [PATCH] wined3d: Use the output signature to map SM4 pixel shader outputs to the appropriate register. --- dlls/d3d10core/device.c | 2 +- dlls/d3d8/device.c | 2 +- dlls/d3d9/pixelshader.c | 3 +- dlls/wined3d/device.c | 9 ++-- dlls/wined3d/pixelshader.c | 7 ++-- dlls/wined3d/shader_sm1.c | 7 +++- dlls/wined3d/shader_sm4.c | 77 +++++++++++++++++++++++++++++++++- dlls/wined3d/vertexshader.c | 7 ++-- dlls/wined3d/wined3d_private.h | 2 +- include/wine/wined3d.idl | 34 ++++++++++++++- 10 files changed, 134 insertions(+), 16 deletions(-) diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c index 5c91cbd5f40..29547a87197 100644 --- a/dlls/d3d10core/device.c +++ b/dlls/d3d10core/device.c @@ -1049,7 +1049,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreatePixelShader(ID3D10Device *if object->refcount = 1; hr = IWineD3DDevice_CreatePixelShader(This->wined3d_device, - shader_code, &object->wined3d_shader, (IUnknown *)object); + shader_code, NULL, &object->wined3d_shader, (IUnknown *)object); if (FAILED(hr)) { ERR("CreatePixelShader failed, hr %#x\n", hr); diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index f5ab8b3a73a..206697d99d4 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -2166,7 +2166,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 i EnterCriticalSection(&d3d8_cs); hr = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, - &object->wineD3DPixelShader, (IUnknown *)object); + NULL, &object->wineD3DPixelShader, (IUnknown *)object); if (FAILED(hr)) { LeaveCriticalSection(&d3d8_cs); diff --git a/dlls/d3d9/pixelshader.c b/dlls/d3d9/pixelshader.c index 9c528d9dba4..3939f5977a8 100644 --- a/dlls/d3d9/pixelshader.c +++ b/dlls/d3d9/pixelshader.c @@ -128,7 +128,8 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9EX iface, object->ref = 1; object->lpVtbl = &Direct3DPixelShader9_Vtbl; EnterCriticalSection(&d3d9_cs); - hrc = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, &object->wineD3DPixelShader , (IUnknown *)object); + hrc = IWineD3DDevice_CreatePixelShader(This->WineD3DDevice, pFunction, NULL, + &object->wineD3DPixelShader, (IUnknown *)object); LeaveCriticalSection(&d3d9_cs); if (hrc != D3D_OK) { diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index af50c77ffea..ec6d3f0422e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2354,7 +2354,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration); } - hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction); + hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction, NULL); if (FAILED(hr)) { WARN("(%p) : Failed to set function, returning %#x\n", iface, hr); @@ -2366,7 +2366,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac return hr; } -static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) { +static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, + const DWORD *pFunction, const struct wined3d_shader_signature *output_signature, + IWineD3DPixelShader **ppPixelShader, IUnknown *parent) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */ HRESULT hr = WINED3D_OK; @@ -2389,7 +2392,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface TRACE("(%p) : Created pixel shader %p\n", This, *ppPixelShader); - hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction); + hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction, output_signature); if (FAILED(hr)) { WARN("(%p) : Failed to set function, returning %#x\n", iface, hr); diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 9b001db65f3..33148c8b9b3 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -204,8 +204,9 @@ static void pshader_set_limits(IWineD3DPixelShaderImpl *This) } } -static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) { - +static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, + const DWORD *pFunction, const struct wined3d_shader_signature *output_signature) +{ IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface; unsigned int i, highest_reg_used = 0, num_regs_used = 0; shader_reg_maps *reg_maps = &This->baseShader.reg_maps; @@ -221,7 +222,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i return WINED3DERR_INVALIDCALL; } This->baseShader.frontend = fe; - This->baseShader.frontend_data = fe->shader_init(pFunction); + This->baseShader.frontend_data = fe->shader_init(pFunction, output_signature); if (!This->baseShader.frontend_data) { FIXME("Failed to initialize frontend.\n"); diff --git a/dlls/wined3d/shader_sm1.c b/dlls/wined3d/shader_sm1.c index 211566a5d1a..a626d52a763 100644 --- a/dlls/wined3d/shader_sm1.c +++ b/dlls/wined3d/shader_sm1.c @@ -410,7 +410,7 @@ static int shader_skip_unrecognized(const struct wined3d_sm1_data *priv, const D return tokens_read; } -static void *shader_sm1_init(const DWORD *byte_code) +static void *shader_sm1_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature) { struct wined3d_sm1_data *priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv)); if (!priv) @@ -419,6 +419,11 @@ static void *shader_sm1_init(const DWORD *byte_code) return NULL; } + if (output_signature) + { + FIXME("SM 1-3 shader shouldn't have output signatures.\n"); + } + switch (*byte_code >> 16) { case WINED3D_SM1_VS: diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c index 4e9f8d5c2da..5cc445db69a 100644 --- a/dlls/wined3d/shader_sm4.c +++ b/dlls/wined3d/shader_sm4.c @@ -71,6 +71,7 @@ struct wined3d_sm4_data { struct wined3d_shader_version shader_version; const DWORD *end; + const struct wined3d_shader_signature *output_signature; }; struct wined3d_sm4_opcode_info @@ -81,6 +82,13 @@ struct wined3d_sm4_opcode_info UINT src_count; }; +struct sysval_map +{ + enum wined3d_sysval_semantic sysval; + WINED3DSHADER_PARAM_REGISTER_TYPE register_type; + UINT register_idx; +}; + static const struct wined3d_sm4_opcode_info opcode_table[] = { {WINED3D_SM4_OP_ADD, WINED3DSIH_ADD, 1, 2}, @@ -100,6 +108,19 @@ static const WINED3DSHADER_PARAM_REGISTER_TYPE register_type_table[] = /* WINED3D_SM4_RT_IMMCONST */ WINED3DSPR_IMMCONST, }; +static const struct sysval_map sysval_map[] = +{ + {WINED3D_SV_DEPTH, WINED3DSPR_DEPTHOUT, 0}, + {WINED3D_SV_TARGET0, WINED3DSPR_COLOROUT, 0}, + {WINED3D_SV_TARGET1, WINED3DSPR_COLOROUT, 1}, + {WINED3D_SV_TARGET2, WINED3DSPR_COLOROUT, 2}, + {WINED3D_SV_TARGET3, WINED3DSPR_COLOROUT, 3}, + {WINED3D_SV_TARGET4, WINED3DSPR_COLOROUT, 4}, + {WINED3D_SV_TARGET5, WINED3DSPR_COLOROUT, 5}, + {WINED3D_SV_TARGET6, WINED3DSPR_COLOROUT, 6}, + {WINED3D_SV_TARGET7, WINED3DSPR_COLOROUT, 7}, +}; + static const struct wined3d_sm4_opcode_info *get_opcode_info(enum wined3d_sm4_opcode opcode) { unsigned int i; @@ -112,7 +133,53 @@ static const struct wined3d_sm4_opcode_info *get_opcode_info(enum wined3d_sm4_op return NULL; } -static void *shader_sm4_init(const DWORD *byte_code) +static void map_sysval(enum wined3d_sysval_semantic sysval, struct wined3d_shader_register *reg) +{ + unsigned int i; + + for (i = 0; i < sizeof(sysval_map) / sizeof(*sysval_map); ++i) + { + if (sysval == sysval_map[i].sysval) + { + reg->type = sysval_map[i].register_type; + reg->idx = sysval_map[i].register_idx; + } + } +} + +static void map_register(struct wined3d_sm4_data *priv, struct wined3d_shader_register *reg) +{ + switch (priv->shader_version.type) + { + case WINED3D_SHADER_TYPE_PIXEL: + if (reg->type == WINED3DSPR_OUTPUT) + { + unsigned int i; + const struct wined3d_shader_signature *s = priv->output_signature; + + if (!s) + { + ERR("Shader has no output signature, unable to map register.\n"); + break; + } + + for (i = 0; i < s->element_count; ++i) + { + if (s->elements[i].register_idx == reg->idx) + { + map_sysval(s->elements[i].sysval_semantic, reg); + break; + } + } + } + break; + + default: + break; + } +} + +static void *shader_sm4_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature) { struct wined3d_sm4_data *priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv)); if (!priv) @@ -121,6 +188,8 @@ static void *shader_sm4_init(const DWORD *byte_code) return NULL; } + priv->output_signature = output_signature; + return priv; } @@ -193,6 +262,7 @@ static void shader_sm4_read_opcode(void *data, const DWORD **ptr, struct wined3d static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr) { + struct wined3d_sm4_data *priv = data; DWORD token = *(*ptr)++; enum wined3d_sm4_register_type register_type; @@ -240,11 +310,14 @@ static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wine src_param->modifiers = 0; src_param->reg.rel_addr = NULL; + + map_register(priv, &src_param->reg); } static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr) { + struct wined3d_sm4_data *priv = data; DWORD token = *(*ptr)++; UINT register_idx = *(*ptr)++; enum wined3d_sm4_register_type register_type; @@ -265,6 +338,8 @@ static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wine dst_param->modifiers = 0; dst_param->shift = 0; dst_param->reg.rel_addr = NULL; + + map_register(priv, &dst_param->reg); } static void shader_sm4_read_semantic(const DWORD **ptr, struct wined3d_shader_semantic *semantic) diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 1491b0c725b..7dba4e37aaf 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -243,8 +243,9 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader* * shader is first used. The reason for this is that we need the vertex * declaration the shader will be used with in order to determine if * the data in a register is of type D3DCOLOR, and needs swizzling. */ -static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, CONST DWORD *pFunction) { - +static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, + const DWORD *pFunction, const struct wined3d_shader_signature *output_signature) +{ IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; const struct wined3d_shader_frontend *fe; @@ -260,7 +261,7 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader return WINED3DERR_INVALIDCALL; } This->baseShader.frontend = fe; - This->baseShader.frontend_data = fe->shader_init(pFunction); + This->baseShader.frontend_data = fe->shader_init(pFunction, output_signature); if (!This->baseShader.frontend_data) { FIXME("Failed to initialize frontend.\n"); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 641ca8c0b05..c227e9cbe6a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -697,7 +697,7 @@ struct wined3d_shader_semantic struct wined3d_shader_frontend { - void *(*shader_init)(const DWORD *ptr); + void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature); void (*shader_free)(void *data); void (*shader_read_header)(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version); void (*shader_read_opcode)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins, UINT *param_size); diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl index db23df921cb..3845ded7bb9 100644 --- a/include/wine/wined3d.idl +++ b/include/wine/wined3d.idl @@ -848,6 +848,19 @@ typedef enum _WINED3DSURFTYPE SURFACE_GDI, /* User surface. No 3D, DirectDraw rendering with GDI */ } WINED3DSURFTYPE; +enum wined3d_sysval_semantic +{ + WINED3D_SV_DEPTH = 0xffffffff, + WINED3D_SV_TARGET0 = 0, + WINED3D_SV_TARGET1 = 1, + WINED3D_SV_TARGET2 = 2, + WINED3D_SV_TARGET3 = 3, + WINED3D_SV_TARGET4 = 4, + WINED3D_SV_TARGET5 = 5, + WINED3D_SV_TARGET6 = 6, + WINED3D_SV_TARGET7 = 7, +}; + const UINT WINED3DCOLORWRITEENABLE_RED = (1<<0); const UINT WINED3DCOLORWRITEENABLE_GREEN = (1<<1); const UINT WINED3DCOLORWRITEENABLE_BLUE = (1<<2); @@ -2117,6 +2130,23 @@ struct wined3d_buffer_desc UINT misc_flags; }; +struct wined3d_shader_signature_element +{ + const char *semantic_name; + UINT semantic_idx; + enum wined3d_sysval_semantic sysval_semantic; + DWORD component_type; + UINT register_idx; + DWORD mask; +}; + +struct wined3d_shader_signature +{ + UINT element_count; + struct wined3d_shader_signature_element *elements; + char *string_data; +}; + interface IWineD3DResource; interface IWineD3DSurface; interface IWineD3DVolume; @@ -2823,7 +2853,8 @@ interface IWineD3DBuffer : IWineD3DResource interface IWineD3DBaseShader : IWineD3DBase { HRESULT SetFunction( - [in] const DWORD *function + [in] const DWORD *function, + [in] const struct wined3d_shader_signature *output_signature ); } @@ -2991,6 +3022,7 @@ interface IWineD3DDevice : IWineD3DBase ); HRESULT CreatePixelShader( [in] const DWORD *function, + [in] const struct wined3d_shader_signature *output_signature, [out] IWineD3DPixelShader **shader, [in] IUnknown *parent );