[PATCH] d3dx9_36: Implement D3DXGetShaderInputSemantics + tests.

Matteo Bruni matteo.mystral at gmail.com
Tue Jun 11 17:17:13 CDT 2013


2013/6/11 Christian Costa <titan.costa at gmail.com>:
> Fixes bug 22682.
> ---
>  dlls/d3dx9_36/d3dx9_36.spec  |    2 +-
>  dlls/d3dx9_36/shader.c       |   50 ++++++++++++++++++++++++++++++++++++++
>  dlls/d3dx9_36/tests/shader.c |   55 ++++++++++++++++++++++++++++++++++++++++++
>  include/d3dx9shader.h        |    1 +
>  4 files changed, 107 insertions(+), 1 deletion(-)
>
> diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
> index f2c229a..0f1387e 100644
> --- a/dlls/d3dx9_36/d3dx9_36.spec
> +++ b/dlls/d3dx9_36/d3dx9_36.spec
> @@ -159,7 +159,7 @@
>  @ stdcall D3DXGetPixelShaderProfile(ptr)
>  @ stdcall D3DXGetShaderConstantTable(ptr ptr)
>  @ stdcall D3DXGetShaderConstantTableEx(ptr long ptr)
> -@ stub D3DXGetShaderInputSemantics(ptr ptr ptr)
> +@ stdcall D3DXGetShaderInputSemantics(ptr ptr ptr)
>  @ stub D3DXGetShaderOutputSemantics(ptr ptr ptr)
>  @ stdcall D3DXGetShaderSamplers(ptr ptr ptr)
>  @ stdcall D3DXGetShaderSize(ptr)
> diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
> index 75bc9b5..3b71b4b 100644
> --- a/dlls/d3dx9_36/shader.c
> +++ b/dlls/d3dx9_36/shader.c
> @@ -1,6 +1,7 @@
>  /*
>   * Copyright 2008 Luis Busquets
>   * Copyright 2009 Matteo Bruni
> + * Copyright 2010, 2013 Christian Costa
>   * Copyright 2011 Travis Athougies
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -1778,3 +1779,52 @@ HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **sample
>
>      return D3D_OK;
>  }
> +
> +HRESULT WINAPI D3DXGetShaderInputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count)
> +{
> +    const DWORD *ptr = byte_code;
> +    UINT i = 0;
> +
> +    TRACE("byte_code = %p, semantics = %p, count = %p\n", byte_code, semantics, count);
> +
> +    if (!byte_code)
> +        return D3DERR_INVALIDCALL;
> +
> +    TRACE("Shader version: %#x\n", *ptr);
> +
> +    /* Look for the END token, skipping the VERSION token */
> +    while (*++ptr != D3DSIO_END)

I think you should be a bit more careful in skipping non-opcode
DWORDs, otherwise you could e.g. potentially match with constants from
DEF instructions - very unlikely to happen in practice, sure, but
since it can be easily avoided, why not?
Take a look at shader_skip_opcode() from wined3d/shader_sm1.c. You can
probably get away without having to write a table with the parameters
count for each SM1 opcode by just skipping DWORDs with the most
significant bit set (see shader_skip_unrecognized() from the same
file). Of course you still have to special case DEF but that should be
it.

> +    {
> +        /* Skip comments */
> +        if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
> +        {
> +            ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
> +        }
> +        else if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_DCL)
> +        {
> +            DWORD param1 = *++ptr;
> +            DWORD param2 = *++ptr;
> +            DWORD usage = param1 & 0x1f;
> +            DWORD usage_index = (param1 >> 16) & 0xf;
> +            DWORD reg_type = (((param2 >> 11) & 0x3) << 3) | ((param2 >> 28) & 0x7);
> +
> +            TRACE("D3DSIO_DCL param1: %#x, param2: %#x, usage: %u, usage_index: %u, reg_type: %u\n",
> +                   param1, param2, usage, usage_index, reg_type);
> +
> +            if (reg_type == D3DSPR_INPUT)
> +            {
> +                if (semantics)
> +                {
> +                    semantics[i].Usage = usage;
> +                    semantics[i].UsageIndex = usage_index;
> +                }
> +                i++;
> +            }
> +        }
> +    }
> +
> +    if (count)
> +        *count = i;
> +
> +    return D3D_OK;
> +}

Have you tried to implement D3DXGetShaderOutputSemantics too? I
suspect most of the code will be pretty much the same, in that case
you could move the common code to a helper function and use it from
both.
You don't necessarily need to do this right now, just mentioning a
potential follow-up.

