首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DirectX 11渲染BGRA32帧

DirectX 11渲染BGRA32帧
EN

Stack Overflow用户
提问于 2022-05-05 13:05:07
回答 1查看 158关注 0票数 2

第一次试着做些什么而我有大麻烦..。我正在使用DirectN库和KlearTouch.MediaPlayer中的SwapChainSurface类。我正在尝试使用BGRA32渲染D3D11Device帧。

为此,我稍微修改了OnNewSurfaceAvailable:

代码语言:javascript
复制
public void OnNewSurfaceAvailable2(Action<ID3D11Device, ID3D11DeviceContext> updateSurface)
{
    if (rendering)
    {
        return;
    }

    try
    {
        if (this.swapChain is null || swapChainComObject is null)
        {
            return;
        }

        swapChainComObject.GetDesc(out var swapChainDesc).ThrowOnError();

        if (swapChainDesc.BufferDesc.Width != PanelWidth || swapChainDesc.BufferDesc.Height != PanelHeight)
        {
            swapChainComObject.ResizeBuffers(2, PanelWidth, PanelHeight, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN, 0).ThrowOnError();
        }

        var device = swapChain.Object.GetDevice1().Object.As<ID3D11Device>();

        device.GetImmediateContext(out var context);

        // context.ClearRenderTargetView(renderTargetView.Object, new []{0f, 1f, 1f, 1f});

        updateSurface(device, context);

        swapChainComObject.Present(1, 0).ThrowOnError();
    }
    catch (ObjectDisposedException)
    {
        Reinitialize();
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("\nException: " + ex, nameof(SwapChainSurface) + '.' + nameof(OnNewSurfaceAvailable));
    }

    rendering = false;
}

从以下位置调用OnSurfaceAvailable2:

代码语言:javascript
复制
void VideoFrameArrived(Bgra32VideoFrame frame)
    {
        DispatcherQueue.TryEnqueue(() =>
        {
            previewSurface.OnNewSurfaceAvailable2((device, context) =>
            {
                var size = frame.m_height * frame.m_height * 4;

                D3D11_TEXTURE2D_DESC td;
                td.ArraySize = 1;
                td.BindFlags = (uint) D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE;
                td.Usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC;
                td.CPUAccessFlags = (uint) D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE;
                td.Format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
                td.Height = (uint) frame.m_height;
                td.Width = (uint) frame.m_width;
                td.MipLevels = 1;
                td.MiscFlags = 0;
                td.SampleDesc.Count = 1;
                td.SampleDesc.Quality = 0;

                D3D11_SUBRESOURCE_DATA srd;
                srd.pSysMem = frame.m_pixelBuffer;
                srd.SysMemPitch = (uint) frame.m_height;
                srd.SysMemSlicePitch = 0;

                var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});

                var mappedResource = context.Map(texture.Object, 0, D3D11_MAP.D3D11_MAP_WRITE_DISCARD);

                var mappedData = mappedResource.pData;
                

                unsafe
                {
                    Buffer.MemoryCopy(frame.m_pixelBuffer.ToPointer(), mappedData.ToPointer(), size, size);
                }

                // Just for debug
                var pixelsInFrame = new byte[size];
                var pixelsInResource = new byte[size];

                Marshal.Copy(frame.m_pixelBuffer, pixelsInFrame, 0, size);
                Marshal.Copy(mappedResource.pData, pixelsInResource, 0, size);
                
                context.Unmap(texture.Object, 0);
            });
        });
    }

问题是,我看不到任何渲染和表面保持黑色,我认为它不应该。

更新:项目储存库

更新2:

我解决了我的问题。我对DX11知之甚少,所以我不得不研究更多的东西是如何在那里工作的。有了这些知识,我更新了存储库,它可以显示来自黑色魔法设计卡的预览。它只是许多问题的例子,所以要小心,在那里自由地寻找或激发灵感。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-06 14:00:02

这里有各种各样的问题。

第一帧到了,你有

代码语言:javascript
复制
var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});

因此,您可以创建一个纹理,但是您不需要在任何地方使用它,它需要被裁剪到交换链(可以在设备上下文上执行CopyResource或绘制全屏三角形/四角)。

请注意,只有当您的交换链具有与您传入的纹理相同的大小时,CopyResource才能工作,这是相当不可能的,所以您将不得不用着色器绘制空白。

此外,您还实际复制了纹理中的数据两次:

代码语言:javascript
复制
 var texture = device.CreateTexture2D<ID3D11Texture2D>(td, new []{srd});

因为您提供了初始数据,所以内容已经存在了。

同时,音调不正确: srd.SysMemPitch = (uint) frame.m_height;

音调是一行的长度(以字节为单位),因此它应该是:

代码语言:javascript
复制
srd.SysMemPitch = frame.GetRowBytes();

还请注意,如果没有转换的Decklink帧,GetRowBytes可能与宽度*4不同(它们可以将行大小对齐到16/32的倍数或其他值)。

其次,对于资源地图,以下内容也是不正确的:

代码语言:javascript
复制
unsafe
{
    Buffer.MemoryCopy(frame.m_pixelBuffer.ToPointer(), mappedData.ToPointer(), size, size);
}

您没有检查纹理的音高/步幅要求(这也可以是不同的),

所以你需要做:

代码语言:javascript
复制
if (mappedResource.RowPitch == frame.GetRowBytes())
{
    //here you can use a direct copy as above
}
else
{
   //here you need to copy data line per line
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72127664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档