我正在尝试在更改窗口大小后立即对后备缓冲区执行更新。 所以我的物体不会受到拉伤。 所以我尝试了这个
_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
我错过了什么吗?
答案 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事件中调用它。