SharpDX UWP 交换链在 Present 时为空引用

问题描述 投票:0回答:1

我正在尝试在 Visual Studio 中设置 SwapChain,我创建了一个 SwapChainPanel UI 元素,我希望交换链绘制到该元素。

当前,当我运行此代码时,在呈现交换链时出现空引用异常。我认为问题出在选角上?我对 DirectX 不太熟悉,但非常感谢任何帮助!

var swapChainPanel = this._swapChainPanel;
var swapChainPanelNative = ComObject.As<SharpDX.DXGI.ISwapChainPanelNative>(swapChainPanel);
swapChainPanelNative.SwapChain = swapChain;

相关代码:

成员变量和构造函数

        private SwapChainPanel _swapChainPanel;
        private SharpDX.Direct3D11.Device device;
        private SharpDX.Direct3D11.DeviceContext deviceContext;
        private SwapChain swapChain;
        private IDirect3DSurface surface;

        private RenderTargetView renderTargetView;
        private Texture2D renderTargetTexture;
        private Texture2D backBuffer;

        // Media player members
        private MediaPlayer mediaPlayer;
        private MediaPlaybackItem mediaPlaybackItem;
        private FFmpegMediaSource ffmpegMediaSource;
        private SoftwareBitmap frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, 512, 512, BitmapAlphaMode.Premultiplied);
        private IDirect3DSurface direct3DSurface;


        public StreamService(SwapChainPanel swapChainPanel)
        {
            _swapChainPanel = swapChainPanel;

            swapChainPanel.Loaded += (sender, args) =>
            {
                // Only create the swap chain after the SwapChainPanel is loaded
                InitializeSwapChain();
                InitializeMediaPlayer();
            };
        }

交换链初始化

        private void InitializeSwapChain()
        {
            // Create Direct3D device and context
            var creationFlags = DeviceCreationFlags.BgraSupport;
            creationFlags |= DeviceCreationFlags.Debug;
            device = new Device(SharpDX.Direct3D.DriverType.Hardware, creationFlags);

            // Descriptions
            SwapChainDescription1 swapChainDesc = new SwapChainDescription1()
            {
                Width = (int)_swapChainPanel.ActualWidth,
                Height = (int)_swapChainPanel.ActualHeight,
                Format = Format.B8G8R8A8_UNorm,
                Stereo = false,
                SampleDescription = new SampleDescription(1, 0),
                Usage = Usage.BackBuffer | Usage.RenderTargetOutput,
                BufferCount = 2,
                SwapEffect = SwapEffect.FlipDiscard,
                Scaling = Scaling.Stretch,
                AlphaMode = AlphaMode.Premultiplied,
                Flags = SwapChainFlags.AllowModeSwitch | SwapChainFlags.AllowTearing
            };

            var textureDesc = new Texture2DDescription
            {
                Width = width,
                Height = height,
                MipLevels = 1,
                ArraySize = 1,
                Format = Format.B8G8R8A8_UNorm,
                SampleDescription = new SampleDescription(1, 0),
                Usage = ResourceUsage.Default,
                BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.None,
            };

            using (var dxgiDevice = device.QueryInterface<SharpDX.DXGI.Device>())
            {
                using (var adapter = dxgiDevice.Adapter)
                {
                    using (var factory = adapter.GetParent<Factory2>())
                    {
                        using (swapChain = new SwapChain1(factory, dxgiDevice, ref swapChainDesc))
                        {
                            var swapChainPanel = this._swapChainPanel;
                            var swapChainPanelNative = ComObject.As<SharpDX.DXGI.ISwapChainPanelNative>(swapChainPanel);
                            swapChainPanelNative.SwapChain = swapChain;

                            // Set render view
                            backBuffer = swapChain.GetBackBuffer<Texture2D>(0);
                            renderTargetView = new RenderTargetView(device, backBuffer);
                            device.ImmediateContext.OutputMerger.SetRenderTargets(renderTargetView);

                            // Set render target texture
                            renderTargetTexture = new Texture2D(device, textureDesc);
                            direct3DSurface = Direct3D11Helper.CreateDirect3DSurfaceFromSharpDXTexture(renderTargetTexture);

                            backBuffer.Dispose();
                        }
                    }
                }
            }
        }

展示交换链

        public void RenderFrame()
        {
                // Clear the render target
                device.ImmediateContext.ClearRenderTargetView(renderTargetView, new RawColor4(1, 1, 1, 1));

                // Set the render target
                device.ImmediateContext.OutputMerger.SetRenderTargets(renderTargetView);

                // Bind the texture that was updated by MediaPlayer to the pixel shader
                using (var shaderResourceView = new ShaderResourceView(device, renderTargetTexture))
                {
                    device.ImmediateContext.PixelShader.SetShaderResource(0, shaderResourceView);

                    // Render quad
                    device.ImmediateContext.Draw(6, 0);
                }

                // Present the frame
                swapChain.Present(1, PresentFlags.None);
                System.Diagnostics.Debug.WriteLine("Frame presented successfully.");
        }
c# uwp directx sharpdx
1个回答
0
投票

在您的代码中,您可以像这样创建交换链:

using swapChain = new SwapChain1(factory, dxgiDevice, ref swapChainDesc);
{
   // do something
}

这意味着一旦您超出范围,它就会被处理掉。当您调用

RenderFrame
时,
swapChain
对象本身不为 null,因为它是本机事物的 .NET 包装器,但它是底层的
NativePointer
,并且您在 SharpDX 代码“下面”中得到一个
NullReferenceException

只需保持您需要的 DirectX 对象处于活动状态,例如:

swapChain = new SwapChain1(factory, dxgiDevice, ref swapChainDesc);

并且您应该将大多数这些“活动”对象(设备、交换链、后台缓冲区)存储在成员变量中(仅在关闭服务代码时处置它们)。但是,您通常可以在使用完中间对象(例如工厂)后立即释放它们。

© www.soinside.com 2019 - 2024. All rights reserved.