[vlc-devel] [PATCH 2/9] direct3d11: use a Texture2DArray in the pixel shader

Steve Lhomme robux4 at gmail.com
Wed Feb 8 15:32:00 CET 2017


On Wed, Feb 8, 2017 at 2:52 PM, Steve Lhomme <robux4 at videolabs.io> wrote:
> So that it can receive a view from a texture with multiple slices, like the
> ones needed by d3d11va.
>
> With this change we move from D3D9.1 compatibility to D3D10. Which is fine as
> we only want D3D11 on Windows 7 and above. If the device cannot compile a
> pixel shader with Texture2DArray, we fall back to Texture2D with a copy of
> the texture when displaying.
>
> Add an advanced parameter to use 0-copy with hardware decoding as some AMD
> hardware have issues using Texture2DArray in the pixel shader but allow it
> anyway.
>
> log when we switch to legacy mode
> ---
>  modules/video_output/win32/direct3d11.c | 104 +++++++++++++++++++++++++++-----
>  1 file changed, 89 insertions(+), 15 deletions(-)
>
> diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
> index 2dfa0b6..b9040ca 100644
> --- a/modules/video_output/win32/direct3d11.c
> +++ b/modules/video_output/win32/direct3d11.c
> @@ -66,6 +66,9 @@ static void Close(vlc_object_t *);
>  #define HW_BLENDING_TEXT N_("Use hardware blending support")
>  #define HW_BLENDING_LONGTEXT N_(\
>      "Try to use hardware acceleration for subtitle/OSD blending.")
> +#define HW_0COPY_TEXT N_("Use 0-copy with hardware decoder")
> +#define HW_0COPY_LONGTEXT N_(\
> +    "Use one less copy per frame displayed, may not work on all hardware.")
>
>  vlc_module_begin ()
>      set_shortname("Direct3D11")
> @@ -75,6 +78,7 @@ vlc_module_begin ()
>      set_subcategory(SUBCAT_VIDEO_VOUT)
>
>      add_bool("direct3d11-hw-blending", true, HW_BLENDING_TEXT, HW_BLENDING_LONGTEXT, true)
> +    add_bool("direct3d11-direct-hw", true, HW_0COPY_TEXT, HW_0COPY_LONGTEXT, true)

This option is needed for now as some (AMD) drivers do not handle NV12
from a Texture2DArray. They are supposed to fix it but I don't know
when the new drivers with the fix will be available. It may not cover
all the GPUs with the issue through.

