程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> DirectX Graphics Infrastructure (DXGI) 全屏設置相關問題,infrastructuredxgi

DirectX Graphics Infrastructure (DXGI) 全屏設置相關問題,infrastructuredxgi

編輯:C#入門知識

DirectX Graphics Infrastructure (DXGI) 全屏設置相關問題,infrastructuredxgi


原文地址: https://msdn.microsoft.com/en-us/library/windows/desktop/ee417025(v=vs.85).aspx

未完待續。。。

 

    DXGI是在Windows Vista時被引入,封裝了Direct3D10,10.1,11和11.1所需的底層工作。從一個Direct3D 9圖形程序員的角度來看,DXGI封裝了大多數枚舉、交換鏈的創建等以前封裝在Direct3D 9 APIs 中的代碼。當你移植一個應用程序到DXGI、Direct3D10.X和Direct3D 11.X時,你需要考慮一些注意事項以確保程序可以順利的運行。

 

全屏相關問題:

    從Direct3D 9過度到DXGI和Direct3D 10.x或Direct3D 11.x時,當從窗口模式轉換到全屏模式所伴隨的問題通常可能會讓起開發者頭痛,主要的問題是Direct3D 9應用程序不像DXGI應用程序需要更深入的接近window styles和 window states。當切換模式的代碼在DXGI中運行時經常引起一些並非預期的效果。

    通常,Direct3D 9應用程序通過設置前台緩存的分辨率迫使設備進入全屏獨占模式,然後設置後台緩存的分辨率相匹配。使用了一個單獨的途徑改變窗體的尺寸,因為程序不得不被window process管理並且任何時候都將接收到一個WM_SIZE處理消息。

 

    DXGI試圖通過合並這兩部分處理以簡化該操作。例如,當窗口模式下窗體的邊框被拖拽時,應用程序會接受到一個WM_SIZE 處理消息,DXGI捕獲此消息並自動改變前台緩存的大小。應用程序只需使用WM_SIZE傳遞的尺寸參數並調用IDXGISwapChain::ResizeBuffers 重置後台緩沖的尺寸。相似的,當窗體在全屏和窗口模式之間切換時,應用程序可簡單的調用  IDXGISwapChain::SetFullscreenState 。DXGI重置前台緩沖大小以匹配剛剛的全屏模式操作,並且發送一個WM_SIZE message到應用程序,應用程序再次調用ResizeBuffers函數就像之前窗體的邊框被拖拽一樣。

SharpDX代碼實例:

//全屏切換觸發事件
void renderForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (SwapChain.IsFullScreen)
            {
                if (e.KeyCode == Keys.Escape)
                {
                    SwapChain.IsFullScreen = false;
                }

            }
            else
            {
                if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.Enter)
                {
                    SwapChain.IsFullScreen = true;
                }
            }
        }

//WM_SIZE事件
 void renderForm_ClientSizeChanged(object sender, EventArgs e)
        {

            if (renderForm.ClientSize.Width != 0 && renderForm.ClientSize.Height != 0)//最小化時尺寸為0
            {
                backBufferWidth = renderForm.ClientSize.Width;
                backBufferHeight = renderForm.ClientSize.Height;

                Disposer.RemoveAndDispose(ref backBufferTexture);
                Disposer.RemoveAndDispose(ref backBufferTargetView);

                //


                SwapChain.ResizeBuffers(1, backBufferWidth, backBufferHeight, Format.R8G8B8A8_UNorm, SwapChainFlags.None);


                backBufferTexture = Texture2D.FromSwapChain<Texture2D>(SwapChain, 0);
                backBufferTargetView = new RenderTargetView(device, backBufferTexture);
                device.ImmediateContext.Rasterizer.SetViewport(new ViewportF(0, 0, backBufferWidth, backBufferHeight, 0.0f, 1.0f));
      }
}

 

 

 

    之前論述的方法遵循一個非常特殊方式,DXGI通過設置默認的桌面分辨率作為全屏模式。然而許多應用程序切換一個預設的分辨率到全屏模式,這種情況下,DXGI提供 IDXGISwapChain::ResizeTarget 函數。這個函數應在調用  SetFullscreenState 之前調用。雖然這些方法可以通過相反的順序調用(先調用SetFullscreenState , 隨後調用 ResizeTarget),這樣做會導致一個額外的WM_SIZE處理消息在應用程序中觸發。(這樣做也會引起閃爍,因為DXGI可能會在兩個模式之間強制執行)。在調用SetFullscreenState後,再次通過被重置的DXGI_MODE_DESC 的成員變量RefreshRate 調用ResizeTarget 是一個明智的操作。這意味著在DXGI中是一個無操作的命令,但是它可以避免接下來討論的刷新率問題。

 

    在全屏模式中,窗口桌面管理(DWM)是無效的,DXGI會以更輕量的方式代替窗口模式下的區域傳輸呈現後台緩沖區中的內容。這種性能的開銷得到釋放。然而,我們還沒有談到如何在確定條件下確保以輕量的方式代替區域的傳輸模式。這種情況下前台緩沖和後台緩沖必須尺寸相同。如果應用程序正確的處理了WM_SIZE處理消息,這顯然不是問題,同樣格式也必須完全相同。

 

   對大部分應用程序來說問題是刷新率,在調用  ResizeTarget 時所指定的刷新率必須是交換鏈使用的 IDXGIOutput 的刷新率,  DXGI_MODE_DESC 被傳入ResizeTarget函數後其成員RefreshRate 的值會被DXGI自動重置計算。不要假定確切刷新率值會被支持。通常,開發者選擇60HZ作為刷新率,並不了解顯示器的刷新率是大約60,000 / 1,001 Hz。如果刷新率不符合期望的60HZ,DXGI會強制進行區域傳輸代替全屏的輕量傳輸。

 

   最後一個問題是開發者經常面對如何在全屏模式下改變分辨率。調用 ResizeTarget 和SetFullscreenState 有時會成功,但是全屏分辨率是桌面的分辨率,同樣,開發者可能會在全屏模式下創建指定的分辨率,我們發現DXGI會忽略我們傳入的指定分辨率。除非特別指出,全屏交換鏈會使用默認桌面的分辨率。當創建全屏分辨率的交換鏈,DXGI_SWAP_CHAIN_DESC 的Flags成員結構體必須設置為DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH 覆蓋默認參數。這個flag同樣也需要被傳入到 ResizeTarget 中動態的開啟或者禁用。

  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved