Потенциальная утечка памяти при выпуске градиентной кисти в Direct2D? - PullRequest
1 голос
/ 19 апреля 2019

У меня есть простая программа на C ++, уменьшенная до 272 строк кода, которая инициализирует Direct2D, затем выполняет цикл из 1000 операций, где она просто создает ID2D1GradientStopCollection с последующим созданием использования ID2D1LinearGradientBrush, а затем немедленно их освобождает (количество выпусков падает доноль на вызовах Release, что указывает на то, что они обычно должны быть нераспределенными).

Однако после каждого выполнения этого цикла я вижу, что память, зарезервированная процессом, увеличивается, и она освобождается только в конце,как только фабрики и устройства direct2D будут выпущены, вместо того чтобы выпускаться после каждого вызова linearGradientBrush-> Release () и GradientStopCollection-> Release (), как я и ожидал.

Странная вещь заключается в том, что когда я создаю /удалите SolidColorBrush вместо LinearGradientBrush (все еще создавая / удаляя GradientStopCollection), тогда утечки памяти больше не наблюдается.

Я что-то не так сделал, вызвав, например,dientStopCollection будет по-прежнему выделяться, потому что все еще используется кистью?(Но я не вижу в этом случае, почему счетчик ссылок после вызова Release для двух объектов падает до нуля; а также, если я добавляю AddRef или удаляю Release, чтобы вызвать неправильный счетчик AddRef / Release наобъекты (и получают ненулевой счетчик ссылок в конце программы), затем слои отладки Direct2D указывают на ошибку внутри d2d1debug3.dll, вызывающую kernelbase.dll в стеке вызовов, таким образом показывая, что счетчик AddRef / Release правильный;все же я все еще наблюдаю эту утечку памяти с помощью TaskManager).

Любая помощь в том, как решить эту проблему, будет оцененана платформе x86 / x64 формы отладки / выпуска

1 Ответ

0 голосов
/ 15 мая 2019

Это ожидаемое поведение, учитывая ваш код.

Внутренне, Direct3D11 выполняет некоторое отслеживание ресурса, и вызывающий релиз отметит ресурс только для удаления, ресурс будет эффективно удален, если выполнены следующие условия:

  • DeviceContext обнуляется
  • Внешний счетчик ресурса равен 0 (тот, который был возвращен Release)
  • Внутренний счетчик ресурса равен 0, он увеличивается, когда ваш ресурс подключен, отсоединен от конвейера (в вашем случае это обрабатывает Direct2D)

Так как в вашем цикле вы вообще не очищаете, ресурсы создаются на GPU, но помечаются только для удаления.

Существует несколько способов очистки устройства:

  • Когда вы вызываете EndDraw (или присутствует в Swapchain), для отображения на экране.
  • Когда вы вручную выполняете Flush в контексте устройства Direct3D (обратите внимание, что вы не должны вызывать Flush вручную, если вы действительно выполняете рендеринг на экране, так как Present / EndDraw позаботится об этом)
  • Когда вы сопоставляете ресурс для обратного чтения процессора (я полагаю, это выходит за рамки вашего использования)
  • Когда внутренний буфер команд заполнен (так как в вашем случае вы не выполняете никаких вызовов рисования, если никогда не заполняетесь).

В случае Direct3d11 вы также должны в конечном итоге вызвать ClearState (это сбрасывает весь конвейер, хотя), но поскольку Direct2D обычно заботится о нераспределении внутренних ресурсов, это не должно быть необходимо и в вашем случае использования.

...