2013-02-14 76 views
1

我正在努力解決這個問題;使用D3D11.1和一個標準的Win32桌面窗口時,我在調整窗口大小時發生內存不足錯誤,但僅在手動調整幾秒鐘的大小時發生。最大限度地工作正常,並調整速度很快工作正常。就好像在手動調整大小的過程中不斷分配某些東西,但我無法弄清楚它是什麼。D3D11.1調整窗口大小時內存不足?

LRESULT CALLBACK ProcessWindow(HWND hWnd, uint32 nMessage, WPARAM wParam, LPARAM lParam) 
{ 
switch(nMessage) 
{ 
case WM_SIZE: 
    OnResize(); 
    return DefWindowProc(hWnd, nMessage, wParam, lParam); 
} 

return DefWindowProc(hWnd, nMessage, wParam, lParam); 
} 



void OnResize() 
{ 
    ResizeSwapChain(); 
    ResetRenderTargets(); 
    ResetDepthStencil(); 
} 



void ResizeSwapChain() 
{ 
if(m_pD3DSwapChain) 
{ 
    m_D3DDepthStencilView.ReleaseAndGetAddressOf(); 
    m_pD3DRenderTarget.ReleaseAndGetAddressOf(); 

    //THE SWAP CHAIN ALREADY EXISTS, RESIZE IT 
    DXErrorOnFail(m_pD3DSwapChain->ResizeBuffers(nBufferCount, 0, 0, SwapChainFormat, 0)); 
} 
} 



bool ResetRenderTargets() 
{ 
ComPtr<ID3D11Texture2D> B; 
DXErrorOnFail(m_pD3DSwapChain->GetBuffer(0, IID_PPV_ARGS(&B))); 

DXErrorOnFail(m_pD3DDevice->CreateRenderTargetView(B.Get(), nullptr, &m_pD3DRenderTarget)); 

B.ReleaseAndGetAddressOf(); 

if(!m_pD3DRenderTarget) 
{ 
    return false; 
} 

return true; 
} 



bool ResetDepthStencil() 
{ 
D3D11_TEXTURE2D_DESC BBD; 

ComPtr<ID3D11Texture2D> B; 
DXErrorOnFail(m_pD3DSwapChain->GetBuffer(0, IID_PPV_ARGS(&B))); 

B->GetDesc(&BBD); 

D3D11_TEXTURE2D_DESC DSD; //DEPTH STENCIL DESC 
memset(&DSD, 0, sizeof(D3D11_TEXTURE2D_DESC)); 

DSD.Width    = BBD.Width; 
DSD.Height    = BBD.Height; 
DSD.MipLevels   = 1; 
DSD.ArraySize   = 1; 
DSD.Format    = DXGI_FORMAT_D24_UNORM_S8_UINT; 
DSD.SampleDesc.Count = 1; 
DSD.SampleDesc.Quality = 0; 
DSD.Usage    = D3D11_USAGE_DEFAULT; 
DSD.BindFlags   = D3D11_BIND_DEPTH_STENCIL; 
DSD.CPUAccessFlags  = 0; 
DSD.MiscFlags   = 0; 

ComPtr<ID3D11Texture2D> DS; 
DXErrorOnFail(m_pD3DDevice->CreateTexture2D(&DSD, nullptr, &DS)); 

D3D11_DEPTH_STENCIL_VIEW_DESC DVD; 
memset(&DVD, 0, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC)); 

DVD.Format    = DSD.Format; 
DVD.ViewDimension  = D3D11_DSV_DIMENSION_TEXTURE2D; 
DVD.Flags    = 0; 
DVD.Texture2D.MipSlice = 0; 

DXErrorOnFail(m_pD3DDevice->CreateDepthStencilView(DS.Get(), &DVD, &m_D3DDepthStencilView)); 

B.ReleaseAndGetAddressOf(); 
DS.ReleaseAndGetAddressOf(); 

if(!m_D3DDepthStencilView) 
{ 
    return false; 
} 

return true; 
} 


bool ResetViewports() 
{ 
D3D11_TEXTURE2D_DESC BBD; //BACK BUFFER DESC 
memset(&BBD, 0, sizeof(D3D11_TEXTURE2D_DESC)); 

ComPtr<ID3D11Texture2D> B; 
DXErrorOnFail(m_pD3DSwapChain->GetBuffer(0, IID_PPV_ARGS(&B))); 

B->GetDesc(&BBD); 

D3D11_VIEWPORT V; 
V.TopLeftX = 0.0f; 
V.TopLeftY = 0.0f; 
V.Width = static_cast<float32>(BBD.Width); 
V.Height = static_cast<float32>(BBD.Height); 
V.MinDepth = D3D11_MIN_DEPTH; 
V.MaxDepth = D3D11_MAX_DEPTH; 

m_pD3DDeviceContext->RSSetViewports(1, &V); 

return true; 
} 

我真的很感謝這方面的任何幫助,謝謝。

回答

0

調整大小時重新分配不是幾個原因是一個好主意:

  • 你會破壞並重新創建資源很多(在這種情況下它是一個簡單的例子,想想有很多中間紋理的複雜應用程序)。
  • 當您調用ReleaseAndGetAddressOf時,DX不會立即銷燬資源,它會在下次刷新緩衝區時執行此操作,因爲在調整大小時可能無法呈現,上下文不會被刷新。

一個更清潔的解決方案是使用Begin/EndResize事件。 WM_ENTERSIZEMOVE WM_EXITSIZEMOVE

在輸入消息上設置一個標誌,並在退出時應用您的更改。

相關問題