Visual Studio, в режиме отладки, показывает мне, что моя игра, которую я программирую, занимает все больше памяти, когда я меняю размер Windows.Все хорошо, пока я не изменяю размер экрана.Я обнаружил, что я теряю от 5 до 10 Кбайт за изменение размера окна.
Я проверил свой код несколько раз и не смог найти, где теряю память.Это может быть только в функции DX :: DeviceResources :: CreateWindowSizeDependentResources ().Вот эта функция:
void DX::DeviceResources::CreateWindowSizeDependentResources()
{
// Effacer le précédent contexte spécifique à la taille de la fenêtre.
ID3D11RenderTargetView* nullViews[] = {nullptr};
m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
m_finalScreenRenderTargetView = nullptr;
m_d2dContext->SetTarget(nullptr);
m_d2dTargetBitmapSwapChain = nullptr;
// m_d3dDepthStencilView = nullptr;
m_d3dContext->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);
m_screen1920X1080_RenderTargetView = nullptr;
m_screen1920X1080_ResourceView = nullptr;
m_d2dTargetBitmap1920Screen = nullptr;
UpdateRenderTargetSize();
if (m_need_intermediate_1920X1080_screen)
{
// Create screen 1920 X 1080
D3D11_TEXTURE2D_DESC desc;
desc.Width = 1920;
desc.Height = 1080;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
ComPtr<ID3D11Texture2D> pTexture;
m_d3dDevice->CreateTexture2D(&desc, NULL, pTexture.GetAddressOf());
DX::ThrowIfFailed(
m_d3dDevice->CreateRenderTargetView1(
pTexture.Get(),
nullptr,
&m_screen1920X1080_RenderTargetView
)
);
D3D11_SHADER_RESOURCE_VIEW_DESC rvDesc;
rvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;//desc.Format; // Use format from the texture
rvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; // Resource is a 2D texture
rvDesc.Texture2D.MostDetailedMip = 0;
rvDesc.Texture2D.MipLevels = 1;
DX::ThrowIfFailed(m_d3dDevice->CreateShaderResourceView(pTexture.Get(), &rvDesc, m_screen1920X1080_ResourceView.GetAddressOf()));
// Create bitmap for Direct2D target for Screen 1920
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
m_dpi,
m_dpi
);
ComPtr<IDXGISurface2> dxgi1920Screen;
DX::ThrowIfFailed(
pTexture->QueryInterface<IDXGISurface2>(dxgi1920Screen.GetAddressOf())
);
DX::ThrowIfFailed(
m_d2dContext->CreateBitmapFromDxgiSurface(
dxgi1920Screen.Get(),
&bitmapProperties,
&m_d2dTargetBitmap1920Screen
)
);
pTexture = nullptr; // release pTexture
dxgi1920Screen = nullptr; // release
}
// La largeur et la hauteur de la chaîne de permutation doivent être basées sur la
// largeur et hauteur en orientation native. Si la fenêtre n'est pas en orientation native
// l'orientation portrait, les dimensions doivent être inversées.
DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation();
bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270;
m_d3dRenderTargetSize.Width = swapDimensions ? m_outputSize.Height : m_outputSize.Width;
m_d3dRenderTargetSize.Height = swapDimensions ? m_outputSize.Width : m_outputSize.Height;
if (m_swapChain != nullptr)
{
// Si la chaîne de permutation existe déjà, la redimensionner.
HRESULT hr = m_swapChain->ResizeBuffers(
2, // Chaîne de permutation mise deux fois en mémoire tampon.
lround(m_d3dRenderTargetSize.Width),
lround(m_d3dRenderTargetSize.Height),
DXGI_FORMAT_B8G8R8A8_UNORM,
0
);
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
// Si le périphérique a été supprimé pour une raison quelconque, un périphérique et une chaîne de permutation doivent être créés.
HandleDeviceLost();
// Tout est maintenant configuré. Ne poursuivez pas l'exécution de cette méthode. HandleDeviceLost entrera à nouveau cette méthode
// et configurer correctement le nouveau périphérique.
return;
}
else
{
DX::ThrowIfFailed(hr);
}
}
else
{
// Sinon, en créer une nouvelle en utilisant le même adaptateur que le périphérique Direct3D existant.
DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Faire correspondre avec la taille de la fenêtre.
swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height);
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // Il s'agit du format de chaîne de permutation le plus courant.
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // Ne pas utiliser l'échantillonnage multiple.
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // Utiliser la double mise en mémoire tampon pour réduire la latence.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // Toutes les applications Windows Store doivent utiliser ce SwapEffect.
swapChainDesc.Flags = 0;
swapChainDesc.Scaling = DXGI_SCALING_NONE;// scaling;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
// Cette séquence obtient la fabrique DXGI utilisée pour créer le périphérique Direct3D ci-dessus.
ComPtr<IDXGIDevice3> dxgiDevice;
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(
dxgiDevice->GetAdapter(&dxgiAdapter)
);
ComPtr<IDXGIFactory4> dxgiFactory;
DX::ThrowIfFailed(
dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
);
ComPtr<IDXGISwapChain1> swapChain;
DX::ThrowIfFailed(
dxgiFactory->CreateSwapChainForCoreWindow(
m_d3dDevice.Get(),
reinterpret_cast<IUnknown*>(m_window.Get()),
&swapChainDesc,
nullptr,
&swapChain
)
);
DX::ThrowIfFailed(
swapChain.As(&m_swapChain)
);
// Vérifier que DXGI ne met pas plus d'un frame à la fois en file d'attente. Cela permet de réduire la latence et
// de veiller à ce que l'application effectue le rendu uniquement après chaque VSync, réduisant de ce fait la consommation d'énergie.
DX::ThrowIfFailed(
dxgiDevice->SetMaximumFrameLatency(1)
);
}
// Définir l'orientation appropriée pour la chaîne de permutation et générer des
// transformations de matrices 2D et 3D pour effectuer le rendu vers la chaîne de permutation pivotée.
// Noter que l’angle de rotation des transformations 2D et 3D est différent.
// Ceci est dû à la différence entre les espaces de coordonnées. En outre,
// la matrice 3D est spécifiée de manière explicite pour éviter les erreurs d'arrondi.
switch (displayRotation)
{
case DXGI_MODE_ROTATION_IDENTITY:
m_orientationTransform2D = Matrix3x2F::Identity();
m_orientationTransform3D = ScreenRotation::Rotation0;
break;
case DXGI_MODE_ROTATION_ROTATE90:
m_orientationTransform2D =
Matrix3x2F::Rotation(90.0f) *
Matrix3x2F::Translation(m_logicalSize.Height, 0.0f);
m_orientationTransform3D = ScreenRotation::Rotation270;
break;
case DXGI_MODE_ROTATION_ROTATE180:
m_orientationTransform2D =
Matrix3x2F::Rotation(180.0f) *
Matrix3x2F::Translation(m_logicalSize.Width, m_logicalSize.Height);
m_orientationTransform3D = ScreenRotation::Rotation180;
break;
case DXGI_MODE_ROTATION_ROTATE270:
m_orientationTransform2D =
Matrix3x2F::Rotation(270.0f) *
Matrix3x2F::Translation(0.0f, m_logicalSize.Width);
m_orientationTransform3D = ScreenRotation::Rotation90;
break;
default:
throw ref new FailureException();
}
DX::ThrowIfFailed(
m_swapChain->SetRotation(displayRotation)
);
// Créer un affichage cible de rendu de la mémoire tampon d'arrière-plan de la chaîne de permutation.
ComPtr<ID3D11Texture2D1> backBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
);
DX::ThrowIfFailed(
m_d3dDevice->CreateRenderTargetView1(
backBuffer.Get(),
nullptr,
&m_finalScreenRenderTargetView
)
);
backBuffer = nullptr; // Release
/* // Créer un affichage gabarit à utiliser avec le rendu 3D si nécessaire.
CD3D11_TEXTURE2D_DESC1 depthStencilDesc(
DXGI_FORMAT_D24_UNORM_S8_UINT,
lround(m_d3dRenderTargetSize.Width),
lround(m_d3dRenderTargetSize.Height),
1, // Cette vue du stencil de profondeur n’a qu’une texture.
1, // Utiliser un niveau mipmap unique.
D3D11_BIND_DEPTH_STENCIL
);
ComPtr<ID3D11Texture2D1> depthStencil;
DX::ThrowIfFailed(
m_d3dDevice->CreateTexture2D1(
&depthStencilDesc,
nullptr,
&depthStencil
)
);
*/
/* CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilView(
depthStencil.Get(),
&depthStencilViewDesc,
&m_d3dDepthStencilView
)
);
*/
// swapchain viewport
m_screenSwapchainViewport = CD3D11_VIEWPORT(
0.0f,
0.0f,
m_d3dRenderTargetSize.Width,
m_d3dRenderTargetSize.Height
);
// screen 960 X 540 viewport
m_screen960X540Viewport = CD3D11_VIEWPORT(
0.0f,
0.0f,
960,
540
);
// screen 1920 X 1080 viewport
m_screen1920X1080Viewport = CD3D11_VIEWPORT(
0.0f,
0.0f,
1920,
1080
);
m_d3dContext->RSSetViewports(1, &m_screenSwapchainViewport);
// Créer une image bitmap cible Direct2D associée à la
// mémoire tampon d'arrière-plan de la chaîne de permutation et la définir en tant que cible actuelle.
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
m_dpi,
m_dpi
);
ComPtr<IDXGISurface2> dxgiBackBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
);
DX::ThrowIfFailed(
m_d2dContext->CreateBitmapFromDxgiSurface(
dxgiBackBuffer.Get(),
&bitmapProperties,
&m_d2dTargetBitmapSwapChain
)
);
dxgiBackBuffer = nullptr; // Release
m_d2dContext->SetTarget(m_d2dTargetBitmapSwapChain.Get());
m_d2dContext->SetDpi(m_effectiveDpi, m_effectiveDpi);
// L'anticrénelage du texte en nuances de gris est recommandé pour toutes les applications Windows Store.
m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
}
А вот ссылка на весь проект на моем OneDrive, в случае, если вы хотите увидеть утечку самостоятельно или если вы хотите увидеть другие части кода:
https://1drv.ms/f/s!Aj7wxGmZTdftgZAZT5YAbLDxbtMNVg Компилировать как код X64.Продолжайте изменять размер окна, перетаскивая правый угол нижнего края игрового окна по кругу, и наблюдайте, как используемая память постоянно увеличивается.