2012-10-16 100 views
3

我在寫一個非常簡單的建模軟件,更像是一個挑戰而非其他任何事情。 直到大約3個星期前,我對SwapChain.ResizeBuffers()函數沒有真正的問題。ResizeBuffers時出現DirectX無效呼叫

我更換了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); 
    } 
+0

我打算猜測這個問題與SlimDX.dll有什麼關係,請聯繫作者尋求幫助。我建議只使用Microsoft庫,它似乎是你正在嘗試使用的庫,它有一個關鍵的錯誤。 –

回答

3

在調整大小之前,您需要釋放與交換鏈相關的所有資源。

因此,這包括渲染視圖(你這樣做),但是當你創建渲染目標視圖時,你在資源上做了addref。

Resource.FromSwapChain<Texture2D>(swapChain, 0) 

向紋理添加ref計數器。既然你沒有緩存它,你不能釋放它。

所以,你需要做的:

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

然後之前調用調整大小:

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

只是測試它在我的引擎,它的工作原理(也你是正確的用0,它也能工作)。

+1

當SwapChain鏈接到窗口句柄時,ResizeBuffers方法可以直接獲取該信息,但不需要提供它。 ResizeBuffers的實現(如DirectX doc中所解釋的那樣)要求SwapChain調整大小,但不會更改任何其他參數。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb174577%28v=vs.85%29.aspx和http://msdn.microsoft.com/en-us/library/windows/桌面/ bb205075%28v = vs.85%29.aspx只是說,因爲這是我已經嘗試過的,但是Microsoft的每個文檔都是這樣實現的。 – LightStriker

+0

@ Marc-AndréJutras:你是對的,對於零,問題來自資源發佈,更新的答案。 – catflier

+0

另外,正如http://msdn.microsoft.com/en-us/library/windows/desktop/bb174577(v=vs.85).aspx上的評論所指定的那樣,請確保與您的交換鏈相關的視圖資源是不綁定到設備上下文。 – catflier