2017-02-10 6 views
1

У меня есть цикл рендеринга, который прослушивает вход для планшетов и выводит из буферов вершин/индекс (между прочим). Данные вершины могут расти и, когда она попадает определенных уровней, DispatchMsg (& тзд) встречает это:Недостаток видеопамяти DirectX11

Unhandled exception at 0x5DDBDEF0 (msvcr110d.dll) in App.exe: 0xC0000005: Access violation writing location 0x00000000. 

Общий размер выделенных вершинных и индексных буферов в сцене вокруг одних и тех же уровнях, каждый раз, когда:

Total Vertices count: 10391370 
Total Indices count: 41565480 
Total Vertices size: 249392880 (bytes) 
Total Indices size: 997571520 (bytes) 

и в другой выборке:

Total Vertices count: 9969300 
Total Indices count: 39877200 
Total Vert size: 239263200 
Total Indices size: 957052800 

вершина и индексные буфера оба D3D11_USAGE_DEFAULT. Общее распределение размеров в сцене выше, чем указано выше, но меньшие буферы часто отпускаются. В конце есть также добавление буферов вершин/индексов.

Сообщение о быть посланными каждый раз (при достижении исключения) является 581, который я считаю, может быть:

#define WM_POINTERUPDATE    0x0245 

Я действительно не против сцены рендеринга медленно, но если я достигая некоторого максимального объема памяти (видеопамять?), есть ли способ, чтобы память медленно перемещалась в/из памяти памяти за счет скорости? Я попытался отключить вызов draw(), который вызывает пиксельные, вершинные шейдеры и вызовы рисования, но исключение все еще происходит. Я бы предпочел компромисс скорости или обходной путь к исключению.

+0

Сколько вертиций вы рисуете? Это похоже на множество данных. 10 миллионов верт? – tadman

+0

Правильно, это кажется высоким, поэтому я ожидаю проблемы в какой-то момент, просто хочу выяснить причину или что можно сделать по этому поводу. – user176692

+0

Это много верт. Я удивлен, что вы могли бы выделить столько, если бы не загорелось. Вы создаете слишком много, например, как их утечка? – tadman

ответ

1

Из цифр в вашем вопросе кажется, что вы выделяете много памяти для ваших данных вершин и индексов (около 1,2 ГБ). Если ваше приложение 32-разрядное (x86, в отличие от x64), он имеет доступ только к 2 ГБ памяти, поэтому вполне может быть, что ваш процесс не работает.

GPU имеет доступ к части системной памяти (что довольно медленно по сравнению с памятью GPU, но лучше, чем без памяти). Например, для графических процессоров NVidia панель управления NVidia показывает ее в разделе «Сведения о системе»> «Общая системная память»; это обычно половина общего объема оперативной памяти в вашей системе.Насколько мне известно, эта системная память занимает часть адресного пространства вашего процесса.

Если ваш «довольно старый» графический процессор имеет 512 МБ памяти, для удовлетворения ваших запросов на память потребуется около 768 МБ дополнительной системной памяти. Это оставляет 1,2 ГБ для вашего приложения. Я предполагаю, что ваше приложение пытается выделить 1,2 ГБ системной памяти в массивах, которые будут принимать ваши данные геометрии, которые вы хотите загрузить на GPU. Это будет просто соответствовать, но ваш код приложения должен быть где-то тоже. В этом гипотетическом случае у вас уже не хватает памяти. Разумеется, вы можете избавиться от массивов системной памяти, как только вы загрузите данные геометрии на GPU, но в этот момент система не имеет достаточного объема памяти для создания буфера памяти GPU с запрошенным размером ,

Переключение проекта на 64-разрядный (x64 в Visual Studio) позволит вашему процессу значительно увеличить объем памяти (в большинстве случаев до того, что доступно в вашей системе и файле подкачки) и решить вашу проблему. Если проблемы с памятью на самом деле являются проблемой.

