Почему я получаю E_OUTOFMEMORY?

По какой-то причине приведенный ниже код выдаст мне ошибку нехватки памяти. Что мне не хватает?

    for(int n = 0; n < 512; ++n)
{
D3D11_TEXTURE2D_DESC texture_desc = {};
texture_desc.Width                = 1920;
texture_desc.Height               = 1080;
texture_desc.MipLevels            = 1;
texture_desc.ArraySize            = 1;
texture_desc.Format               = DXGI_FORMAT_R8G8B8A8_UNORM;
texture_desc.SampleDesc.Count     = 1;
texture_desc.Usage                = D3D11_USAGE_DEFAULT;
texture_desc.BindFlags            = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;

ID3D11Texture2D* target_d3d_ptr;
HRESULT hr = this->device_ptr->CreateTexture2D(&texture_desc, nullptr, &target_d3d_ptr);
if(FAILED(hr))
throw runtime_error(_com_error(hr).ErrorMessage());

target_d3d_ptr->Release();
}

4

Решение

Просто идея, но вы рассматривали это:
1920 * 1080 * 32 бит = 8294400 байт
Теперь 8294400 байт x 485 текстур = 3,836 ГБ памяти.
Это прямо на пределе 32-битной машины. Я не знаю, кодируете ли вы 32- или 64-битную программу, но если она 32-битная, то максимальная виртуальная память, на которую вы можете адресовать, составляет чуть менее 4 ГБ, и 512 текстур забирают вас за этот предел. Учитывая, что Release не освобождает эту память немедленно, и если вы на самом деле кодируете в 32-битном, тогда должно быть понятно, почему у вас не хватает памяти.

2

Другие решения

Может быть, это не ваш случай, но, например, метод COM от Microsoft CComObject::CreateInstance может вернуться E_OUTOFMEMORY (по крайней мере, в реализации, которую я могу найти в моей среде, т.е. Visual Studio 2012), и, на мой взгляд, это может вводить в заблуждение.

Метод COM выглядит примерно так (в atlcom.h)

ATLPREFAST_SUPPRESS(6387)
template <class Base>
_Success_(return == S_OK) HRESULT WINAPI CComObject<Base>::CreateInstance(
_Deref_out_ CComObject<Base>** pp) throw()
{
// code omitted

HRESULT hRes = E_OUTOFMEMORY;
CComObject<Base>* p = NULL;
ATLTRY(p = new CComObject<Base>())
if (p != NULL)
{
// code omitted
}
*pp = p;
return hRes;
}
ATLPREFAST_UNSUPPRESS()

и мне кажется, что приведенный выше код может вернуть E_OUTOFMEMORY даже если у вас еще много памяти: макрос ATLTRY просто оборачивает звонок new в блоке try-catch (…) и так, если конструктор Base не выбрасывает исключение, любой вид исключения, даже не связанный с проблемами памяти, то p будет NULL и функция вернется E_OUTOFMEMORY,

2

Оказывается, что catflier предоставил ответ на этот вопрос в комментарии:

релиз не выпускает сразу, а так как в коде нет
звонки это никогда не сделает Вызов любого устройства Flush метод
или наличие какого-либо swapchain (который очистит устройство) вызовет
удаление ресурса

2
По вопросам рекламы [email protected]