[vlc-devel] [PATCH 8/9] d3d11: add a shader to merge 2 fields into one surface

Steve Lhomme robux4 at ycbcr.xyz
Mon Nov 16 13:44:19 CET 2020


---
 modules/video_output/win32/d3d11_quad.c    | 51 ++++++++++++++++++++++
 modules/video_output/win32/d3d11_quad.h    |  4 ++
 modules/video_output/win32/d3d11_shaders.c | 47 ++++++++++++++++----
 modules/video_output/win32/d3d11_shaders.h |  2 +
 4 files changed, 95 insertions(+), 9 deletions(-)

diff --git a/modules/video_output/win32/d3d11_quad.c b/modules/video_output/win32/d3d11_quad.c
index b90ecacad8f..90b37fe8de5 100644
--- a/modules/video_output/win32/d3d11_quad.c
+++ b/modules/video_output/win32/d3d11_quad.c
@@ -90,6 +90,55 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vertex_shad
     }
 }
 
+void D3D11_RenderMergeQuad(d3d11_device_t *d3d_dev, d3d_vertex_shader_t *vsshader, d3d_quad_t *quad,
+                           ID3D11ShaderResourceView *field1Resources[D3D11_MAX_SHADER_VIEW],
+                           ID3D11ShaderResourceView *field2Resources[D3D11_MAX_SHADER_VIEW],
+                           d3d11_select_plane_t selectPlane, void *selectOpaque)
+{
+    UINT offset = 0;
+
+    /* Render the quad */
+    ID3D11DeviceContext_IASetPrimitiveTopology(d3d_dev->d3dcontext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+    /* vertex shader */
+    ID3D11DeviceContext_IASetInputLayout(d3d_dev->d3dcontext, vsshader->layout);
+    ID3D11DeviceContext_IASetVertexBuffers(d3d_dev->d3dcontext, 0, 1, &quad->pVertexBuffer, &quad->vertexStride, &offset);
+    ID3D11DeviceContext_IASetIndexBuffer(d3d_dev->d3dcontext, quad->pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+    if ( quad->viewpointShaderConstant )
+        ID3D11DeviceContext_VSSetConstantBuffers(d3d_dev->d3dcontext, 0, 1, &quad->viewpointShaderConstant);
+
+    ID3D11DeviceContext_VSSetShader(d3d_dev->d3dcontext, vsshader->shader, NULL, 0);
+
+    if (quad->SamplerStates[0])
+        ID3D11DeviceContext_PSSetSamplers(d3d_dev->d3dcontext, 0, 2, quad->SamplerStates);
+
+    /* pixel shader */
+    ID3D11DeviceContext_PSSetConstantBuffers(d3d_dev->d3dcontext, 0, ARRAY_SIZE(quad->pPixelShaderConstants), quad->pPixelShaderConstants);
+    assert(quad->resourceCount <= D3D11_MAX_SHADER_VIEW);
+
+    for (size_t i=0; i<D3D11_MAX_SHADER_VIEW; i++)
+    {
+        if (!quad->d3dpixelShader[i])
+            break;
+
+        if (unlikely(!selectPlane(selectOpaque, i)))
+            continue;
+
+        ID3D11ShaderResourceView *resources[8] = {
+            field1Resources[0], field1Resources[1], NULL, NULL,
+            field2Resources[0], field2Resources[1], NULL, NULL,
+        };
+
+        ID3D11DeviceContext_PSSetShaderResources(d3d_dev->d3dcontext, 0, 8, resources);
+
+        ID3D11DeviceContext_PSSetShader(d3d_dev->d3dcontext, quad->d3dpixelShader[i], NULL, 0);
+
+        ID3D11DeviceContext_RSSetViewports(d3d_dev->d3dcontext, 1, &quad->cropViewport[i]);
+
+        ID3D11DeviceContext_DrawIndexed(d3d_dev->d3dcontext, quad->indexCount, 0, 0);
+    }
+}
+
 static bool AllocQuadVertices(vlc_object_t *o, d3d11_device_t *d3d_dev, d3d_quad_t *quad, video_projection_mode_t projection)
 {
     HRESULT hr;
@@ -1010,6 +1059,8 @@ int D3D11_SetupQuad(vlc_object_t *o, d3d11_device_t *d3d_dev, const video_format
 
     quad->shaderConstants.LuminanceScale = (float)displayFormat->luminance_peak / GetFormatLuminance(o, fmt);
 
+    quad->shaderConstants.Height = fmt->i_height;
+
     /* pixel shader constant buffer */
     quad->shaderConstants.Opacity = 1.0;
     if (fmt->i_visible_width == fmt->i_width)
diff --git a/modules/video_output/win32/d3d11_quad.h b/modules/video_output/win32/d3d11_quad.h
index 8b7e231c384..50033af3800 100644
--- a/modules/video_output/win32/d3d11_quad.h
+++ b/modules/video_output/win32/d3d11_quad.h
@@ -50,6 +50,10 @@ typedef bool (*d3d11_select_plane_t)(void *opaque, size_t plane_index);
 void D3D11_RenderQuad(d3d11_device_t *, d3d_quad_t *, d3d_vertex_shader_t *,
                       ID3D11ShaderResourceView *resourceViews[D3D11_MAX_SHADER_VIEW],
                       d3d11_select_plane_t selectPlane, void *selectOpaque);
+void D3D11_RenderMergeQuad(d3d11_device_t *, d3d_vertex_shader_t *, d3d_quad_t *,
+                           ID3D11ShaderResourceView *field1Resources[D3D11_MAX_SHADER_VIEW],
+                           ID3D11ShaderResourceView *field2Resources[D3D11_MAX_SHADER_VIEW],
+                           d3d11_select_plane_t selectPlane, void *selectOpaque);
 
 int D3D11_AllocateQuad(vlc_object_t *, d3d11_device_t *, video_projection_mode_t, d3d_quad_t *);
 #define D3D11_AllocateQuad(a,b,c,d)  D3D11_AllocateQuad(VLC_OBJECT(a),b,c,d)
diff --git a/modules/video_output/win32/d3d11_shaders.c b/modules/video_output/win32/d3d11_shaders.c
index 2e58ade8613..8a820d8159d 100644
--- a/modules/video_output/win32/d3d11_shaders.c
+++ b/modules/video_output/win32/d3d11_shaders.c
@@ -54,6 +54,8 @@ static const char* globPixelShaderDefault = "\
     float BoundaryX;\n\
     float BoundaryY;\n\
     float LuminanceScale;\n\
+    float Height;\n\
+    float reserved[3];\n\
   };\n\
   cbuffer PS_COLOR_TRANSFORM : register(b1)\n\
   {\n\
@@ -305,15 +307,42 @@ HRESULT (D3D11_CompilePixelShader)(vlc_object_t *o, const d3d11_shader_compiler_
         {
         case DXGI_FORMAT_NV12:
         case DXGI_FORMAT_P010:
-            psz_sampler[0] =
-                    "sample.x  = shaderTexture[0].Sample(samplerState, coords).x;\n"
-                    "sample.y = 0.0;\n"
-                    "sample.z = 0.0;\n"
-                    "sample.a = 1;";
-            psz_sampler[1] =
-                    "sample.xy  = shaderTexture[1].Sample(samplerState, coords).xy;\n"
-                    "sample.z = 0.0;\n"
-                    "sample.a = 1;";
+            switch (texture_count)
+            {
+            case 1:
+                psz_sampler[0] =
+                        "sample.x  = shaderTexture[0].Sample(samplerState, coords).x;\n"
+                        "sample.y = 0.0;\n"
+                        "sample.z = 0.0;\n"
+                        "sample.a = 1;";
+                psz_sampler[1] =
+                        "sample.xy  = shaderTexture[1].Sample(samplerState, coords).xy;\n"
+                        "sample.z = 0.0;\n"
+                        "sample.a = 1;";
+                break;
+            case 2:
+                psz_sampler[0] =
+                        "const int sample_line = coords.y * Height;\n"
+                        "if ( ( sample_line % 2 ) == 0 )\n"
+                            "sample.x  = shaderTexture[0].Sample(samplerState, coords).x;\n"
+                        "else\n"
+                            "sample.x  = shaderTexture[4].Sample(samplerState, coords).x;\n"
+                        "sample.y = 0.0;\n"
+                        "sample.z = 0.0;\n"
+                        "sample.a = 1;";
+                psz_sampler[1] =
+                        "const int sample_line = coords.y * Height;\n"
+                        "if ( ( sample_line % 2 ) == 0 )\n"
+                            "sample.xy  = shaderTexture[1].Sample(samplerState, coords).xy;\n"
+                        "else\n"
+                            "sample.xy  = shaderTexture[5].Sample(samplerState, coords).xy;\n"
+                        "sample.z = 0.0;\n"
+                        "sample.a = 1;";
+                break;
+            default:
+                vlc_assert_unreachable(); //unsupported
+                break;
+            }
             break;
         case DXGI_FORMAT_R8G8B8A8_UNORM:
         case DXGI_FORMAT_B8G8R8A8_UNORM:
diff --git a/modules/video_output/win32/d3d11_shaders.h b/modules/video_output/win32/d3d11_shaders.h
index ff52633ddf3..212022d70f2 100644
--- a/modules/video_output/win32/d3d11_shaders.h
+++ b/modules/video_output/win32/d3d11_shaders.h
@@ -54,6 +54,8 @@ typedef struct {
     FLOAT BoundaryX;
     FLOAT BoundaryY;
     FLOAT LuminanceScale;
+    FLOAT Height;
+    FLOAT reserved[3]; // unused for now
 } PS_CONSTANT_BUFFER;
 
 typedef struct {
-- 
2.26.2



More information about the vlc-devel mailing list