Другое дело: я заметил, что - если ваши цифры правы - вы выделяете 24 байта на индекс для буфера индекса, столько же, сколько вы выделяете для каждой вершины в буфере вершин. Это верно? Индекс (который является просто смещением в буфер вершин) не должен превышать 4 байта. Вы действительно пытаетесь выделить в 6 раз больше памяти GPU, сколько вам нужно, или это неправильный расчет в вашем приложении?

Если вы быстро отпустите и затем заново создадите буфер на графическом процессоре, тогда D3D может поддерживать «старый» буфер на некоторое время (по крайней мере, пока он все еще привязан к контуру GPU), поэтому он может из-за этого. Таким образом, это может помочь развязать буферы, которые вы собираетесь выпустить (путем вызова IASetVertexBuffers(NULL, 0, 0, 0, 0) и IASetIndexBuffer(NULL, DXGI_FORMAT_R16_UINT, 0)).

+0

Выделение индексов может быть отключено, но каждая вершина была повторно использована совсем немного, чтобы построить пирамиду или тип алмазного типа. Это заменяется контрольными точками и тесселяционными или геометрическими шейдерами для рендеринга в реальном времени и сферами для автономного рендеринга. 32-разрядное адресное пространство - огромная проблема, спасибо за то, что вы упомянули об этом, я полностью забыл об этом. Я использую некоторые 32-битные библиотеки, которые я создал, и их нужно будет перенести. Также теперь используется W5100 Firepro, который также расширит возможности памяти. – user176692

+0

Чтобы быть ясным, это не число индексов, которые кажутся слишком высокими (повторное использование индексов FTW), а количество памяти (количество байтов), которое занимают ваши индексы. Индексы 41565480 в вашем первом примере должны занимать 41565480 * 4 = 166261920 байт (166 МБ), но по вашему вопросу выделено 997571520 байт (997 МБ!), Что позволяет использовать память почти наверняка после ограничений памяти 32-битного процесса , Поскольку объем заявленной памяти - это количество индексов, умноженное на 24 (это ваш размер вершин), это может быть ошибка в вычислении размера индекса индекса или просто опечатка. – Pepor

+0

Я так думаю! Если бы это прокомментировало, но не было уверенным, какие сообщения отладки я использовал // debugMsg («Ind size:» + iToS (sizeof (Vertex) * editingModel-> builtIndicesCount)); Поэтому он выделял меньше, просто отображая неверно в моем журнале отладки.Уже использование контрольных точек и изменение способа построения геометрии, но хороший улов! – user176692

1

Найден ответ и решил проблему. В зависимости от количества входящих вершин, CreateBuffer терпел неудачу или сбой malloc/HeapAlloc.

Я все еще не уверен на 100%, если графический процессор должен быть пейджинговой памятью в основной системной памяти через определенную точку или если это неизбежно, поскольку данные сцены должны оставаться на памяти графического процессора во время вычислений каждого кадра (глубина, освещение , и т. д.), но я думаю, что A) пейджинг был бы возможен только в том случае, если я вручную удалю/переустановил буферы (в любом случае будет медленным), а B) размер выделенных буферов (вершин, индексов ...) проблема, а не вычисления на каждом кадре.

Я попытался переключиться на использование других буферов (USAGE_DYNAMIC), но ошибки распределения по-прежнему происходили на тех же уровнях.

Я быстро изменил размеры буфера (буферы, требующие заполнения), и теперь до 20 миллионов вершин. Мой GPU довольно старый, так что это неплохо, хотя некоторые рендеринги могут пойти далеко за рамки этого, я знаю.

Идет фокусироваться на обходных методах и уменьшать детали где и когда это возможно. Я думаю, что могу получить ~ 15 раз больше деталей с тесселяцией, поэтому не в плохом состоянии.

Если у кого-то есть более глубокое понимание, можете переключиться на правильный ответ, но не уверен, что я собираюсь пойти по другому пути здесь.

Смежные вопросы