SharpDx windowResize

时间:2013-09-06 13:01:52

标签: c# directx-11 window-resize sharpdx dxgi

我正在尝试在更改窗口大小后立即对后备缓冲区执行更新。 所以我的物体不会受到拉伤。 所以我尝试了这个

_renderForm.Resize += OnRenderFormOnResize;
private void OnRenderFormOnResize(object sender, EventArgs args)
        {
            // Resize  depth bufer ?
            MessageBox.Show("Width: "+_renderForm.ClientSize.Width.ToString() +" | Height: "+ _renderForm.ClientSize.Height.ToString());

            _swapChain.ResizeBuffers(_desc.BufferCount, _renderForm.ClientSize.Width, _renderForm.ClientSize.Height, Format.Unknown, SwapChainFlags.None);
            DoResize();
        }

一旦窗口大小发生变化,我就会收到此错误。

  

DXGI_ERROR_IVALID_CALL / InvalidCall

我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

如果依赖于视图的任何视图仍处于活动状态,则不允许调整交换链的大小。因此,请确保在从后备缓冲区创建的RenderTargetView / ShaderResourceViews上调用release / dispose,然后在调用Resize后创建新的。

另外请注意,这些意见需要从管线分离(所以如果你SwapChain相关的RenderTargetView仍难免,请确保您之前解除绑定),othewise DX11运行时会等待他们成为处置之前独立的,所以电话会失败。

编辑: 要确保你有你所需要的,最简单的方法是建立自己swapchain类,它有所有你所需要的必要的数据(请注意,我的情况下DX11Device也只是包装的设备)。

public class DX11SwapChain : IDX11RenderTarget
{
    private DX11Device device;
    private IntPtr handle;
    private SwapChain swapchain;

    public RenderTargetView RenderView { get; protected set; }
    public RenderTargetViewDescription RenderViewDesc { get; protected set; }

    public Texture2DDescription TextureDesc { get; protected set; }
    private Texture2D resource;


    public IntPtr Handle { get { return this.handle; } }
}

这是构造函数:

    public DX11SwapChain(DX11Device device, IntPtr handle, Format format, SampleDescription sampledesc)
    {
        this.device = device;
        this.handle = handle;

        SwapChainDescription sd = new SwapChainDescription()
        {
            BufferCount = 1,
            ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), format),
            IsWindowed = true,
            OutputHandle = handle,
            SampleDescription = sampledesc,
            SwapEffect = SwapEffect.Discard,
            Usage = Usage.RenderTargetOutput | Usage.ShaderInput,
            Flags = SwapChainFlags.None
        };

        this.swapchain = new SwapChain(device.Factory, device.Device, sd);

        this.resource = Texture2D.FromSwapChain<Texture2D>(this.swapchain, 0);
        this.TextureDesc = this.resource.Description;

        this.RenderView = new RenderTargetView(device.Device, this.resource);
        this.RenderViewDesc = this.RenderView.Description;

    }

Resize方法:

    public void Resize()
    {
        this.Resize(0, 0);
    }

    public void Resize(int w, int h)
    {
        if (this.RenderView != null) { this.RenderView.Dispose(); }
        this.resource.Dispose();

        this.swapchain.ResizeBuffers(1,w, h, SharpDX.DXGI.Format.Unknown, SwapChainFlags.AllowModeSwitch);

        this.resource = Texture2D.FromSwapChain<Texture2D>(this.swapchain, 0);

        this.TextureDesc = this.resource.Description;
        this.RenderView = new RenderTargetView(device.Device, this.resource);
    }

此外,在调用resize之前,最好调用(最终你也可以进行小型刷新):

 device.ImmediateContext.ClearState();

确保取消绑定所有内容。

请注意,如果您使用依赖于大小的资源,则还需要通知您的应用程序(以便重新创建临时渲染目标/深度缓冲区等元素)。

因此,在这种情况下,您可以将一个Resized事件添加到SwapChain类(并在画布上侦听它)。我个人并不喜欢这个,因为我经常在同一个应用程序中使用几个SwapChains。

另一种简单的方法是添加方法:

 ResizeResources(int widh,int height);

进入canvas类,并在renderform resize事件中调用它。