>  #if VLC_WINSTORE_APP
>      add_integer("winrt-d3dcontext",    0x0, NULL, NULL, true); /* ID3D11DeviceContext* */
> @@ -141,6 +145,10 @@ struct vout_display_sys_t
>      ID3D11VertexShader        *flatVSShader;
>      ID3D11VertexShader        *projectionVSShader;
>
> +    /* copy from the decoder pool into picSquad before display
> +     * Uses a Texture2D with slices rather than a Texture2DArray for the decoder */
> +    bool                     legacy_shader;
> +
>      // SPU
>      vlc_fourcc_t             pSubpictureChromas[2];
>      const char               *psz_rgbaPxShader;
> @@ -298,7 +306,7 @@ static const char* globPixelShaderDefault = "\
>      float whitePadding;\
>      float4x4 Colorspace;\
>    };\
> -  Texture2D shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
> +  Texture2D%s shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
>    SamplerState SampleType;\
>    \
>    struct PS_INPUT\
> @@ -335,7 +343,7 @@ static const char *globPixelShaderBiplanarYUV_2RGB = "\
>      float whitePadding;\
>      float4x4 Colorspace;\
>    };\
> -  Texture2D shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
> +  Texture2D%s shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
>    SamplerState SampleType;\
>    \
>    struct PS_INPUT\
> @@ -373,7 +381,7 @@ static const char *globPixelShaderBiplanarYUYV_2RGB = "\
>      float whitePadding;\
>      float4x4 Colorspace;\
>    };\
> -  Texture2D shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
> +  Texture2D%s shaderTexture[" STRINGIZE(D3D11_MAX_SHADER_VIEW) "];\
>    SamplerState SampleType;\
>    \
>    struct PS_INPUT\
> @@ -632,9 +640,19 @@ static int AllocateShaderView(vout_display_t *vd, const d3d_format_t *format,
>      D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc = {
>          .Format = format->resourceFormat[0],
>      };
> -    resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
> -    resviewDesc.Texture2D.MipLevels = 1;
>
> +    if (sys->legacy_shader)
> +    {
> +        resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
> +        resviewDesc.Texture2D.MipLevels = 1;
> +    }
> +    else
> +    {
> +        resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
> +        resviewDesc.Texture2DArray.MipLevels = -1;
> +        resviewDesc.Texture2DArray.ArraySize = 1;
> +        resviewDesc.Texture2DArray.FirstArraySlice = slice_index;
> +    }
>      hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, picsys->resource, &resviewDesc, &picsys->resourceView[0]);
>      if (FAILED(hr)) {
>          msg_Err(vd, "Could not Create the Y/RGB Texture ResourceView slice %d. (hr=0x%lX)", slice_index, hr);
> @@ -1119,7 +1137,19 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
>      vout_display_sys_t *sys = vd->sys;
>
>  #ifdef HAVE_ID3D11VIDEODECODER
> -    if (is_d3d11_opaque(picture->format.i_chroma)) {
> +    if (!is_d3d11_opaque(picture->format.i_chroma))
> +    {
> +        picture_sys_pool_t *p_psys = (picture_sys_pool_t*)picture->p_sys;
> +        Direct3D11UnmapPoolTexture(picture);
> +        ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
> +                                                  sys->picQuad.picSys.resource,
> +                                                  0, 0, 0, 0,
> +                                                  (ID3D11Resource*) p_psys->texture,
> +                                                  0, NULL);
> +    }
> +    else
> +    if (sys->legacy_shader)
> +    {
>          picture_sys_t *p_sys = picture->p_sys;
>          if( sys->context_lock != INVALID_HANDLE_VALUE )
>          {
> @@ -1189,11 +1219,11 @@ static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
>
>      ID3D11DeviceContext_ClearDepthStencilView(sys->d3dcontext, sys->d3ddepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
>
> -    if ( !is_d3d11_opaque(picture->format.i_chroma))
> -        Direct3D11UnmapPoolTexture(picture);
> -
>      /* Render the quad */
> -    DisplayD3DPicture(sys, &sys->picQuad, sys->picQuad.picSys.resourceView);
> +    if (sys->legacy_shader || !is_d3d11_opaque(picture->format.i_chroma))
> +        DisplayD3DPicture(sys, &sys->picQuad, sys->picQuad.picSys.resourceView);
> +    else
> +        DisplayD3DPicture(sys, &sys->picQuad, picture->p_sys->resourceView);
>
>      if (subpicture) {
>          // draw the additional vertices
> @@ -1347,7 +1377,7 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
>      for (UINT driver = 0; driver < ARRAYSIZE(driverAttempts); driver++) {
>          D3D_FEATURE_LEVEL i_feature_level;
>          hr = D3D11CreateDevice(NULL, driverAttempts[driver], NULL, creationFlags,
> -                    featureLevels, 9, D3D11_SDK_VERSION,
> +                    featureLevels, 6, D3D11_SDK_VERSION,
>                      &sys->d3ddevice, &i_feature_level, &sys->d3dcontext);
>          if (SUCCEEDED(hr)) {
>  #ifndef NDEBUG
> @@ -1527,12 +1557,28 @@ static ID3DBlob* CompileShader(vout_display_t *vd, const char *psz_shader, bool
>  {
>      vout_display_sys_t *sys = vd->sys;
>      ID3DBlob* pShaderBlob = NULL, *pErrBlob;
> +    char *shader;
> +    if (!pixel)
> +        shader = (char*)psz_shader;
> +    else
> +    {
> +        shader = malloc(strlen(psz_shader) + 32);
> +        if (!shader)
> +        {
> +            msg_Err(vd, "no room for the Pixel Shader");
> +            return NULL;
> +        }
> +        sprintf(shader, psz_shader, sys->legacy_shader ? "" : "Array", sys->legacy_shader ? "" : "Array");
> +    }
>
>      /* TODO : Match the version to the D3D_FEATURE_LEVEL */
> -    HRESULT hr = D3DCompile(psz_shader, strlen(psz_shader),
> +    HRESULT hr = D3DCompile(shader, strlen(shader),
>                              NULL, NULL, NULL, pixel ? "PS" : "VS",
> -                            pixel ? "ps_4_0_level_9_1" : "vs_4_0_level_9_1",
> +                            pixel ? (sys->legacy_shader ? "ps_4_0_level_9_1" : "ps_4_0") :
> +                                    (sys->legacy_shader ? "vs_4_0_level_9_1" : "vs_4_0"),
>                              0, 0, &pShaderBlob, &pErrBlob);
> +    if (pixel)
> +        free(shader);
>
>      if (FAILED(hr)) {
>          char *err = pErrBlob ? ID3D10Blob_GetBufferPointer(pErrBlob) : NULL;
> @@ -1622,13 +1668,41 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
>          ID3D11DepthStencilState_Release(pDepthStencilState);
>      }
>
> +#ifdef HAVE_ID3D11VIDEODECODER
> +    sys->legacy_shader = !var_InheritBool(vd, "direct3d11-direct-hw");
> +#if 0
> +    IDXGIAdapter *pAdapter = D3D11DeviceAdapter(sys->d3ddevice);
> +    if (pAdapter) {
> +        DXGI_ADAPTER_DESC adapterDesc;
> +        if (SUCCEEDED(IDXGIAdapter_GetDesc(pAdapter, &adapterDesc)) &&
> +                      adapterDesc.VendorId == 0x1002) {
> +            /* ATI/AMD hardware has issues with pixel shaders with Texture2DArray */
> +            sys->legacy_shader = true;
> +        }
> +        IDXGIAdapter_Release(pAdapter);
> +    }
> +#endif
> +#else
> +    sys->legacy_shader = true;
> +#endif
>      vd->info.is_slow = !is_d3d11_opaque(fmt->i_chroma);
>
>      hr = CompilePixelShader(vd, sys->d3dPxShader, &sys->picQuadPixelShader);
>      if (FAILED(hr))
>      {
> -        msg_Err(vd, "Failed to create the pixel shader. (hr=0x%lX)", hr);
> -        return VLC_EGENERIC;
> +#ifdef HAVE_ID3D11VIDEODECODER
> +        if (!sys->legacy_shader)
> +        {
> +            sys->legacy_shader = true;
> +            msg_Dbg(vd, "fallback to legacy shader mode");
> +            hr = CompilePixelShader(vd, sys->d3dPxShader, &sys->picQuadPixelShader);
> +        }
> +#endif
> +        if (FAILED(hr))
> +        {
> +            msg_Err(vd, "Failed to create the pixel shader. (hr=0x%lX)", hr);
> +            return VLC_EGENERIC;
> +        }
>      }
>
>      if (sys->psz_rgbaPxShader != NULL)
> --
> 2.10.2
>


More information about the vlc-devel mailing list