wined3d: Use the output signature to map SM4 pixel shader outputs to the appropriate register.

Henri Verbeet hverbeet at codeweavers.com
Fri May 8 10:44:25 CDT 2009


---
 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 5c91cbd..29547a8 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 f5ab8b3..206697d 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 9c528d9..3939f59 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 af50c77..ec6d3f0 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 9b001db..33148c8 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 211566a..a626d52 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 4e9f8d5..5cc445d 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 1491b0c..7dba4e3 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 641ca8c..c227e9c 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 db23df9..3845ded 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
     );
-- 
1.6.0.6



--------------020400060100070009080608--



More information about the wine-patches mailing list