2015-10-16 6 views
7

В Microsoft example для использования PixelShader они используют одноэлементный. Я видел ту же картину в other places, и здесь они говорятСледует ли использовать одноэлементный PixelShader?

Пиксельный шейдер хранится в частном статическом поле _pixelShader. Это поле является статическим, потому что одного экземпляра скомпилированного шейдерного кода достаточно для всего класса.

Мы видели несколько проблем с утечкой памяти при использовании этого шаблона. В PixelShader задействована обработка событий, которая не всегда корректно очищается. Нам пришлось freeze их, и мы увидели некоторое улучшение. Нам пришлось вручную сделать некоторые отряды.

 // Attach/detach effect as UI element is loaded/unloaded. This avoids 
     // a memory leak in the shader code as described here: 
     element.Loaded += (obj, args) => 
     { 
      effect.PixelShader = ms_shader; 
      element.Effect = effect; 
     }; 
     element.Unloaded += (obj, args) => 
     { 
      effect.PixelShader = null; 
      element.Effect = null; 
     }; 

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

ответ

1

Определенно NO. Однако причина не в том, что она сама по себе не с PixelShader, но ее использование в ShaderEffect.
Почти все реализации пользовательских Shader Effects для WPF основаны на образцах Microsoft .NET 3.5, которые не были обновлены для .NET 4.0. Было хорошо использовать экземпляр singleton PixelShader для всех эффектов, поддерживающих только шейдеры ps_2_0. С .NET 4.0 Microsoft представила поддержку пиксельных шейдеров ps_3_0 (для устройств с ускорением GPU), а вместе с ними они ввели утечку памяти в класс ShaderEffect.
ShaderEffect отслеживает его свойство PixelShader и проверяет, что он не использует регистры ps_3_0 для байт-кода ps_2_0 путем сильной подписки на внутреннее событие PixelShader под названием _shaderBytecodeChanged. Поэтому singleton PixelShader, используемый несколькими экземплярами ShaderEffect, служит корнем доминирования для GC и сохраняет все объекты, которые использовались с любым экземпляром соответствующих ShaderEffect. То есть known memory leak, который не будет исправлен.
Если вы хотели бы использовать PixelShader в качестве одноэлементных без утечек, то вы должны будете использовать во время выполнения взлома: каждый раз, когда PixelShader экземпляр назначен PixelShader свойству ShaderEffect класса, _shaderBytecodeChanged поле PixelShader экземпляра должны быть удалены вручную, например:

Конечно, эти операции могут быть оптимизированы путем создания вспомогательных методов во время выполнения с помощью инфраструктуры или аналогичных механизмов DynamicMethod. Однако это следует использовать только для шейдеров, которые, безусловно, являются ps_2_0 или определенно ps_3_0