3

我正在编写一个非常简单的建模软件,这更像是一个挑战。大约 3 周前,我对 SwapChain.ResizeBuffers() 函数没有真正的问题。

我更换了 PC,切换到 Visual Studio Express 2012(从 Pro 9),并使用相应的 SlimDX.dll 将我的解决方案切换到 x64。

它仍然运行良好,但是当我调整托管视口的窗口大小时,它得到:DXGI_ERROR_INVALID_CALL (-2005270527)。

谷歌上的快速搜索告诉我,战地 3 也可能与某些特定驱动程序有这个问题。是否可以?

我已经阅读了我能找到的关于该功能的所有内容,但不知何故,我找不到现在正在搞砸的变化。希望有人能看到我做错了什么。

    // Form we are attached to.
    private Dockable dock;

    // Rendering stuff.
    private Device device;
    private Viewport viewport;
    private SwapChain swapChain;
    private RenderTargetView renderView;
    private DepthStencilView depthView;

    public Renderer(Dockable form)
    {
        if (form == null)
            return;

        dock = form;

        CreateSwapchain();
        Resize();
    }

    private void CreateSwapchain()
    {
        // Swap Chain & Device
        SwapChainDescription description = new SwapChainDescription()
        {
            BufferCount = 1,
            Usage = Usage.RenderTargetOutput,
            OutputHandle = dock.Handle,
            IsWindowed = true,
            ModeDescription = new ModeDescription(dock.ClientSize.Width, dock.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
            SampleDescription = new SampleDescription(1, 0),
            Flags = SwapChainFlags.AllowModeSwitch,
            SwapEffect = SwapEffect.Discard
        };

        Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug, description, out device, out swapChain);
    }

    private void CreateRenderView()
    {
        // Dispose before resizing.
        if (renderView != null)
            renderView.Dispose();

        if (depthView != null)
            depthView.Dispose();

        swapChain.ResizeBuffers(0, 0, 0, Format.Unknown, 0); // ERROR : DXGI_ERROR_INVALID_CALL when resizing the window, but not when creating it.
        renderView = new RenderTargetView(device, Resource.FromSwapChain<Texture2D>(swapChain, 0));

        Texture2DDescription depthBufferDesc = new Texture2DDescription()
        {
            ArraySize = 1,
            BindFlags = BindFlags.DepthStencil,
            CpuAccessFlags = CpuAccessFlags.None,
            Format = Format.D16_UNorm,
            Height = dock.ClientSize.Height,
            Width = dock.ClientSize.Width,
            MipLevels = 1,
            OptionFlags = ResourceOptionFlags.None,
            SampleDescription = new SampleDescription(1, 0),
            Usage = ResourceUsage.Default
        };

        depthView = new DepthStencilView(device, new Texture2D(device, depthBufferDesc));
    }

    public void Resize()
    {
        CreateRenderView();

        viewport = new Viewport(0.0f, 0.0f, dock.ClientSize.Width, dock.ClientSize.Height);
        device.ImmediateContext.Rasterizer.SetViewports(viewport);
        device.ImmediateContext.OutputMerger.SetTargets(depthView, renderView);
    }
4

1 回答 1

4

在调整交换链大小之前,您需要释放与交换链关联的所有资源。

所以这包括渲染视图(你做的),但是当你创建你的渲染目标视图时你会在资源上添加引用。

Resource.FromSwapChain<Texture2D>(swapChain, 0)

为纹理添加一个参考计数器。由于您不缓存它,因此您无法释放它。

所以你需要这样做:

Texture2D resource = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
renderView = new RenderTargetView(device, resource);

然后在调用调整大小之前:

if (resource != null) { resource.Dispose(); }

刚刚在我的引擎上对其进行了测试,它可以工作(你也对 0 正确,它也可以工作)。

于 2012-10-16T20:37:28.760 回答