Обычно внутренняя реализация подсчета ссылок COM выполняется поточно-ориентированным способом (атомные приращения / убывания), поэтому можно безопасно вызывать AddRef
и Release
из нескольких потоков.
Конечно, если refcount идет в 0, то у вас есть уничтожение объекта, поэтому важно, чтобы, если у вас было несколько потоков, использующих один и тот же ресурс, у него было соответствующее количество ссылок для поддержания его работоспособности. В Direct3D уничтожение объектов, как правило, отложенное уничтожение , поэтому фактическая очистка объекта может не произойти в течение нескольких кадров, но вы все равно должны сохранять ненулевой пересчет, если кто-либо ссылается на него.
Direct3D 11 использует те же правила, что и Direct3D 10. Он использует «слабые ссылки» для методов конвейерного набора, поэтому просто установить ресурс в контексте устройства не достаточно для увеличения счетчика ссылок. IOW: если у вас есть два потока, которые рендерится с одним и тем же ресурсом, то каждый поток должен хранить счетчик ссылок на объект, чтобы он оставался «живым», независимо от того, «активен ли он» в контексте устройства в любой данный момент.
Это работает таким образом, чтобы избежать накладных расходов на постоянное увеличение / уменьшение счетчиков ссылок каждого кадра рендеринга. В Direct3D 9 это происходило тысячи раз за кадр или более.
Кроме того, если ID3D11Device
достигает нулевого повторного счета, он и все его дочерние объекты освобождаются независимо от количества ссылок на отдельные дочерние устройства.
См. Документы Microsoft .
Лучший ответ - использовать умный указатель, такой как Microsoft :: WRL :: ComPtr , и каждый поток, использующий данный ресурс, имеет собственный ComPtr
, указывающий на этот ресурс. Таким образом, единственный реальный особый случай, который у вас будет, это когда вы отключаете устройство (например, отвечаете на DXGI_ERROR_DEVICE_REMOVED
или делаете «чистый выход»).