> diff --git a/dlls/d3dx9_36/tests/shader.c b/dlls/d3dx9_36/tests/shader.c
> index f7be174..471cd8c 100644
> --- a/dlls/d3dx9_36/tests/shader.c
> +++ b/dlls/d3dx9_36/tests/shader.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright 2008 Luis Busquets
> + * Copyright 2010, 2013 Christian Costa
>   * Copyright 2011 Travis Athougies
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -271,6 +272,22 @@ static const D3DXCONSTANT_DESC ctab_samplers_expected[] = {
>      {"sampler2",   D3DXRS_SAMPLER, 3, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER3D, 1, 1, 1, 0, 4,  NULL},
>      {"notsampler", D3DXRS_FLOAT4,  2, 1, D3DXPC_VECTOR, D3DXPT_FLOAT,     1, 4, 1, 0, 16, NULL}};
>
> +static const DWORD semantics_vs11[] = {
> +    0xfffe0101,                                                             /* vs_1_1                       */
> +    0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position0 v0 (input)     */
> +    0x0000001f, 0x80000005, 0x900f0001,                                     /* dcl_texcoord0 v1 (input)     */
> +    0x0000001f, 0x80010005, 0x900f0002,                                     /* dcl_texcoord1 v2 (input)     */
> +    0x0000001f, 0x8000000a, 0xe00f0000,                                     /* dcl_color0    oD0 (output)   */
> +    0x0000ffff};                                                            /* END                          */
> +
> +static const DWORD semantics_vs30[] = {
> +    0xfffe0300,                                                             /* vs_3_0                       */
> +    0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position0 v0 (input)     */
> +    0x0000001f, 0x80000005, 0x900f0001,                                     /* dcl_texcoord0 v1 (input)     */
> +    0x0000001f, 0x80010005, 0x900f0002,                                     /* dcl_texcoord1 v2 (input)     */
> +    0x0000001f, 0x8000000a, 0xe00f0000,                                     /* dcl_color0    o0 (output)    */
> +    0x0000ffff};                                                            /* END                          */
> +
>  static void test_get_shader_size(void)
>  {
>      UINT shader_size, expected;
> @@ -1900,6 +1917,43 @@ static void test_get_shader_constant_variables(void)
>      ok(count == 0, "Release failed, got %u, expected %u\n", count, 0);
>  }
>
> +static void test_get_shader_semantics(void)
> +{
> +    HRESULT ret;
> +    D3DXSEMANTIC semantics[MAXD3DDECLLENGTH];
> +    UINT count;
> +
> +    /* Check parameters */
> +    ret = D3DXGetShaderInputSemantics(NULL, semantics, &count);
> +    ok(ret == D3DERR_INVALIDCALL, "Returned %#x, expected %#x\n", ret, D3DERR_INVALIDCALL);
> +    ret = D3DXGetShaderInputSemantics(semantics_vs11, semantics, NULL);
> +    ok(ret == D3D_OK, "Failed with %#xn", ret);
> +    count = 0xdeadbeef;
> +    ret = D3DXGetShaderInputSemantics(semantics_vs11, NULL, &count);
> +    ok(ret == D3D_OK, "Failed with %#xn", ret);
> +    ok(count == 3, "Got %u, expected 1\n", count);
> +
> +    ret = D3DXGetShaderInputSemantics(semantics_vs11, semantics, &count);
> +    ok(ret == D3D_OK, "Failed with %#xn", ret);
> +    ok(count == 3, "Got %u, expected 1\n", count);
> +    ok(semantics[0].Usage == D3DDECLUSAGE_POSITION, "Got %u, expected %u\n", semantics[0].Usage, D3DDECLUSAGE_POSITION);
> +    ok(semantics[0].UsageIndex == 0, "Got %u, expected 0\n", semantics[0].UsageIndex);
> +    ok(semantics[1].Usage == D3DDECLUSAGE_TEXCOORD, "Got %u, expected %u\n", semantics[1].Usage, D3DDECLUSAGE_TEXCOORD);
> +    ok(semantics[1].UsageIndex == 0, "Got %u, expected 0\n", semantics[0].UsageIndex);
> +    ok(semantics[2].Usage == D3DDECLUSAGE_TEXCOORD, "Got %u, expected %u\n", semantics[2].Usage, D3DDECLUSAGE_TEXCOORD);
> +    ok(semantics[2].UsageIndex == 1, "Got %u, expected 1\n", semantics[0].UsageIndex);
> +
> +    ret = D3DXGetShaderInputSemantics(semantics_vs30, semantics, &count);
> +    ok(ret == D3D_OK, "Failed with %#xn", ret);
> +    ok(count == 3, "Got %u, expected 1\n", count);
> +    ok(semantics[0].Usage == D3DDECLUSAGE_POSITION, "Got %u, expected %u\n", semantics[0].Usage, D3DDECLUSAGE_POSITION);
> +    ok(semantics[0].UsageIndex == 0, "Got %u, expected 0\n", semantics[0].UsageIndex);
> +    ok(semantics[1].Usage == D3DDECLUSAGE_TEXCOORD, "Got %u, expected %u\n", semantics[1].Usage, D3DDECLUSAGE_TEXCOORD);
> +    ok(semantics[1].UsageIndex == 0, "Got %u, expected 0\n", semantics[0].UsageIndex);
> +    ok(semantics[2].Usage == D3DDECLUSAGE_TEXCOORD, "Got %u, expected %u\n", semantics[2].Usage, D3DDECLUSAGE_TEXCOORD);
> +    ok(semantics[2].UsageIndex == 1, "Got %u, expected 1\n", semantics[0].UsageIndex);
> +}
> +
>  START_TEST(shader)
>  {
>      test_get_shader_size();
> @@ -1911,4 +1965,5 @@ START_TEST(shader)
>      test_get_sampler_index();
>      test_get_shader_samplers();
>      test_get_shader_constant_variables();
> +    test_get_shader_semantics();
>  }
> diff --git a/include/d3dx9shader.h b/include/d3dx9shader.h
> index 0b30519..f5ba1c4 100644
> --- a/include/d3dx9shader.h
> +++ b/include/d3dx9shader.h
> @@ -269,6 +269,7 @@ DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code);
>  const char * WINAPI D3DXGetVertexShaderProfile(struct IDirect3DDevice9 *device);
>  HRESULT WINAPI D3DXFindShaderComment(CONST DWORD* byte_code, DWORD fourcc, LPCVOID* data, UINT* size);
>  HRESULT WINAPI D3DXGetShaderSamplers(CONST DWORD *byte_code, LPCSTR *samplers, UINT *count);
> +HRESULT WINAPI D3DXGetShaderInputSemantics(const DWORD *byte_code, D3DXSEMANTIC *semantics, UINT *count);
>
>  HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines,
>          ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages);
>
>
>



More information about the wine-devel mailing list